gsd-pi 2.44.0-dev.62b5d6c → 2.44.0-dev.848dd4c
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/README.md +30 -12
- package/dist/resources/extensions/gsd/auto-start.js +10 -0
- package/dist/resources/extensions/gsd/commands/handlers/workflow.js +5 -0
- package/dist/web/standalone/.next/BUILD_ID +1 -1
- package/dist/web/standalone/.next/app-path-routes-manifest.json +18 -18
- package/dist/web/standalone/.next/build-manifest.json +2 -2
- package/dist/web/standalone/.next/prerender-manifest.json +3 -3
- package/dist/web/standalone/.next/server/app/_global-error.html +2 -2
- package/dist/web/standalone/.next/server/app/_global-error.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.html +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/index.html +1 -1
- package/dist/web/standalone/.next/server/app/index.rsc +1 -1
- package/dist/web/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/index.segments/_full.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/index.segments/_head.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/index.segments/_index.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/index.segments/_tree.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app-paths-manifest.json +18 -18
- package/dist/web/standalone/.next/server/pages/404.html +1 -1
- package/dist/web/standalone/.next/server/pages/500.html +2 -2
- package/dist/web/standalone/.next/server/server-reference-manifest.json +1 -1
- package/package.json +1 -1
- package/packages/pi-coding-agent/dist/core/auth-storage.test.js +6 -8
- package/packages/pi-coding-agent/dist/core/auth-storage.test.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/extensions/runner.test.js +24 -26
- package/packages/pi-coding-agent/dist/core/extensions/runner.test.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/fs-utils.test.js +29 -48
- package/packages/pi-coding-agent/dist/core/fs-utils.test.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/resolve-config-value.test.js +34 -44
- package/packages/pi-coding-agent/dist/core/resolve-config-value.test.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/session-manager.test.js +30 -34
- package/packages/pi-coding-agent/dist/core/session-manager.test.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/tools/edit-diff.test.js +10 -12
- package/packages/pi-coding-agent/dist/core/tools/edit-diff.test.js.map +1 -1
- package/packages/pi-coding-agent/dist/resources/extensions/memory/storage.test.js +43 -47
- package/packages/pi-coding-agent/dist/resources/extensions/memory/storage.test.js.map +1 -1
- package/packages/pi-coding-agent/src/core/auth-storage.test.ts +7 -7
- package/packages/pi-coding-agent/src/core/extensions/runner.test.ts +26 -26
- package/packages/pi-coding-agent/src/core/fs-utils.test.ts +31 -43
- package/packages/pi-coding-agent/src/core/resolve-config-value.test.ts +40 -45
- package/packages/pi-coding-agent/src/core/session-manager.test.ts +33 -33
- package/packages/pi-coding-agent/src/core/tools/edit-diff.test.ts +17 -17
- package/packages/pi-coding-agent/src/resources/extensions/memory/storage.test.ts +74 -74
- package/src/resources/extensions/gsd/auto-start.ts +14 -0
- package/src/resources/extensions/gsd/commands/handlers/workflow.ts +8 -0
- package/src/resources/extensions/gsd/tests/all-milestones-complete-merge.test.ts +99 -99
- package/src/resources/extensions/gsd/tests/auto-lock-creation.test.ts +14 -16
- package/src/resources/extensions/gsd/tests/auto-paused-session-validation.test.ts +43 -57
- package/src/resources/extensions/gsd/tests/auto-preflight.test.ts +11 -13
- package/src/resources/extensions/gsd/tests/auto-recovery.test.ts +465 -523
- package/src/resources/extensions/gsd/tests/auto-secrets-gate.test.ts +73 -75
- package/src/resources/extensions/gsd/tests/auto-start-needs-discussion.test.ts +34 -56
- package/src/resources/extensions/gsd/tests/auto-worktree-milestone-merge.test.ts +533 -656
- package/src/resources/extensions/gsd/tests/auto-worktree.test.ts +165 -143
- package/src/resources/extensions/gsd/tests/cache-staleness-regression.test.ts +29 -52
- package/src/resources/extensions/gsd/tests/captures.test.ts +148 -176
- package/src/resources/extensions/gsd/tests/claude-import-tui.test.ts +32 -33
- package/src/resources/extensions/gsd/tests/collect-from-manifest.test.ts +141 -143
- package/src/resources/extensions/gsd/tests/commands-inspect-open-db.test.ts +25 -25
- package/src/resources/extensions/gsd/tests/commands-logs.test.ts +81 -81
- package/src/resources/extensions/gsd/tests/complete-milestone.test.ts +38 -59
- package/src/resources/extensions/gsd/tests/complete-slice.test.ts +228 -263
- package/src/resources/extensions/gsd/tests/complete-task.test.ts +250 -302
- package/src/resources/extensions/gsd/tests/context-store.test.ts +354 -367
- package/src/resources/extensions/gsd/tests/continue-here.test.ts +68 -72
- package/src/resources/extensions/gsd/tests/cost-projection.test.ts +92 -106
- package/src/resources/extensions/gsd/tests/crash-recovery.test.ts +27 -35
- package/src/resources/extensions/gsd/tests/dashboard-budget.test.ts +220 -237
- package/src/resources/extensions/gsd/tests/db-writer.test.ts +390 -420
- package/src/resources/extensions/gsd/tests/definition-loader.test.ts +76 -92
- package/src/resources/extensions/gsd/tests/derive-state-crossval.test.ts +68 -83
- package/src/resources/extensions/gsd/tests/derive-state-db.test.ts +152 -183
- package/src/resources/extensions/gsd/tests/derive-state-deps.test.ts +78 -101
- package/src/resources/extensions/gsd/tests/derive-state.test.ts +192 -227
- package/src/resources/extensions/gsd/tests/detection.test.ts +232 -278
- package/src/resources/extensions/gsd/tests/dev-engine-wrapper.test.ts +30 -34
- package/src/resources/extensions/gsd/tests/dispatch-guard.test.ts +164 -180
- package/src/resources/extensions/gsd/tests/dispatch-missing-task-plans.test.ts +43 -49
- package/src/resources/extensions/gsd/tests/dispatch-uat-last-completed.test.ts +28 -32
- package/src/resources/extensions/gsd/tests/doctor-completion-deferral.test.ts +27 -29
- package/src/resources/extensions/gsd/tests/doctor-delimiter-fix.test.ts +34 -38
- package/src/resources/extensions/gsd/tests/doctor-enhancements.test.ts +54 -75
- package/src/resources/extensions/gsd/tests/doctor-environment-worktree.test.ts +21 -32
- package/src/resources/extensions/gsd/tests/doctor-environment.test.ts +72 -97
- package/src/resources/extensions/gsd/tests/doctor-fixlevel.test.ts +38 -44
- package/src/resources/extensions/gsd/tests/doctor-git.test.ts +104 -145
- package/src/resources/extensions/gsd/tests/doctor-proactive.test.ts +84 -106
- package/src/resources/extensions/gsd/tests/doctor-roadmap-summary-atomicity.test.ts +54 -60
- package/src/resources/extensions/gsd/tests/doctor-runtime.test.ts +72 -93
- package/src/resources/extensions/gsd/tests/doctor.test.ts +104 -134
- package/src/resources/extensions/gsd/tests/ensure-db-open.test.ts +123 -131
- package/src/resources/extensions/gsd/tests/exit-command.test.ts +20 -24
- package/src/resources/extensions/gsd/tests/feature-branch-lifecycle-integration.test.ts +48 -57
- package/src/resources/extensions/gsd/tests/files-loadfile-eisdir.test.ts +5 -7
- package/src/resources/extensions/gsd/tests/flag-file-db.test.ts +30 -42
- package/src/resources/extensions/gsd/tests/freeform-decisions.test.ts +198 -206
- package/src/resources/extensions/gsd/tests/git-locale.test.ts +13 -27
- package/src/resources/extensions/gsd/tests/git-service.test.ts +285 -388
- package/src/resources/extensions/gsd/tests/gitignore-tracked-gsd.test.ts +31 -39
- package/src/resources/extensions/gsd/tests/graph-operations.test.ts +63 -69
- package/src/resources/extensions/gsd/tests/gsd-db.test.ts +255 -264
- package/src/resources/extensions/gsd/tests/gsd-inspect.test.ts +108 -119
- package/src/resources/extensions/gsd/tests/gsd-recover.test.ts +81 -103
- package/src/resources/extensions/gsd/tests/gsd-tools.test.ts +229 -262
- package/src/resources/extensions/gsd/tests/headless-answers.test.ts +13 -13
- package/src/resources/extensions/gsd/tests/health-widget.test.ts +29 -37
- package/src/resources/extensions/gsd/tests/idle-recovery.test.ts +81 -102
- package/src/resources/extensions/gsd/tests/init-wizard.test.ts +16 -18
- package/src/resources/extensions/gsd/tests/integration-edge.test.ts +41 -46
- package/src/resources/extensions/gsd/tests/integration-lifecycle.test.ts +42 -53
- package/src/resources/extensions/gsd/tests/integration-mixed-milestones.test.ts +75 -91
- package/src/resources/extensions/gsd/tests/integration-proof.test.ts +18 -18
- package/src/resources/extensions/gsd/tests/markdown-renderer.test.ts +150 -194
- package/src/resources/extensions/gsd/tests/md-importer.test.ts +101 -125
- package/src/resources/extensions/gsd/tests/memory-extractor.test.ts +45 -54
- package/src/resources/extensions/gsd/tests/memory-store.test.ts +80 -93
- package/src/resources/extensions/gsd/tests/migrate-command.test.ts +57 -66
- package/src/resources/extensions/gsd/tests/migrate-hierarchy.test.ts +83 -93
- package/src/resources/extensions/gsd/tests/migrate-parser.test.ts +161 -170
- package/src/resources/extensions/gsd/tests/migrate-transformer.test.ts +125 -141
- package/src/resources/extensions/gsd/tests/migrate-validator-parsers.test.ts +107 -131
- package/src/resources/extensions/gsd/tests/migrate-writer-integration.test.ts +87 -96
- package/src/resources/extensions/gsd/tests/migrate-writer.test.ts +125 -164
- package/src/resources/extensions/gsd/tests/must-have-parser.test.ts +81 -94
- package/src/resources/extensions/gsd/tests/none-mode-gates.test.ts +35 -36
- package/src/resources/extensions/gsd/tests/overrides.test.ts +99 -106
- package/src/resources/extensions/gsd/tests/parallel-crash-recovery.test.ts +40 -47
- package/src/resources/extensions/gsd/tests/parallel-worker-monitoring.test.ts +25 -28
- package/src/resources/extensions/gsd/tests/parallel-workers-multi-milestone-e2e.test.ts +66 -83
- package/src/resources/extensions/gsd/tests/park-edge-cases.test.ts +54 -77
- package/src/resources/extensions/gsd/tests/park-milestone.test.ts +68 -115
- package/src/resources/extensions/gsd/tests/parsers.test.ts +546 -611
- package/src/resources/extensions/gsd/tests/paths.test.ts +72 -87
- package/src/resources/extensions/gsd/tests/post-unit-hooks.test.ts +77 -117
- package/src/resources/extensions/gsd/tests/prompt-db.test.ts +56 -56
- package/src/resources/extensions/gsd/tests/queue-draft-detection.test.ts +93 -119
- package/src/resources/extensions/gsd/tests/queue-order.test.ts +70 -82
- package/src/resources/extensions/gsd/tests/queue-reorder-e2e.test.ts +42 -55
- package/src/resources/extensions/gsd/tests/quick-auto-guard.test.ts +100 -0
- package/src/resources/extensions/gsd/tests/quick-branch-lifecycle.test.ts +45 -73
- package/src/resources/extensions/gsd/tests/reassess-prompt.test.ts +28 -38
- package/src/resources/extensions/gsd/tests/replan-slice.test.ts +73 -80
- package/src/resources/extensions/gsd/tests/repo-identity-worktree.test.ts +71 -74
- package/src/resources/extensions/gsd/tests/requirements.test.ts +70 -75
- package/src/resources/extensions/gsd/tests/retry-state-reset.test.ts +44 -66
- package/src/resources/extensions/gsd/tests/roadmap-parse-regression.test.ts +114 -181
- package/src/resources/extensions/gsd/tests/rule-registry.test.ts +63 -65
- package/src/resources/extensions/gsd/tests/run-uat.test.ts +66 -128
- package/src/resources/extensions/gsd/tests/session-lock-multipath.test.ts +18 -25
- package/src/resources/extensions/gsd/tests/session-lock-regression.test.ts +37 -44
- package/src/resources/extensions/gsd/tests/shared-wal.test.ts +19 -26
- package/src/resources/extensions/gsd/tests/sqlite-unavailable-gate.test.ts +63 -0
- package/src/resources/extensions/gsd/tests/stalled-tool-recovery.test.ts +6 -8
- package/src/resources/extensions/gsd/tests/symlink-numbered-variants.test.ts +22 -28
- package/src/resources/extensions/gsd/tests/token-savings.test.ts +54 -56
- package/src/resources/extensions/gsd/tests/tool-call-loop-guard.test.ts +23 -25
- package/src/resources/extensions/gsd/tests/tool-naming.test.ts +9 -11
- package/src/resources/extensions/gsd/tests/unique-milestone-ids.test.ts +66 -82
- package/src/resources/extensions/gsd/tests/unit-runtime.test.ts +46 -47
- package/src/resources/extensions/gsd/tests/visualizer-critical-path.test.ts +20 -22
- package/src/resources/extensions/gsd/tests/visualizer-data.test.ts +84 -86
- package/src/resources/extensions/gsd/tests/visualizer-overlay.test.ts +41 -43
- package/src/resources/extensions/gsd/tests/visualizer-views.test.ts +94 -96
- package/src/resources/extensions/gsd/tests/windows-path-normalization.test.ts +11 -13
- package/src/resources/extensions/gsd/tests/worker-registry.test.ts +27 -29
- package/src/resources/extensions/gsd/tests/workflow-templates.test.ts +50 -52
- package/src/resources/extensions/gsd/tests/worktree-bugfix.test.ts +10 -13
- package/src/resources/extensions/gsd/tests/worktree-db-integration.test.ts +14 -18
- package/src/resources/extensions/gsd/tests/worktree-db.test.ts +38 -39
- package/src/resources/extensions/gsd/tests/worktree-e2e.test.ts +17 -21
- package/src/resources/extensions/gsd/tests/worktree-health.test.ts +25 -30
- package/src/resources/extensions/gsd/tests/worktree-integration.test.ts +30 -37
- package/src/resources/extensions/gsd/tests/worktree-symlink-removal.test.ts +15 -22
- package/src/resources/extensions/gsd/tests/worktree-sync-milestones.test.ts +59 -66
- package/src/resources/extensions/gsd/tests/worktree.test.ts +44 -50
- /package/dist/web/standalone/.next/static/{fOnWQBjWXMKUs4bqTg530 → -zps1Q9mQmioAKLcQiCr8}/_buildManifest.js +0 -0
- /package/dist/web/standalone/.next/static/{fOnWQBjWXMKUs4bqTg530 → -zps1Q9mQmioAKLcQiCr8}/_ssgManifest.js +0 -0
|
@@ -18,9 +18,8 @@ import {
|
|
|
18
18
|
getActiveTaskFromDb,
|
|
19
19
|
} from '../gsd-db.ts';
|
|
20
20
|
import { migrateHierarchyToDb } from '../md-importer.ts';
|
|
21
|
-
import {
|
|
22
|
-
|
|
23
|
-
const { assertEq, assertTrue, report } = createTestContext();
|
|
21
|
+
import { describe, test, beforeEach, afterEach } from 'node:test';
|
|
22
|
+
import assert from 'node:assert/strict';
|
|
24
23
|
|
|
25
24
|
// ─── Fixture Helpers ───────────────────────────────────────────────────────
|
|
26
25
|
|
|
@@ -98,11 +97,9 @@ const PLAN_S02_1_TASK = `# S02: Second Slice
|
|
|
98
97
|
// Test Cases
|
|
99
98
|
// ═══════════════════════════════════════════════════════════════════════════
|
|
100
99
|
|
|
101
|
-
async function main(): Promise<void> {
|
|
102
|
-
|
|
103
100
|
// ─── Test (a): Single milestone with 2 slices, 3 tasks ────────────────
|
|
104
|
-
|
|
105
|
-
|
|
101
|
+
|
|
102
|
+
test('migrate-hier: single milestone with 2 slices, 3 tasks', () => {
|
|
106
103
|
const base = createFixtureBase();
|
|
107
104
|
try {
|
|
108
105
|
writeFile(base, 'milestones/M001/M001-ROADMAP.md', ROADMAP_2_SLICES);
|
|
@@ -112,48 +109,48 @@ async function main(): Promise<void> {
|
|
|
112
109
|
openDatabase(':memory:');
|
|
113
110
|
const counts = migrateHierarchyToDb(base);
|
|
114
111
|
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
112
|
+
assert.deepStrictEqual(counts.milestones, 1, 'single-ms: 1 milestone inserted');
|
|
113
|
+
assert.deepStrictEqual(counts.slices, 2, 'single-ms: 2 slices inserted');
|
|
114
|
+
assert.deepStrictEqual(counts.tasks, 4, 'single-ms: 4 tasks inserted (3 + 1)');
|
|
118
115
|
|
|
119
116
|
const milestones = getAllMilestones();
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
117
|
+
assert.deepStrictEqual(milestones.length, 1, 'single-ms: 1 milestone in DB');
|
|
118
|
+
assert.deepStrictEqual(milestones[0]!.id, 'M001', 'single-ms: milestone ID is M001');
|
|
119
|
+
assert.deepStrictEqual(milestones[0]!.title, 'M001: Test Milestone', 'single-ms: milestone title correct');
|
|
120
|
+
assert.deepStrictEqual(milestones[0]!.status, 'active', 'single-ms: milestone status is active');
|
|
124
121
|
|
|
125
122
|
const slices = getMilestoneSlices('M001');
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
123
|
+
assert.deepStrictEqual(slices.length, 2, 'single-ms: 2 slices in DB');
|
|
124
|
+
assert.deepStrictEqual(slices[0]!.id, 'S01', 'single-ms: first slice is S01');
|
|
125
|
+
assert.deepStrictEqual(slices[0]!.title, 'First Slice', 'single-ms: S01 title correct');
|
|
126
|
+
assert.deepStrictEqual(slices[0]!.risk, 'low', 'single-ms: S01 risk is low');
|
|
127
|
+
assert.deepStrictEqual(slices[0]!.status, 'pending', 'single-ms: S01 status is pending');
|
|
128
|
+
assert.deepStrictEqual(slices[1]!.id, 'S02', 'single-ms: second slice is S02');
|
|
129
|
+
assert.deepStrictEqual(slices[1]!.risk, 'high', 'single-ms: S02 risk is high');
|
|
133
130
|
|
|
134
131
|
const s01Tasks = getSliceTasks('M001', 'S01');
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
132
|
+
assert.deepStrictEqual(s01Tasks.length, 3, 'single-ms: 3 tasks for S01');
|
|
133
|
+
assert.deepStrictEqual(s01Tasks[0]!.id, 'T01', 'single-ms: first task is T01');
|
|
134
|
+
assert.deepStrictEqual(s01Tasks[0]!.title, 'First Task', 'single-ms: T01 title correct');
|
|
135
|
+
assert.deepStrictEqual(s01Tasks[0]!.status, 'pending', 'single-ms: T01 status is pending');
|
|
136
|
+
assert.deepStrictEqual(s01Tasks[1]!.id, 'T02', 'single-ms: second task is T02');
|
|
137
|
+
assert.deepStrictEqual(s01Tasks[1]!.status, 'complete', 'single-ms: T02 status is complete (was [x])');
|
|
138
|
+
assert.deepStrictEqual(s01Tasks[2]!.id, 'T03', 'single-ms: third task is T03');
|
|
142
139
|
|
|
143
140
|
const s02Tasks = getSliceTasks('M001', 'S02');
|
|
144
|
-
|
|
145
|
-
|
|
141
|
+
assert.deepStrictEqual(s02Tasks.length, 1, 'single-ms: 1 task for S02');
|
|
142
|
+
assert.deepStrictEqual(s02Tasks[0]!.id, 'T01', 'single-ms: S02 T01 correct');
|
|
146
143
|
|
|
147
144
|
closeDatabase();
|
|
148
145
|
} finally {
|
|
149
146
|
closeDatabase();
|
|
150
147
|
cleanup(base);
|
|
151
148
|
}
|
|
152
|
-
|
|
149
|
+
});
|
|
153
150
|
|
|
154
151
|
// ─── Test (b): Multi-milestone — M001 complete, M002 active with deps ─
|
|
155
|
-
|
|
156
|
-
|
|
152
|
+
|
|
153
|
+
test('migrate-hier: multi-milestone with deps', () => {
|
|
157
154
|
const base = createFixtureBase();
|
|
158
155
|
try {
|
|
159
156
|
// M001: complete (has SUMMARY)
|
|
@@ -197,35 +194,35 @@ Depends on M001 completion.
|
|
|
197
194
|
openDatabase(':memory:');
|
|
198
195
|
const counts = migrateHierarchyToDb(base);
|
|
199
196
|
|
|
200
|
-
|
|
197
|
+
assert.deepStrictEqual(counts.milestones, 2, 'multi-ms: 2 milestones inserted');
|
|
201
198
|
|
|
202
199
|
const m001 = getMilestone('M001');
|
|
203
|
-
|
|
204
|
-
|
|
200
|
+
assert.ok(m001 !== null, 'multi-ms: M001 exists');
|
|
201
|
+
assert.deepStrictEqual(m001!.status, 'complete', 'multi-ms: M001 is complete');
|
|
205
202
|
|
|
206
203
|
const m002 = getMilestone('M002');
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
204
|
+
assert.ok(m002 !== null, 'multi-ms: M002 exists');
|
|
205
|
+
assert.deepStrictEqual(m002!.status, 'active', 'multi-ms: M002 is active');
|
|
206
|
+
assert.deepStrictEqual(m002!.depends_on, ['M001'], 'multi-ms: M002 depends on M001');
|
|
210
207
|
|
|
211
208
|
// Active milestone should be M002
|
|
212
209
|
const active = getActiveMilestoneFromDb();
|
|
213
|
-
|
|
210
|
+
assert.deepStrictEqual(active?.id, 'M002', 'multi-ms: active milestone is M002');
|
|
214
211
|
|
|
215
212
|
// Active slice in M002 should be S01 (S02 depends on S01)
|
|
216
213
|
const activeSlice = getActiveSliceFromDb('M002');
|
|
217
|
-
|
|
214
|
+
assert.deepStrictEqual(activeSlice?.id, 'S01', 'multi-ms: active slice is S01');
|
|
218
215
|
|
|
219
216
|
closeDatabase();
|
|
220
217
|
} finally {
|
|
221
218
|
closeDatabase();
|
|
222
219
|
cleanup(base);
|
|
223
220
|
}
|
|
224
|
-
|
|
221
|
+
});
|
|
225
222
|
|
|
226
223
|
// ─── Test (c): Partially-completed slice — some tasks [x], some [ ] ───
|
|
227
|
-
|
|
228
|
-
|
|
224
|
+
|
|
225
|
+
test('migrate-hier: partially-completed slice', () => {
|
|
229
226
|
const base = createFixtureBase();
|
|
230
227
|
try {
|
|
231
228
|
const roadmap = `# M001: Partial
|
|
@@ -260,25 +257,25 @@ Depends on M001 completion.
|
|
|
260
257
|
migrateHierarchyToDb(base);
|
|
261
258
|
|
|
262
259
|
const tasks = getSliceTasks('M001', 'S01');
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
260
|
+
assert.deepStrictEqual(tasks.length, 3, 'partial: 3 tasks');
|
|
261
|
+
assert.deepStrictEqual(tasks[0]!.status, 'complete', 'partial: T01 is complete');
|
|
262
|
+
assert.deepStrictEqual(tasks[1]!.status, 'complete', 'partial: T02 is complete');
|
|
263
|
+
assert.deepStrictEqual(tasks[2]!.status, 'pending', 'partial: T03 is pending');
|
|
267
264
|
|
|
268
265
|
// Active task should be T03
|
|
269
266
|
const activeTask = getActiveTaskFromDb('M001', 'S01');
|
|
270
|
-
|
|
267
|
+
assert.deepStrictEqual(activeTask?.id, 'T03', 'partial: active task is T03');
|
|
271
268
|
|
|
272
269
|
closeDatabase();
|
|
273
270
|
} finally {
|
|
274
271
|
closeDatabase();
|
|
275
272
|
cleanup(base);
|
|
276
273
|
}
|
|
277
|
-
|
|
274
|
+
});
|
|
278
275
|
|
|
279
276
|
// ─── Test (d): Ghost milestone skipped ────────────────────────────────
|
|
280
|
-
|
|
281
|
-
|
|
277
|
+
|
|
278
|
+
test('migrate-hier: ghost milestone skipped', () => {
|
|
282
279
|
const base = createFixtureBase();
|
|
283
280
|
try {
|
|
284
281
|
// M001: real milestone
|
|
@@ -289,21 +286,21 @@ Depends on M001 completion.
|
|
|
289
286
|
openDatabase(':memory:');
|
|
290
287
|
const counts = migrateHierarchyToDb(base);
|
|
291
288
|
|
|
292
|
-
|
|
289
|
+
assert.deepStrictEqual(counts.milestones, 1, 'ghost: only 1 milestone inserted');
|
|
293
290
|
const milestones = getAllMilestones();
|
|
294
|
-
|
|
295
|
-
|
|
291
|
+
assert.deepStrictEqual(milestones.length, 1, 'ghost: 1 milestone in DB');
|
|
292
|
+
assert.deepStrictEqual(milestones[0]!.id, 'M001', 'ghost: only M001 in DB');
|
|
296
293
|
|
|
297
294
|
closeDatabase();
|
|
298
295
|
} finally {
|
|
299
296
|
closeDatabase();
|
|
300
297
|
cleanup(base);
|
|
301
298
|
}
|
|
302
|
-
|
|
299
|
+
});
|
|
303
300
|
|
|
304
301
|
// ─── Test (e): Idempotent re-run — calling twice doesn't duplicate ────
|
|
305
|
-
|
|
306
|
-
|
|
302
|
+
|
|
303
|
+
test('migrate-hier: idempotent re-run', () => {
|
|
307
304
|
const base = createFixtureBase();
|
|
308
305
|
try {
|
|
309
306
|
writeFile(base, 'milestones/M001/M001-ROADMAP.md', ROADMAP_2_SLICES);
|
|
@@ -313,31 +310,31 @@ Depends on M001 completion.
|
|
|
313
310
|
|
|
314
311
|
// First run
|
|
315
312
|
const counts1 = migrateHierarchyToDb(base);
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
313
|
+
assert.deepStrictEqual(counts1.milestones, 1, 'idempotent-1: 1 milestone first run');
|
|
314
|
+
assert.deepStrictEqual(counts1.slices, 2, 'idempotent-1: 2 slices first run');
|
|
315
|
+
assert.deepStrictEqual(counts1.tasks, 3, 'idempotent-1: 3 tasks first run');
|
|
319
316
|
|
|
320
317
|
// Second run — INSERT OR IGNORE means no duplicates
|
|
321
318
|
const counts2 = migrateHierarchyToDb(base);
|
|
322
319
|
// Counts reflect attempts, not actual inserts (INSERT OR IGNORE silently skips)
|
|
323
320
|
// The important thing: DB doesn't have duplicates
|
|
324
321
|
const milestones = getAllMilestones();
|
|
325
|
-
|
|
322
|
+
assert.deepStrictEqual(milestones.length, 1, 'idempotent-2: still 1 milestone after second run');
|
|
326
323
|
const slices = getMilestoneSlices('M001');
|
|
327
|
-
|
|
324
|
+
assert.deepStrictEqual(slices.length, 2, 'idempotent-2: still 2 slices after second run');
|
|
328
325
|
const tasks = getSliceTasks('M001', 'S01');
|
|
329
|
-
|
|
326
|
+
assert.deepStrictEqual(tasks.length, 3, 'idempotent-2: still 3 tasks for S01 after second run');
|
|
330
327
|
|
|
331
328
|
closeDatabase();
|
|
332
329
|
} finally {
|
|
333
330
|
closeDatabase();
|
|
334
331
|
cleanup(base);
|
|
335
332
|
}
|
|
336
|
-
|
|
333
|
+
});
|
|
337
334
|
|
|
338
335
|
// ─── Test (f): Empty roadmap — milestone inserted but no slices ───────
|
|
339
|
-
|
|
340
|
-
|
|
336
|
+
|
|
337
|
+
test('migrate-hier: empty roadmap, no slices', () => {
|
|
341
338
|
const base = createFixtureBase();
|
|
342
339
|
try {
|
|
343
340
|
const emptyRoadmap = `# M001: Empty Milestone
|
|
@@ -353,27 +350,27 @@ Depends on M001 completion.
|
|
|
353
350
|
openDatabase(':memory:');
|
|
354
351
|
const counts = migrateHierarchyToDb(base);
|
|
355
352
|
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
353
|
+
assert.deepStrictEqual(counts.milestones, 1, 'empty-roadmap: 1 milestone inserted');
|
|
354
|
+
assert.deepStrictEqual(counts.slices, 0, 'empty-roadmap: 0 slices inserted');
|
|
355
|
+
assert.deepStrictEqual(counts.tasks, 0, 'empty-roadmap: 0 tasks inserted');
|
|
359
356
|
|
|
360
357
|
const milestones = getAllMilestones();
|
|
361
|
-
|
|
362
|
-
|
|
358
|
+
assert.deepStrictEqual(milestones.length, 1, 'empty-roadmap: 1 milestone in DB');
|
|
359
|
+
assert.deepStrictEqual(milestones[0]!.title, 'M001: Empty Milestone', 'empty-roadmap: title correct');
|
|
363
360
|
|
|
364
361
|
const slices = getMilestoneSlices('M001');
|
|
365
|
-
|
|
362
|
+
assert.deepStrictEqual(slices.length, 0, 'empty-roadmap: no slices in DB');
|
|
366
363
|
|
|
367
364
|
closeDatabase();
|
|
368
365
|
} finally {
|
|
369
366
|
closeDatabase();
|
|
370
367
|
cleanup(base);
|
|
371
368
|
}
|
|
372
|
-
|
|
369
|
+
});
|
|
373
370
|
|
|
374
371
|
// ─── Test (g): Slice depends parsed correctly ─────────────────────────
|
|
375
|
-
|
|
376
|
-
|
|
372
|
+
|
|
373
|
+
test('migrate-hier: slice depends parsed', () => {
|
|
377
374
|
const base = createFixtureBase();
|
|
378
375
|
try {
|
|
379
376
|
const roadmap = `# M001: Deps Test
|
|
@@ -397,21 +394,21 @@ Depends on M001 completion.
|
|
|
397
394
|
migrateHierarchyToDb(base);
|
|
398
395
|
|
|
399
396
|
const slices = getMilestoneSlices('M001');
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
397
|
+
assert.deepStrictEqual(slices.length, 3, 'depends: 3 slices');
|
|
398
|
+
assert.deepStrictEqual(slices[0]!.depends, [], 'depends: S01 has no deps');
|
|
399
|
+
assert.deepStrictEqual(slices[1]!.depends, ['S01'], 'depends: S02 depends on S01');
|
|
400
|
+
assert.deepStrictEqual(slices[2]!.depends, ['S01', 'S02'], 'depends: S03 depends on S01,S02');
|
|
404
401
|
|
|
405
402
|
closeDatabase();
|
|
406
403
|
} finally {
|
|
407
404
|
closeDatabase();
|
|
408
405
|
cleanup(base);
|
|
409
406
|
}
|
|
410
|
-
|
|
407
|
+
});
|
|
411
408
|
|
|
412
409
|
// ─── Test (h): Demo text extracted from roadmap ───────────────────────
|
|
413
|
-
|
|
414
|
-
|
|
410
|
+
|
|
411
|
+
test('migrate-hier: demo text extracted', () => {
|
|
415
412
|
const base = createFixtureBase();
|
|
416
413
|
try {
|
|
417
414
|
writeFile(base, 'milestones/M001/M001-ROADMAP.md', ROADMAP_2_SLICES);
|
|
@@ -420,20 +417,13 @@ Depends on M001 completion.
|
|
|
420
417
|
migrateHierarchyToDb(base);
|
|
421
418
|
|
|
422
419
|
const slices = getMilestoneSlices('M001');
|
|
423
|
-
|
|
424
|
-
|
|
420
|
+
assert.deepStrictEqual(slices[0]!.demo, 'First slice done.', 'demo: S01 demo text correct');
|
|
421
|
+
assert.deepStrictEqual(slices[1]!.demo, 'All slices done.', 'demo: S02 demo text correct');
|
|
425
422
|
|
|
426
423
|
closeDatabase();
|
|
427
424
|
} finally {
|
|
428
425
|
closeDatabase();
|
|
429
426
|
cleanup(base);
|
|
430
427
|
}
|
|
431
|
-
}
|
|
432
|
-
|
|
433
|
-
report();
|
|
434
|
-
}
|
|
435
|
-
|
|
436
|
-
main().catch((error) => {
|
|
437
|
-
console.error(error);
|
|
438
|
-
process.exit(1);
|
|
439
428
|
});
|
|
429
|
+
|