gsd-pi 2.57.0-dev.f22a903 → 2.57.0
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/dist/resources/extensions/gsd/auto/infra-errors.js +0 -4
- package/dist/resources/extensions/gsd/auto-dispatch.js +3 -3
- package/dist/resources/extensions/gsd/auto-worktree.js +2 -7
- package/dist/resources/extensions/gsd/bootstrap/db-tools.js +1 -2
- package/dist/resources/extensions/gsd/dispatch-guard.js +1 -11
- package/dist/resources/extensions/gsd/gsd-db.js +1 -8
- package/dist/resources/extensions/gsd/parallel-orchestrator.js +6 -23
- package/dist/resources/extensions/gsd/preferences.js +15 -29
- package/dist/resources/extensions/gsd/prompts/validate-milestone.md +2 -2
- package/dist/resources/extensions/gsd/tools/validate-milestone.js +0 -4
- package/dist/web/standalone/.next/BUILD_ID +1 -1
- package/dist/web/standalone/.next/app-path-routes-manifest.json +12 -12
- package/dist/web/standalone/.next/build-manifest.json +4 -4
- package/dist/web/standalone/.next/prerender-manifest.json +3 -3
- package/dist/web/standalone/.next/react-loadable-manifest.json +1 -1
- package/dist/web/standalone/.next/required-server-files.json +3 -3
- package/dist/web/standalone/.next/server/app/_global-error/page.js +3 -3
- package/dist/web/standalone/.next/server/app/_global-error/page_client-reference-manifest.js +1 -1
- 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/page.js +2 -2
- package/dist/web/standalone/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.html +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.rsc +3 -3
- package/dist/web/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +3 -3
- 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 +3 -3
- 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/api/boot/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/boot/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/bridge-terminal/input/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/bridge-terminal/input/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/bridge-terminal/resize/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/bridge-terminal/resize/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/bridge-terminal/stream/route.js +2 -2
- package/dist/web/standalone/.next/server/app/api/bridge-terminal/stream/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/browse-directories/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/browse-directories/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/captures/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/captures/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/cleanup/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/cleanup/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/dev-mode/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/dev-mode/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/doctor/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/doctor/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/experimental/route.js +2 -2
- package/dist/web/standalone/.next/server/app/api/experimental/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/export-data/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/export-data/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/files/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/files/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/forensics/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/forensics/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/git/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/git/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/history/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/history/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/hooks/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/hooks/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/inspect/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/inspect/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/knowledge/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/knowledge/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/live-state/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/live-state/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/onboarding/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/onboarding/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/preferences/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/preferences/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/projects/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/projects/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/recovery/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/recovery/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/remote-questions/route.js +2 -2
- package/dist/web/standalone/.next/server/app/api/remote-questions/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/session/browser/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/session/browser/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/session/command/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/session/command/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/session/events/route.js +2 -2
- package/dist/web/standalone/.next/server/app/api/session/events/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/session/manage/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/session/manage/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/settings-data/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/settings-data/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/shutdown/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/shutdown/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/skill-health/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/skill-health/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/steer/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/steer/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/switch-root/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/switch-root/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/terminal/input/route.js +2 -2
- package/dist/web/standalone/.next/server/app/api/terminal/input/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/terminal/resize/route.js +2 -2
- package/dist/web/standalone/.next/server/app/api/terminal/resize/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/terminal/sessions/route.js +2 -2
- package/dist/web/standalone/.next/server/app/api/terminal/sessions/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/terminal/stream/route.js +4 -4
- package/dist/web/standalone/.next/server/app/api/terminal/stream/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/terminal/upload/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/terminal/upload/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/undo/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/undo/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/update/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/update/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/visualizer/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/visualizer/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/index.html +1 -1
- package/dist/web/standalone/.next/server/app/index.rsc +4 -4
- package/dist/web/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +2 -2
- package/dist/web/standalone/.next/server/app/index.segments/_full.segment.rsc +4 -4
- 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 +3 -3
- package/dist/web/standalone/.next/server/app/index.segments/_tree.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/page.js +2 -2
- package/dist/web/standalone/.next/server/app/page_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app-paths-manifest.json +12 -12
- package/dist/web/standalone/.next/server/chunks/2229.js +1 -1
- package/dist/web/standalone/.next/server/chunks/7471.js +3 -3
- package/dist/web/standalone/.next/server/middleware-build-manifest.js +1 -1
- package/dist/web/standalone/.next/server/middleware-react-loadable-manifest.js +1 -1
- package/dist/web/standalone/.next/server/middleware.js +2 -2
- package/dist/web/standalone/.next/server/next-font-manifest.js +1 -1
- package/dist/web/standalone/.next/server/next-font-manifest.json +1 -1
- 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/dist/web/standalone/.next/static/chunks/6502.2305d0afd2385711.js +9 -0
- package/dist/web/standalone/.next/static/chunks/app/_not-found/{page-f2a7482d42a5614b.js → page-2f24283c162b6ab3.js} +1 -1
- package/dist/web/standalone/.next/static/chunks/app/{layout-a16c7a7ecdf0c2cf.js → layout-9ecfd95f343793f0.js} +1 -1
- package/dist/web/standalone/.next/static/chunks/app/page-62be3b5fa91e4c8f.js +1 -0
- package/dist/web/standalone/.next/static/chunks/main-app-d3d4c336195465f9.js +1 -0
- package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/global-error-ab5a8926e07ec673.js +1 -0
- package/dist/web/standalone/.next/static/chunks/{webpack-61d3afac6d0f0ce7.js → webpack-4332cbd5dd1be584.js} +1 -1
- package/dist/web/standalone/node_modules/node-pty/build/Makefile +2 -2
- package/dist/web/standalone/node_modules/node-pty/build/Release/pty.node +0 -0
- package/dist/web/standalone/node_modules/node-pty/build/pty.target.mk +14 -14
- package/dist/web/standalone/node_modules/node-pty/node-addon-api/node_addon_api.target.mk +14 -14
- package/dist/web/standalone/node_modules/node-pty/node-addon-api/node_addon_api_except.target.mk +14 -14
- package/dist/web/standalone/node_modules/node-pty/node-addon-api/node_addon_api_maybe.target.mk +14 -14
- package/dist/web/standalone/server.js +1 -1
- package/package.json +1 -1
- package/src/resources/extensions/gsd/auto/infra-errors.ts +0 -3
- package/src/resources/extensions/gsd/auto-dispatch.ts +3 -3
- package/src/resources/extensions/gsd/auto-worktree.ts +2 -7
- package/src/resources/extensions/gsd/bootstrap/db-tools.ts +1 -2
- package/src/resources/extensions/gsd/dispatch-guard.ts +1 -12
- package/src/resources/extensions/gsd/gsd-db.ts +1 -6
- package/src/resources/extensions/gsd/parallel-orchestrator.ts +6 -23
- package/src/resources/extensions/gsd/preferences.ts +14 -32
- package/src/resources/extensions/gsd/prompts/validate-milestone.md +2 -2
- package/src/resources/extensions/gsd/tests/dispatch-guard.test.ts +0 -47
- package/src/resources/extensions/gsd/tests/parallel-worker-monitoring.test.ts +8 -9
- package/src/resources/extensions/gsd/tests/preferences.test.ts +0 -34
- package/src/resources/extensions/gsd/tests/prompt-contracts.test.ts +0 -7
- package/src/resources/extensions/gsd/tests/validate-milestone-write-order.test.ts +1 -23
- package/src/resources/extensions/gsd/tests/validation-gate-patterns.test.ts +2 -44
- package/src/resources/extensions/gsd/tools/validate-milestone.ts +0 -5
- package/dist/web/standalone/.next/static/chunks/6502.8b732f67a11b11b4.js +0 -9
- package/dist/web/standalone/.next/static/chunks/app/page-0c485498795110d6.js +0 -1
- package/dist/web/standalone/.next/static/chunks/main-app-fdab67f7802d7832.js +0 -1
- package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/global-error-459824ffb8c323dd.js +0 -1
- package/src/resources/extensions/gsd/tests/worktree-db-same-file.test.ts +0 -175
- /package/dist/web/standalone/.next/static/{OS7_z6QaL6uqp8q5pjHSJ → yowc5qPtuKxjOr22KmOAy}/_buildManifest.js +0 -0
- /package/dist/web/standalone/.next/static/{OS7_z6QaL6uqp8q5pjHSJ → yowc5qPtuKxjOr22KmOAy}/_ssgManifest.js +0 -0
|
@@ -22,7 +22,6 @@ import { normalizeStringArray } from "../shared/format-utils.js";
|
|
|
22
22
|
import { resolveProfileDefaults as _resolveProfileDefaults } from "./preferences-models.js";
|
|
23
23
|
|
|
24
24
|
import {
|
|
25
|
-
KNOWN_PREFERENCE_KEYS,
|
|
26
25
|
MODE_DEFAULTS,
|
|
27
26
|
type WorkflowMode,
|
|
28
27
|
type GSDPreferences,
|
|
@@ -251,7 +250,7 @@ function parseFrontmatterBlock(frontmatter: string): GSDPreferences {
|
|
|
251
250
|
* - planner: sonnet
|
|
252
251
|
*/
|
|
253
252
|
function parseHeadingListFormat(content: string): GSDPreferences {
|
|
254
|
-
const result: Record<string, string
|
|
253
|
+
const result: Record<string, Record<string, string>> = {};
|
|
255
254
|
let currentSection: string | null = null;
|
|
256
255
|
|
|
257
256
|
for (const rawLine of content.split('\n')) {
|
|
@@ -259,44 +258,27 @@ function parseHeadingListFormat(content: string): GSDPreferences {
|
|
|
259
258
|
const headingMatch = line.match(/^##\s+(.+)$/);
|
|
260
259
|
if (headingMatch) {
|
|
261
260
|
currentSection = headingMatch[1].trim().toLowerCase().replace(/\s+/g, '_');
|
|
262
|
-
if (!result[currentSection]) result[currentSection] = [];
|
|
263
261
|
continue;
|
|
264
262
|
}
|
|
265
|
-
if (currentSection
|
|
266
|
-
|
|
263
|
+
if (currentSection) {
|
|
264
|
+
const itemMatch = line.match(/^-\s+([^:]+):\s*(.*)$/);
|
|
265
|
+
if (itemMatch) {
|
|
266
|
+
if (!result[currentSection]) result[currentSection] = {};
|
|
267
|
+
const value = itemMatch[2].trim();
|
|
268
|
+
// Coerce "true"/"false" strings and numbers
|
|
269
|
+
result[currentSection][itemMatch[1].trim()] = value;
|
|
270
|
+
}
|
|
267
271
|
}
|
|
268
272
|
}
|
|
269
273
|
|
|
274
|
+
// Convert string values to appropriate types via YAML parser for each section
|
|
270
275
|
const typed: Record<string, unknown> = {};
|
|
271
|
-
for (const [section,
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
const usesLegacyListItems = lines.every((line) => /^\s*-\s+[^:]+:\s*.*$/.test(line));
|
|
275
|
-
const yamlBlock = usesLegacyListItems
|
|
276
|
-
? lines.map((line) => line.replace(/^\s*-\s+/, '')).join('\n')
|
|
277
|
-
: lines.join('\n');
|
|
278
|
-
|
|
276
|
+
for (const [section, entries] of Object.entries(result)) {
|
|
277
|
+
const yamlLines = Object.entries(entries).map(([k, v]) => `${k}: ${v}`).join('\n');
|
|
279
278
|
try {
|
|
280
|
-
|
|
281
|
-
if (typeof parsed !== 'object' || parsed === null) continue;
|
|
282
|
-
|
|
283
|
-
let targetSection = section;
|
|
284
|
-
let value: unknown = parsed;
|
|
285
|
-
|
|
286
|
-
if (!Array.isArray(parsed)) {
|
|
287
|
-
const keys = Object.keys(parsed);
|
|
288
|
-
if (keys.length === 1) {
|
|
289
|
-
const [onlyKey] = keys;
|
|
290
|
-
if (onlyKey === section || (!KNOWN_PREFERENCE_KEYS.has(section) && KNOWN_PREFERENCE_KEYS.has(onlyKey))) {
|
|
291
|
-
targetSection = onlyKey;
|
|
292
|
-
value = (parsed as Record<string, unknown>)[onlyKey];
|
|
293
|
-
}
|
|
294
|
-
}
|
|
295
|
-
}
|
|
296
|
-
|
|
297
|
-
typed[targetSection] = value;
|
|
279
|
+
typed[section] = parseYaml(yamlLines);
|
|
298
280
|
} catch {
|
|
299
|
-
|
|
281
|
+
typed[section] = entries;
|
|
300
282
|
}
|
|
301
283
|
}
|
|
302
284
|
|
|
@@ -26,7 +26,7 @@ All relevant context has been preloaded below — the roadmap, all slice summari
|
|
|
26
26
|
4. Check **requirement coverage** — are all active requirements addressed by at least one slice?
|
|
27
27
|
5. If **Verification Classes** are provided in the inlined context above, check each non-empty class:
|
|
28
28
|
- For each verification class (Contract, Integration, Operational, UAT), determine whether slice summaries, UAT results, or observable behavior provide evidence that this verification tier was addressed.
|
|
29
|
-
- Document the compliance status of each class in
|
|
29
|
+
- Document the compliance status of each class in your verdict rationale.
|
|
30
30
|
- If `Operational` verification is non-empty and no evidence of operational verification exists, flag this explicitly — it means planned operational checks (migrations, deployments, runtime verification) were not proven.
|
|
31
31
|
- A milestone with unaddressed verification classes may still pass if the gaps are minor, but the gaps MUST be documented in the Deferred Work Inventory.
|
|
32
32
|
6. Determine a verdict:
|
|
@@ -36,7 +36,7 @@ All relevant context has been preloaded below — the roadmap, all slice summari
|
|
|
36
36
|
|
|
37
37
|
## Persist Validation
|
|
38
38
|
|
|
39
|
-
**Persist validation results through `gsd_validate_milestone`.** Call it with: `milestoneId`, `verdict`, `remediationRound`, `successCriteriaChecklist`, `sliceDeliveryAudit`, `crossSliceIntegration`, `requirementCoverage`, `
|
|
39
|
+
**Persist validation results through `gsd_validate_milestone`.** Call it with: `milestoneId`, `verdict`, `remediationRound`, `successCriteriaChecklist`, `sliceDeliveryAudit`, `crossSliceIntegration`, `requirementCoverage`, `verdictRationale`, and `remediationPlan` (if verdict is `needs-remediation`). The tool writes the validation to the DB and renders VALIDATION.md to disk.
|
|
40
40
|
|
|
41
41
|
If verdict is `needs-remediation`:
|
|
42
42
|
- After calling `gsd_validate_milestone`, use `gsd_reassess_roadmap` to add remediation slices. Pass `milestoneId`, a synthetic `completedSliceId` (e.g. "VALIDATION"), `verdict: "roadmap-adjusted"`, `assessment` text, and `sliceChanges` with the new slices in the `added` array. The tool persists the changes to the DB and re-renders ROADMAP.md.
|
|
@@ -216,50 +216,3 @@ test("dispatch guard works without git repo", (t) => {
|
|
|
216
216
|
|
|
217
217
|
assert.equal(getPriorSliceCompletionBlocker(repo, "main", "plan-slice", "M001/S02"), null);
|
|
218
218
|
});
|
|
219
|
-
|
|
220
|
-
test("dispatch guard skips cross-milestone check when GSD_MILESTONE_LOCK is set (#2797)", (t) => {
|
|
221
|
-
const repo = setupRepo();
|
|
222
|
-
t.after(() => {
|
|
223
|
-
delete process.env.GSD_MILESTONE_LOCK;
|
|
224
|
-
teardownRepo(repo);
|
|
225
|
-
});
|
|
226
|
-
|
|
227
|
-
mkdirSync(join(repo, ".gsd", "milestones", "M010"), { recursive: true });
|
|
228
|
-
mkdirSync(join(repo, ".gsd", "milestones", "M011"), { recursive: true });
|
|
229
|
-
mkdirSync(join(repo, ".gsd", "milestones", "M012"), { recursive: true });
|
|
230
|
-
|
|
231
|
-
// M010 and M011 have incomplete slices
|
|
232
|
-
insertMilestone({ id: "M010", title: "Analytics" });
|
|
233
|
-
insertSlice({ id: "S01", milestoneId: "M010", title: "Data Quality", status: "pending", depends: [], sequence: 1 });
|
|
234
|
-
|
|
235
|
-
insertMilestone({ id: "M011", title: "Builder Onboarding" });
|
|
236
|
-
insertSlice({ id: "S01", milestoneId: "M011", title: "Schema", status: "pending", depends: [], sequence: 1 });
|
|
237
|
-
|
|
238
|
-
insertMilestone({ id: "M012", title: "Shared Components" });
|
|
239
|
-
insertSlice({ id: "S01", milestoneId: "M012", title: "Foundation", status: "pending", depends: [], sequence: 1 });
|
|
240
|
-
insertSlice({ id: "S02", milestoneId: "M012", title: "Migrate Pages", status: "pending", depends: ["S01"], sequence: 2 });
|
|
241
|
-
|
|
242
|
-
writeFileSync(join(repo, ".gsd", "milestones", "M010", "M010-ROADMAP.md"), "# M010\n");
|
|
243
|
-
writeFileSync(join(repo, ".gsd", "milestones", "M011", "M011-ROADMAP.md"), "# M011\n");
|
|
244
|
-
writeFileSync(join(repo, ".gsd", "milestones", "M012", "M012-ROADMAP.md"), "# M012\n");
|
|
245
|
-
|
|
246
|
-
// Without lock: M012 blocked by M010's incomplete S01
|
|
247
|
-
delete process.env.GSD_MILESTONE_LOCK;
|
|
248
|
-
assert.match(
|
|
249
|
-
getPriorSliceCompletionBlocker(repo, "main", "execute-task", "M012/S01/T01") ?? "",
|
|
250
|
-
/earlier slice M010\/S01 is not complete/,
|
|
251
|
-
);
|
|
252
|
-
|
|
253
|
-
// With lock: M012 only checks its own intra-milestone deps — S01 has none, so unblocked
|
|
254
|
-
process.env.GSD_MILESTONE_LOCK = "M012";
|
|
255
|
-
assert.equal(
|
|
256
|
-
getPriorSliceCompletionBlocker(repo, "main", "execute-task", "M012/S01/T01"),
|
|
257
|
-
null,
|
|
258
|
-
);
|
|
259
|
-
|
|
260
|
-
// With lock: M012/S02 still blocked by M012/S01 (intra-milestone dep preserved)
|
|
261
|
-
assert.equal(
|
|
262
|
-
getPriorSliceCompletionBlocker(repo, "main", "execute-task", "M012/S02/T01"),
|
|
263
|
-
"Cannot dispatch execute-task M012/S02/T01: dependency slice M012/S01 is not complete.",
|
|
264
|
-
);
|
|
265
|
-
});
|
|
@@ -131,15 +131,14 @@ describe("parallel-worker-monitoring", () => {
|
|
|
131
131
|
assert.ok(!(5.01 < ceiling), "5.01 is over ceiling");
|
|
132
132
|
});
|
|
133
133
|
|
|
134
|
-
it("worker spawn args
|
|
135
|
-
// Verify the spawn command
|
|
136
|
-
//
|
|
137
|
-
const expectedArgs = ["
|
|
138
|
-
assert.ok(expectedArgs.includes("
|
|
139
|
-
assert.ok(expectedArgs.includes("
|
|
140
|
-
assert.ok(expectedArgs.
|
|
141
|
-
|
|
142
|
-
"headless comes before auto");
|
|
134
|
+
it("worker spawn args include --mode json", () => {
|
|
135
|
+
// Verify the spawn command includes JSON mode for NDJSON output.
|
|
136
|
+
// We can't easily test the actual spawn, but we verify the args pattern.
|
|
137
|
+
const expectedArgs = ["--mode", "json", "--print", "/gsd auto"];
|
|
138
|
+
assert.ok(expectedArgs.includes("--mode"), "args include --mode");
|
|
139
|
+
assert.ok(expectedArgs.includes("json"), "args include json");
|
|
140
|
+
assert.ok(expectedArgs.indexOf("--mode") < expectedArgs.indexOf("json"),
|
|
141
|
+
"--mode comes before json");
|
|
143
142
|
});
|
|
144
143
|
|
|
145
144
|
it("refreshWorkerStatuses restores persisted workers from disk", () => {
|
|
@@ -352,40 +352,6 @@ test("handles empty models config", () => {
|
|
|
352
352
|
assert.equal(prefs!.models, undefined);
|
|
353
353
|
});
|
|
354
354
|
|
|
355
|
-
test("parses raw YAML blocks under headings", () => {
|
|
356
|
-
const content = `## Parallel
|
|
357
|
-
enabled: true
|
|
358
|
-
max_workers: 3
|
|
359
|
-
`;
|
|
360
|
-
const prefs = parsePreferencesMarkdown(content);
|
|
361
|
-
assert.notEqual(prefs, null);
|
|
362
|
-
assert.equal(prefs!.parallel?.enabled, true);
|
|
363
|
-
assert.equal(prefs!.parallel?.max_workers, 3);
|
|
364
|
-
});
|
|
365
|
-
|
|
366
|
-
test("unwraps nested top-level preference key under descriptive headings", () => {
|
|
367
|
-
const content = `## Parallel Orchestration
|
|
368
|
-
parallel:
|
|
369
|
-
enabled: true
|
|
370
|
-
max_workers: 3
|
|
371
|
-
`;
|
|
372
|
-
const prefs = parsePreferencesMarkdown(content);
|
|
373
|
-
assert.notEqual(prefs, null);
|
|
374
|
-
assert.equal(prefs!.parallel?.enabled, true);
|
|
375
|
-
assert.equal(prefs!.parallel?.max_workers, 3);
|
|
376
|
-
});
|
|
377
|
-
|
|
378
|
-
test("preserves legacy heading list format", () => {
|
|
379
|
-
const content = `## Git
|
|
380
|
-
- isolation: branch
|
|
381
|
-
- auto_push: true
|
|
382
|
-
`;
|
|
383
|
-
const prefs = parsePreferencesMarkdown(content);
|
|
384
|
-
assert.notEqual(prefs, null);
|
|
385
|
-
assert.equal(prefs!.git?.isolation, "branch");
|
|
386
|
-
assert.equal(prefs!.git?.auto_push, true);
|
|
387
|
-
});
|
|
388
|
-
|
|
389
355
|
// ── Warn-once for unrecognized format (#2373) ────────────────────────────────
|
|
390
356
|
|
|
391
357
|
test("unrecognized format warning is emitted at most once (#2373)", () => {
|
|
@@ -181,13 +181,6 @@ test("reassess-roadmap prompt references gsd_reassess_roadmap tool", () => {
|
|
|
181
181
|
assert.match(prompt, /gsd_reassess_roadmap/);
|
|
182
182
|
});
|
|
183
183
|
|
|
184
|
-
test("validate-milestone prompt persists verification classes through gsd_validate_milestone", () => {
|
|
185
|
-
const prompt = readPrompt("validate-milestone");
|
|
186
|
-
assert.match(prompt, /verification classes section/i);
|
|
187
|
-
assert.match(prompt, /verificationClasses/);
|
|
188
|
-
assert.match(prompt, /gsd_validate_milestone/);
|
|
189
|
-
});
|
|
190
|
-
|
|
191
184
|
// ─── Prompt migration: replan-slice → gsd_replan_slice ────────────────
|
|
192
185
|
|
|
193
186
|
test("replan-slice prompt names gsd_replan_slice as the tool to use", () => {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { describe, it, afterEach } from "node:test";
|
|
2
2
|
import assert from "node:assert/strict";
|
|
3
|
-
import { mkdirSync, existsSync,
|
|
3
|
+
import { mkdirSync, existsSync, rmSync, writeFileSync } from "node:fs";
|
|
4
4
|
import { join } from "node:path";
|
|
5
5
|
import { tmpdir } from "node:os";
|
|
6
6
|
import { randomUUID } from "node:crypto";
|
|
@@ -24,7 +24,6 @@ const VALID_PARAMS = {
|
|
|
24
24
|
sliceDeliveryAudit: "| S01 | delivered |",
|
|
25
25
|
crossSliceIntegration: "No issues",
|
|
26
26
|
requirementCoverage: "All covered",
|
|
27
|
-
verificationClasses: "- Contract: covered\n- Integration: covered\n- Operational: gap noted",
|
|
28
27
|
verdictRationale: "Everything checks out",
|
|
29
28
|
};
|
|
30
29
|
|
|
@@ -60,27 +59,6 @@ describe("handleValidateMilestone write ordering (#2725)", () => {
|
|
|
60
59
|
// Disk file exists
|
|
61
60
|
const filePath = join(base, ".gsd", "milestones", "M001", "M001-VALIDATION.md");
|
|
62
61
|
assert.ok(existsSync(filePath), "VALIDATION.md should exist on disk");
|
|
63
|
-
const validationMd = readFileSync(filePath, "utf-8");
|
|
64
|
-
assert.match(validationMd, /## Verification Class Compliance/);
|
|
65
|
-
assert.match(validationMd, /- Contract: covered/);
|
|
66
|
-
assert.match(validationMd, /## Verdict Rationale/);
|
|
67
|
-
});
|
|
68
|
-
|
|
69
|
-
it("omits verification class section when no verification classes are supplied", async () => {
|
|
70
|
-
base = makeTmpBase();
|
|
71
|
-
const dbPath = join(base, ".gsd", "gsd.db");
|
|
72
|
-
openDatabase(dbPath);
|
|
73
|
-
insertMilestone({ id: "M001" });
|
|
74
|
-
|
|
75
|
-
const result = await handleValidateMilestone(
|
|
76
|
-
{ ...VALID_PARAMS, verificationClasses: undefined },
|
|
77
|
-
base,
|
|
78
|
-
);
|
|
79
|
-
assert.ok(!("error" in result), `unexpected error: ${"error" in result ? result.error : ""}`);
|
|
80
|
-
|
|
81
|
-
const filePath = join(base, ".gsd", "milestones", "M001", "M001-VALIDATION.md");
|
|
82
|
-
const validationMd = readFileSync(filePath, "utf-8");
|
|
83
|
-
assert.doesNotMatch(validationMd, /## Verification Class Compliance/);
|
|
84
62
|
});
|
|
85
63
|
|
|
86
64
|
it("rolls back DB row when disk write fails", async () => {
|
|
@@ -23,9 +23,9 @@ import assert from "node:assert/strict";
|
|
|
23
23
|
function hasOperationalEvidence(validationContent: string): boolean {
|
|
24
24
|
const structuredMatch =
|
|
25
25
|
validationContent.includes("Operational") &&
|
|
26
|
-
(validationContent.includes("MET") || validationContent.includes("N/A")
|
|
26
|
+
(validationContent.includes("MET") || validationContent.includes("N/A"));
|
|
27
27
|
const proseMatch =
|
|
28
|
-
/[Oo]perational[\s
|
|
28
|
+
/[Oo]perational[\s:][^\n]*(?:pass|verified|confirmed|met|complete|true|yes|addressed|covered|n\/a|not\s+applicable)/i.test(
|
|
29
29
|
validationContent,
|
|
30
30
|
);
|
|
31
31
|
return structuredMatch || proseMatch;
|
|
@@ -104,48 +104,6 @@ test('prose: "Operational: complete" passes', () => {
|
|
|
104
104
|
assert.ok(hasOperationalEvidence(content));
|
|
105
105
|
});
|
|
106
106
|
|
|
107
|
-
// ─── Issue #2862: checkmark emoji ────────────────────────────────────────────
|
|
108
|
-
|
|
109
|
-
test('prose: "Operational: ✅" checkmark emoji passes (issue #2862)', () => {
|
|
110
|
-
const content = `- **Operational:** ✅ DECISIONS.md documents D009-D013`;
|
|
111
|
-
assert.ok(hasOperationalEvidence(content));
|
|
112
|
-
});
|
|
113
|
-
|
|
114
|
-
// ─── Issue #2866: multi-line, "satisfied", markdown bold ─────────────────────
|
|
115
|
-
|
|
116
|
-
test('multi-line: verdict on next line after Operational heading passes (issue #2866)', () => {
|
|
117
|
-
const content = `### Operational Verification
|
|
118
|
-
All endpoints responsive. Health checks pass.`;
|
|
119
|
-
assert.ok(hasOperationalEvidence(content));
|
|
120
|
-
});
|
|
121
|
-
|
|
122
|
-
test('prose: "PARTIALLY SATISFIED" passes (issue #2866)', () => {
|
|
123
|
-
const content = `Operational class: ⚠️ PARTIALLY SATISFIED`;
|
|
124
|
-
assert.ok(hasOperationalEvidence(content));
|
|
125
|
-
});
|
|
126
|
-
|
|
127
|
-
test('prose: "FULLY SATISFIED" passes (issue #2866)', () => {
|
|
128
|
-
const content = `**Operational**: FULLY SATISFIED — all monitoring in place.`;
|
|
129
|
-
assert.ok(hasOperationalEvidence(content));
|
|
130
|
-
});
|
|
131
|
-
|
|
132
|
-
test('structured: Operational + SATISFIED passes (issue #2866)', () => {
|
|
133
|
-
const content = `| Criteria | Status |
|
|
134
|
-
| Operational | SATISFIED |`;
|
|
135
|
-
assert.ok(hasOperationalEvidence(content));
|
|
136
|
-
});
|
|
137
|
-
|
|
138
|
-
test('table with markdown bold: **Operational** passes (issue #2866)', () => {
|
|
139
|
-
const content = `| **Operational** | ⚠️ Partially satisfied — monitoring gap noted |`;
|
|
140
|
-
assert.ok(hasOperationalEvidence(content));
|
|
141
|
-
});
|
|
142
|
-
|
|
143
|
-
test('multi-line: Operational label and "confirmed" separated by line break passes (issue #2866)', () => {
|
|
144
|
-
const content = `## Operational
|
|
145
|
-
Smoke tests confirmed all services healthy after deploy.`;
|
|
146
|
-
assert.ok(hasOperationalEvidence(content));
|
|
147
|
-
});
|
|
148
|
-
|
|
149
107
|
// ─── Rejection cases ─────────────────────────────────────────────────────────
|
|
150
108
|
|
|
151
109
|
test("no operational evidence: unrelated content fails", () => {
|
|
@@ -25,7 +25,6 @@ export interface ValidateMilestoneParams {
|
|
|
25
25
|
sliceDeliveryAudit: string;
|
|
26
26
|
crossSliceIntegration: string;
|
|
27
27
|
requirementCoverage: string;
|
|
28
|
-
verificationClasses?: string;
|
|
29
28
|
verdictRationale: string;
|
|
30
29
|
remediationPlan?: string;
|
|
31
30
|
}
|
|
@@ -56,10 +55,6 @@ ${params.crossSliceIntegration}
|
|
|
56
55
|
## Requirement Coverage
|
|
57
56
|
${params.requirementCoverage}
|
|
58
57
|
|
|
59
|
-
${params.verificationClasses ? `## Verification Class Compliance
|
|
60
|
-
${params.verificationClasses}
|
|
61
|
-
|
|
62
|
-
` : ""}
|
|
63
58
|
## Verdict Rationale
|
|
64
59
|
${params.verdictRationale}
|
|
65
60
|
`;
|