gsd-pi 2.44.0-dev.62b5d6c → 2.44.0-dev.a5271fc
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/bootstrap/system-context.js +46 -12
- package/dist/resources/extensions/gsd/commands/handlers/workflow.js +5 -0
- package/dist/resources/extensions/gsd/preferences.js +9 -1
- package/dist/resources/extensions/gsd/state.js +19 -2
- package/dist/web/standalone/.next/BUILD_ID +1 -1
- package/dist/web/standalone/.next/app-path-routes-manifest.json +19 -19
- 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 +19 -19
- 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/bootstrap/system-context.ts +48 -11
- package/src/resources/extensions/gsd/commands/handlers/workflow.ts +8 -0
- package/src/resources/extensions/gsd/preferences.ts +11 -1
- package/src/resources/extensions/gsd/state.ts +19 -1
- 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 +183 -181
- 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/knowledge.test.ts +89 -0
- 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/preferences.test.ts +27 -0
- 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 → JyimLR2pZuvKEzv26gI3w}/_buildManifest.js +0 -0
- /package/dist/web/standalone/.next/static/{fOnWQBjWXMKUs4bqTg530 → JyimLR2pZuvKEzv26gI3w}/_ssgManifest.js +0 -0
|
@@ -12,20 +12,16 @@
|
|
|
12
12
|
* Also covers dependency expansion (range syntax) and edge cases.
|
|
13
13
|
*/
|
|
14
14
|
|
|
15
|
+
import { describe, test } from 'node:test';
|
|
16
|
+
import assert from 'node:assert/strict';
|
|
15
17
|
import { parseRoadmapSlices, expandDependencies } from '../roadmap-slices.ts';
|
|
16
|
-
import { createTestContext } from './test-helpers.ts';
|
|
17
|
-
|
|
18
|
-
const { assertEq, assertTrue, report } = createTestContext();
|
|
19
|
-
|
|
20
|
-
async function main(): Promise<void> {
|
|
21
|
-
|
|
22
18
|
// ═══════════════════════════════════════════════════════════════════════
|
|
23
19
|
// A. Standard machine-readable format (should always work)
|
|
24
20
|
// ═══════════════════════════════════════════════════════════════════════
|
|
25
21
|
|
|
26
|
-
console.log('\n=== A. Standard checkbox format ===');
|
|
27
22
|
|
|
28
|
-
|
|
23
|
+
describe('roadmap-parse-regression', () => {
|
|
24
|
+
test('A. Standard checkbox format', () => {
|
|
29
25
|
const content = [
|
|
30
26
|
'# M001: Test Project',
|
|
31
27
|
'',
|
|
@@ -40,30 +36,27 @@ async function main(): Promise<void> {
|
|
|
40
36
|
].join('\n');
|
|
41
37
|
|
|
42
38
|
const slices = parseRoadmapSlices(content);
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
39
|
+
assert.deepStrictEqual(slices.length, 3, 'standard format: 3 slices');
|
|
40
|
+
assert.deepStrictEqual(slices[0].id, 'S01', 'S01 id');
|
|
41
|
+
assert.deepStrictEqual(slices[0].title, 'First Slice', 'S01 title');
|
|
42
|
+
assert.deepStrictEqual(slices[0].done, false, 'S01 not done');
|
|
43
|
+
assert.deepStrictEqual(slices[0].risk, 'low', 'S01 risk');
|
|
44
|
+
assert.deepStrictEqual(slices[0].depends.length, 0, 'S01 no deps');
|
|
45
|
+
|
|
46
|
+
assert.deepStrictEqual(slices[1].id, 'S02', 'S02 id');
|
|
47
|
+
assert.deepStrictEqual(slices[1].depends.length, 1, 'S02 has 1 dep');
|
|
48
|
+
assert.deepStrictEqual(slices[1].depends[0], 'S01', 'S02 depends on S01');
|
|
49
|
+
|
|
50
|
+
assert.deepStrictEqual(slices[2].id, 'S03', 'S03 id');
|
|
51
|
+
assert.deepStrictEqual(slices[2].done, true, 'S03 is done');
|
|
52
|
+
assert.deepStrictEqual(slices[2].risk, 'high', 'S03 risk');
|
|
53
|
+
assert.deepStrictEqual(slices[2].depends.length, 2, 'S03 has 2 deps');
|
|
54
|
+
});
|
|
59
55
|
|
|
60
56
|
// ═══════════════════════════════════════════════════════════════════════
|
|
61
57
|
// B. Prose fallback: H2 with colon (the only format the old regex matched)
|
|
62
58
|
// ═══════════════════════════════════════════════════════════════════════
|
|
63
|
-
|
|
64
|
-
console.log('\n=== B. Prose fallback: H2 with colon ===');
|
|
65
|
-
|
|
66
|
-
{
|
|
59
|
+
test('B. Prose fallback: H2 with colon', () => {
|
|
67
60
|
const content = [
|
|
68
61
|
'# M001: Test',
|
|
69
62
|
'',
|
|
@@ -78,20 +71,17 @@ async function main(): Promise<void> {
|
|
|
78
71
|
].join('\n');
|
|
79
72
|
|
|
80
73
|
const slices = parseRoadmapSlices(content);
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
74
|
+
assert.deepStrictEqual(slices.length, 2, 'prose H2 colon: 2 slices');
|
|
75
|
+
assert.deepStrictEqual(slices[0].id, 'S01', 'S01 id');
|
|
76
|
+
assert.deepStrictEqual(slices[0].title, 'Setup Foundation', 'S01 title');
|
|
77
|
+
assert.deepStrictEqual(slices[1].id, 'S02', 'S02 id');
|
|
78
|
+
assert.deepStrictEqual(slices[1].title, 'Core Features', 'S02 title');
|
|
79
|
+
});
|
|
87
80
|
|
|
88
81
|
// ═══════════════════════════════════════════════════════════════════════
|
|
89
82
|
// C. Regression #1248: H3 headers (the old regex only matched ##)
|
|
90
83
|
// ═══════════════════════════════════════════════════════════════════════
|
|
91
|
-
|
|
92
|
-
console.log('\n=== C. #1248: H3 headers ===');
|
|
93
|
-
|
|
94
|
-
{
|
|
84
|
+
test('C. #1248: H3 headers', () => {
|
|
95
85
|
const content = [
|
|
96
86
|
'# M001: Test',
|
|
97
87
|
'',
|
|
@@ -106,18 +96,15 @@ async function main(): Promise<void> {
|
|
|
106
96
|
].join('\n');
|
|
107
97
|
|
|
108
98
|
const slices = parseRoadmapSlices(content);
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
99
|
+
assert.deepStrictEqual(slices.length, 2, '#1248 H3: 2 slices parsed');
|
|
100
|
+
assert.deepStrictEqual(slices[0].id, 'S01', 'S01 from H3');
|
|
101
|
+
assert.deepStrictEqual(slices[1].id, 'S02', 'S02 from H3');
|
|
102
|
+
});
|
|
113
103
|
|
|
114
104
|
// ═══════════════════════════════════════════════════════════════════════
|
|
115
105
|
// D. Regression #1248: H4 headers
|
|
116
106
|
// ═══════════════════════════════════════════════════════════════════════
|
|
117
|
-
|
|
118
|
-
console.log('\n=== D. #1248: H4 headers ===');
|
|
119
|
-
|
|
120
|
-
{
|
|
107
|
+
test('D. #1248: H4 headers', () => {
|
|
121
108
|
const content = [
|
|
122
109
|
'# M001: Test',
|
|
123
110
|
'',
|
|
@@ -128,16 +115,13 @@ async function main(): Promise<void> {
|
|
|
128
115
|
].join('\n');
|
|
129
116
|
|
|
130
117
|
const slices = parseRoadmapSlices(content);
|
|
131
|
-
|
|
132
|
-
|
|
118
|
+
assert.deepStrictEqual(slices.length, 2, '#1248 H4: 2 slices parsed');
|
|
119
|
+
});
|
|
133
120
|
|
|
134
121
|
// ═══════════════════════════════════════════════════════════════════════
|
|
135
122
|
// E. Regression #1248: H1 header (unusual but LLMs produce it)
|
|
136
123
|
// ═══════════════════════════════════════════════════════════════════════
|
|
137
|
-
|
|
138
|
-
console.log('\n=== E. #1248: H1 headers ===');
|
|
139
|
-
|
|
140
|
-
{
|
|
124
|
+
test('E. #1248: H1 headers', () => {
|
|
141
125
|
const content = [
|
|
142
126
|
'# S01: Setup Foundation',
|
|
143
127
|
'',
|
|
@@ -150,97 +134,76 @@ async function main(): Promise<void> {
|
|
|
150
134
|
].join('\n');
|
|
151
135
|
|
|
152
136
|
const slices = parseRoadmapSlices(content);
|
|
153
|
-
|
|
154
|
-
|
|
137
|
+
assert.deepStrictEqual(slices.length, 2, '#1248 H1: 2 slices parsed');
|
|
138
|
+
});
|
|
155
139
|
|
|
156
140
|
// ═══════════════════════════════════════════════════════════════════════
|
|
157
141
|
// F. Regression #1248: Bold-wrapped IDs
|
|
158
142
|
// ═══════════════════════════════════════════════════════════════════════
|
|
159
|
-
|
|
160
|
-
console.log('\n=== F. #1248: Bold-wrapped ===');
|
|
161
|
-
|
|
162
|
-
{
|
|
143
|
+
test('F. #1248: Bold-wrapped', () => {
|
|
163
144
|
const content1 = '## **S01: Setup Foundation**\n\nDo stuff.\n\n## **S02: Features**\n\nMore stuff.\n';
|
|
164
145
|
const slices1 = parseRoadmapSlices(content1);
|
|
165
|
-
|
|
166
|
-
|
|
146
|
+
assert.deepStrictEqual(slices1.length, 2, 'bold-wrapped: 2 slices');
|
|
147
|
+
assert.deepStrictEqual(slices1[0].title, 'Setup Foundation', 'bold-wrapped: title extracted without bold');
|
|
167
148
|
|
|
168
149
|
const content2 = '## **S01**: Setup Foundation\n\n## **S02**: Features\n';
|
|
169
150
|
const slices2 = parseRoadmapSlices(content2);
|
|
170
|
-
|
|
171
|
-
|
|
151
|
+
assert.deepStrictEqual(slices2.length, 2, 'bold ID only: 2 slices');
|
|
152
|
+
});
|
|
172
153
|
|
|
173
154
|
// ═══════════════════════════════════════════════════════════════════════
|
|
174
155
|
// G. Regression #1248: Dot separator
|
|
175
156
|
// ═══════════════════════════════════════════════════════════════════════
|
|
176
|
-
|
|
177
|
-
console.log('\n=== G. #1248: Dot separator ===');
|
|
178
|
-
|
|
179
|
-
{
|
|
157
|
+
test('G. #1248: Dot separator', () => {
|
|
180
158
|
const content = '## S01. Setup Foundation\n\n## S02. Core Features\n';
|
|
181
159
|
const slices = parseRoadmapSlices(content);
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
160
|
+
assert.deepStrictEqual(slices.length, 2, 'dot separator: 2 slices');
|
|
161
|
+
assert.deepStrictEqual(slices[0].title, 'Setup Foundation', 'dot separator: title');
|
|
162
|
+
});
|
|
185
163
|
|
|
186
164
|
// ═══════════════════════════════════════════════════════════════════════
|
|
187
165
|
// H. Regression #1248: Em dash separator
|
|
188
166
|
// ═══════════════════════════════════════════════════════════════════════
|
|
189
|
-
|
|
190
|
-
console.log('\n=== H. #1248: Em/en dash separators ===');
|
|
191
|
-
|
|
192
|
-
{
|
|
167
|
+
test('H. #1248: Em/en dash separators', () => {
|
|
193
168
|
const content = '## S01 — Setup Foundation\n\n## S02 – Core Features\n';
|
|
194
169
|
const slices = parseRoadmapSlices(content);
|
|
195
|
-
|
|
196
|
-
|
|
170
|
+
assert.deepStrictEqual(slices.length, 2, 'em/en dash: 2 slices');
|
|
171
|
+
});
|
|
197
172
|
|
|
198
173
|
// ═══════════════════════════════════════════════════════════════════════
|
|
199
174
|
// I. Regression #1248: Space-only separator (no punctuation)
|
|
200
175
|
// ═══════════════════════════════════════════════════════════════════════
|
|
201
|
-
|
|
202
|
-
console.log('\n=== I. #1248: Space-only separator ===');
|
|
203
|
-
|
|
204
|
-
{
|
|
176
|
+
test('I. #1248: Space-only separator', () => {
|
|
205
177
|
const content = '## S01 Setup Foundation\n\n## S02 Core Features\n';
|
|
206
178
|
const slices = parseRoadmapSlices(content);
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
179
|
+
assert.deepStrictEqual(slices.length, 2, 'space-only: 2 slices');
|
|
180
|
+
assert.deepStrictEqual(slices[0].title, 'Setup Foundation', 'space-only: title');
|
|
181
|
+
});
|
|
210
182
|
|
|
211
183
|
// ═══════════════════════════════════════════════════════════════════════
|
|
212
184
|
// J. Regression #1248: Non-zero-padded IDs
|
|
213
185
|
// ═══════════════════════════════════════════════════════════════════════
|
|
214
|
-
|
|
215
|
-
console.log('\n=== J. #1248: Non-zero-padded IDs ===');
|
|
216
|
-
|
|
217
|
-
{
|
|
186
|
+
test('J. #1248: Non-zero-padded IDs', () => {
|
|
218
187
|
const content = '## S1: Setup\n\n## S2: Features\n';
|
|
219
188
|
const slices = parseRoadmapSlices(content);
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
189
|
+
assert.deepStrictEqual(slices.length, 2, 'non-padded: 2 slices');
|
|
190
|
+
assert.deepStrictEqual(slices[0].id, 'S1', 'non-padded: S1');
|
|
191
|
+
});
|
|
223
192
|
|
|
224
193
|
// ═══════════════════════════════════════════════════════════════════════
|
|
225
194
|
// K. Regression #1248: "Slice" prefix
|
|
226
195
|
// ═══════════════════════════════════════════════════════════════════════
|
|
227
|
-
|
|
228
|
-
console.log('\n=== K. #1248: "Slice" prefix ===');
|
|
229
|
-
|
|
230
|
-
{
|
|
196
|
+
test('K. #1248: "Slice" prefix', () => {
|
|
231
197
|
const content = '## Slice S01: Setup Foundation\n\n## Slice S02: Core Features\n';
|
|
232
198
|
const slices = parseRoadmapSlices(content);
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
199
|
+
assert.deepStrictEqual(slices.length, 2, 'Slice prefix: 2 slices');
|
|
200
|
+
assert.deepStrictEqual(slices[0].id, 'S01', 'Slice prefix: S01');
|
|
201
|
+
});
|
|
236
202
|
|
|
237
203
|
// ═══════════════════════════════════════════════════════════════════════
|
|
238
204
|
// L. Prose with "Depends on:" line
|
|
239
205
|
// ═══════════════════════════════════════════════════════════════════════
|
|
240
|
-
|
|
241
|
-
console.log('\n=== L. Prose with Depends on: ===');
|
|
242
|
-
|
|
243
|
-
{
|
|
206
|
+
test('L. Prose with Depends on:', () => {
|
|
244
207
|
const content = [
|
|
245
208
|
'## S01: Foundation',
|
|
246
209
|
'',
|
|
@@ -254,20 +217,17 @@ async function main(): Promise<void> {
|
|
|
254
217
|
].join('\n');
|
|
255
218
|
|
|
256
219
|
const slices = parseRoadmapSlices(content);
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
220
|
+
assert.deepStrictEqual(slices.length, 2, 'prose deps: 2 slices');
|
|
221
|
+
assert.deepStrictEqual(slices[1].depends.length, 1, 'S02 has 1 dep');
|
|
222
|
+
assert.deepStrictEqual(slices[1].depends[0], 'S01', 'S02 depends on S01');
|
|
223
|
+
});
|
|
261
224
|
|
|
262
225
|
// ═══════════════════════════════════════════════════════════════════════
|
|
263
226
|
// M. Empty / edge cases
|
|
264
227
|
// ═══════════════════════════════════════════════════════════════════════
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
{
|
|
269
|
-
assertEq(parseRoadmapSlices('').length, 0, 'empty content → 0 slices');
|
|
270
|
-
assertEq(parseRoadmapSlices('# Just a title\n\nSome text.').length, 0, 'no slices at all → 0');
|
|
228
|
+
test('M. Edge cases', () => {
|
|
229
|
+
assert.deepStrictEqual(parseRoadmapSlices('').length, 0, 'empty content → 0 slices');
|
|
230
|
+
assert.deepStrictEqual(parseRoadmapSlices('# Just a title\n\nSome text.').length, 0, 'no slices at all → 0');
|
|
271
231
|
|
|
272
232
|
// Mixed format: ## Slices section with one checkbox + prose below
|
|
273
233
|
const mixed = [
|
|
@@ -281,81 +241,69 @@ async function main(): Promise<void> {
|
|
|
281
241
|
].join('\n');
|
|
282
242
|
const mixedSlices = parseRoadmapSlices(mixed);
|
|
283
243
|
// The ## Slices section takes priority — prose headers outside it aren't picked up
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
244
|
+
assert.deepStrictEqual(mixedSlices.length, 1, 'mixed: only 1 slice from ## Slices section');
|
|
245
|
+
assert.deepStrictEqual(mixedSlices[0].id, 'S01', 'mixed: S01 from checkbox');
|
|
246
|
+
});
|
|
287
247
|
|
|
288
248
|
// ═══════════════════════════════════════════════════════════════════════
|
|
289
249
|
// N. Dependency range expansion
|
|
290
250
|
// ═══════════════════════════════════════════════════════════════════════
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
{
|
|
295
|
-
assertEq(
|
|
251
|
+
test('N. Dependency range expansion', () => {
|
|
252
|
+
assert.deepStrictEqual(
|
|
296
253
|
expandDependencies(['S01-S04']),
|
|
297
254
|
['S01', 'S02', 'S03', 'S04'],
|
|
298
255
|
'S01-S04 → 4 individual deps',
|
|
299
256
|
);
|
|
300
257
|
|
|
301
|
-
|
|
258
|
+
assert.deepStrictEqual(
|
|
302
259
|
expandDependencies(['S01..S03']),
|
|
303
260
|
['S01', 'S02', 'S03'],
|
|
304
261
|
'S01..S03 → 3 individual deps',
|
|
305
262
|
);
|
|
306
263
|
|
|
307
|
-
|
|
264
|
+
assert.deepStrictEqual(
|
|
308
265
|
expandDependencies(['S01']),
|
|
309
266
|
['S01'],
|
|
310
267
|
'single dep passes through',
|
|
311
268
|
);
|
|
312
269
|
|
|
313
|
-
|
|
270
|
+
assert.deepStrictEqual(
|
|
314
271
|
expandDependencies(['S01', 'S03-S05']),
|
|
315
272
|
['S01', 'S03', 'S04', 'S05'],
|
|
316
273
|
'mixed single + range',
|
|
317
274
|
);
|
|
318
275
|
|
|
319
|
-
|
|
276
|
+
assert.deepStrictEqual(
|
|
320
277
|
expandDependencies(['']),
|
|
321
278
|
[],
|
|
322
279
|
'empty string filtered out',
|
|
323
280
|
);
|
|
324
|
-
|
|
281
|
+
});
|
|
325
282
|
|
|
326
283
|
// ═══════════════════════════════════════════════════════════════════════
|
|
327
284
|
// O. No-separator colon-less: "S01:Title" (no space after colon)
|
|
328
285
|
// ═══════════════════════════════════════════════════════════════════════
|
|
329
|
-
|
|
330
|
-
console.log('\n=== O. No space after colon ===');
|
|
331
|
-
|
|
332
|
-
{
|
|
286
|
+
test('O. No space after colon', () => {
|
|
333
287
|
const content = '## S01:Foundation\n\n## S02:Features\n';
|
|
334
288
|
const slices = parseRoadmapSlices(content);
|
|
335
289
|
// The regex uses [:\s.—–-]* which allows colon with no space
|
|
336
|
-
|
|
337
|
-
|
|
290
|
+
assert.deepStrictEqual(slices.length, 2, 'no-space-colon: 2 slices');
|
|
291
|
+
});
|
|
338
292
|
|
|
339
293
|
// ═══════════════════════════════════════════════════════════════════════
|
|
340
294
|
// P. Three-digit padded IDs
|
|
341
295
|
// ═══════════════════════════════════════════════════════════════════════
|
|
342
|
-
|
|
343
|
-
console.log('\n=== P. Three-digit padded IDs ===');
|
|
344
|
-
|
|
345
|
-
{
|
|
296
|
+
test('P. Three-digit padded IDs', () => {
|
|
346
297
|
const content = '## S001: Foundation\n\n## S002: Features\n';
|
|
347
298
|
const slices = parseRoadmapSlices(content);
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
299
|
+
assert.deepStrictEqual(slices.length, 2, 'three-digit: 2 slices');
|
|
300
|
+
assert.deepStrictEqual(slices[0].id, 'S001', 'three-digit: S001');
|
|
301
|
+
});
|
|
351
302
|
|
|
352
303
|
// ═══════════════════════════════════════════════════════════════════════
|
|
353
304
|
// Q. Regression #1736: Table format under ## Slices
|
|
354
305
|
// ═══════════════════════════════════════════════════════════════════════
|
|
355
|
-
|
|
356
|
-
console.log('\n=== Q. #1736: Table format under ## Slices ===');
|
|
357
|
-
|
|
358
|
-
{
|
|
306
|
+
test('Q. #1736: Table format under ## Slices', () => {
|
|
359
307
|
const content = [
|
|
360
308
|
'# M001: Test',
|
|
361
309
|
'',
|
|
@@ -371,22 +319,19 @@ async function main(): Promise<void> {
|
|
|
371
319
|
].join('\n');
|
|
372
320
|
|
|
373
321
|
const slices = parseRoadmapSlices(content);
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
322
|
+
assert.deepStrictEqual(slices.length, 3, '#1736 table: 3 slices');
|
|
323
|
+
assert.deepStrictEqual(slices[0].id, 'S01', '#1736 table: S01 id');
|
|
324
|
+
assert.deepStrictEqual(slices[0].title, 'Setup Foundation', '#1736 table: S01 title');
|
|
325
|
+
assert.deepStrictEqual(slices[0].done, true, '#1736 table: S01 done');
|
|
326
|
+
assert.deepStrictEqual(slices[0].risk, 'low', '#1736 table: S01 risk');
|
|
327
|
+
assert.deepStrictEqual(slices[1].done, false, '#1736 table: S02 not done');
|
|
328
|
+
assert.deepStrictEqual(slices[2].done, true, '#1736 table: S03 done');
|
|
329
|
+
});
|
|
382
330
|
|
|
383
331
|
// ═══════════════════════════════════════════════════════════════════════
|
|
384
332
|
// R. Regression #1736: Table format under ## Slice Overview
|
|
385
333
|
// ═══════════════════════════════════════════════════════════════════════
|
|
386
|
-
|
|
387
|
-
console.log('\n=== R. #1736: Table format under ## Slice Overview ===');
|
|
388
|
-
|
|
389
|
-
{
|
|
334
|
+
test('R. #1736: Table format under ## Slice Overview', () => {
|
|
390
335
|
const content = [
|
|
391
336
|
'# M002: Overview Heading',
|
|
392
337
|
'',
|
|
@@ -400,18 +345,15 @@ async function main(): Promise<void> {
|
|
|
400
345
|
].join('\n');
|
|
401
346
|
|
|
402
347
|
const slices = parseRoadmapSlices(content);
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
348
|
+
assert.deepStrictEqual(slices.length, 2, '#1736 overview: 2 slices');
|
|
349
|
+
assert.deepStrictEqual(slices[0].done, true, '#1736 overview: S01 done');
|
|
350
|
+
assert.deepStrictEqual(slices[1].done, false, '#1736 overview: S02 not done');
|
|
351
|
+
});
|
|
407
352
|
|
|
408
353
|
// ═══════════════════════════════════════════════════════════════════════
|
|
409
354
|
// S. Regression #1736: Table with Done/Complete text status
|
|
410
355
|
// ═══════════════════════════════════════════════════════════════════════
|
|
411
|
-
|
|
412
|
-
console.log('\n=== S. #1736: Table with text status ===');
|
|
413
|
-
|
|
414
|
-
{
|
|
356
|
+
test('S. #1736: Table with text status', () => {
|
|
415
357
|
const content = [
|
|
416
358
|
'# M003: Status Text',
|
|
417
359
|
'',
|
|
@@ -426,19 +368,16 @@ async function main(): Promise<void> {
|
|
|
426
368
|
].join('\n');
|
|
427
369
|
|
|
428
370
|
const slices = parseRoadmapSlices(content);
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
371
|
+
assert.deepStrictEqual(slices.length, 3, '#1736 text status: 3 slices');
|
|
372
|
+
assert.ok(slices[0].done, '#1736 text status: Done = true');
|
|
373
|
+
assert.ok(!slices[1].done, '#1736 text status: Pending = false');
|
|
374
|
+
assert.ok(slices[2].done, '#1736 text status: Completed = true');
|
|
375
|
+
});
|
|
434
376
|
|
|
435
377
|
// ═══════════════════════════════════════════════════════════════════════
|
|
436
378
|
// T. Regression #1736: Checkbox format still works after table support
|
|
437
379
|
// ═══════════════════════════════════════════════════════════════════════
|
|
438
|
-
|
|
439
|
-
console.log('\n=== T. #1736: Checkbox format unchanged ===');
|
|
440
|
-
|
|
441
|
-
{
|
|
380
|
+
test('T. #1736: Checkbox format unchanged', () => {
|
|
442
381
|
const content = [
|
|
443
382
|
'# M005: Unchanged',
|
|
444
383
|
'',
|
|
@@ -451,16 +390,10 @@ async function main(): Promise<void> {
|
|
|
451
390
|
].join('\n');
|
|
452
391
|
|
|
453
392
|
const slices = parseRoadmapSlices(content);
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
report();
|
|
461
|
-
}
|
|
462
|
-
|
|
463
|
-
main().catch((error) => {
|
|
464
|
-
console.error(error);
|
|
465
|
-
process.exit(1);
|
|
393
|
+
assert.deepStrictEqual(slices.length, 2, '#1736 checkbox compat: 2 slices');
|
|
394
|
+
assert.deepStrictEqual(slices[0].done, true, '#1736 checkbox compat: S01 done');
|
|
395
|
+
assert.deepStrictEqual(slices[0].demo, 'demo works.', '#1736 checkbox compat: demo');
|
|
396
|
+
assert.deepStrictEqual(slices[1].done, false, '#1736 checkbox compat: S02 not done');
|
|
397
|
+
});
|
|
398
|
+
|
|
466
399
|
});
|