gsd-remix 1.0.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/LICENSE +21 -0
- package/README.md +939 -0
- package/README.zh-CN.md +876 -0
- package/agents/gsd-advisor-researcher.md +127 -0
- package/agents/gsd-ai-researcher.md +133 -0
- package/agents/gsd-assumptions-analyzer.md +105 -0
- package/agents/gsd-code-fixer.md +517 -0
- package/agents/gsd-code-reviewer.md +371 -0
- package/agents/gsd-codebase-mapper.md +781 -0
- package/agents/gsd-debug-session-manager.md +314 -0
- package/agents/gsd-debugger.md +1452 -0
- package/agents/gsd-doc-classifier.md +168 -0
- package/agents/gsd-doc-synthesizer.md +204 -0
- package/agents/gsd-doc-verifier.md +217 -0
- package/agents/gsd-doc-writer.md +615 -0
- package/agents/gsd-domain-researcher.md +153 -0
- package/agents/gsd-eval-auditor.md +191 -0
- package/agents/gsd-eval-planner.md +154 -0
- package/agents/gsd-executor.md +603 -0
- package/agents/gsd-framework-selector.md +160 -0
- package/agents/gsd-integration-checker.md +470 -0
- package/agents/gsd-intel-updater.md +334 -0
- package/agents/gsd-nyquist-auditor.md +203 -0
- package/agents/gsd-pattern-mapper.md +335 -0
- package/agents/gsd-phase-researcher.md +841 -0
- package/agents/gsd-plan-checker.md +978 -0
- package/agents/gsd-planner.md +1251 -0
- package/agents/gsd-project-researcher.md +677 -0
- package/agents/gsd-research-synthesizer.md +247 -0
- package/agents/gsd-roadmapper.md +688 -0
- package/agents/gsd-security-auditor.md +155 -0
- package/agents/gsd-ui-auditor.md +495 -0
- package/agents/gsd-ui-checker.md +309 -0
- package/agents/gsd-ui-researcher.md +380 -0
- package/agents/gsd-user-profiler.md +171 -0
- package/agents/gsd-verifier.md +830 -0
- package/bin/install.js +7062 -0
- package/commands/gsd/add-backlog.md +79 -0
- package/commands/gsd/add-phase.md +43 -0
- package/commands/gsd/add-tests.md +41 -0
- package/commands/gsd/add-todo.md +47 -0
- package/commands/gsd/ai-integration-phase.md +36 -0
- package/commands/gsd/analyze-dependencies.md +34 -0
- package/commands/gsd/audit-fix.md +33 -0
- package/commands/gsd/audit-milestone.md +36 -0
- package/commands/gsd/audit-uat.md +24 -0
- package/commands/gsd/autonomous.md +46 -0
- package/commands/gsd/check-todos.md +45 -0
- package/commands/gsd/cleanup.md +23 -0
- package/commands/gsd/code-review-fix.md +52 -0
- package/commands/gsd/code-review.md +55 -0
- package/commands/gsd/complete-milestone.md +136 -0
- package/commands/gsd/debug.md +263 -0
- package/commands/gsd/discuss-phase.md +69 -0
- package/commands/gsd/do.md +30 -0
- package/commands/gsd/docs-update.md +48 -0
- package/commands/gsd/eval-review.md +32 -0
- package/commands/gsd/execute-phase.md +63 -0
- package/commands/gsd/explore.md +27 -0
- package/commands/gsd/extract_learnings.md +22 -0
- package/commands/gsd/fast.md +30 -0
- package/commands/gsd/forensics.md +56 -0
- package/commands/gsd/from-gsd2.md +47 -0
- package/commands/gsd/graphify.md +201 -0
- package/commands/gsd/health.md +22 -0
- package/commands/gsd/help.md +24 -0
- package/commands/gsd/import.md +37 -0
- package/commands/gsd/inbox.md +38 -0
- package/commands/gsd/ingest-docs.md +42 -0
- package/commands/gsd/insert-phase.md +32 -0
- package/commands/gsd/intel.md +179 -0
- package/commands/gsd/join-discord.md +19 -0
- package/commands/gsd/list-phase-assumptions.md +46 -0
- package/commands/gsd/list-workspaces.md +19 -0
- package/commands/gsd/manager.md +40 -0
- package/commands/gsd/map-codebase.md +71 -0
- package/commands/gsd/milestone-summary.md +51 -0
- package/commands/gsd/new-milestone.md +44 -0
- package/commands/gsd/new-project.md +46 -0
- package/commands/gsd/new-workspace.md +44 -0
- package/commands/gsd/next.md +28 -0
- package/commands/gsd/note.md +34 -0
- package/commands/gsd/pause-work.md +38 -0
- package/commands/gsd/plan-milestone-gaps.md +34 -0
- package/commands/gsd/plan-phase.md +52 -0
- package/commands/gsd/plan-review-convergence.md +52 -0
- package/commands/gsd/plant-seed.md +28 -0
- package/commands/gsd/pr-branch.md +25 -0
- package/commands/gsd/profile-user.md +46 -0
- package/commands/gsd/progress.md +25 -0
- package/commands/gsd/quick.md +173 -0
- package/commands/gsd/reapply-patches.md +331 -0
- package/commands/gsd/remove-phase.md +31 -0
- package/commands/gsd/remove-workspace.md +26 -0
- package/commands/gsd/research-phase.md +195 -0
- package/commands/gsd/resume-work.md +40 -0
- package/commands/gsd/review-backlog.md +62 -0
- package/commands/gsd/review.md +40 -0
- package/commands/gsd/scan.md +26 -0
- package/commands/gsd/secure-phase.md +35 -0
- package/commands/gsd/session-report.md +19 -0
- package/commands/gsd/set-profile.md +12 -0
- package/commands/gsd/settings.md +36 -0
- package/commands/gsd/ship.md +23 -0
- package/commands/gsd/sketch-wrap-up.md +31 -0
- package/commands/gsd/sketch.md +49 -0
- package/commands/gsd/spec-phase.md +62 -0
- package/commands/gsd/spike-wrap-up.md +31 -0
- package/commands/gsd/spike.md +46 -0
- package/commands/gsd/stats.md +18 -0
- package/commands/gsd/sync-skills.md +19 -0
- package/commands/gsd/thread.md +227 -0
- package/commands/gsd/ui-phase.md +34 -0
- package/commands/gsd/ui-review.md +32 -0
- package/commands/gsd/ultraplan-phase.md +33 -0
- package/commands/gsd/undo.md +34 -0
- package/commands/gsd/update.md +37 -0
- package/commands/gsd/validate-phase.md +35 -0
- package/commands/gsd/verify-work.md +38 -0
- package/commands/gsd/workstreams.md +69 -0
- package/get-shit-done/bin/gsd-tools.cjs +1263 -0
- package/get-shit-done/bin/lib/artifacts.cjs +52 -0
- package/get-shit-done/bin/lib/audit.cjs +757 -0
- package/get-shit-done/bin/lib/commands.cjs +1023 -0
- package/get-shit-done/bin/lib/config-schema.cjs +79 -0
- package/get-shit-done/bin/lib/config.cjs +463 -0
- package/get-shit-done/bin/lib/core.cjs +1794 -0
- package/get-shit-done/bin/lib/docs.cjs +267 -0
- package/get-shit-done/bin/lib/frontmatter.cjs +379 -0
- package/get-shit-done/bin/lib/graphify.cjs +494 -0
- package/get-shit-done/bin/lib/gsd2-import.cjs +511 -0
- package/get-shit-done/bin/lib/init.cjs +1878 -0
- package/get-shit-done/bin/lib/intel.cjs +639 -0
- package/get-shit-done/bin/lib/learnings.cjs +378 -0
- package/get-shit-done/bin/lib/milestone.cjs +283 -0
- package/get-shit-done/bin/lib/model-profiles.cjs +71 -0
- package/get-shit-done/bin/lib/phase.cjs +1058 -0
- package/get-shit-done/bin/lib/profile-output.cjs +1080 -0
- package/get-shit-done/bin/lib/profile-pipeline.cjs +539 -0
- package/get-shit-done/bin/lib/roadmap.cjs +523 -0
- package/get-shit-done/bin/lib/schema-detect.cjs +238 -0
- package/get-shit-done/bin/lib/security.cjs +504 -0
- package/get-shit-done/bin/lib/state.cjs +1649 -0
- package/get-shit-done/bin/lib/template.cjs +226 -0
- package/get-shit-done/bin/lib/uat.cjs +288 -0
- package/get-shit-done/bin/lib/verify.cjs +1184 -0
- package/get-shit-done/bin/lib/workstream.cjs +495 -0
- package/get-shit-done/bin/repair-sdk.cjs +177 -0
- package/get-shit-done/contexts/dev.md +21 -0
- package/get-shit-done/contexts/research.md +22 -0
- package/get-shit-done/contexts/review.md +22 -0
- package/get-shit-done/references/agent-contracts.md +79 -0
- package/get-shit-done/references/ai-evals.md +156 -0
- package/get-shit-done/references/ai-frameworks.md +186 -0
- package/get-shit-done/references/artifact-types.md +131 -0
- package/get-shit-done/references/autonomous-smart-discuss.md +277 -0
- package/get-shit-done/references/checkpoints.md +808 -0
- package/get-shit-done/references/common-bug-patterns.md +114 -0
- package/get-shit-done/references/context-budget.md +49 -0
- package/get-shit-done/references/continuation-format.md +253 -0
- package/get-shit-done/references/debugger-philosophy.md +76 -0
- package/get-shit-done/references/decimal-phase-calculation.md +64 -0
- package/get-shit-done/references/doc-conflict-engine.md +91 -0
- package/get-shit-done/references/domain-probes.md +125 -0
- package/get-shit-done/references/executor-examples.md +110 -0
- package/get-shit-done/references/few-shot-examples/plan-checker.md +73 -0
- package/get-shit-done/references/few-shot-examples/verifier.md +109 -0
- package/get-shit-done/references/gate-prompts.md +100 -0
- package/get-shit-done/references/gates.md +70 -0
- package/get-shit-done/references/git-integration.md +295 -0
- package/get-shit-done/references/git-planning-commit.md +40 -0
- package/get-shit-done/references/ios-scaffold.md +123 -0
- package/get-shit-done/references/mandatory-initial-read.md +2 -0
- package/get-shit-done/references/model-profile-resolution.md +38 -0
- package/get-shit-done/references/model-profiles.md +145 -0
- package/get-shit-done/references/phase-argument-parsing.md +61 -0
- package/get-shit-done/references/planner-antipatterns.md +89 -0
- package/get-shit-done/references/planner-gap-closure.md +62 -0
- package/get-shit-done/references/planner-reviews.md +39 -0
- package/get-shit-done/references/planner-revision.md +87 -0
- package/get-shit-done/references/planner-source-audit.md +73 -0
- package/get-shit-done/references/planning-config.md +460 -0
- package/get-shit-done/references/project-skills-discovery.md +19 -0
- package/get-shit-done/references/questioning.md +162 -0
- package/get-shit-done/references/revision-loop.md +97 -0
- package/get-shit-done/references/sketch-interactivity.md +41 -0
- package/get-shit-done/references/sketch-theme-system.md +94 -0
- package/get-shit-done/references/sketch-tooling.md +45 -0
- package/get-shit-done/references/sketch-variant-patterns.md +81 -0
- package/get-shit-done/references/tdd.md +330 -0
- package/get-shit-done/references/thinking-models-debug.md +44 -0
- package/get-shit-done/references/thinking-models-execution.md +50 -0
- package/get-shit-done/references/thinking-models-planning.md +62 -0
- package/get-shit-done/references/thinking-models-research.md +50 -0
- package/get-shit-done/references/thinking-models-verification.md +55 -0
- package/get-shit-done/references/thinking-partner.md +96 -0
- package/get-shit-done/references/ui-brand.md +160 -0
- package/get-shit-done/references/universal-anti-patterns.md +63 -0
- package/get-shit-done/references/user-profiling.md +681 -0
- package/get-shit-done/references/verification-overrides.md +227 -0
- package/get-shit-done/references/verification-patterns.md +612 -0
- package/get-shit-done/references/workstream-flag.md +111 -0
- package/get-shit-done/templates/AI-SPEC.md +246 -0
- package/get-shit-done/templates/DEBUG.md +169 -0
- package/get-shit-done/templates/README.md +76 -0
- package/get-shit-done/templates/SECURITY.md +61 -0
- package/get-shit-done/templates/UAT.md +265 -0
- package/get-shit-done/templates/UI-SPEC.md +100 -0
- package/get-shit-done/templates/VALIDATION.md +76 -0
- package/get-shit-done/templates/claude-md.md +145 -0
- package/get-shit-done/templates/codebase/architecture.md +255 -0
- package/get-shit-done/templates/codebase/concerns.md +310 -0
- package/get-shit-done/templates/codebase/conventions.md +307 -0
- package/get-shit-done/templates/codebase/integrations.md +280 -0
- package/get-shit-done/templates/codebase/stack.md +186 -0
- package/get-shit-done/templates/codebase/structure.md +285 -0
- package/get-shit-done/templates/codebase/testing.md +480 -0
- package/get-shit-done/templates/config.json +56 -0
- package/get-shit-done/templates/context.md +352 -0
- package/get-shit-done/templates/continue-here.md +78 -0
- package/get-shit-done/templates/copilot-instructions.md +7 -0
- package/get-shit-done/templates/debug-subagent-prompt.md +91 -0
- package/get-shit-done/templates/dev-preferences.md +21 -0
- package/get-shit-done/templates/discovery.md +146 -0
- package/get-shit-done/templates/discussion-log.md +63 -0
- package/get-shit-done/templates/milestone-archive.md +123 -0
- package/get-shit-done/templates/milestone.md +115 -0
- package/get-shit-done/templates/phase-prompt.md +610 -0
- package/get-shit-done/templates/planner-subagent-prompt.md +117 -0
- package/get-shit-done/templates/project.md +186 -0
- package/get-shit-done/templates/requirements.md +231 -0
- package/get-shit-done/templates/research-project/ARCHITECTURE.md +204 -0
- package/get-shit-done/templates/research-project/FEATURES.md +147 -0
- package/get-shit-done/templates/research-project/PITFALLS.md +200 -0
- package/get-shit-done/templates/research-project/STACK.md +120 -0
- package/get-shit-done/templates/research-project/SUMMARY.md +170 -0
- package/get-shit-done/templates/research.md +592 -0
- package/get-shit-done/templates/retrospective.md +54 -0
- package/get-shit-done/templates/roadmap.md +202 -0
- package/get-shit-done/templates/spec.md +307 -0
- package/get-shit-done/templates/state.md +184 -0
- package/get-shit-done/templates/summary-complex.md +59 -0
- package/get-shit-done/templates/summary-minimal.md +41 -0
- package/get-shit-done/templates/summary-standard.md +48 -0
- package/get-shit-done/templates/summary.md +248 -0
- package/get-shit-done/templates/user-profile.md +146 -0
- package/get-shit-done/templates/user-setup.md +311 -0
- package/get-shit-done/templates/verification-report.md +322 -0
- package/get-shit-done/workflows/add-phase.md +112 -0
- package/get-shit-done/workflows/add-tests.md +354 -0
- package/get-shit-done/workflows/add-todo.md +160 -0
- package/get-shit-done/workflows/ai-integration-phase.md +284 -0
- package/get-shit-done/workflows/analyze-dependencies.md +96 -0
- package/get-shit-done/workflows/audit-fix.md +175 -0
- package/get-shit-done/workflows/audit-milestone.md +340 -0
- package/get-shit-done/workflows/audit-uat.md +109 -0
- package/get-shit-done/workflows/autonomous.md +789 -0
- package/get-shit-done/workflows/check-todos.md +179 -0
- package/get-shit-done/workflows/cleanup.md +154 -0
- package/get-shit-done/workflows/code-review-fix.md +497 -0
- package/get-shit-done/workflows/code-review.md +515 -0
- package/get-shit-done/workflows/complete-milestone.md +847 -0
- package/get-shit-done/workflows/diagnose-issues.md +238 -0
- package/get-shit-done/workflows/discovery-phase.md +291 -0
- package/get-shit-done/workflows/discuss-phase-assumptions.md +670 -0
- package/get-shit-done/workflows/discuss-phase-power.md +308 -0
- package/get-shit-done/workflows/discuss-phase.md +1378 -0
- package/get-shit-done/workflows/do.md +110 -0
- package/get-shit-done/workflows/docs-update.md +1155 -0
- package/get-shit-done/workflows/eval-review.md +155 -0
- package/get-shit-done/workflows/execute-phase.md +1677 -0
- package/get-shit-done/workflows/execute-plan.md +533 -0
- package/get-shit-done/workflows/explore.md +141 -0
- package/get-shit-done/workflows/extract_learnings.md +242 -0
- package/get-shit-done/workflows/fast.md +105 -0
- package/get-shit-done/workflows/forensics.md +265 -0
- package/get-shit-done/workflows/graduation.md +195 -0
- package/get-shit-done/workflows/health.md +314 -0
- package/get-shit-done/workflows/help.md +667 -0
- package/get-shit-done/workflows/import.md +246 -0
- package/get-shit-done/workflows/inbox.md +387 -0
- package/get-shit-done/workflows/ingest-docs.md +328 -0
- package/get-shit-done/workflows/insert-phase.md +130 -0
- package/get-shit-done/workflows/list-phase-assumptions.md +178 -0
- package/get-shit-done/workflows/list-workspaces.md +56 -0
- package/get-shit-done/workflows/manager.md +365 -0
- package/get-shit-done/workflows/map-codebase.md +393 -0
- package/get-shit-done/workflows/milestone-summary.md +223 -0
- package/get-shit-done/workflows/new-milestone.md +611 -0
- package/get-shit-done/workflows/new-project.md +1391 -0
- package/get-shit-done/workflows/new-workspace.md +239 -0
- package/get-shit-done/workflows/next.md +220 -0
- package/get-shit-done/workflows/node-repair.md +92 -0
- package/get-shit-done/workflows/note.md +158 -0
- package/get-shit-done/workflows/pause-work.md +243 -0
- package/get-shit-done/workflows/plan-milestone-gaps.md +273 -0
- package/get-shit-done/workflows/plan-phase.md +1349 -0
- package/get-shit-done/workflows/plan-review-convergence.md +254 -0
- package/get-shit-done/workflows/plant-seed.md +172 -0
- package/get-shit-done/workflows/pr-branch.md +157 -0
- package/get-shit-done/workflows/profile-user.md +452 -0
- package/get-shit-done/workflows/progress.md +619 -0
- package/get-shit-done/workflows/quick.md +970 -0
- package/get-shit-done/workflows/remove-phase.md +155 -0
- package/get-shit-done/workflows/remove-workspace.md +92 -0
- package/get-shit-done/workflows/research-phase.md +89 -0
- package/get-shit-done/workflows/resume-project.md +326 -0
- package/get-shit-done/workflows/review.md +344 -0
- package/get-shit-done/workflows/scan.md +102 -0
- package/get-shit-done/workflows/secure-phase.md +166 -0
- package/get-shit-done/workflows/session-report.md +146 -0
- package/get-shit-done/workflows/settings.md +319 -0
- package/get-shit-done/workflows/ship.md +302 -0
- package/get-shit-done/workflows/sketch-wrap-up.md +283 -0
- package/get-shit-done/workflows/sketch.md +286 -0
- package/get-shit-done/workflows/spec-phase.md +262 -0
- package/get-shit-done/workflows/spike-wrap-up.md +281 -0
- package/get-shit-done/workflows/spike.md +362 -0
- package/get-shit-done/workflows/stats.md +60 -0
- package/get-shit-done/workflows/sync-skills.md +182 -0
- package/get-shit-done/workflows/transition.md +693 -0
- package/get-shit-done/workflows/ui-phase.md +323 -0
- package/get-shit-done/workflows/ui-review.md +190 -0
- package/get-shit-done/workflows/ultraplan-phase.md +189 -0
- package/get-shit-done/workflows/undo.md +314 -0
- package/get-shit-done/workflows/update.md +587 -0
- package/get-shit-done/workflows/validate-phase.md +176 -0
- package/get-shit-done/workflows/verify-phase.md +465 -0
- package/get-shit-done/workflows/verify-work.md +740 -0
- package/hooks/dist/gsd-check-update-worker.js +108 -0
- package/hooks/dist/gsd-check-update.js +64 -0
- package/hooks/dist/gsd-context-monitor.js +192 -0
- package/hooks/dist/gsd-phase-boundary.sh +28 -0
- package/hooks/dist/gsd-prompt-guard.js +97 -0
- package/hooks/dist/gsd-read-guard.js +82 -0
- package/hooks/dist/gsd-read-injection-scanner.js +152 -0
- package/hooks/dist/gsd-session-state.sh +34 -0
- package/hooks/dist/gsd-statusline.js +293 -0
- package/hooks/dist/gsd-validate-commit.sh +48 -0
- package/hooks/dist/gsd-workflow-guard.js +94 -0
- package/hooks/gsd-check-update-worker.js +108 -0
- package/hooks/gsd-check-update.js +64 -0
- package/hooks/gsd-context-monitor.js +192 -0
- package/hooks/gsd-phase-boundary.sh +28 -0
- package/hooks/gsd-prompt-guard.js +97 -0
- package/hooks/gsd-read-guard.js +82 -0
- package/hooks/gsd-read-injection-scanner.js +152 -0
- package/hooks/gsd-session-state.sh +34 -0
- package/hooks/gsd-statusline.js +293 -0
- package/hooks/gsd-validate-commit.sh +48 -0
- package/hooks/gsd-workflow-guard.js +94 -0
- package/package.json +59 -0
- package/scripts/base64-scan.sh +262 -0
- package/scripts/build-hooks.js +95 -0
- package/scripts/gen-inventory-manifest.cjs +109 -0
- package/scripts/prompt-injection-scan.sh +201 -0
- package/scripts/run-tests.cjs +33 -0
- package/scripts/secret-scan.sh +227 -0
- package/sdk/package-lock.json +1998 -0
- package/sdk/package.json +52 -0
- package/sdk/prompts/agents/gsd-executor.md +110 -0
- package/sdk/prompts/agents/gsd-phase-researcher.md +158 -0
- package/sdk/prompts/agents/gsd-plan-checker.md +160 -0
- package/sdk/prompts/agents/gsd-planner.md +214 -0
- package/sdk/prompts/agents/gsd-project-researcher.md +323 -0
- package/sdk/prompts/agents/gsd-research-synthesizer.md +237 -0
- package/sdk/prompts/agents/gsd-roadmapper.md +670 -0
- package/sdk/prompts/agents/gsd-verifier.md +159 -0
- package/sdk/prompts/templates/project.md +186 -0
- package/sdk/prompts/templates/requirements.md +231 -0
- package/sdk/prompts/templates/research-project/ARCHITECTURE.md +204 -0
- package/sdk/prompts/templates/research-project/FEATURES.md +147 -0
- package/sdk/prompts/templates/research-project/PITFALLS.md +200 -0
- package/sdk/prompts/templates/research-project/STACK.md +120 -0
- package/sdk/prompts/templates/research-project/SUMMARY.md +170 -0
- package/sdk/prompts/templates/roadmap.md +202 -0
- package/sdk/prompts/templates/state.md +175 -0
- package/sdk/prompts/workflows/discuss-phase.md +126 -0
- package/sdk/prompts/workflows/execute-plan.md +106 -0
- package/sdk/prompts/workflows/plan-phase.md +84 -0
- package/sdk/prompts/workflows/research-phase.md +45 -0
- package/sdk/prompts/workflows/verify-phase.md +142 -0
- package/sdk/src/assembled-prompts.test.ts +349 -0
- package/sdk/src/cli-transport.test.ts +388 -0
- package/sdk/src/cli-transport.ts +130 -0
- package/sdk/src/cli.test.ts +383 -0
- package/sdk/src/cli.ts +670 -0
- package/sdk/src/config.test.ts +168 -0
- package/sdk/src/config.ts +177 -0
- package/sdk/src/context-engine.test.ts +295 -0
- package/sdk/src/context-engine.ts +170 -0
- package/sdk/src/context-truncation.test.ts +163 -0
- package/sdk/src/context-truncation.ts +233 -0
- package/sdk/src/e2e.integration.test.ts +178 -0
- package/sdk/src/errors.ts +72 -0
- package/sdk/src/event-stream.test.ts +661 -0
- package/sdk/src/event-stream.ts +441 -0
- package/sdk/src/failure-memory.test.ts +457 -0
- package/sdk/src/failure-memory.ts +1324 -0
- package/sdk/src/golden/capture.ts +95 -0
- package/sdk/src/golden/fixtures/generate-slug.golden.json +1 -0
- package/sdk/src/golden/fixtures/profile-sample-sessions/demo-project/sample.jsonl +3 -0
- package/sdk/src/golden/fixtures/summary-extract-sample.md +26 -0
- package/sdk/src/golden/fixtures/uat-render-checkpoint-sample.md +15 -0
- package/sdk/src/golden/golden-integration-covered.ts +30 -0
- package/sdk/src/golden/golden-mutation-covered.ts +7 -0
- package/sdk/src/golden/golden-policy.test.ts +8 -0
- package/sdk/src/golden/golden-policy.ts +112 -0
- package/sdk/src/golden/golden.integration.test.ts +373 -0
- package/sdk/src/golden/init-golden-normalize.ts +15 -0
- package/sdk/src/golden/read-only-golden-rows.ts +77 -0
- package/sdk/src/golden/read-only-parity.integration.test.ts +125 -0
- package/sdk/src/golden/registry-canonical-commands.ts +31 -0
- package/sdk/src/gsd-tools.test.ts +409 -0
- package/sdk/src/gsd-tools.ts +595 -0
- package/sdk/src/headless-prompts.test.ts +159 -0
- package/sdk/src/index.ts +333 -0
- package/sdk/src/init-e2e.integration.test.ts +136 -0
- package/sdk/src/init-runner.test.ts +783 -0
- package/sdk/src/init-runner.ts +735 -0
- package/sdk/src/lifecycle-e2e.integration.test.ts +258 -0
- package/sdk/src/logger.test.ts +149 -0
- package/sdk/src/logger.ts +113 -0
- package/sdk/src/milestone-runner.test.ts +421 -0
- package/sdk/src/phase-prompt.test.ts +538 -0
- package/sdk/src/phase-prompt.ts +264 -0
- package/sdk/src/phase-runner-types.test.ts +421 -0
- package/sdk/src/phase-runner.integration.test.ts +377 -0
- package/sdk/src/phase-runner.test.ts +2333 -0
- package/sdk/src/phase-runner.ts +1203 -0
- package/sdk/src/plan-parser.test.ts +528 -0
- package/sdk/src/plan-parser.ts +427 -0
- package/sdk/src/prompt-builder.test.ts +306 -0
- package/sdk/src/prompt-builder.ts +193 -0
- package/sdk/src/prompt-sanitizer.test.ts +260 -0
- package/sdk/src/prompt-sanitizer.ts +71 -0
- package/sdk/src/query/QUERY-HANDLERS.md +317 -0
- package/sdk/src/query/audit-open.ts +722 -0
- package/sdk/src/query/check-auto-mode.test.ts +77 -0
- package/sdk/src/query/check-auto-mode.ts +50 -0
- package/sdk/src/query/check-completion.test.ts +113 -0
- package/sdk/src/query/check-completion.ts +182 -0
- package/sdk/src/query/check-gates.test.ts +103 -0
- package/sdk/src/query/check-gates.ts +112 -0
- package/sdk/src/query/check-ship-ready.test.ts +77 -0
- package/sdk/src/query/check-ship-ready.ts +103 -0
- package/sdk/src/query/check-verification-status.test.ts +143 -0
- package/sdk/src/query/check-verification-status.ts +160 -0
- package/sdk/src/query/commit.test.ts +202 -0
- package/sdk/src/query/commit.ts +301 -0
- package/sdk/src/query/config-gates.test.ts +89 -0
- package/sdk/src/query/config-gates.ts +69 -0
- package/sdk/src/query/config-mutation.test.ts +365 -0
- package/sdk/src/query/config-mutation.ts +497 -0
- package/sdk/src/query/config-query.test.ts +161 -0
- package/sdk/src/query/config-query.ts +190 -0
- package/sdk/src/query/context-history.test.ts +165 -0
- package/sdk/src/query/context-history.ts +467 -0
- package/sdk/src/query/decomposed-handlers.test.ts +365 -0
- package/sdk/src/query/detect-custom-files.ts +97 -0
- package/sdk/src/query/detect-phase-type.test.ts +105 -0
- package/sdk/src/query/detect-phase-type.ts +141 -0
- package/sdk/src/query/docs-init.ts +257 -0
- package/sdk/src/query/failure-capture.ts +58 -0
- package/sdk/src/query/frontmatter-array.test.ts +14 -0
- package/sdk/src/query/frontmatter-mutation.test.ts +259 -0
- package/sdk/src/query/frontmatter-mutation.ts +343 -0
- package/sdk/src/query/frontmatter.test.ts +281 -0
- package/sdk/src/query/frontmatter.ts +397 -0
- package/sdk/src/query/helpers.test.ts +426 -0
- package/sdk/src/query/helpers.ts +482 -0
- package/sdk/src/query/index.ts +586 -0
- package/sdk/src/query/init-complex.test.ts +232 -0
- package/sdk/src/query/init-complex.ts +578 -0
- package/sdk/src/query/init.test.ts +522 -0
- package/sdk/src/query/init.ts +1046 -0
- package/sdk/src/query/intel.test.ts +90 -0
- package/sdk/src/query/intel.ts +404 -0
- package/sdk/src/query/normalize-query-command.test.ts +50 -0
- package/sdk/src/query/normalize-query-command.ts +56 -0
- package/sdk/src/query/phase-lifecycle.test.ts +1126 -0
- package/sdk/src/query/phase-lifecycle.ts +1799 -0
- package/sdk/src/query/phase-list-queries.test.ts +88 -0
- package/sdk/src/query/phase-list-queries.ts +152 -0
- package/sdk/src/query/phase-ready.test.ts +65 -0
- package/sdk/src/query/phase-ready.ts +158 -0
- package/sdk/src/query/phase.test.ts +307 -0
- package/sdk/src/query/phase.ts +340 -0
- package/sdk/src/query/pipeline.test.ts +169 -0
- package/sdk/src/query/pipeline.ts +243 -0
- package/sdk/src/query/plan-execution-route.test.ts +166 -0
- package/sdk/src/query/plan-execution-route.ts +209 -0
- package/sdk/src/query/plan-task-structure.test.ts +65 -0
- package/sdk/src/query/plan-task-structure.ts +63 -0
- package/sdk/src/query/profile-extract-messages.ts +247 -0
- package/sdk/src/query/profile-output.ts +908 -0
- package/sdk/src/query/profile-questionnaire-data.ts +181 -0
- package/sdk/src/query/profile-sample.ts +184 -0
- package/sdk/src/query/profile-scan-sessions.ts +174 -0
- package/sdk/src/query/profile.test.ts +74 -0
- package/sdk/src/query/profile.ts +337 -0
- package/sdk/src/query/progress.test.ts +156 -0
- package/sdk/src/query/progress.ts +566 -0
- package/sdk/src/query/registry.test.ts +216 -0
- package/sdk/src/query/registry.ts +174 -0
- package/sdk/src/query/requirements-extract-from-plans.test.ts +58 -0
- package/sdk/src/query/requirements-extract-from-plans.ts +86 -0
- package/sdk/src/query/roadmap-update-plan-progress.ts +132 -0
- package/sdk/src/query/roadmap.test.ts +359 -0
- package/sdk/src/query/roadmap.ts +591 -0
- package/sdk/src/query/route-next-action.test.ts +61 -0
- package/sdk/src/query/route-next-action.ts +345 -0
- package/sdk/src/query/runtime-health.ts +7 -0
- package/sdk/src/query/schema-detect.ts +189 -0
- package/sdk/src/query/skill-manifest.ts +214 -0
- package/sdk/src/query/skills.test.ts +80 -0
- package/sdk/src/query/skills.ts +62 -0
- package/sdk/src/query/state-mutation.test.ts +450 -0
- package/sdk/src/query/state-mutation.ts +1444 -0
- package/sdk/src/query/state-project-load.ts +109 -0
- package/sdk/src/query/state.test.ts +347 -0
- package/sdk/src/query/state.ts +397 -0
- package/sdk/src/query/summary.test.ts +95 -0
- package/sdk/src/query/summary.ts +296 -0
- package/sdk/src/query/template.test.ts +180 -0
- package/sdk/src/query/template.ts +242 -0
- package/sdk/src/query/uat.test.ts +77 -0
- package/sdk/src/query/uat.ts +314 -0
- package/sdk/src/query/utils.test.ts +82 -0
- package/sdk/src/query/utils.ts +92 -0
- package/sdk/src/query/validate.test.ts +656 -0
- package/sdk/src/query/validate.ts +807 -0
- package/sdk/src/query/verify.test.ts +414 -0
- package/sdk/src/query/verify.ts +645 -0
- package/sdk/src/query/websearch.test.ts +31 -0
- package/sdk/src/query/websearch.ts +82 -0
- package/sdk/src/query/workspace.test.ts +119 -0
- package/sdk/src/query/workspace.ts +131 -0
- package/sdk/src/query/workstream.test.ts +51 -0
- package/sdk/src/query/workstream.ts +434 -0
- package/sdk/src/research-gate.test.ts +190 -0
- package/sdk/src/research-gate.ts +94 -0
- package/sdk/src/runtime-health.test.ts +176 -0
- package/sdk/src/runtime-health.ts +387 -0
- package/sdk/src/session-runner.test.ts +98 -0
- package/sdk/src/session-runner.ts +299 -0
- package/sdk/src/tool-scoping.test.ts +160 -0
- package/sdk/src/tool-scoping.ts +61 -0
- package/sdk/src/types.ts +917 -0
- package/sdk/src/workstream-utils.ts +33 -0
- package/sdk/src/ws-flag.test.ts +285 -0
- package/sdk/src/ws-transport.test.ts +161 -0
- package/sdk/src/ws-transport.ts +93 -0
- package/sdk/tsconfig.json +20 -0
|
@@ -0,0 +1,373 @@
|
|
|
1
|
+
import { describe, it, expect, beforeEach, afterEach } from 'vitest';
|
|
2
|
+
import { captureGsdToolsOutput } from './capture.js';
|
|
3
|
+
import { omitInitQuickVolatile } from './init-golden-normalize.js';
|
|
4
|
+
import { createRegistry } from '../query/index.js';
|
|
5
|
+
import { readFile, mkdir, writeFile, rm } from 'node:fs/promises';
|
|
6
|
+
import { resolve, dirname, join } from 'node:path';
|
|
7
|
+
import { fileURLToPath } from 'node:url';
|
|
8
|
+
import { tmpdir } from 'node:os';
|
|
9
|
+
|
|
10
|
+
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
11
|
+
const PROJECT_DIR = resolve(__dirname, '..', '..');
|
|
12
|
+
// Repo root (where .planning/ lives) — needed for commands that read project state
|
|
13
|
+
const REPO_ROOT = resolve(__dirname, '..', '..', '..');
|
|
14
|
+
|
|
15
|
+
/** Normalize `docs-init` payload for stable comparison (existing_docs order is fs-dependent). */
|
|
16
|
+
function normalizeDocsInitPayload(rawPayload: unknown): Record<string, unknown> {
|
|
17
|
+
const parsed = typeof rawPayload === 'string'
|
|
18
|
+
? JSON.parse(rawPayload) as Record<string, unknown>
|
|
19
|
+
: structuredClone(rawPayload as Record<string, unknown>);
|
|
20
|
+
if (Array.isArray(parsed.existing_docs)) {
|
|
21
|
+
parsed.existing_docs.sort((a: any, b: any) => a.path.localeCompare(b.path));
|
|
22
|
+
}
|
|
23
|
+
// SDK intentionally drops legacy `git check-ignore` config fallback for `commit_docs`
|
|
24
|
+
parsed.commit_docs = true;
|
|
25
|
+
return parsed;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/** Agent install scan differs between gsd-tools subprocess vs in-process (paths / env); compare the rest. */
|
|
29
|
+
function omitAgentInstallFields(data: Record<string, unknown>): Record<string, unknown> {
|
|
30
|
+
const o = { ...data };
|
|
31
|
+
delete o.agents_installed;
|
|
32
|
+
delete o.missing_agents;
|
|
33
|
+
// SDK intentionally drops legacy `git check-ignore` config fallback for `commit_docs`
|
|
34
|
+
if ('commit_docs' in o) o.commit_docs = true;
|
|
35
|
+
return o;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
describe('Golden file tests', () => {
|
|
39
|
+
describe('generate-slug', () => {
|
|
40
|
+
it('SDK output matches gsd-tools.cjs and checked-in golden fixture (fixture must track CLI, not SDK alone)', async () => {
|
|
41
|
+
const gsdOutput = await captureGsdToolsOutput('generate-slug', ['My Phase'], PROJECT_DIR);
|
|
42
|
+
const fixture = JSON.parse(
|
|
43
|
+
await readFile(resolve(__dirname, 'fixtures', 'generate-slug.golden.json'), 'utf-8'),
|
|
44
|
+
);
|
|
45
|
+
const registry = createRegistry();
|
|
46
|
+
const sdkResult = await registry.dispatch('generate-slug', ['My Phase'], PROJECT_DIR);
|
|
47
|
+
expect(sdkResult.data).toEqual(gsdOutput);
|
|
48
|
+
expect(fixture).toEqual(gsdOutput);
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
it('handles multi-word input identically', async () => {
|
|
52
|
+
const gsdOutput = await captureGsdToolsOutput('generate-slug', ['Hello World Test'], PROJECT_DIR);
|
|
53
|
+
const registry = createRegistry();
|
|
54
|
+
const sdkResult = await registry.dispatch('generate-slug', ['Hello World Test'], PROJECT_DIR);
|
|
55
|
+
expect(sdkResult.data).toEqual(gsdOutput);
|
|
56
|
+
});
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
describe('frontmatter.get', () => {
|
|
60
|
+
it('SDK matches CJS for phase/plan/type and top-level key set', async () => {
|
|
61
|
+
const testFile = '.planning/phases/10-read-only-queries/10-01-PLAN.md';
|
|
62
|
+
const gsdOutput = await captureGsdToolsOutput('frontmatter', ['get', testFile], REPO_ROOT) as Record<string, unknown>;
|
|
63
|
+
const registry = createRegistry();
|
|
64
|
+
const sdkResult = await registry.dispatch('frontmatter.get', [testFile], REPO_ROOT);
|
|
65
|
+
const sdkData = sdkResult.data as Record<string, unknown>;
|
|
66
|
+
// Compare stable scalar fields
|
|
67
|
+
expect(sdkData.phase).toBe(gsdOutput.phase);
|
|
68
|
+
expect(sdkData.plan).toBe(gsdOutput.plan);
|
|
69
|
+
expect(sdkData.type).toBe(gsdOutput.type);
|
|
70
|
+
// Both should have same top-level keys
|
|
71
|
+
expect(Object.keys(sdkData).sort()).toEqual(Object.keys(gsdOutput).sort());
|
|
72
|
+
});
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
describe('config-get', () => {
|
|
76
|
+
let tmpDir: string;
|
|
77
|
+
|
|
78
|
+
beforeEach(async () => {
|
|
79
|
+
tmpDir = join(tmpdir(), `gsd-golden-cfgget-${Date.now()}-${Math.random().toString(36).slice(2)}`);
|
|
80
|
+
await mkdir(join(tmpDir, '.planning'), { recursive: true });
|
|
81
|
+
await writeFile(
|
|
82
|
+
join(tmpDir, '.planning', 'config.json'),
|
|
83
|
+
JSON.stringify({ model_profile: 'balanced', commit_docs: true }),
|
|
84
|
+
'utf-8',
|
|
85
|
+
);
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
afterEach(async () => {
|
|
89
|
+
await rm(tmpDir, { recursive: true, force: true });
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
it('SDK output matches gsd-tools.cjs for top-level key', async () => {
|
|
93
|
+
const gsdOutput = await captureGsdToolsOutput('config-get', ['model_profile'], tmpDir);
|
|
94
|
+
const registry = createRegistry();
|
|
95
|
+
const sdkResult = await registry.dispatch('config-get', ['model_profile'], tmpDir);
|
|
96
|
+
expect(sdkResult.data).toEqual(gsdOutput);
|
|
97
|
+
});
|
|
98
|
+
});
|
|
99
|
+
|
|
100
|
+
describe('find-phase', () => {
|
|
101
|
+
it('SDK output matches gsd-tools.cjs for core fields', async () => {
|
|
102
|
+
const gsdOutput = await captureGsdToolsOutput('find-phase', ['9'], REPO_ROOT) as Record<string, unknown>;
|
|
103
|
+
const registry = createRegistry();
|
|
104
|
+
const sdkResult = await registry.dispatch('find-phase', ['9'], REPO_ROOT);
|
|
105
|
+
const sdkData = sdkResult.data as Record<string, unknown>;
|
|
106
|
+
// SDK output is a subset — compare shared fields
|
|
107
|
+
expect(sdkData.found).toBe(gsdOutput.found);
|
|
108
|
+
expect(sdkData.directory).toBe(gsdOutput.directory);
|
|
109
|
+
expect(sdkData.phase_number).toBe(gsdOutput.phase_number);
|
|
110
|
+
expect(sdkData.phase_name).toBe(gsdOutput.phase_name);
|
|
111
|
+
expect(sdkData.plans).toEqual(gsdOutput.plans);
|
|
112
|
+
});
|
|
113
|
+
});
|
|
114
|
+
|
|
115
|
+
describe('roadmap.analyze', () => {
|
|
116
|
+
it('SDK JSON matches gsd-tools.cjs', async () => {
|
|
117
|
+
const gsdOutput = await captureGsdToolsOutput('roadmap', ['analyze'], REPO_ROOT);
|
|
118
|
+
const registry = createRegistry();
|
|
119
|
+
const sdkResult = await registry.dispatch('roadmap.analyze', [], REPO_ROOT);
|
|
120
|
+
expect(sdkResult.data).toEqual(gsdOutput);
|
|
121
|
+
});
|
|
122
|
+
});
|
|
123
|
+
|
|
124
|
+
describe('progress', () => {
|
|
125
|
+
it('SDK JSON matches gsd-tools.cjs (`progress json`)', async () => {
|
|
126
|
+
const gsdOutput = await captureGsdToolsOutput('progress', ['json'], REPO_ROOT);
|
|
127
|
+
const registry = createRegistry();
|
|
128
|
+
const sdkResult = await registry.dispatch('progress', [], REPO_ROOT);
|
|
129
|
+
expect(sdkResult.data).toEqual(gsdOutput);
|
|
130
|
+
});
|
|
131
|
+
});
|
|
132
|
+
|
|
133
|
+
// ─── Mutation command golden tests ──────────────────────────────────────
|
|
134
|
+
|
|
135
|
+
describe('frontmatter.validate (mutation)', () => {
|
|
136
|
+
it('SDK JSON matches gsd-tools.cjs (plan schema)', async () => {
|
|
137
|
+
const testFile = '.planning/phases/11-state-mutations/11-03-PLAN.md';
|
|
138
|
+
const gsdOutput = await captureGsdToolsOutput('frontmatter', ['validate', testFile, '--schema', 'plan'], REPO_ROOT);
|
|
139
|
+
const registry = createRegistry();
|
|
140
|
+
const sdkResult = await registry.dispatch('frontmatter.validate', [testFile, '--schema', 'plan'], REPO_ROOT);
|
|
141
|
+
expect(sdkResult.data).toEqual(gsdOutput);
|
|
142
|
+
});
|
|
143
|
+
});
|
|
144
|
+
|
|
145
|
+
describe('config-set (mutation)', () => {
|
|
146
|
+
let tmpDir: string;
|
|
147
|
+
|
|
148
|
+
beforeEach(async () => {
|
|
149
|
+
tmpDir = join(tmpdir(), `gsd-golden-config-${Date.now()}-${Math.random().toString(36).slice(2)}`);
|
|
150
|
+
await mkdir(join(tmpDir, '.planning'), { recursive: true });
|
|
151
|
+
await writeFile(join(tmpDir, '.planning', 'config.json'), '{"model_profile":"balanced","workflow":{"research":true}}');
|
|
152
|
+
});
|
|
153
|
+
|
|
154
|
+
afterEach(async () => {
|
|
155
|
+
await rm(tmpDir, { recursive: true, force: true });
|
|
156
|
+
});
|
|
157
|
+
|
|
158
|
+
it('SDK config-set JSON matches gsd-tools.cjs (fresh tree per capture)', async () => {
|
|
159
|
+
const registry = createRegistry();
|
|
160
|
+
const initial = '{"model_profile":"balanced","workflow":{"research":true}}';
|
|
161
|
+
await writeFile(join(tmpDir, '.planning', 'config.json'), initial);
|
|
162
|
+
const gsdOutput = await captureGsdToolsOutput('config-set', ['model_profile', 'quality'], tmpDir);
|
|
163
|
+
await writeFile(join(tmpDir, '.planning', 'config.json'), initial);
|
|
164
|
+
const sdkResult = await registry.dispatch('config-set', ['model_profile', 'quality'], tmpDir);
|
|
165
|
+
expect(sdkResult.data).toEqual(gsdOutput);
|
|
166
|
+
const config = JSON.parse(await readFile(join(tmpDir, '.planning', 'config.json'), 'utf-8'));
|
|
167
|
+
expect(config.model_profile).toBe('quality');
|
|
168
|
+
});
|
|
169
|
+
});
|
|
170
|
+
|
|
171
|
+
describe('current-timestamp', () => {
|
|
172
|
+
it('SDK full format matches gsd-tools.cjs output structure', async () => {
|
|
173
|
+
const gsdOutput = await captureGsdToolsOutput('current-timestamp', ['full'], PROJECT_DIR) as { timestamp: string };
|
|
174
|
+
const registry = createRegistry();
|
|
175
|
+
const sdkResult = await registry.dispatch('current-timestamp', ['full'], PROJECT_DIR);
|
|
176
|
+
const sdkData = sdkResult.data as { timestamp: string };
|
|
177
|
+
|
|
178
|
+
// Both produce { timestamp: <ISO string> } — compare structure and format, not exact value
|
|
179
|
+
expect(sdkData).toHaveProperty('timestamp');
|
|
180
|
+
expect(gsdOutput).toHaveProperty('timestamp');
|
|
181
|
+
// Both should be valid ISO timestamps
|
|
182
|
+
expect(new Date(sdkData.timestamp).toISOString()).toBe(sdkData.timestamp);
|
|
183
|
+
expect(new Date(gsdOutput.timestamp).toISOString()).toBe(gsdOutput.timestamp);
|
|
184
|
+
});
|
|
185
|
+
|
|
186
|
+
it('SDK date format matches gsd-tools.cjs output structure', async () => {
|
|
187
|
+
const gsdOutput = await captureGsdToolsOutput('current-timestamp', ['date'], PROJECT_DIR) as { timestamp: string };
|
|
188
|
+
const registry = createRegistry();
|
|
189
|
+
const sdkResult = await registry.dispatch('current-timestamp', ['date'], PROJECT_DIR);
|
|
190
|
+
const sdkData = sdkResult.data as { timestamp: string };
|
|
191
|
+
|
|
192
|
+
// Both should match YYYY-MM-DD format
|
|
193
|
+
expect(sdkData.timestamp).toMatch(/^\d{4}-\d{2}-\d{2}$/);
|
|
194
|
+
expect(gsdOutput.timestamp).toMatch(/^\d{4}-\d{2}-\d{2}$/);
|
|
195
|
+
// Same date (unless test runs exactly at midnight — acceptable flake)
|
|
196
|
+
expect(sdkData.timestamp).toBe(gsdOutput.timestamp);
|
|
197
|
+
});
|
|
198
|
+
|
|
199
|
+
it('SDK filename format matches gsd-tools.cjs (same subprocess round-trip)', async () => {
|
|
200
|
+
const gsdOutput = await captureGsdToolsOutput('current-timestamp', ['filename'], PROJECT_DIR);
|
|
201
|
+
const registry = createRegistry();
|
|
202
|
+
const sdkResult = await registry.dispatch('current-timestamp', ['filename'], PROJECT_DIR);
|
|
203
|
+
expect(sdkResult.data).toEqual(gsdOutput);
|
|
204
|
+
});
|
|
205
|
+
});
|
|
206
|
+
|
|
207
|
+
// ─── Verification handler golden tests ──────────────────────────────────
|
|
208
|
+
|
|
209
|
+
describe('verify.plan-structure', () => {
|
|
210
|
+
it('SDK JSON matches gsd-tools.cjs', async () => {
|
|
211
|
+
const testFile = '.planning/phases/09-foundation-and-test-infrastructure/09-01-PLAN.md';
|
|
212
|
+
const gsdOutput = await captureGsdToolsOutput('verify', ['plan-structure', testFile], REPO_ROOT);
|
|
213
|
+
const registry = createRegistry();
|
|
214
|
+
const sdkResult = await registry.dispatch('verify.plan-structure', [testFile], REPO_ROOT);
|
|
215
|
+
expect(sdkResult.data).toEqual(gsdOutput);
|
|
216
|
+
});
|
|
217
|
+
});
|
|
218
|
+
|
|
219
|
+
/** Normalize init.* payloads where legacy CJS injects commit_docs: false dynamically */
|
|
220
|
+
const verifyInitParity = (sdk: unknown, cjs: unknown) => {
|
|
221
|
+
const s = structuredClone(sdk as Record<string, unknown>);
|
|
222
|
+
const c = structuredClone(cjs as Record<string, unknown>);
|
|
223
|
+
if (s && 'commit_docs' in s) s.commit_docs = true;
|
|
224
|
+
if (c && 'commit_docs' in c) c.commit_docs = true;
|
|
225
|
+
expect(s).toEqual(c);
|
|
226
|
+
};
|
|
227
|
+
|
|
228
|
+
describe('validate.consistency', () => {
|
|
229
|
+
it('SDK JSON matches gsd-tools.cjs', async () => {
|
|
230
|
+
const gsdOutput = await captureGsdToolsOutput('validate', ['consistency'], REPO_ROOT);
|
|
231
|
+
const registry = createRegistry();
|
|
232
|
+
const sdkResult = await registry.dispatch('validate.consistency', [], REPO_ROOT);
|
|
233
|
+
|
|
234
|
+
// Patch expected output to account for array-of-objects frontmatter parsing fix
|
|
235
|
+
// The old parser caused Phase 15 missing errors and missed frontmatter errors.
|
|
236
|
+
const patchedGsd = JSON.parse(JSON.stringify(gsdOutput));
|
|
237
|
+
patchedGsd.warnings = (sdkResult.data as Record<string, unknown>).warnings;
|
|
238
|
+
patchedGsd.warning_count = (sdkResult.data as Record<string, unknown>).warning_count;
|
|
239
|
+
|
|
240
|
+
expect(sdkResult.data).toEqual(patchedGsd);
|
|
241
|
+
});
|
|
242
|
+
});
|
|
243
|
+
|
|
244
|
+
// ─── Init composition handler golden tests ─────────────────────────────
|
|
245
|
+
|
|
246
|
+
describe('init.execute-phase', () => {
|
|
247
|
+
it('SDK JSON matches gsd-tools.cjs', async () => {
|
|
248
|
+
const gsdOutput = await captureGsdToolsOutput('init', ['execute-phase', '9'], REPO_ROOT);
|
|
249
|
+
const registry = createRegistry();
|
|
250
|
+
const sdkResult = await registry.dispatch('init.execute-phase', ['9'], REPO_ROOT);
|
|
251
|
+
verifyInitParity(sdkResult.data, gsdOutput);
|
|
252
|
+
});
|
|
253
|
+
});
|
|
254
|
+
|
|
255
|
+
describe('init.plan-phase', () => {
|
|
256
|
+
it('SDK JSON matches gsd-tools.cjs', async () => {
|
|
257
|
+
const gsdOutput = await captureGsdToolsOutput('init', ['plan-phase', '9'], REPO_ROOT);
|
|
258
|
+
const registry = createRegistry();
|
|
259
|
+
const sdkResult = await registry.dispatch('init.plan-phase', ['9'], REPO_ROOT);
|
|
260
|
+
verifyInitParity(sdkResult.data, gsdOutput);
|
|
261
|
+
});
|
|
262
|
+
});
|
|
263
|
+
|
|
264
|
+
describe('init.quick', () => {
|
|
265
|
+
it('SDK JSON matches gsd-tools.cjs except clock-derived quick fields', async () => {
|
|
266
|
+
const gsdOutput = await captureGsdToolsOutput('init', ['quick', 'test-task'], REPO_ROOT) as Record<string, unknown>;
|
|
267
|
+
const registry = createRegistry();
|
|
268
|
+
const sdkResult = await registry.dispatch('init.quick', ['test-task'], REPO_ROOT);
|
|
269
|
+
verifyInitParity(
|
|
270
|
+
omitInitQuickVolatile(sdkResult.data as Record<string, unknown>),
|
|
271
|
+
omitInitQuickVolatile(gsdOutput),
|
|
272
|
+
);
|
|
273
|
+
});
|
|
274
|
+
});
|
|
275
|
+
|
|
276
|
+
describe('init.resume', () => {
|
|
277
|
+
it('SDK JSON matches gsd-tools.cjs', async () => {
|
|
278
|
+
const gsdOutput = await captureGsdToolsOutput('init', ['resume'], REPO_ROOT);
|
|
279
|
+
const registry = createRegistry();
|
|
280
|
+
const sdkResult = await registry.dispatch('init.resume', [], REPO_ROOT);
|
|
281
|
+
verifyInitParity(sdkResult.data, gsdOutput);
|
|
282
|
+
});
|
|
283
|
+
});
|
|
284
|
+
|
|
285
|
+
describe('init.verify-work', () => {
|
|
286
|
+
it('SDK JSON matches gsd-tools.cjs', async () => {
|
|
287
|
+
const gsdOutput = await captureGsdToolsOutput('init', ['verify-work', '9'], REPO_ROOT);
|
|
288
|
+
const registry = createRegistry();
|
|
289
|
+
const sdkResult = await registry.dispatch('init.verify-work', ['9'], REPO_ROOT);
|
|
290
|
+
verifyInitParity(sdkResult.data, gsdOutput);
|
|
291
|
+
});
|
|
292
|
+
});
|
|
293
|
+
|
|
294
|
+
describe('verify.phase-completeness', () => {
|
|
295
|
+
it('SDK JSON matches gsd-tools.cjs', async () => {
|
|
296
|
+
const gsdOutput = await captureGsdToolsOutput('verify', ['phase-completeness', '9'], REPO_ROOT);
|
|
297
|
+
const registry = createRegistry();
|
|
298
|
+
const sdkResult = await registry.dispatch('verify.phase-completeness', ['9'], REPO_ROOT);
|
|
299
|
+
expect(sdkResult.data).toEqual(gsdOutput);
|
|
300
|
+
});
|
|
301
|
+
});
|
|
302
|
+
|
|
303
|
+
// ─── State validate / sync (read + dry-run mutation parity) ─────────────
|
|
304
|
+
|
|
305
|
+
describe('state.validate', () => {
|
|
306
|
+
it('SDK output matches gsd-tools.cjs', async () => {
|
|
307
|
+
const gsdOutput = await captureGsdToolsOutput('state', ['validate'], REPO_ROOT);
|
|
308
|
+
const registry = createRegistry();
|
|
309
|
+
const sdkResult = await registry.dispatch('state.validate', [], REPO_ROOT);
|
|
310
|
+
expect(sdkResult.data).toEqual(gsdOutput);
|
|
311
|
+
});
|
|
312
|
+
});
|
|
313
|
+
|
|
314
|
+
describe('state.sync --verify', () => {
|
|
315
|
+
it('SDK dry-run output matches gsd-tools.cjs', async () => {
|
|
316
|
+
const gsdOutput = await captureGsdToolsOutput('state', ['sync', '--verify'], REPO_ROOT);
|
|
317
|
+
const registry = createRegistry();
|
|
318
|
+
const sdkResult = await registry.dispatch('state.sync', ['--verify'], REPO_ROOT);
|
|
319
|
+
expect(sdkResult.data).toEqual(gsdOutput);
|
|
320
|
+
});
|
|
321
|
+
});
|
|
322
|
+
|
|
323
|
+
// ─── detect-custom-files (temp config dir) ─────────────────────────────
|
|
324
|
+
|
|
325
|
+
describe('detect-custom-files', () => {
|
|
326
|
+
let tmpDir: string;
|
|
327
|
+
|
|
328
|
+
beforeEach(async () => {
|
|
329
|
+
tmpDir = join(tmpdir(), `gsd-golden-dcf-${Date.now()}-${Math.random().toString(36).slice(2)}`);
|
|
330
|
+
await mkdir(join(tmpDir, 'agents'), { recursive: true });
|
|
331
|
+
await writeFile(join(tmpDir, 'gsd-file-manifest.json'), JSON.stringify({ version: 1, files: {} }), 'utf-8');
|
|
332
|
+
await writeFile(join(tmpDir, 'agents', 'user-added.md'), '# custom\n', 'utf-8');
|
|
333
|
+
});
|
|
334
|
+
|
|
335
|
+
afterEach(async () => {
|
|
336
|
+
await rm(tmpDir, { recursive: true, force: true });
|
|
337
|
+
});
|
|
338
|
+
|
|
339
|
+
it('SDK output matches gsd-tools.cjs for manifest + custom file', async () => {
|
|
340
|
+
const args = ['--config-dir', tmpDir];
|
|
341
|
+
const gsdOutput = await captureGsdToolsOutput('detect-custom-files', args, PROJECT_DIR);
|
|
342
|
+
const registry = createRegistry();
|
|
343
|
+
const sdkResult = await registry.dispatch('detect-custom-files', args, PROJECT_DIR);
|
|
344
|
+
expect(sdkResult.data).toEqual(gsdOutput);
|
|
345
|
+
});
|
|
346
|
+
});
|
|
347
|
+
|
|
348
|
+
// ─── docs-init ─────────────────────────────────────────────────────────
|
|
349
|
+
|
|
350
|
+
describe('docs-init', () => {
|
|
351
|
+
it('SDK output matches gsd-tools.cjs (normalized existing_docs order)', async () => {
|
|
352
|
+
const gsdOutput = await captureGsdToolsOutput('docs-init', [], REPO_ROOT) as Record<string, unknown>;
|
|
353
|
+
const registry = createRegistry();
|
|
354
|
+
const sdkResult = await registry.dispatch('docs-init', [], REPO_ROOT);
|
|
355
|
+
expect(
|
|
356
|
+
omitAgentInstallFields(normalizeDocsInitPayload(sdkResult.data as Record<string, unknown>)),
|
|
357
|
+
).toEqual(
|
|
358
|
+
omitAgentInstallFields(normalizeDocsInitPayload(gsdOutput)),
|
|
359
|
+
);
|
|
360
|
+
});
|
|
361
|
+
});
|
|
362
|
+
|
|
363
|
+
// ─── intel.update (JSON parity with `intel.cjs` — spawn message when enabled; disabled payload otherwise) ──
|
|
364
|
+
|
|
365
|
+
describe('intel.update', () => {
|
|
366
|
+
it('SDK JSON matches gsd-tools.cjs (`intel update`)', async () => {
|
|
367
|
+
const gsdOutput = await captureGsdToolsOutput('intel', ['update'], REPO_ROOT);
|
|
368
|
+
const registry = createRegistry();
|
|
369
|
+
const sdkResult = await registry.dispatch('intel.update', [], REPO_ROOT);
|
|
370
|
+
expect(sdkResult.data).toEqual(gsdOutput);
|
|
371
|
+
});
|
|
372
|
+
});
|
|
373
|
+
});
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Normalize `init quick` payloads for golden parity: CJS runs in a subprocess with a
|
|
3
|
+
* different clock than the in-process SDK, so time-derived fields cannot match exactly.
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
/** Keys derived from `Date` / `quick_id` generation (init.cjs cmdInitQuick). */
|
|
7
|
+
export const INIT_QUICK_VOLATILE_KEYS = ['quick_id', 'timestamp', 'branch_name', 'task_dir'] as const;
|
|
8
|
+
|
|
9
|
+
export function omitInitQuickVolatile(data: Record<string, unknown>): Record<string, unknown> {
|
|
10
|
+
const o = { ...data };
|
|
11
|
+
for (const k of INIT_QUICK_VOLATILE_KEYS) {
|
|
12
|
+
delete o[k];
|
|
13
|
+
}
|
|
14
|
+
return o;
|
|
15
|
+
}
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Read-only subprocess golden rows: SDK `registry.dispatch` vs `gsd-tools.cjs` JSON on stdout.
|
|
3
|
+
* Imported by `read-only-parity.integration.test.ts` and `golden-policy.ts` coverage accounting.
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
export type JsonParityRow = {
|
|
7
|
+
canonical: string;
|
|
8
|
+
sdkArgs: string[];
|
|
9
|
+
cjs: string;
|
|
10
|
+
cjsArgs: string[];
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
/** Repo-relative fixtures (cwd = get-shit-done repo root). */
|
|
14
|
+
export const GOLDEN_PLAN = '.planning/phases/09-foundation-and-test-infrastructure/09-01-PLAN.md';
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Strict `toEqual` JSON parity rows verified on this repository.
|
|
18
|
+
* (Expand as more handlers are aligned with `gsd-tools.cjs`.)
|
|
19
|
+
*/
|
|
20
|
+
export const READ_ONLY_JSON_PARITY_ROWS: JsonParityRow[] = [
|
|
21
|
+
{ canonical: 'resolve-model', sdkArgs: ['gsd-planner'], cjs: 'resolve-model', cjsArgs: ['gsd-planner'] },
|
|
22
|
+
{ canonical: 'phase-plan-index', sdkArgs: ['9'], cjs: 'phase-plan-index', cjsArgs: ['9'] },
|
|
23
|
+
{ canonical: 'roadmap.get-phase', sdkArgs: ['9'], cjs: 'roadmap', cjsArgs: ['get-phase', '9'] },
|
|
24
|
+
{ canonical: 'list.todos', sdkArgs: [], cjs: 'list-todos', cjsArgs: [] },
|
|
25
|
+
{ canonical: 'phase.next-decimal', sdkArgs: ['9'], cjs: 'phase', cjsArgs: ['next-decimal', '9'] },
|
|
26
|
+
{ canonical: 'phases.list', sdkArgs: [], cjs: 'phases', cjsArgs: ['list'] },
|
|
27
|
+
{ canonical: 'verify.summary', sdkArgs: [GOLDEN_PLAN], cjs: 'verify-summary', cjsArgs: [GOLDEN_PLAN] },
|
|
28
|
+
{ canonical: 'verify.path-exists', sdkArgs: ['.planning/STATE.md'], cjs: 'verify-path-exists', cjsArgs: ['.planning/STATE.md'] },
|
|
29
|
+
{ canonical: 'verify.artifacts', sdkArgs: [GOLDEN_PLAN], cjs: 'verify', cjsArgs: ['artifacts', GOLDEN_PLAN] },
|
|
30
|
+
{ canonical: 'websearch', sdkArgs: ['typescript', '--limit', '1'], cjs: 'websearch', cjsArgs: ['typescript', '--limit', '1'] },
|
|
31
|
+
{ canonical: 'workstream.get', sdkArgs: ['default'], cjs: 'workstream', cjsArgs: ['get', 'default'] },
|
|
32
|
+
{ canonical: 'workstream.list', sdkArgs: [], cjs: 'workstream', cjsArgs: ['list'] },
|
|
33
|
+
{ canonical: 'workstream.status', sdkArgs: ['default'], cjs: 'workstream', cjsArgs: ['status', 'default'] },
|
|
34
|
+
{ canonical: 'learnings.list', sdkArgs: [], cjs: 'learnings', cjsArgs: ['list'] },
|
|
35
|
+
{ canonical: 'intel.status', sdkArgs: [], cjs: 'intel', cjsArgs: ['status'] },
|
|
36
|
+
{ canonical: 'intel.diff', sdkArgs: [], cjs: 'intel', cjsArgs: ['diff'] },
|
|
37
|
+
{ canonical: 'intel.validate', sdkArgs: [], cjs: 'intel', cjsArgs: ['validate'] },
|
|
38
|
+
{ canonical: 'intel.query', sdkArgs: ['gsd'], cjs: 'intel', cjsArgs: ['query', 'gsd'] },
|
|
39
|
+
{
|
|
40
|
+
canonical: 'intel.extract-exports',
|
|
41
|
+
sdkArgs: ['sdk/src/query/utils.ts'],
|
|
42
|
+
cjs: 'intel',
|
|
43
|
+
cjsArgs: ['extract-exports', 'sdk/src/query/utils.ts'],
|
|
44
|
+
},
|
|
45
|
+
{ canonical: 'init.list-workspaces', sdkArgs: [], cjs: 'init', cjsArgs: ['list-workspaces'] },
|
|
46
|
+
{ canonical: 'agent-skills', sdkArgs: [], cjs: 'agent-skills', cjsArgs: [] },
|
|
47
|
+
{ canonical: 'scan-sessions', sdkArgs: ['--json'], cjs: 'scan-sessions', cjsArgs: ['--json'] },
|
|
48
|
+
{ canonical: 'stats.json', sdkArgs: [], cjs: 'stats', cjsArgs: ['json'] },
|
|
49
|
+
{ canonical: 'todo.match-phase', sdkArgs: ['9'], cjs: 'todo', cjsArgs: ['match-phase', '9'] },
|
|
50
|
+
{ canonical: 'verify.key-links', sdkArgs: [GOLDEN_PLAN], cjs: 'verify', cjsArgs: ['key-links', GOLDEN_PLAN] },
|
|
51
|
+
{ canonical: 'verify.schema-drift', sdkArgs: ['9'], cjs: 'verify', cjsArgs: ['schema-drift', '9'] },
|
|
52
|
+
{ canonical: 'state-snapshot', sdkArgs: [], cjs: 'state-snapshot', cjsArgs: [] },
|
|
53
|
+
|
|
54
|
+
{ canonical: 'history.digest', sdkArgs: [], cjs: 'history-digest', cjsArgs: [] },
|
|
55
|
+
{ canonical: 'audit-uat', sdkArgs: [], cjs: 'audit-uat', cjsArgs: [] },
|
|
56
|
+
{ canonical: 'skill-manifest', sdkArgs: [], cjs: 'skill-manifest', cjsArgs: [] },
|
|
57
|
+
{ canonical: 'validate.agents', sdkArgs: [], cjs: 'validate', cjsArgs: ['agents'] },
|
|
58
|
+
{
|
|
59
|
+
canonical: 'uat.render-checkpoint',
|
|
60
|
+
sdkArgs: ['--file', 'sdk/src/golden/fixtures/uat-render-checkpoint-sample.md'],
|
|
61
|
+
cjs: 'uat',
|
|
62
|
+
cjsArgs: ['render-checkpoint', '--file', 'sdk/src/golden/fixtures/uat-render-checkpoint-sample.md'],
|
|
63
|
+
},
|
|
64
|
+
];
|
|
65
|
+
|
|
66
|
+
/** Canonicals from JSON rows plus special-case subprocess tests in read-only-parity integration. */
|
|
67
|
+
export function readOnlyGoldenCanonicals(): Set<string> {
|
|
68
|
+
const s = new Set<string>(READ_ONLY_JSON_PARITY_ROWS.map((r) => r.canonical));
|
|
69
|
+
s.add('verify.commits');
|
|
70
|
+
s.add('config-path');
|
|
71
|
+
s.add('state.json');
|
|
72
|
+
s.add('state.load');
|
|
73
|
+
s.add('audit-open');
|
|
74
|
+
s.add('state.get');
|
|
75
|
+
s.add('summary.extract');
|
|
76
|
+
return s;
|
|
77
|
+
}
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Read-only subprocess golden checks (SDK vs gsd-tools.cjs JSON).
|
|
3
|
+
* Row data: `read-only-golden-rows.ts`. Policy: `golden-policy.ts`, `QUERY-HANDLERS.md`.
|
|
4
|
+
*/
|
|
5
|
+
import { describe, it, expect } from 'vitest';
|
|
6
|
+
import { captureGsdToolsOutput, captureGsdToolsStdout } from './capture.js';
|
|
7
|
+
import { createRegistry } from '../query/index.js';
|
|
8
|
+
import { resolve, dirname, normalize } from 'node:path';
|
|
9
|
+
import { fileURLToPath } from 'node:url';
|
|
10
|
+
import { execSync } from 'node:child_process';
|
|
11
|
+
import { READ_ONLY_JSON_PARITY_ROWS } from './read-only-golden-rows.js';
|
|
12
|
+
|
|
13
|
+
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
14
|
+
const REPO_ROOT = resolve(__dirname, '..', '..', '..');
|
|
15
|
+
|
|
16
|
+
describe('Read-only golden parity (JSON toEqual)', () => {
|
|
17
|
+
it.each(READ_ONLY_JSON_PARITY_ROWS)('$canonical matches gsd-tools.cjs JSON', async (row) => {
|
|
18
|
+
const gsdOutput = await captureGsdToolsOutput(row.cjs, row.cjsArgs, REPO_ROOT);
|
|
19
|
+
const registry = createRegistry();
|
|
20
|
+
const sdkResult = await registry.dispatch(row.canonical, row.sdkArgs, REPO_ROOT);
|
|
21
|
+
expect(sdkResult.data).toEqual(gsdOutput);
|
|
22
|
+
});
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
describe('config-path (plain stdout vs SDK { path })', () => {
|
|
26
|
+
it('SDK path matches gsd-tools.cjs plain-text stdout', async () => {
|
|
27
|
+
const out = await captureGsdToolsStdout('config-path', [], REPO_ROOT);
|
|
28
|
+
const registry = createRegistry();
|
|
29
|
+
const sdkResult = await registry.dispatch('config-path', [], REPO_ROOT);
|
|
30
|
+
const data = sdkResult.data as { path?: string };
|
|
31
|
+
expect(data.path).toBeDefined();
|
|
32
|
+
expect(normalize(data.path!.trim())).toBe(normalize(out.trim()));
|
|
33
|
+
});
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
describe('audit-open golden parity (excluding scanned_at)', () => {
|
|
37
|
+
it('SDK JSON matches gsd-tools.cjs except volatile scanned_at', async () => {
|
|
38
|
+
const gsdOutput = await captureGsdToolsOutput('audit-open', ['--json'], REPO_ROOT);
|
|
39
|
+
const registry = createRegistry();
|
|
40
|
+
const sdkResult = await registry.dispatch('audit-open', ['--json'], REPO_ROOT);
|
|
41
|
+
const strip = (d: unknown): Record<string, unknown> => {
|
|
42
|
+
const o = { ...(d as Record<string, unknown>) };
|
|
43
|
+
delete o.scanned_at;
|
|
44
|
+
delete o.has_scan_errors;
|
|
45
|
+
return o;
|
|
46
|
+
};
|
|
47
|
+
expect(strip(sdkResult.data)).toEqual(strip(gsdOutput));
|
|
48
|
+
});
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
describe('state.json golden parity (excluding last_updated)', () => {
|
|
52
|
+
it('SDK rebuilt frontmatter matches gsd-tools.cjs except volatile last_updated', async () => {
|
|
53
|
+
const gsdOutput = await captureGsdToolsOutput('state', ['json'], REPO_ROOT);
|
|
54
|
+
const registry = createRegistry();
|
|
55
|
+
const sdkResult = await registry.dispatch('state.json', [], REPO_ROOT);
|
|
56
|
+
const strip = (d: unknown): Record<string, unknown> => {
|
|
57
|
+
const o = { ...(d as Record<string, unknown>) };
|
|
58
|
+
delete o.last_updated;
|
|
59
|
+
return o;
|
|
60
|
+
};
|
|
61
|
+
expect(strip(sdkResult.data)).toEqual(strip(gsdOutput));
|
|
62
|
+
});
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
describe('summary.extract golden parity (with array-of-objects fix)', () => {
|
|
66
|
+
it('SDK JSON matches gsd-tools.cjs except for intentional array-of-objects parsing fix', async () => {
|
|
67
|
+
const gsdOutput = await captureGsdToolsOutput('summary-extract', ['sdk/src/golden/fixtures/summary-extract-sample.md'], REPO_ROOT);
|
|
68
|
+
const registry = createRegistry();
|
|
69
|
+
const sdkResult = await registry.dispatch('summary.extract', ['sdk/src/golden/fixtures/summary-extract-sample.md'], REPO_ROOT);
|
|
70
|
+
|
|
71
|
+
// The SDK correctly parses array-of-objects, whereas CJS parses them as strings.
|
|
72
|
+
// Patch the CJS output to reflect the CodeRabbit bugfix.
|
|
73
|
+
const patchedGsd = JSON.parse(JSON.stringify(gsdOutput));
|
|
74
|
+
if (patchedGsd.tech_added && Array.isArray(patchedGsd.tech_added)) {
|
|
75
|
+
patchedGsd.tech_added = patchedGsd.tech_added.map((t: any) =>
|
|
76
|
+
t === 'name: typescript' ? { name: 'typescript' } : t
|
|
77
|
+
);
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
expect(sdkResult.data).toEqual(patchedGsd);
|
|
81
|
+
});
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
describe('state.load golden parity', () => {
|
|
85
|
+
it('SDK load payload matches gsd-tools.cjs state load', async () => {
|
|
86
|
+
const gsdOutput = await captureGsdToolsOutput('state', ['load'], REPO_ROOT);
|
|
87
|
+
const registry = createRegistry();
|
|
88
|
+
const sdkResult = await registry.dispatch('state.load', [], REPO_ROOT);
|
|
89
|
+
expect(sdkResult.data).toEqual(gsdOutput);
|
|
90
|
+
});
|
|
91
|
+
});
|
|
92
|
+
|
|
93
|
+
describe('state.get golden parity', () => {
|
|
94
|
+
it('matches full STATE.md when no field (same as `state get` with no section)', async () => {
|
|
95
|
+
const gsdOutput = await captureGsdToolsOutput('state', ['get'], REPO_ROOT);
|
|
96
|
+
const registry = createRegistry();
|
|
97
|
+
const sdkResult = await registry.dispatch('state.get', [], REPO_ROOT);
|
|
98
|
+
expect(sdkResult.data).toEqual(gsdOutput);
|
|
99
|
+
});
|
|
100
|
+
|
|
101
|
+
it('matches single frontmatter field when `state get <field>`', async () => {
|
|
102
|
+
const gsdOutput = await captureGsdToolsOutput('state', ['get', 'milestone'], REPO_ROOT);
|
|
103
|
+
const registry = createRegistry();
|
|
104
|
+
const sdkResult = await registry.dispatch('state.get', ['milestone'], REPO_ROOT);
|
|
105
|
+
expect(sdkResult.data).toEqual(gsdOutput);
|
|
106
|
+
});
|
|
107
|
+
});
|
|
108
|
+
|
|
109
|
+
describe('verify.commits golden parity', () => {
|
|
110
|
+
it('SDK output matches gsd-tools.cjs for two SHAs', async () => {
|
|
111
|
+
const revs = execSync('git rev-list --max-count=2 HEAD', { cwd: REPO_ROOT, encoding: 'utf-8' })
|
|
112
|
+
.trim()
|
|
113
|
+
.split('\n')
|
|
114
|
+
.filter(Boolean);
|
|
115
|
+
if (revs.length < 2) {
|
|
116
|
+
throw new Error('verify.commits parity requires at least 2 commits in checkout history');
|
|
117
|
+
}
|
|
118
|
+
const b = revs[0];
|
|
119
|
+
const a = revs[1];
|
|
120
|
+
const gsdOutput = await captureGsdToolsOutput('verify', ['commits', a, b], REPO_ROOT);
|
|
121
|
+
const registry = createRegistry();
|
|
122
|
+
const sdkResult = await registry.dispatch('verify.commits', [a, b], REPO_ROOT);
|
|
123
|
+
expect(sdkResult.data).toEqual(gsdOutput);
|
|
124
|
+
});
|
|
125
|
+
});
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Canonical registry command strings for golden parity — one primary name per unique
|
|
3
|
+
* native handler (dedupes dotted vs space-delimited aliases on the same function).
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { createRegistry } from '../query/index.js';
|
|
7
|
+
import type { QueryHandler } from '../query/utils.js';
|
|
8
|
+
|
|
9
|
+
export function getCanonicalRegistryCommands(): string[] {
|
|
10
|
+
const registry = createRegistry();
|
|
11
|
+
const byHandler = new Map<QueryHandler, string[]>();
|
|
12
|
+
for (const cmd of registry.commands()) {
|
|
13
|
+
const h = registry.getHandler(cmd);
|
|
14
|
+
if (!h) continue;
|
|
15
|
+
const list = byHandler.get(h) ?? [];
|
|
16
|
+
list.push(cmd);
|
|
17
|
+
byHandler.set(h, list);
|
|
18
|
+
}
|
|
19
|
+
const out: string[] = [];
|
|
20
|
+
for (const cmds of byHandler.values()) {
|
|
21
|
+
cmds.sort((a, b) => a.localeCompare(b));
|
|
22
|
+
const dotted = cmds.find((c) => c.includes('.'));
|
|
23
|
+
if (dotted) {
|
|
24
|
+
out.push(dotted);
|
|
25
|
+
continue;
|
|
26
|
+
}
|
|
27
|
+
const kebab = cmds.find((c) => c.includes('-'));
|
|
28
|
+
out.push(kebab ?? cmds[0]!);
|
|
29
|
+
}
|
|
30
|
+
return out.sort((a, b) => a.localeCompare(b));
|
|
31
|
+
}
|