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
|
@@ -31,9 +31,9 @@ import type {
|
|
|
31
31
|
GSDSliceSummaryData,
|
|
32
32
|
GSDTaskSummaryData,
|
|
33
33
|
} from '../migrate/types.ts';
|
|
34
|
-
import {
|
|
34
|
+
import { describe, test, beforeEach, afterEach } from 'node:test';
|
|
35
|
+
import assert from 'node:assert/strict';
|
|
35
36
|
|
|
36
|
-
const { assertEq, assertTrue, report } = createTestContext();
|
|
37
37
|
// ─── Test Data Builders ────────────────────────────────────────────────────
|
|
38
38
|
|
|
39
39
|
function makeTask(overrides: Partial<GSDTask> = {}): GSDTask {
|
|
@@ -103,11 +103,7 @@ function makeTaskSummary(overrides: Partial<GSDTaskSummaryData> = {}): GSDTaskSu
|
|
|
103
103
|
};
|
|
104
104
|
}
|
|
105
105
|
|
|
106
|
-
|
|
107
|
-
// Scenario A: Roadmap round-trip with 2 slices (1 done, 1 not)
|
|
108
|
-
// ═══════════════════════════════════════════════════════════════════════════
|
|
109
|
-
|
|
110
|
-
{
|
|
106
|
+
test('Scenario A: Roadmap round-trip with 2 slices (1 done, 1 not)', () => {
|
|
111
107
|
const milestone = makeMilestone({
|
|
112
108
|
slices: [
|
|
113
109
|
makeSlice({
|
|
@@ -132,35 +128,31 @@ function makeTaskSummary(overrides: Partial<GSDTaskSummaryData> = {}): GSDTaskSu
|
|
|
132
128
|
const output = formatRoadmap(milestone);
|
|
133
129
|
const parsed = parseRoadmap(output);
|
|
134
130
|
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
}
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
// Scenario B: Plan round-trip with 3 tasks (mixed done)
|
|
161
|
-
// ═══════════════════════════════════════════════════════════════════════════
|
|
162
|
-
|
|
163
|
-
{
|
|
131
|
+
assert.deepStrictEqual(parsed.title, 'M001: Core Platform', 'roadmap: title');
|
|
132
|
+
assert.deepStrictEqual(parsed.vision, 'Build the core platform', 'roadmap: vision');
|
|
133
|
+
assert.deepStrictEqual(parsed.successCriteria.length, 2, 'roadmap: successCriteria count');
|
|
134
|
+
assert.deepStrictEqual(parsed.successCriteria[0], 'All tests pass', 'roadmap: successCriteria[0]');
|
|
135
|
+
assert.deepStrictEqual(parsed.successCriteria[1], 'Deploy to staging', 'roadmap: successCriteria[1]');
|
|
136
|
+
assert.deepStrictEqual(parsed.slices.length, 2, 'roadmap: slices count');
|
|
137
|
+
|
|
138
|
+
assert.deepStrictEqual(parsed.slices[0].id, 'S01', 'roadmap: S01 id');
|
|
139
|
+
assert.deepStrictEqual(parsed.slices[0].title, 'Auth System', 'roadmap: S01 title');
|
|
140
|
+
assert.deepStrictEqual(parsed.slices[0].done, true, 'roadmap: S01 done');
|
|
141
|
+
assert.deepStrictEqual(parsed.slices[0].risk, 'high', 'roadmap: S01 risk');
|
|
142
|
+
assert.deepStrictEqual(parsed.slices[0].depends.length, 0, 'roadmap: S01 depends empty');
|
|
143
|
+
assert.deepStrictEqual(parsed.slices[0].demo, 'Login flow works', 'roadmap: S01 demo');
|
|
144
|
+
|
|
145
|
+
assert.deepStrictEqual(parsed.slices[1].id, 'S02', 'roadmap: S02 id');
|
|
146
|
+
assert.deepStrictEqual(parsed.slices[1].title, 'Dashboard', 'roadmap: S02 title');
|
|
147
|
+
assert.deepStrictEqual(parsed.slices[1].done, false, 'roadmap: S02 done');
|
|
148
|
+
assert.deepStrictEqual(parsed.slices[1].risk, 'low', 'roadmap: S02 risk');
|
|
149
|
+
assert.deepStrictEqual(parsed.slices[1].depends, ['S01'], 'roadmap: S02 depends');
|
|
150
|
+
assert.deepStrictEqual(parsed.slices[1].demo, 'Dashboard renders data', 'roadmap: S02 demo');
|
|
151
|
+
|
|
152
|
+
assert.deepStrictEqual(parsed.boundaryMap.length, 0, 'roadmap: boundaryMap empty');
|
|
153
|
+
});
|
|
154
|
+
|
|
155
|
+
test('Scenario B: Plan round-trip with 3 tasks (mixed done)', () => {
|
|
164
156
|
const slice = makeSlice({
|
|
165
157
|
id: 'S01',
|
|
166
158
|
title: 'Auth System',
|
|
@@ -176,31 +168,27 @@ function makeTaskSummary(overrides: Partial<GSDTaskSummaryData> = {}): GSDTaskSu
|
|
|
176
168
|
const output = formatPlan(slice);
|
|
177
169
|
const parsed = parsePlan(output);
|
|
178
170
|
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
171
|
+
assert.deepStrictEqual(parsed.id, 'S01', 'plan: id');
|
|
172
|
+
assert.deepStrictEqual(parsed.title, 'Auth System', 'plan: title');
|
|
173
|
+
assert.deepStrictEqual(parsed.goal, 'Working authentication system', 'plan: goal');
|
|
174
|
+
assert.deepStrictEqual(parsed.demo, 'Login works with valid credentials', 'plan: demo');
|
|
175
|
+
assert.deepStrictEqual(parsed.tasks.length, 3, 'plan: tasks count');
|
|
184
176
|
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
177
|
+
assert.deepStrictEqual(parsed.tasks[0].id, 'T01', 'plan: T01 id');
|
|
178
|
+
assert.deepStrictEqual(parsed.tasks[0].title, 'Setup Models', 'plan: T01 title');
|
|
179
|
+
assert.deepStrictEqual(parsed.tasks[0].done, true, 'plan: T01 done');
|
|
180
|
+
assert.deepStrictEqual(parsed.tasks[0].estimate, '15m', 'plan: T01 estimate');
|
|
189
181
|
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
assertEq(parsed.tasks[2].id, 'T03', 'plan: T03 id');
|
|
195
|
-
assertEq(parsed.tasks[2].done, true, 'plan: T03 done');
|
|
196
|
-
assertEq(parsed.tasks[2].estimate, '20m', 'plan: T03 estimate');
|
|
197
|
-
}
|
|
182
|
+
assert.deepStrictEqual(parsed.tasks[1].id, 'T02', 'plan: T02 id');
|
|
183
|
+
assert.deepStrictEqual(parsed.tasks[1].done, false, 'plan: T02 done');
|
|
184
|
+
assert.deepStrictEqual(parsed.tasks[1].estimate, '30m', 'plan: T02 estimate');
|
|
198
185
|
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
186
|
+
assert.deepStrictEqual(parsed.tasks[2].id, 'T03', 'plan: T03 id');
|
|
187
|
+
assert.deepStrictEqual(parsed.tasks[2].done, true, 'plan: T03 done');
|
|
188
|
+
assert.deepStrictEqual(parsed.tasks[2].estimate, '20m', 'plan: T03 estimate');
|
|
189
|
+
});
|
|
202
190
|
|
|
203
|
-
{
|
|
191
|
+
test('Scenario C: Slice summary round-trip with full data', () => {
|
|
204
192
|
const slice = makeSlice({
|
|
205
193
|
id: 'S01',
|
|
206
194
|
title: 'Auth System',
|
|
@@ -211,28 +199,24 @@ function makeTaskSummary(overrides: Partial<GSDTaskSummaryData> = {}): GSDTaskSu
|
|
|
211
199
|
const output = formatSliceSummary(slice, 'M001');
|
|
212
200
|
const parsed = parseSummary(output);
|
|
213
201
|
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
}
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
// Scenario D: Task summary round-trip
|
|
233
|
-
// ═══════════════════════════════════════════════════════════════════════════
|
|
234
|
-
|
|
235
|
-
{
|
|
202
|
+
assert.deepStrictEqual(parsed.frontmatter.id, 'S01', 'sliceSummary: id');
|
|
203
|
+
assert.deepStrictEqual(parsed.frontmatter.parent, 'M001', 'sliceSummary: parent');
|
|
204
|
+
assert.deepStrictEqual(parsed.frontmatter.milestone, 'M001', 'sliceSummary: milestone');
|
|
205
|
+
assert.deepStrictEqual(parsed.frontmatter.provides, ['auth-flow', 'jwt-tokens'], 'sliceSummary: provides');
|
|
206
|
+
assert.deepStrictEqual(parsed.frontmatter.requires.length, 0, 'sliceSummary: requires empty');
|
|
207
|
+
assert.deepStrictEqual(parsed.frontmatter.affects.length, 0, 'sliceSummary: affects empty');
|
|
208
|
+
assert.deepStrictEqual(parsed.frontmatter.key_files, ['src/auth.ts', 'src/middleware.ts'], 'sliceSummary: key_files');
|
|
209
|
+
assert.deepStrictEqual(parsed.frontmatter.key_decisions, ['Use JWT over sessions'], 'sliceSummary: key_decisions');
|
|
210
|
+
assert.deepStrictEqual(parsed.frontmatter.patterns_established, ['Middleware pattern'], 'sliceSummary: patterns_established');
|
|
211
|
+
assert.deepStrictEqual(parsed.frontmatter.duration, '2h', 'sliceSummary: duration');
|
|
212
|
+
assert.deepStrictEqual(parsed.frontmatter.completed_at, '2026-03-10', 'sliceSummary: completed_at');
|
|
213
|
+
assert.deepStrictEqual(parsed.frontmatter.verification_result, 'passed', 'sliceSummary: verification_result');
|
|
214
|
+
assert.deepStrictEqual(parsed.frontmatter.blocker_discovered, false, 'sliceSummary: blocker_discovered');
|
|
215
|
+
assert.ok(parsed.whatHappened.includes('Implemented full auth system'), 'sliceSummary: whatHappened content');
|
|
216
|
+
assert.deepStrictEqual(parsed.title, 'S01: Auth System', 'sliceSummary: title');
|
|
217
|
+
});
|
|
218
|
+
|
|
219
|
+
test('Scenario D: Task summary round-trip', () => {
|
|
236
220
|
const task = makeTask({
|
|
237
221
|
id: 'T01',
|
|
238
222
|
title: 'Setup Auth',
|
|
@@ -243,22 +227,18 @@ function makeTaskSummary(overrides: Partial<GSDTaskSummaryData> = {}): GSDTaskSu
|
|
|
243
227
|
const output = formatTaskSummary(task, 'S01', 'M001');
|
|
244
228
|
const parsed = parseSummary(output);
|
|
245
229
|
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
}
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
// Scenario E: Requirements round-trip with mixed statuses
|
|
259
|
-
// ═══════════════════════════════════════════════════════════════════════════
|
|
260
|
-
|
|
261
|
-
{
|
|
230
|
+
assert.deepStrictEqual(parsed.frontmatter.id, 'T01', 'taskSummary: id');
|
|
231
|
+
assert.deepStrictEqual(parsed.frontmatter.parent, 'S01', 'taskSummary: parent');
|
|
232
|
+
assert.deepStrictEqual(parsed.frontmatter.milestone, 'M001', 'taskSummary: milestone');
|
|
233
|
+
assert.deepStrictEqual(parsed.frontmatter.provides, ['auth-endpoint'], 'taskSummary: provides');
|
|
234
|
+
assert.deepStrictEqual(parsed.frontmatter.key_files, ['src/auth.ts'], 'taskSummary: key_files');
|
|
235
|
+
assert.deepStrictEqual(parsed.frontmatter.duration, '45m', 'taskSummary: duration');
|
|
236
|
+
assert.deepStrictEqual(parsed.frontmatter.completed_at, '2026-03-09', 'taskSummary: completed_at');
|
|
237
|
+
assert.ok(parsed.whatHappened.includes('Built the auth endpoint'), 'taskSummary: whatHappened content');
|
|
238
|
+
assert.deepStrictEqual(parsed.title, 'T01: Setup Auth', 'taskSummary: title');
|
|
239
|
+
});
|
|
240
|
+
|
|
241
|
+
test('Scenario E: Requirements round-trip with mixed statuses', () => {
|
|
262
242
|
const requirements: GSDRequirement[] = [
|
|
263
243
|
{ id: 'R001', title: 'Auth Required', class: 'core-capability', status: 'active', description: 'Must have auth', source: 'spec', primarySlice: 'S01' },
|
|
264
244
|
{ id: 'R002', title: 'Logging', class: 'observability', status: 'active', description: 'Must log', source: 'spec', primarySlice: 'S02' },
|
|
@@ -270,110 +250,93 @@ function makeTaskSummary(overrides: Partial<GSDTaskSummaryData> = {}): GSDTaskSu
|
|
|
270
250
|
const output = formatRequirements(requirements);
|
|
271
251
|
const counts = parseRequirementCounts(output);
|
|
272
252
|
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
}
|
|
279
|
-
|
|
280
|
-
// ═══════════════════════════════════════════════════════════════════════════
|
|
281
|
-
// Scenario F: Edge cases
|
|
282
|
-
// ═══════════════════════════════════════════════════════════════════════════
|
|
253
|
+
assert.deepStrictEqual(counts.active, 2, 'requirements: active count');
|
|
254
|
+
assert.deepStrictEqual(counts.validated, 1, 'requirements: validated count');
|
|
255
|
+
assert.deepStrictEqual(counts.deferred, 1, 'requirements: deferred count');
|
|
256
|
+
assert.deepStrictEqual(counts.outOfScope, 1, 'requirements: outOfScope count');
|
|
257
|
+
assert.deepStrictEqual(counts.total, 5, 'requirements: total count');
|
|
258
|
+
});
|
|
283
259
|
|
|
284
|
-
|
|
285
|
-
{
|
|
260
|
+
test('F1: Empty vision → fallback text', () => {
|
|
286
261
|
const milestone = makeMilestone({ vision: '' });
|
|
287
262
|
const output = formatRoadmap(milestone);
|
|
288
263
|
const parsed = parseRoadmap(output);
|
|
289
|
-
|
|
290
|
-
}
|
|
264
|
+
assert.deepStrictEqual(parsed.vision, '(migrated project)', 'edge: empty vision fallback');
|
|
265
|
+
});
|
|
291
266
|
|
|
292
|
-
|
|
293
|
-
{
|
|
267
|
+
test('F2: Empty successCriteria → empty array', () => {
|
|
294
268
|
const milestone = makeMilestone({ successCriteria: [] });
|
|
295
269
|
const output = formatRoadmap(milestone);
|
|
296
270
|
const parsed = parseRoadmap(output);
|
|
297
|
-
|
|
298
|
-
}
|
|
271
|
+
assert.deepStrictEqual(parsed.successCriteria.length, 0, 'edge: empty successCriteria');
|
|
272
|
+
});
|
|
299
273
|
|
|
300
|
-
|
|
301
|
-
{
|
|
274
|
+
test('F3: Empty tasks → empty array in parsed plan', () => {
|
|
302
275
|
const slice = makeSlice({ tasks: [] });
|
|
303
276
|
const output = formatPlan(slice);
|
|
304
277
|
const parsed = parsePlan(output);
|
|
305
|
-
|
|
306
|
-
}
|
|
278
|
+
assert.deepStrictEqual(parsed.tasks.length, 0, 'edge: empty tasks');
|
|
279
|
+
});
|
|
307
280
|
|
|
308
|
-
|
|
309
|
-
{
|
|
281
|
+
test('F4: Null summary → empty string from formatSliceSummary', () => {
|
|
310
282
|
const slice = makeSlice({ summary: null });
|
|
311
283
|
const output = formatSliceSummary(slice, 'M001');
|
|
312
|
-
|
|
313
|
-
}
|
|
284
|
+
assert.deepStrictEqual(output, '', 'edge: null summary returns empty string');
|
|
285
|
+
});
|
|
314
286
|
|
|
315
|
-
|
|
316
|
-
{
|
|
287
|
+
test('F5: Done=true checkbox in roadmap', () => {
|
|
317
288
|
const milestone = makeMilestone({
|
|
318
289
|
slices: [makeSlice({ id: 'S01', done: true })],
|
|
319
290
|
});
|
|
320
291
|
const output = formatRoadmap(milestone);
|
|
321
292
|
const parsed = parseRoadmap(output);
|
|
322
|
-
|
|
323
|
-
}
|
|
293
|
+
assert.deepStrictEqual(parsed.slices[0].done, true, 'edge: done checkbox true');
|
|
294
|
+
});
|
|
324
295
|
|
|
325
|
-
|
|
326
|
-
{
|
|
296
|
+
test('F6: Done=false checkbox in roadmap', () => {
|
|
327
297
|
const milestone = makeMilestone({
|
|
328
298
|
slices: [makeSlice({ id: 'S01', done: false })],
|
|
329
299
|
});
|
|
330
300
|
const output = formatRoadmap(milestone);
|
|
331
301
|
const parsed = parseRoadmap(output);
|
|
332
|
-
|
|
333
|
-
}
|
|
302
|
+
assert.deepStrictEqual(parsed.slices[0].done, false, 'edge: done checkbox false');
|
|
303
|
+
});
|
|
334
304
|
|
|
335
|
-
|
|
336
|
-
{
|
|
305
|
+
test('F7: Null task summary → empty string from formatTaskSummary', () => {
|
|
337
306
|
const task = makeTask({ summary: null });
|
|
338
307
|
const output = formatTaskSummary(task, 'S01', 'M001');
|
|
339
|
-
|
|
340
|
-
}
|
|
308
|
+
assert.deepStrictEqual(output, '', 'edge: null task summary returns empty string');
|
|
309
|
+
});
|
|
341
310
|
|
|
342
|
-
|
|
343
|
-
{
|
|
311
|
+
test('F8: Empty requirements → all zeros', () => {
|
|
344
312
|
const output = formatRequirements([]);
|
|
345
313
|
const counts = parseRequirementCounts(output);
|
|
346
|
-
|
|
347
|
-
}
|
|
314
|
+
assert.deepStrictEqual(counts.total, 0, 'edge: empty requirements total 0');
|
|
315
|
+
});
|
|
348
316
|
|
|
349
|
-
|
|
350
|
-
{
|
|
317
|
+
test('F9: formatProject with empty content → produces valid stub', () => {
|
|
351
318
|
const output = formatProject('');
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
}
|
|
319
|
+
assert.ok(output.includes('# Project'), 'edge: empty project has heading');
|
|
320
|
+
assert.ok(output.length > 10, 'edge: empty project not blank');
|
|
321
|
+
});
|
|
355
322
|
|
|
356
|
-
|
|
357
|
-
{
|
|
323
|
+
test('F10: formatProject with existing content → passes through', () => {
|
|
358
324
|
const content = '# My Project\n\nDescription here.\n';
|
|
359
325
|
const output = formatProject(content);
|
|
360
|
-
|
|
361
|
-
}
|
|
326
|
+
assert.deepStrictEqual(output, content, 'edge: project passthrough');
|
|
327
|
+
});
|
|
362
328
|
|
|
363
|
-
|
|
364
|
-
{
|
|
329
|
+
test('F11: formatDecisions with empty content → produces valid stub', () => {
|
|
365
330
|
const output = formatDecisions('');
|
|
366
|
-
|
|
367
|
-
}
|
|
331
|
+
assert.ok(output.includes('# Decisions'), 'edge: empty decisions has heading');
|
|
332
|
+
});
|
|
368
333
|
|
|
369
|
-
|
|
370
|
-
{
|
|
334
|
+
test('F12: formatContext produces valid content', () => {
|
|
371
335
|
const output = formatContext('M001');
|
|
372
|
-
|
|
373
|
-
}
|
|
336
|
+
assert.ok(output.includes('M001'), 'edge: context mentions milestone');
|
|
337
|
+
});
|
|
374
338
|
|
|
375
|
-
|
|
376
|
-
{
|
|
339
|
+
test('F13: formatState produces valid content', () => {
|
|
377
340
|
const milestones = [makeMilestone({
|
|
378
341
|
slices: [
|
|
379
342
|
makeSlice({ done: true }),
|
|
@@ -381,20 +344,18 @@ function makeTaskSummary(overrides: Partial<GSDTaskSummaryData> = {}): GSDTaskSu
|
|
|
381
344
|
],
|
|
382
345
|
})];
|
|
383
346
|
const output = formatState(milestones);
|
|
384
|
-
|
|
385
|
-
}
|
|
347
|
+
assert.ok(output.includes('1/2'), 'edge: state shows slice progress');
|
|
348
|
+
});
|
|
386
349
|
|
|
387
|
-
|
|
388
|
-
{
|
|
350
|
+
test('F14: Task with no estimate → no est backtick in plan', () => {
|
|
389
351
|
const slice = makeSlice({
|
|
390
352
|
tasks: [makeTask({ id: 'T01', title: 'Quick Fix', estimate: '' })],
|
|
391
353
|
});
|
|
392
354
|
const output = formatPlan(slice);
|
|
393
355
|
const parsed = parsePlan(output);
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
}
|
|
356
|
+
assert.deepStrictEqual(parsed.tasks[0].id, 'T01', 'edge: task no estimate id');
|
|
357
|
+
assert.deepStrictEqual(parsed.tasks[0].estimate, '', 'edge: task no estimate empty');
|
|
358
|
+
});
|
|
397
359
|
|
|
398
360
|
// ═══════════════════════════════════════════════════════════════════════════
|
|
399
361
|
|
|
400
|
-
report();
|