@therocketcode/gsd-core 1.4.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/.claude-plugin/plugin.json +23 -0
- package/GEMINI.md +53 -0
- package/LICENSE +21 -0
- package/README.ja-JP.md +125 -0
- package/README.ko-KR.md +125 -0
- package/README.md +144 -0
- package/README.pt-BR.md +125 -0
- package/README.zh-CN.md +125 -0
- package/agents/gsd-advisor-researcher.md +108 -0
- package/agents/gsd-ai-researcher.md +114 -0
- package/agents/gsd-assumptions-analyzer.md +105 -0
- package/agents/gsd-code-fixer.md +668 -0
- package/agents/gsd-code-reviewer.md +387 -0
- package/agents/gsd-codebase-mapper.md +853 -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 +616 -0
- package/agents/gsd-domain-researcher.md +147 -0
- package/agents/gsd-eval-auditor.md +191 -0
- package/agents/gsd-eval-planner.md +154 -0
- package/agents/gsd-executor.md +785 -0
- package/agents/gsd-framework-selector.md +160 -0
- package/agents/gsd-integration-checker.md +470 -0
- package/agents/gsd-intel-updater.md +342 -0
- package/agents/gsd-nyquist-auditor.md +203 -0
- package/agents/gsd-pattern-mapper.md +335 -0
- package/agents/gsd-phase-researcher.md +867 -0
- package/agents/gsd-plan-checker.md +978 -0
- package/agents/gsd-planner.md +1204 -0
- package/agents/gsd-project-researcher.md +611 -0
- package/agents/gsd-research-synthesizer.md +259 -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 +374 -0
- package/agents/gsd-user-profiler.md +171 -0
- package/agents/gsd-verifier.md +923 -0
- package/assets/gsd-logo-2000-transparent.png +0 -0
- package/assets/gsd-logo-2000-transparent.svg +17 -0
- package/assets/gsd-logo-2000.png +0 -0
- package/assets/gsd-logo-2000.svg +21 -0
- package/assets/terminal.svg +68 -0
- package/bin/install.js +12726 -0
- package/bin/lib/ui-safety-gate.cjs +107 -0
- package/commands/gsd/add-tests.md +42 -0
- package/commands/gsd/ai-integration-phase.md +37 -0
- package/commands/gsd/audit-fix.md +34 -0
- package/commands/gsd/audit-milestone.md +37 -0
- package/commands/gsd/audit-uat.md +24 -0
- package/commands/gsd/autonomous.md +48 -0
- package/commands/gsd/capture.md +62 -0
- package/commands/gsd/cleanup.md +24 -0
- package/commands/gsd/code-review.md +59 -0
- package/commands/gsd/complete-milestone.md +143 -0
- package/commands/gsd/config.md +56 -0
- package/commands/gsd/debug.md +52 -0
- package/commands/gsd/discover-product.md +65 -0
- package/commands/gsd/discuss-phase.md +77 -0
- package/commands/gsd/docs-update.md +49 -0
- package/commands/gsd/eval-review.md +33 -0
- package/commands/gsd/execute-phase.md +66 -0
- package/commands/gsd/explore.md +27 -0
- package/commands/gsd/extract-learnings.md +23 -0
- package/commands/gsd/fast.md +31 -0
- package/commands/gsd/forensics.md +57 -0
- package/commands/gsd/graphify.md +204 -0
- package/commands/gsd/health.md +31 -0
- package/commands/gsd/help.md +28 -0
- package/commands/gsd/import.md +45 -0
- package/commands/gsd/inbox.md +39 -0
- package/commands/gsd/ingest-docs.md +42 -0
- package/commands/gsd/manager.md +45 -0
- package/commands/gsd/map-codebase.md +83 -0
- package/commands/gsd/milestone-summary.md +51 -0
- package/commands/gsd/model-domain.md +65 -0
- package/commands/gsd/mvp-phase.md +45 -0
- package/commands/gsd/new-milestone.md +45 -0
- package/commands/gsd/new-project.md +47 -0
- package/commands/gsd/ns-context.md +23 -0
- package/commands/gsd/ns-ideate.md +24 -0
- package/commands/gsd/ns-manage.md +29 -0
- package/commands/gsd/ns-project.md +22 -0
- package/commands/gsd/ns-review.md +26 -0
- package/commands/gsd/ns-workflow.md +28 -0
- package/commands/gsd/pause-work.md +43 -0
- package/commands/gsd/phase.md +56 -0
- package/commands/gsd/plan-phase.md +64 -0
- package/commands/gsd/plan-review-convergence.md +59 -0
- package/commands/gsd/pr-branch.md +26 -0
- package/commands/gsd/profile-user.md +46 -0
- package/commands/gsd/progress.md +48 -0
- package/commands/gsd/quick.md +174 -0
- package/commands/gsd/recommend-architecture.md +64 -0
- package/commands/gsd/resume-work.md +30 -0
- package/commands/gsd/review-backlog.md +63 -0
- package/commands/gsd/review.md +42 -0
- package/commands/gsd/secure-phase.md +36 -0
- package/commands/gsd/settings.md +29 -0
- package/commands/gsd/ship.md +24 -0
- package/commands/gsd/sketch.md +60 -0
- package/commands/gsd/spec-phase.md +63 -0
- package/commands/gsd/spike.md +57 -0
- package/commands/gsd/stats.md +20 -0
- package/commands/gsd/surface.md +155 -0
- package/commands/gsd/testing-strategy.md +65 -0
- package/commands/gsd/thread.md +24 -0
- package/commands/gsd/ui-phase.md +35 -0
- package/commands/gsd/ui-review.md +33 -0
- package/commands/gsd/ultraplan-phase.md +34 -0
- package/commands/gsd/undo.md +35 -0
- package/commands/gsd/update.md +49 -0
- package/commands/gsd/validate-phase.md +36 -0
- package/commands/gsd/verify-work.md +39 -0
- package/commands/gsd/workspace.md +52 -0
- package/commands/gsd/workstreams.md +70 -0
- package/gemini-extension.json +6 -0
- package/gsd-core/bin/check-latest-version.cjs +161 -0
- package/gsd-core/bin/gsd-tools.cjs +1928 -0
- package/gsd-core/bin/lib/active-workstream-store.cjs +291 -0
- package/gsd-core/bin/lib/adr-parser.cjs +399 -0
- package/gsd-core/bin/lib/agent-command-router.cjs +68 -0
- package/gsd-core/bin/lib/artifacts.cjs +51 -0
- package/gsd-core/bin/lib/audit.cjs +743 -0
- package/gsd-core/bin/lib/check-command-router.cjs +343 -0
- package/gsd-core/bin/lib/cjs-command-router-adapter.cjs +81 -0
- package/gsd-core/bin/lib/cli-exit.cjs +42 -0
- package/gsd-core/bin/lib/clock.cjs +95 -0
- package/gsd-core/bin/lib/clusters.cjs +132 -0
- package/gsd-core/bin/lib/code-review-flags.cjs +59 -0
- package/gsd-core/bin/lib/command-aliases.cjs +809 -0
- package/gsd-core/bin/lib/command-arg-projection.cjs +55 -0
- package/gsd-core/bin/lib/command-routing-hub.cjs +300 -0
- package/gsd-core/bin/lib/commands.cjs +1203 -0
- package/gsd-core/bin/lib/config-schema.cjs +29 -0
- package/gsd-core/bin/lib/config-types.cjs +19 -0
- package/gsd-core/bin/lib/config.cjs +738 -0
- package/gsd-core/bin/lib/configuration.cjs +239 -0
- package/gsd-core/bin/lib/context-utilization.cjs +48 -0
- package/gsd-core/bin/lib/core.cjs +2051 -0
- package/gsd-core/bin/lib/decisions.cjs +118 -0
- package/gsd-core/bin/lib/docs.cjs +252 -0
- package/gsd-core/bin/lib/drift.cjs +364 -0
- package/gsd-core/bin/lib/fallow-runner.cjs +115 -0
- package/gsd-core/bin/lib/frontmatter.cjs +442 -0
- package/gsd-core/bin/lib/gap-checker.cjs +257 -0
- package/gsd-core/bin/lib/graphify.cjs +496 -0
- package/gsd-core/bin/lib/gsd2-import.cjs +456 -0
- package/gsd-core/bin/lib/init-command-router.cjs +62 -0
- package/gsd-core/bin/lib/init.cjs +1815 -0
- package/gsd-core/bin/lib/install-profiles.cjs +584 -0
- package/gsd-core/bin/lib/installer-migration-authoring.cjs +122 -0
- package/gsd-core/bin/lib/installer-migration-report.cjs +350 -0
- package/gsd-core/bin/lib/installer-migrations/000-first-time-baseline.cjs +218 -0
- package/gsd-core/bin/lib/installer-migrations/001-legacy-orphan-files.cjs +48 -0
- package/gsd-core/bin/lib/installer-migrations/002-codex-legacy-hooks-json.cjs +94 -0
- package/gsd-core/bin/lib/installer-migrations/003-rename-get-shit-done-to-gsd-core.cjs +108 -0
- package/gsd-core/bin/lib/installer-migrations.cjs +823 -0
- package/gsd-core/bin/lib/intel.cjs +590 -0
- package/gsd-core/bin/lib/learnings.cjs +270 -0
- package/gsd-core/bin/lib/legacy-cleanup.cjs +253 -0
- package/gsd-core/bin/lib/milestone.cjs +373 -0
- package/gsd-core/bin/lib/model-catalog.cjs +154 -0
- package/gsd-core/bin/lib/model-profiles.cjs +24 -0
- package/gsd-core/bin/lib/observability/event.cjs +51 -0
- package/gsd-core/bin/lib/observability/logger.cjs +146 -0
- package/gsd-core/bin/lib/observability/redaction.cjs +48 -0
- package/gsd-core/bin/lib/package-identity.cjs +35 -0
- package/gsd-core/bin/lib/package-legitimacy.cjs +368 -0
- package/gsd-core/bin/lib/phase-command-router.cjs +189 -0
- package/gsd-core/bin/lib/phase-lifecycle.cjs +74 -0
- package/gsd-core/bin/lib/phase.cjs +1307 -0
- package/gsd-core/bin/lib/phases-command-router.cjs +43 -0
- package/gsd-core/bin/lib/plan-scan.cjs +91 -0
- package/gsd-core/bin/lib/planning-workspace.cjs +245 -0
- package/gsd-core/bin/lib/profile-output.cjs +1120 -0
- package/gsd-core/bin/lib/profile-pipeline.cjs +517 -0
- package/gsd-core/bin/lib/project-root.cjs +119 -0
- package/gsd-core/bin/lib/prompt-budget.cjs +305 -0
- package/gsd-core/bin/lib/research-provider.cjs +137 -0
- package/gsd-core/bin/lib/research-store.cjs +167 -0
- package/gsd-core/bin/lib/review-reviewer-selection.cjs +121 -0
- package/gsd-core/bin/lib/roadmap-command-router.cjs +166 -0
- package/gsd-core/bin/lib/roadmap-upgrade.cjs +476 -0
- package/gsd-core/bin/lib/roadmap.cjs +600 -0
- package/gsd-core/bin/lib/runtime-artifact-layout.cjs +312 -0
- package/gsd-core/bin/lib/runtime-config-adapter-registry.cjs +56 -0
- package/gsd-core/bin/lib/runtime-homes.cjs +190 -0
- package/gsd-core/bin/lib/runtime-name-policy.cjs +96 -0
- package/gsd-core/bin/lib/runtime-slash.cjs +119 -0
- package/gsd-core/bin/lib/schema-detect.cjs +159 -0
- package/gsd-core/bin/lib/secrets.cjs +34 -0
- package/gsd-core/bin/lib/security.cjs +480 -0
- package/gsd-core/bin/lib/semver-compare.cjs +42 -0
- package/gsd-core/bin/lib/shell-command-projection.cjs +533 -0
- package/gsd-core/bin/lib/state-command-router.cjs +160 -0
- package/gsd-core/bin/lib/state-document.cjs +259 -0
- package/gsd-core/bin/lib/state.cjs +2010 -0
- package/gsd-core/bin/lib/surface.cjs +449 -0
- package/gsd-core/bin/lib/task-command-router.cjs +85 -0
- package/gsd-core/bin/lib/template.cjs +237 -0
- package/gsd-core/bin/lib/uat.cjs +297 -0
- package/gsd-core/bin/lib/ui-safety-gate.cjs +98 -0
- package/gsd-core/bin/lib/update-context.cjs +218 -0
- package/gsd-core/bin/lib/validate-command-router.cjs +91 -0
- package/gsd-core/bin/lib/validate.cjs +112 -0
- package/gsd-core/bin/lib/verification-command-router.cjs +31 -0
- package/gsd-core/bin/lib/verification.cjs +193 -0
- package/gsd-core/bin/lib/verify-command-router.cjs +44 -0
- package/gsd-core/bin/lib/verify.cjs +1451 -0
- package/gsd-core/bin/lib/workstream-inventory-builder.cjs +81 -0
- package/gsd-core/bin/lib/workstream-inventory.cjs +147 -0
- package/gsd-core/bin/lib/workstream-name-policy.cjs +91 -0
- package/gsd-core/bin/lib/workstream.cjs +380 -0
- package/gsd-core/bin/lib/worktree-base-ref.cjs +325 -0
- package/gsd-core/bin/lib/worktree-safety.cjs +943 -0
- package/gsd-core/bin/shared/config-defaults.manifest.json +98 -0
- package/gsd-core/bin/shared/config-schema.manifest.json +192 -0
- package/gsd-core/bin/shared/model-catalog.json +149 -0
- package/gsd-core/bin/shared/runtime-aliases.manifest.json +75 -0
- package/gsd-core/bin/verify-reapply-patches.cjs +349 -0
- package/gsd-core/contexts/dev.md +21 -0
- package/gsd-core/contexts/research.md +22 -0
- package/gsd-core/contexts/review.md +23 -0
- package/gsd-core/references/agent-contracts.md +79 -0
- package/gsd-core/references/ai-evals.md +156 -0
- package/gsd-core/references/ai-frameworks.md +186 -0
- package/gsd-core/references/architecture-decision.md +74 -0
- package/gsd-core/references/artifact-types.md +131 -0
- package/gsd-core/references/auth-in-tests.md +91 -0
- package/gsd-core/references/autonomous-smart-discuss.md +277 -0
- package/gsd-core/references/checkpoints.md +814 -0
- package/gsd-core/references/common-bug-patterns.md +114 -0
- package/gsd-core/references/context-budget.md +85 -0
- package/gsd-core/references/continuation-format.md +253 -0
- package/gsd-core/references/db-test-isolation.md +54 -0
- package/gsd-core/references/debugger-philosophy.md +76 -0
- package/gsd-core/references/decimal-phase-calculation.md +64 -0
- package/gsd-core/references/doc-conflict-engine.md +91 -0
- package/gsd-core/references/domain-modeling.md +80 -0
- package/gsd-core/references/domain-probes.md +125 -0
- package/gsd-core/references/e2e-tiering.md +35 -0
- package/gsd-core/references/execute-mvp-tdd.md +81 -0
- package/gsd-core/references/executor-examples.md +110 -0
- package/gsd-core/references/few-shot-examples/plan-checker.md +73 -0
- package/gsd-core/references/few-shot-examples/verifier.md +109 -0
- package/gsd-core/references/flaky-test-checklist.md +22 -0
- package/gsd-core/references/gate-prompts.md +100 -0
- package/gsd-core/references/gates.md +70 -0
- package/gsd-core/references/git-integration.md +298 -0
- package/gsd-core/references/git-planning-commit.md +40 -0
- package/gsd-core/references/ios-scaffold.md +123 -0
- package/gsd-core/references/mandatory-initial-read.md +2 -0
- package/gsd-core/references/model-profile-resolution.md +38 -0
- package/gsd-core/references/model-profiles.md +245 -0
- package/gsd-core/references/mvp-concepts.md +49 -0
- package/gsd-core/references/phase-argument-parsing.md +61 -0
- package/gsd-core/references/planner-antipatterns.md +89 -0
- package/gsd-core/references/planner-chunked.md +49 -0
- package/gsd-core/references/planner-gap-closure.md +62 -0
- package/gsd-core/references/planner-graphify-auto-update.md +67 -0
- package/gsd-core/references/planner-human-verify-mode.md +57 -0
- package/gsd-core/references/planner-interface-context.md +62 -0
- package/gsd-core/references/planner-load-graph-context.md +36 -0
- package/gsd-core/references/planner-mvp-mode.md +53 -0
- package/gsd-core/references/planner-reviews.md +39 -0
- package/gsd-core/references/planner-revision.md +87 -0
- package/gsd-core/references/planner-source-audit.md +73 -0
- package/gsd-core/references/planning-config.md +473 -0
- package/gsd-core/references/product-discovery.md +49 -0
- package/gsd-core/references/project-skills-discovery.md +19 -0
- package/gsd-core/references/questioning.md +162 -0
- package/gsd-core/references/realistic-test-data.md +44 -0
- package/gsd-core/references/research-documentation-lookup.md +29 -0
- package/gsd-core/references/research-philosophy.md +29 -0
- package/gsd-core/references/research-verification-protocol.md +27 -0
- package/gsd-core/references/revision-loop.md +97 -0
- package/gsd-core/references/scout-codebase.md +51 -0
- package/gsd-core/references/skeleton-template.md +48 -0
- package/gsd-core/references/sketch-interactivity.md +41 -0
- package/gsd-core/references/sketch-theme-system.md +94 -0
- package/gsd-core/references/sketch-tooling.md +45 -0
- package/gsd-core/references/sketch-variant-patterns.md +81 -0
- package/gsd-core/references/spidr-splitting.md +69 -0
- package/gsd-core/references/tdd.md +330 -0
- package/gsd-core/references/test-containers.md +55 -0
- package/gsd-core/references/test-strategy.md +75 -0
- package/gsd-core/references/thinking-models-debug.md +44 -0
- package/gsd-core/references/thinking-models-execution.md +50 -0
- package/gsd-core/references/thinking-models-planning.md +62 -0
- package/gsd-core/references/thinking-models-research.md +50 -0
- package/gsd-core/references/thinking-models-verification.md +55 -0
- package/gsd-core/references/thinking-partner.md +96 -0
- package/gsd-core/references/ui-brand.md +162 -0
- package/gsd-core/references/universal-anti-patterns.md +63 -0
- package/gsd-core/references/user-profiling.md +681 -0
- package/gsd-core/references/user-story-template.md +58 -0
- package/gsd-core/references/verification-overrides.md +227 -0
- package/gsd-core/references/verification-patterns.md +612 -0
- package/gsd-core/references/verify-mvp-mode.md +85 -0
- package/gsd-core/references/workstream-flag.md +111 -0
- package/gsd-core/references/worktree-branch-check.md +38 -0
- package/gsd-core/references/worktree-path-safety.md +67 -0
- package/gsd-core/templates/AI-SPEC.md +246 -0
- package/gsd-core/templates/DEBUG.md +169 -0
- package/gsd-core/templates/README.md +77 -0
- package/gsd-core/templates/SECURITY.md +61 -0
- package/gsd-core/templates/UAT.md +265 -0
- package/gsd-core/templates/UI-SPEC.md +100 -0
- package/gsd-core/templates/VALIDATION.md +76 -0
- package/gsd-core/templates/adr.md +58 -0
- package/gsd-core/templates/claude-md.md +145 -0
- package/gsd-core/templates/codebase/architecture.md +255 -0
- package/gsd-core/templates/codebase/concerns.md +310 -0
- package/gsd-core/templates/codebase/conventions.md +307 -0
- package/gsd-core/templates/codebase/integrations.md +280 -0
- package/gsd-core/templates/codebase/stack.md +186 -0
- package/gsd-core/templates/codebase/structure.md +285 -0
- package/gsd-core/templates/codebase/testing.md +480 -0
- package/gsd-core/templates/config.json +62 -0
- package/gsd-core/templates/context.md +352 -0
- package/gsd-core/templates/continue-here.md +78 -0
- package/gsd-core/templates/copilot-instructions.md +7 -0
- package/gsd-core/templates/debug-subagent-prompt.md +91 -0
- package/gsd-core/templates/dev-preferences.md +21 -0
- package/gsd-core/templates/discovery.md +146 -0
- package/gsd-core/templates/discussion-log.md +63 -0
- package/gsd-core/templates/domain-model.md +54 -0
- package/gsd-core/templates/milestone-archive.md +123 -0
- package/gsd-core/templates/milestone.md +115 -0
- package/gsd-core/templates/phase-prompt.md +610 -0
- package/gsd-core/templates/planner-subagent-prompt.md +117 -0
- package/gsd-core/templates/product-brief.md +55 -0
- package/gsd-core/templates/project.md +186 -0
- package/gsd-core/templates/requirements.md +231 -0
- package/gsd-core/templates/research-project/ARCHITECTURE.md +204 -0
- package/gsd-core/templates/research-project/FEATURES.md +147 -0
- package/gsd-core/templates/research-project/PITFALLS.md +200 -0
- package/gsd-core/templates/research-project/STACK.md +120 -0
- package/gsd-core/templates/research-project/SUMMARY.md +170 -0
- package/gsd-core/templates/research.md +592 -0
- package/gsd-core/templates/retrospective.md +54 -0
- package/gsd-core/templates/roadmap.md +202 -0
- package/gsd-core/templates/spec.md +307 -0
- package/gsd-core/templates/state.md +195 -0
- package/gsd-core/templates/summary-complex.md +59 -0
- package/gsd-core/templates/summary-minimal.md +41 -0
- package/gsd-core/templates/summary-standard.md +48 -0
- package/gsd-core/templates/summary.md +248 -0
- package/gsd-core/templates/test-strategy.md +50 -0
- package/gsd-core/templates/user-profile.md +146 -0
- package/gsd-core/templates/user-setup.md +311 -0
- package/gsd-core/templates/verification-report.md +322 -0
- package/gsd-core/workflows/_runtime-launcher.snippet.sh +1 -0
- package/gsd-core/workflows/add-backlog.md +91 -0
- package/gsd-core/workflows/add-phase.md +113 -0
- package/gsd-core/workflows/add-tests.md +355 -0
- package/gsd-core/workflows/add-todo.md +161 -0
- package/gsd-core/workflows/ai-integration-phase.md +295 -0
- package/gsd-core/workflows/analyze-dependencies.md +96 -0
- package/gsd-core/workflows/audit-fix.md +178 -0
- package/gsd-core/workflows/audit-milestone.md +360 -0
- package/gsd-core/workflows/audit-uat.md +110 -0
- package/gsd-core/workflows/autonomous.md +797 -0
- package/gsd-core/workflows/check-todos.md +180 -0
- package/gsd-core/workflows/cleanup.md +195 -0
- package/gsd-core/workflows/code-review-fix.md +502 -0
- package/gsd-core/workflows/code-review.md +658 -0
- package/gsd-core/workflows/complete-milestone.md +855 -0
- package/gsd-core/workflows/debug.md +237 -0
- package/gsd-core/workflows/diagnose-issues.md +245 -0
- package/gsd-core/workflows/discover-product.md +112 -0
- package/gsd-core/workflows/discovery-phase.md +291 -0
- package/gsd-core/workflows/discuss-phase/modes/advisor.md +176 -0
- package/gsd-core/workflows/discuss-phase/modes/all.md +28 -0
- package/gsd-core/workflows/discuss-phase/modes/analyze.md +44 -0
- package/gsd-core/workflows/discuss-phase/modes/auto.md +57 -0
- package/gsd-core/workflows/discuss-phase/modes/batch.md +52 -0
- package/gsd-core/workflows/discuss-phase/modes/chain.md +98 -0
- package/gsd-core/workflows/discuss-phase/modes/default.md +141 -0
- package/gsd-core/workflows/discuss-phase/modes/power.md +44 -0
- package/gsd-core/workflows/discuss-phase/modes/text.md +55 -0
- package/gsd-core/workflows/discuss-phase/templates/checkpoint.json +18 -0
- package/gsd-core/workflows/discuss-phase/templates/context.md +136 -0
- package/gsd-core/workflows/discuss-phase/templates/discussion-log.md +50 -0
- package/gsd-core/workflows/discuss-phase-assumptions.md +675 -0
- package/gsd-core/workflows/discuss-phase-power.md +291 -0
- package/gsd-core/workflows/discuss-phase.md +499 -0
- package/gsd-core/workflows/do.md +111 -0
- package/gsd-core/workflows/docs-update.md +1176 -0
- package/gsd-core/workflows/edit-phase.md +295 -0
- package/gsd-core/workflows/eval-review.md +156 -0
- package/gsd-core/workflows/execute-phase/steps/codebase-drift-gate.md +95 -0
- package/gsd-core/workflows/execute-phase/steps/per-plan-worktree-gate.md +94 -0
- package/gsd-core/workflows/execute-phase/steps/post-merge-gate.md +117 -0
- package/gsd-core/workflows/execute-phase.md +1752 -0
- package/gsd-core/workflows/execute-plan.md +526 -0
- package/gsd-core/workflows/explore.md +146 -0
- package/gsd-core/workflows/extract-learnings.md +243 -0
- package/gsd-core/workflows/fast.md +124 -0
- package/gsd-core/workflows/forensics.md +279 -0
- package/gsd-core/workflows/graduation.md +196 -0
- package/gsd-core/workflows/health.md +224 -0
- package/gsd-core/workflows/help/modes/brief.md +22 -0
- package/gsd-core/workflows/help/modes/default.md +50 -0
- package/gsd-core/workflows/help/modes/full.md +789 -0
- package/gsd-core/workflows/help/modes/topic.md +74 -0
- package/gsd-core/workflows/help.md +24 -0
- package/gsd-core/workflows/import.md +256 -0
- package/gsd-core/workflows/inbox.md +387 -0
- package/gsd-core/workflows/ingest-docs.md +340 -0
- package/gsd-core/workflows/insert-phase.md +152 -0
- package/gsd-core/workflows/list-phase-assumptions.md +178 -0
- package/gsd-core/workflows/list-workspaces.md +57 -0
- package/gsd-core/workflows/manager.md +393 -0
- package/gsd-core/workflows/map-codebase.md +446 -0
- package/gsd-core/workflows/milestone-summary.md +224 -0
- package/gsd-core/workflows/model-domain.md +162 -0
- package/gsd-core/workflows/mvp-phase.md +222 -0
- package/gsd-core/workflows/new-milestone.md +635 -0
- package/gsd-core/workflows/new-project.md +1555 -0
- package/gsd-core/workflows/new-workspace.md +240 -0
- package/gsd-core/workflows/next.md +299 -0
- package/gsd-core/workflows/node-repair.md +92 -0
- package/gsd-core/workflows/note.md +158 -0
- package/gsd-core/workflows/pause-work.md +244 -0
- package/gsd-core/workflows/plan-milestone-gaps.md +281 -0
- package/gsd-core/workflows/plan-phase.md +1814 -0
- package/gsd-core/workflows/plan-review-convergence.md +346 -0
- package/gsd-core/workflows/plant-seed.md +230 -0
- package/gsd-core/workflows/pr-branch.md +157 -0
- package/gsd-core/workflows/profile-user.md +453 -0
- package/gsd-core/workflows/progress.md +699 -0
- package/gsd-core/workflows/quick.md +1017 -0
- package/gsd-core/workflows/reapply-patches.md +426 -0
- package/gsd-core/workflows/recommend-architecture.md +135 -0
- package/gsd-core/workflows/remove-phase.md +156 -0
- package/gsd-core/workflows/remove-workspace.md +108 -0
- package/gsd-core/workflows/resume-project.md +332 -0
- package/gsd-core/workflows/review.md +748 -0
- package/gsd-core/workflows/scan.md +107 -0
- package/gsd-core/workflows/secure-phase.md +182 -0
- package/gsd-core/workflows/session-report.md +146 -0
- package/gsd-core/workflows/settings-advanced.md +810 -0
- package/gsd-core/workflows/settings-integrations.md +312 -0
- package/gsd-core/workflows/settings.md +566 -0
- package/gsd-core/workflows/ship.md +405 -0
- package/gsd-core/workflows/sketch-wrap-up.md +286 -0
- package/gsd-core/workflows/sketch.md +361 -0
- package/gsd-core/workflows/spec-phase.md +263 -0
- package/gsd-core/workflows/spike-wrap-up.md +307 -0
- package/gsd-core/workflows/spike.md +453 -0
- package/gsd-core/workflows/stats.md +80 -0
- package/gsd-core/workflows/sync-skills.md +182 -0
- package/gsd-core/workflows/testing-strategy.md +122 -0
- package/gsd-core/workflows/thread.md +222 -0
- package/gsd-core/workflows/transition.md +694 -0
- package/gsd-core/workflows/ui-phase.md +328 -0
- package/gsd-core/workflows/ui-review.md +193 -0
- package/gsd-core/workflows/ultraplan-phase.md +199 -0
- package/gsd-core/workflows/undo.md +314 -0
- package/gsd-core/workflows/update.md +496 -0
- package/gsd-core/workflows/validate-phase.md +181 -0
- package/gsd-core/workflows/verify-phase.md +544 -0
- package/gsd-core/workflows/verify-work.md +781 -0
- package/hooks/dist/gsd-check-update-worker.js +108 -0
- package/hooks/dist/gsd-check-update.js +66 -0
- package/hooks/dist/gsd-config-reload.js +133 -0
- package/hooks/dist/gsd-context-monitor.js +195 -0
- package/hooks/dist/gsd-cursor-post-tool.js +75 -0
- package/hooks/dist/gsd-cursor-session-start.js +52 -0
- package/hooks/dist/gsd-graphify-update.sh +158 -0
- package/hooks/dist/gsd-phase-boundary.sh +47 -0
- package/hooks/dist/gsd-prompt-guard.js +97 -0
- package/hooks/dist/gsd-read-guard.js +101 -0
- package/hooks/dist/gsd-read-injection-scanner.js +203 -0
- package/hooks/dist/gsd-session-state.sh +59 -0
- package/hooks/dist/gsd-statusline.js +566 -0
- package/hooks/dist/gsd-update-banner.js +138 -0
- package/hooks/dist/gsd-validate-commit.sh +57 -0
- package/hooks/dist/gsd-workflow-guard.js +167 -0
- package/hooks/dist/gsd-worktree-path-guard.js +169 -0
- package/hooks/dist/lib/git-cmd.js +150 -0
- package/hooks/dist/lib/gsd-graphify-rebuild.sh +65 -0
- package/hooks/dist/managed-hooks-registry.cjs +38 -0
- package/hooks/gsd-check-update-worker.js +108 -0
- package/hooks/gsd-check-update.js +66 -0
- package/hooks/gsd-config-reload.js +133 -0
- package/hooks/gsd-context-monitor.js +195 -0
- package/hooks/gsd-cursor-post-tool.js +75 -0
- package/hooks/gsd-cursor-session-start.js +52 -0
- package/hooks/gsd-graphify-update.sh +158 -0
- package/hooks/gsd-phase-boundary.sh +47 -0
- package/hooks/gsd-prompt-guard.js +97 -0
- package/hooks/gsd-read-guard.js +101 -0
- package/hooks/gsd-read-injection-scanner.js +203 -0
- package/hooks/gsd-session-state.sh +59 -0
- package/hooks/gsd-statusline.js +566 -0
- package/hooks/gsd-update-banner.js +138 -0
- package/hooks/gsd-validate-commit.sh +57 -0
- package/hooks/gsd-workflow-guard.js +167 -0
- package/hooks/gsd-worktree-path-guard.js +169 -0
- package/hooks/hooks.json +69 -0
- package/hooks/lib/git-cmd.js +150 -0
- package/hooks/lib/gsd-graphify-rebuild.sh +65 -0
- package/hooks/managed-hooks-registry.cjs +38 -0
- package/package.json +115 -0
- package/scripts/affected-tests-lib.cjs +542 -0
- package/scripts/audit-workflow-script-paths.cjs +73 -0
- package/scripts/base64-scan.sh +351 -0
- package/scripts/build-hooks.js +247 -0
- package/scripts/changeset/README.md +129 -0
- package/scripts/changeset/cli.cjs +590 -0
- package/scripts/changeset/github-release-notes.cjs +199 -0
- package/scripts/changeset/lint.cjs +111 -0
- package/scripts/changeset/new.cjs +137 -0
- package/scripts/changeset/parse.cjs +114 -0
- package/scripts/changeset/render.cjs +34 -0
- package/scripts/changeset/serialize.cjs +130 -0
- package/scripts/check-alias-drift.cjs +114 -0
- package/scripts/check-env.cjs +312 -0
- package/scripts/check-npm-integrity.cjs +215 -0
- package/scripts/ci-guard-runner.cjs +22 -0
- package/scripts/ci-prepare-test-scope.cjs +51 -0
- package/scripts/ci-rebase-check.cjs +86 -0
- package/scripts/ci-test-scope.cjs +431 -0
- package/scripts/command-contract-helpers.cjs +64 -0
- package/scripts/diff-touches-shipped-paths.cjs +155 -0
- package/scripts/fix-slash-commands.cjs +147 -0
- package/scripts/gen-inventory-manifest.cjs +115 -0
- package/scripts/gen-research-agents.cjs +276 -0
- package/scripts/generate-package-identity.cjs +125 -0
- package/scripts/issue-dedupe.cjs +278 -0
- package/scripts/lib/allowlist-ratchet.cjs +136 -0
- package/scripts/lib/cli-exit.cjs +56 -0
- package/scripts/lint-command-contract.cjs +114 -0
- package/scripts/lint-descriptions.cjs +87 -0
- package/scripts/lint-docs-required.cjs +222 -0
- package/scripts/lint-legacy-dir-name.cjs +160 -0
- package/scripts/lint-package-identity-drift.cjs +141 -0
- package/scripts/lint-pr-check-project-dir.cjs +99 -0
- package/scripts/lint-shell-command-projection-drift.cjs +62 -0
- package/scripts/lint-skill-deps.cjs +185 -0
- package/scripts/lint-test-file-count.allowlist.json +135 -0
- package/scripts/lint-test-file-count.cjs +246 -0
- package/scripts/mutation-matrix.cjs +222 -0
- package/scripts/pr-template-policy.cjs +268 -0
- package/scripts/prompt-injection-scan.sh +207 -0
- package/scripts/release-notes/discord-release-summary.cjs +373 -0
- package/scripts/release-notes/format-github-release-notes.cjs +261 -0
- package/scripts/release-tarball-smoke.cjs +629 -0
- package/scripts/research-profiles.cjs +149 -0
- package/scripts/run-affected-tests.cjs +7 -0
- package/scripts/run-cross-platform-tests.cjs +67 -0
- package/scripts/run-tests.cjs +315 -0
- package/scripts/secret-scan-lint.sh +231 -0
- package/scripts/secret-scan.sh +358 -0
- package/scripts/setup-branch-protection.sh +236 -0
- package/scripts/strip-prose-atrefs.cjs +106 -0
- package/scripts/sync-manifest-versions.cjs +119 -0
- package/scripts/sync-rulesets.sh +34 -0
- package/scripts/sync-runtime-launcher.cjs +399 -0
- package/scripts/test-failure-reasons.cjs +34 -0
- package/scripts/verify-npm-publish.cjs +240 -0
- package/scripts/workflow-policy.cjs +450 -0
|
@@ -0,0 +1,480 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Security — Input validation, path traversal prevention, and prompt injection guards
|
|
4
|
+
*
|
|
5
|
+
* This module centralizes security checks for GSD tooling. Because GSD generates
|
|
6
|
+
* markdown files that become LLM system prompts (agent instructions, workflow state,
|
|
7
|
+
* phase plans), any user-controlled text that flows into these files is a potential
|
|
8
|
+
* indirect prompt injection vector.
|
|
9
|
+
*
|
|
10
|
+
* Threat model:
|
|
11
|
+
* 1. Path traversal: user-supplied file paths escape the project directory
|
|
12
|
+
* 2. Prompt injection: malicious text in arguments/PRDs embeds LLM instructions
|
|
13
|
+
* 3. Shell metacharacter injection: user text interpreted by shell
|
|
14
|
+
* 4. JSON injection: malformed JSON crashes or corrupts state
|
|
15
|
+
* 5. Regex DoS: crafted input causes catastrophic backtracking
|
|
16
|
+
*
|
|
17
|
+
* ADR-457 build-at-publish: the hand-written bin/lib/security.cjs collapsed
|
|
18
|
+
* to a TypeScript source of truth. Behaviour is preserved byte-for-behaviour
|
|
19
|
+
* from the prior hand-written .cjs; only types are added.
|
|
20
|
+
*/
|
|
21
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
22
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
23
|
+
};
|
|
24
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
25
|
+
exports.MARKDOWN_LINK_PATTERNS = exports.INJECTION_PATTERNS = void 0;
|
|
26
|
+
exports.validatePath = validatePath;
|
|
27
|
+
exports.loadTrustedGlobalRoots = loadTrustedGlobalRoots;
|
|
28
|
+
exports.requireSafePath = requireSafePath;
|
|
29
|
+
exports.scanForInjection = scanForInjection;
|
|
30
|
+
exports.sanitizeForPrompt = sanitizeForPrompt;
|
|
31
|
+
exports.sanitizeForDisplay = sanitizeForDisplay;
|
|
32
|
+
exports.validateShellArg = validateShellArg;
|
|
33
|
+
exports.safeJsonParse = safeJsonParse;
|
|
34
|
+
exports.validatePhaseNumber = validatePhaseNumber;
|
|
35
|
+
exports.validateFieldName = validateFieldName;
|
|
36
|
+
exports.validatePromptStructure = validatePromptStructure;
|
|
37
|
+
exports.scanEntropyAnomalies = scanEntropyAnomalies;
|
|
38
|
+
const node_fs_1 = __importDefault(require("node:fs"));
|
|
39
|
+
const node_os_1 = __importDefault(require("node:os"));
|
|
40
|
+
const node_path_1 = __importDefault(require("node:path"));
|
|
41
|
+
// ─── Path Traversal Prevention ──────────────────────────────────────────────
|
|
42
|
+
/**
|
|
43
|
+
* Validate that a file path resolves within an allowed base directory.
|
|
44
|
+
* Prevents path traversal attacks via ../ sequences, symlinks, or absolute paths.
|
|
45
|
+
*/
|
|
46
|
+
function validatePath(filePath, baseDir, opts = {}) {
|
|
47
|
+
if (!filePath || typeof filePath !== 'string') {
|
|
48
|
+
return { safe: false, resolved: '', error: 'Empty or invalid file path' };
|
|
49
|
+
}
|
|
50
|
+
if (!baseDir || typeof baseDir !== 'string') {
|
|
51
|
+
return { safe: false, resolved: '', error: 'Empty or invalid base directory' };
|
|
52
|
+
}
|
|
53
|
+
if (filePath.includes('\0')) {
|
|
54
|
+
return { safe: false, resolved: '', error: 'Path contains null bytes' };
|
|
55
|
+
}
|
|
56
|
+
let resolvedBase;
|
|
57
|
+
try {
|
|
58
|
+
resolvedBase = node_fs_1.default.realpathSync(node_path_1.default.resolve(baseDir));
|
|
59
|
+
}
|
|
60
|
+
catch {
|
|
61
|
+
resolvedBase = node_path_1.default.resolve(baseDir);
|
|
62
|
+
}
|
|
63
|
+
let resolvedPath;
|
|
64
|
+
if (node_path_1.default.isAbsolute(filePath)) {
|
|
65
|
+
if (!opts.allowAbsolute) {
|
|
66
|
+
return { safe: false, resolved: '', error: 'Absolute paths not allowed' };
|
|
67
|
+
}
|
|
68
|
+
resolvedPath = node_path_1.default.resolve(filePath);
|
|
69
|
+
}
|
|
70
|
+
else {
|
|
71
|
+
resolvedPath = node_path_1.default.resolve(baseDir, filePath);
|
|
72
|
+
}
|
|
73
|
+
try {
|
|
74
|
+
resolvedPath = node_fs_1.default.realpathSync(resolvedPath);
|
|
75
|
+
}
|
|
76
|
+
catch {
|
|
77
|
+
const parentDir = node_path_1.default.dirname(resolvedPath);
|
|
78
|
+
try {
|
|
79
|
+
const realParent = node_fs_1.default.realpathSync(parentDir);
|
|
80
|
+
resolvedPath = node_path_1.default.join(realParent, node_path_1.default.basename(resolvedPath));
|
|
81
|
+
}
|
|
82
|
+
catch {
|
|
83
|
+
// Parent doesn't exist either — keep the resolved path as-is
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
const normalizedBase = resolvedBase + node_path_1.default.sep;
|
|
87
|
+
const normalizedPath = resolvedPath + node_path_1.default.sep;
|
|
88
|
+
if (resolvedPath !== resolvedBase && !normalizedPath.startsWith(normalizedBase)) {
|
|
89
|
+
return {
|
|
90
|
+
safe: false,
|
|
91
|
+
resolved: resolvedPath,
|
|
92
|
+
error: `Path escapes allowed directory: ${resolvedPath} is outside ${resolvedBase}`,
|
|
93
|
+
};
|
|
94
|
+
}
|
|
95
|
+
return { safe: true, resolved: resolvedPath };
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* Load the opt-in trusted global roots allowlist from config.
|
|
99
|
+
*
|
|
100
|
+
* Reads `config.agent_skills_security.trusted_global_roots` (an array of
|
|
101
|
+
* path strings). Each entry is canonicalized via realpathSync: non-strings
|
|
102
|
+
* are dropped, leading `~/` is expanded to `os.homedir()`, entries that are
|
|
103
|
+
* not absolute after expansion are dropped (project-relative paths are
|
|
104
|
+
* rejected as a security boundary), and entries that do not exist on disk are
|
|
105
|
+
* dropped (a non-existent root is not trustworthy). The canonical realpath is
|
|
106
|
+
* used for all subsequent checks and as the stored value — this closes the
|
|
107
|
+
* case-insensitive bypass on macOS APFS (`/users/alice` vs `/Users/alice`)
|
|
108
|
+
* and ensures trust doesn't drift across re-invocations if a root is
|
|
109
|
+
* re-created at a different target. Results are de-duplicated by canonical path.
|
|
110
|
+
*/
|
|
111
|
+
function loadTrustedGlobalRoots(config) {
|
|
112
|
+
const roots = config?.['agent_skills_security'];
|
|
113
|
+
const raw = roots?.['trusted_global_roots'];
|
|
114
|
+
if (!Array.isArray(raw))
|
|
115
|
+
return [];
|
|
116
|
+
// Compute canonical homedir once for case-insensitive-safe comparison.
|
|
117
|
+
let realHome;
|
|
118
|
+
try {
|
|
119
|
+
realHome = node_fs_1.default.realpathSync(node_os_1.default.homedir());
|
|
120
|
+
}
|
|
121
|
+
catch {
|
|
122
|
+
realHome = node_os_1.default.homedir();
|
|
123
|
+
}
|
|
124
|
+
const seen = new Set();
|
|
125
|
+
const result = [];
|
|
126
|
+
for (const entry of raw) {
|
|
127
|
+
if (typeof entry !== 'string')
|
|
128
|
+
continue;
|
|
129
|
+
let expanded;
|
|
130
|
+
if (entry === '~') {
|
|
131
|
+
expanded = node_os_1.default.homedir();
|
|
132
|
+
}
|
|
133
|
+
else if (entry.startsWith('~/')) {
|
|
134
|
+
expanded = node_path_1.default.join(node_os_1.default.homedir(), entry.slice(2));
|
|
135
|
+
}
|
|
136
|
+
else {
|
|
137
|
+
expanded = entry;
|
|
138
|
+
}
|
|
139
|
+
if (!node_path_1.default.isAbsolute(expanded))
|
|
140
|
+
continue; // reject project-relative
|
|
141
|
+
// Canonicalize: resolve symlinks and normalise case. If the path doesn't
|
|
142
|
+
// exist or can't be read, skip it — a non-existent root is not trustworthy.
|
|
143
|
+
let real;
|
|
144
|
+
try {
|
|
145
|
+
real = node_fs_1.default.realpathSync(expanded);
|
|
146
|
+
}
|
|
147
|
+
catch {
|
|
148
|
+
continue; // non-existent or unreadable — skip
|
|
149
|
+
}
|
|
150
|
+
// Reject dangerously broad roots: filesystem root (e.g. '/' or 'C:\' or UNC '\\server\share').
|
|
151
|
+
// Normalize both sides by stripping trailing path separators before comparing so that
|
|
152
|
+
// Windows UNC shares (where path.parse().root includes a trailing separator) are caught.
|
|
153
|
+
const stripTrailingSep = (p) => p.replace(/[\\/]+$/, '');
|
|
154
|
+
if (stripTrailingSep(node_path_1.default.parse(real).root) === stripTrailingSep(real))
|
|
155
|
+
continue;
|
|
156
|
+
// Reject homedir itself (canonical compare closes case-insensitive bypass).
|
|
157
|
+
// Apply stripTrailingSep for robustness on platforms where realpathSync may
|
|
158
|
+
// or may not include a trailing separator on the homedir path.
|
|
159
|
+
if (stripTrailingSep(real) === stripTrailingSep(realHome))
|
|
160
|
+
continue;
|
|
161
|
+
if (seen.has(real))
|
|
162
|
+
continue;
|
|
163
|
+
seen.add(real);
|
|
164
|
+
result.push(real);
|
|
165
|
+
}
|
|
166
|
+
return result;
|
|
167
|
+
}
|
|
168
|
+
/**
|
|
169
|
+
* Validate a file path and throw on traversal attempt.
|
|
170
|
+
* Convenience wrapper around validatePath for use in CLI commands.
|
|
171
|
+
*/
|
|
172
|
+
function requireSafePath(filePath, baseDir, label, opts = {}) {
|
|
173
|
+
const result = validatePath(filePath, baseDir, opts);
|
|
174
|
+
if (!result.safe) {
|
|
175
|
+
throw new Error(`${label || 'Path'} validation failed: ${result.error}`);
|
|
176
|
+
}
|
|
177
|
+
return result.resolved;
|
|
178
|
+
}
|
|
179
|
+
// ─── Prompt Injection Detection ────────────────────────────────────────────────────
|
|
180
|
+
/**
|
|
181
|
+
* Patterns that indicate prompt injection attempts in user-supplied text.
|
|
182
|
+
* These patterns catch common indirect prompt injection techniques where
|
|
183
|
+
* an attacker embeds LLM instructions in text that will be read by an agent.
|
|
184
|
+
*
|
|
185
|
+
* Note: This is defense-in-depth — not a complete solution. The primary defense
|
|
186
|
+
* is proper input/output boundaries in agent prompts.
|
|
187
|
+
*/
|
|
188
|
+
exports.INJECTION_PATTERNS = [
|
|
189
|
+
// Direct instruction override attempts
|
|
190
|
+
/ignore\s+(all\s+)?previous\s+instructions/i,
|
|
191
|
+
/ignore\s+(all\s+)?above\s+instructions/i,
|
|
192
|
+
/disregard\s+(all\s+)?previous/i,
|
|
193
|
+
/forget\s+(all\s+)?(your\s+)?instructions/i,
|
|
194
|
+
/override\s+(system|previous)\s+(prompt|instructions)/i,
|
|
195
|
+
// Role/identity manipulation
|
|
196
|
+
/you\s+are\s+now\s+(?:a|an|the)\s+/i,
|
|
197
|
+
/act\s+as\s+(?:a|an|the)\s+(?!plan|phase|wave)/i,
|
|
198
|
+
/pretend\s+(?:you(?:'re| are)\s+|to\s+be\s+)/i,
|
|
199
|
+
/from\s+now\s+on,?\s+you\s+(?:are|will|should|must)/i,
|
|
200
|
+
// System prompt extraction
|
|
201
|
+
/(?:print|output|reveal|show|display|repeat)\s+(?:your\s+)?(?:system\s+)?(?:prompt|instructions)/i,
|
|
202
|
+
/what\s+(?:are|is)\s+your\s+(?:system\s+)?(?:prompt|instructions)/i,
|
|
203
|
+
// Hidden instruction markers (XML/HTML tags that mimic system messages)
|
|
204
|
+
// Note: <instructions> is excluded — GSD uses it as legitimate prompt structure
|
|
205
|
+
// Requires > to close the tag (not just whitespace) to avoid matching generic types like Promise<User | null>
|
|
206
|
+
/<\/?(?:system|assistant|human)>/i,
|
|
207
|
+
/\[SYSTEM\]/i,
|
|
208
|
+
/\[\/?(INST)\]/i,
|
|
209
|
+
/<<\s*SYS\s*>>/i,
|
|
210
|
+
// Exfiltration attempts
|
|
211
|
+
/(?:send|post|fetch|curl|wget)\s+(?:to|from)\s+https?:\/\//i,
|
|
212
|
+
/(?:base64|btoa|encode)\s+(?:and\s+)?(?:send|exfiltrate|output)/i,
|
|
213
|
+
// Tool manipulation
|
|
214
|
+
/(?:run|execute|call|invoke)\s+(?:the\s+)?(?:bash|shell|exec|spawn)\s+(?:tool|command)/i,
|
|
215
|
+
];
|
|
216
|
+
// Explicit safe-list for data: MIME types that are benign in link targets.
|
|
217
|
+
// Note: image/svg+xml is intentionally NOT in this list (SVG can host <script>).
|
|
218
|
+
const DATA_URI_SAFE_MIME_RE = /^data:(image\/(png|jpe?g|gif|webp|bmp|ico|avif|heic)|font\/(woff2?|otf|ttf))(;[^,]*)?,/i;
|
|
219
|
+
exports.MARKDOWN_LINK_PATTERNS = [
|
|
220
|
+
{
|
|
221
|
+
pattern: /\]\(\s*javascript:/i,
|
|
222
|
+
ruleId: 'MD-LINK-JS-SCHEME',
|
|
223
|
+
},
|
|
224
|
+
{
|
|
225
|
+
pattern: /\]\(\s*data:/i,
|
|
226
|
+
ruleId: 'MD-LINK-DATA-SCHEME',
|
|
227
|
+
safePredicate: (line) => {
|
|
228
|
+
const m = line.match(/\]\(\s*(data:[^)]*)/i);
|
|
229
|
+
if (!m)
|
|
230
|
+
return false;
|
|
231
|
+
return DATA_URI_SAFE_MIME_RE.test(m[1]);
|
|
232
|
+
},
|
|
233
|
+
},
|
|
234
|
+
{
|
|
235
|
+
pattern: /\]\(\s*https?:\/\/[^/\s]+:[^/@\s]+@/i,
|
|
236
|
+
ruleId: 'MD-LINK-USERINFO',
|
|
237
|
+
},
|
|
238
|
+
{
|
|
239
|
+
pattern: /[?&](token|access_token|id_token|refresh_token|api_key|apikey|secret|password|client_secret|code)=/i,
|
|
240
|
+
ruleId: 'MD-LINK-TOKEN-IN-QUERY',
|
|
241
|
+
},
|
|
242
|
+
];
|
|
243
|
+
const OBFUSCATION_PATTERN_ENTRIES = [
|
|
244
|
+
{
|
|
245
|
+
pattern: /\b(\w\s){4,}\w\b/,
|
|
246
|
+
message: 'Character-spacing obfuscation pattern detected (e.g. "i g n o r e")',
|
|
247
|
+
},
|
|
248
|
+
{
|
|
249
|
+
pattern: /<\/?(system|human|assistant|user)\s*>/i,
|
|
250
|
+
message: 'Delimiter injection pattern: <system>/<human>/<assistant>/<user> tag detected',
|
|
251
|
+
},
|
|
252
|
+
{
|
|
253
|
+
pattern: /0x[0-9a-fA-F]{16,}/,
|
|
254
|
+
message: 'Long hex sequence detected — possible encoded payload',
|
|
255
|
+
},
|
|
256
|
+
];
|
|
257
|
+
/**
|
|
258
|
+
* Scan text for potential prompt injection patterns.
|
|
259
|
+
* Returns an array of findings (empty = clean).
|
|
260
|
+
*/
|
|
261
|
+
function scanForInjection(text, opts = {}) {
|
|
262
|
+
if (!text || typeof text !== 'string') {
|
|
263
|
+
return { clean: true, findings: [], structuredFindings: [] };
|
|
264
|
+
}
|
|
265
|
+
const findings = [];
|
|
266
|
+
const structuredFindings = [];
|
|
267
|
+
for (const pattern of exports.INJECTION_PATTERNS) {
|
|
268
|
+
if (pattern.test(text)) {
|
|
269
|
+
findings.push(`Matched injection pattern: ${pattern.source}`);
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
for (const entry of OBFUSCATION_PATTERN_ENTRIES) {
|
|
273
|
+
if (entry.pattern.test(text)) {
|
|
274
|
+
findings.push(entry.message);
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
const lines = text.split('\n');
|
|
278
|
+
for (const entry of exports.MARKDOWN_LINK_PATTERNS) {
|
|
279
|
+
for (let i = 0; i < lines.length; i++) {
|
|
280
|
+
const line = lines[i];
|
|
281
|
+
const m = line.match(entry.pattern);
|
|
282
|
+
if (!m)
|
|
283
|
+
continue;
|
|
284
|
+
if (entry.safePredicate && entry.safePredicate(line))
|
|
285
|
+
continue;
|
|
286
|
+
const matchText = m[0];
|
|
287
|
+
findings.push(`Matched markdown link pattern [${entry.ruleId}]: ${matchText}`);
|
|
288
|
+
structuredFindings.push({
|
|
289
|
+
ruleId: entry.ruleId,
|
|
290
|
+
file: opts.file,
|
|
291
|
+
line: i + 1,
|
|
292
|
+
match: matchText,
|
|
293
|
+
});
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
if (opts.strict) {
|
|
297
|
+
// Check for suspicious Unicode that could hide instructions
|
|
298
|
+
// (zero-width chars, RTL override, homoglyph attacks)
|
|
299
|
+
if (/[\u200B-\u200F\u2028-\u202F\uFEFF\u00AD]/.test(text)) {
|
|
300
|
+
findings.push('Contains suspicious zero-width or invisible Unicode characters');
|
|
301
|
+
}
|
|
302
|
+
// Layer 1: Unicode tag block U+E0000–E007F (2025 supply-chain attack vector)
|
|
303
|
+
// These characters are invisible and can embed hidden instructions
|
|
304
|
+
if (/[\uDB40\uDC00-\uDB40\uDC7F]/u.test(text) || /[\u{E0000}-\u{E007F}]/u.test(text)) {
|
|
305
|
+
findings.push('Contains Unicode tag block characters (U+E0000–E007F) — invisible instruction injection vector');
|
|
306
|
+
}
|
|
307
|
+
// Check for extremely long strings that could be prompt stuffing.
|
|
308
|
+
// Normalize CRLF → LF before measuring so Windows checkouts don't inflate the count.
|
|
309
|
+
const normalizedLength = text.replace(/\r\n/g, '\n').replace(/\r/g, '\n').length;
|
|
310
|
+
if (normalizedLength > 50000) {
|
|
311
|
+
findings.push(`Suspicious text length: ${normalizedLength} chars (potential prompt stuffing)`);
|
|
312
|
+
}
|
|
313
|
+
}
|
|
314
|
+
return { clean: findings.length === 0, findings, structuredFindings };
|
|
315
|
+
}
|
|
316
|
+
/**
|
|
317
|
+
* Sanitize text that will be embedded in agent prompts or planning documents.
|
|
318
|
+
* Strips known injection markers while preserving legitimate content.
|
|
319
|
+
*/
|
|
320
|
+
function sanitizeForPrompt(text) {
|
|
321
|
+
if (!text || typeof text !== 'string')
|
|
322
|
+
return text;
|
|
323
|
+
let sanitized = text;
|
|
324
|
+
// Strip zero-width characters that could hide instructions
|
|
325
|
+
sanitized = sanitized.replace(/[\u200B-\u200F\u2028-\u202F\uFEFF\u00AD]/g, '');
|
|
326
|
+
// Neutralize XML/HTML tags that mimic system boundaries
|
|
327
|
+
// Note: <instructions> is excluded — GSD uses it as legitimate prompt structure
|
|
328
|
+
sanitized = sanitized.replace(/<(\/?)\s*(?:system|assistant|human|user)\s*>/gi, (_, slash) => `<${slash || ''}system-text>`);
|
|
329
|
+
// Neutralize [SYSTEM] / [INST] / [/INST] markers
|
|
330
|
+
sanitized = sanitized.replace(/\[(\/?)(SYSTEM|INST)\]/gi, (_, slash, tag) => `[${slash}${tag.toUpperCase()}-TEXT]`);
|
|
331
|
+
// Neutralize <<SYS>> and <</SYS>> markers (Llama-style delimiters)
|
|
332
|
+
sanitized = sanitized.replace(/<<\/?\s*SYS\s*>>/gi, '«SYS-TEXT»');
|
|
333
|
+
return sanitized;
|
|
334
|
+
}
|
|
335
|
+
/**
|
|
336
|
+
* Sanitize text that will be displayed back to the user.
|
|
337
|
+
* Removes protocol-like leak markers that should never surface in checkpoints.
|
|
338
|
+
*/
|
|
339
|
+
function sanitizeForDisplay(text) {
|
|
340
|
+
if (!text || typeof text !== 'string')
|
|
341
|
+
return text;
|
|
342
|
+
let sanitized = sanitizeForPrompt(text);
|
|
343
|
+
const protocolLeakPatterns = [
|
|
344
|
+
/^\s*(?:assistant|user|system)\s+to=[^:\s]+:[^\n]+$/i,
|
|
345
|
+
/^\s*<\|(?:assistant|user|system)[^|]*\|>\s*$/i,
|
|
346
|
+
];
|
|
347
|
+
sanitized = sanitized
|
|
348
|
+
.split('\n')
|
|
349
|
+
.filter(line => !protocolLeakPatterns.some(pattern => pattern.test(line)))
|
|
350
|
+
.join('\n');
|
|
351
|
+
return sanitized;
|
|
352
|
+
}
|
|
353
|
+
// ─── Shell Safety ───────────────────────────────────────────────────────────────────────
|
|
354
|
+
/**
|
|
355
|
+
* Validate that a string is safe to use as a shell argument when quoted.
|
|
356
|
+
*/
|
|
357
|
+
function validateShellArg(value, label) {
|
|
358
|
+
if (!value || typeof value !== 'string') {
|
|
359
|
+
throw new Error(`${label || 'Argument'}: empty or invalid value`);
|
|
360
|
+
}
|
|
361
|
+
if (value.includes('\0')) {
|
|
362
|
+
throw new Error(`${label || 'Argument'}: contains null bytes`);
|
|
363
|
+
}
|
|
364
|
+
if (/[$`]/.test(value) && /\$\(|`/.test(value)) {
|
|
365
|
+
throw new Error(`${label || 'Argument'}: contains potential command substitution`);
|
|
366
|
+
}
|
|
367
|
+
return value;
|
|
368
|
+
}
|
|
369
|
+
// ─── JSON Safety ──────────────────────────────────────────────────────────────────────────
|
|
370
|
+
/**
|
|
371
|
+
* Safely parse JSON with error handling and optional size limits.
|
|
372
|
+
*/
|
|
373
|
+
function safeJsonParse(text, opts = {}) {
|
|
374
|
+
const maxLength = opts.maxLength || 1048576;
|
|
375
|
+
const label = opts.label || 'JSON';
|
|
376
|
+
if (!text || typeof text !== 'string') {
|
|
377
|
+
return { ok: false, error: `${label}: empty or invalid input` };
|
|
378
|
+
}
|
|
379
|
+
if (text.length > maxLength) {
|
|
380
|
+
return { ok: false, error: `${label}: input exceeds ${maxLength} byte limit (got ${text.length})` };
|
|
381
|
+
}
|
|
382
|
+
try {
|
|
383
|
+
const value = JSON.parse(text);
|
|
384
|
+
return { ok: true, value };
|
|
385
|
+
}
|
|
386
|
+
catch (err) {
|
|
387
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
388
|
+
return { ok: false, error: `${label}: parse error — ${msg}` };
|
|
389
|
+
}
|
|
390
|
+
}
|
|
391
|
+
// ─── Phase/Argument Validation ─────────────────────────────────────────────────────────
|
|
392
|
+
/**
|
|
393
|
+
* Validate a phase number argument.
|
|
394
|
+
*/
|
|
395
|
+
function validatePhaseNumber(phase) {
|
|
396
|
+
if (!phase || typeof phase !== 'string') {
|
|
397
|
+
return { valid: false, error: 'Phase number is required' };
|
|
398
|
+
}
|
|
399
|
+
const trimmed = phase.trim();
|
|
400
|
+
if (/^\d{1,4}[A-Z]?(?:\.\d{1,3})*$/i.test(trimmed)) {
|
|
401
|
+
return { valid: true, normalized: trimmed };
|
|
402
|
+
}
|
|
403
|
+
if (/^[A-Z][A-Z0-9]*(?:-[A-Z0-9]+){1,4}$/i.test(trimmed) && trimmed.length <= 30) {
|
|
404
|
+
return { valid: true, normalized: trimmed };
|
|
405
|
+
}
|
|
406
|
+
return { valid: false, error: `Invalid phase number format: "${trimmed}"` };
|
|
407
|
+
}
|
|
408
|
+
/**
|
|
409
|
+
* Validate a STATE.md field name to prevent injection into regex patterns.
|
|
410
|
+
*/
|
|
411
|
+
function validateFieldName(field) {
|
|
412
|
+
if (!field || typeof field !== 'string') {
|
|
413
|
+
return { valid: false, error: 'Field name is required' };
|
|
414
|
+
}
|
|
415
|
+
if (/^[A-Za-z][A-Za-z0-9 _.\-/]{0,60}$/.test(field)) {
|
|
416
|
+
return { valid: true };
|
|
417
|
+
}
|
|
418
|
+
return { valid: false, error: `Invalid field name: "${field}"` };
|
|
419
|
+
}
|
|
420
|
+
// ─── Layer 3: Structural Schema Validation ──────────────────────────────────────────────────────────────────────────
|
|
421
|
+
const KNOWN_VALID_TAGS = new Set([
|
|
422
|
+
'objective', 'process', 'step', 'success_criteria', 'critical_rules',
|
|
423
|
+
'available_agent_types', 'purpose', 'required_reading',
|
|
424
|
+
]);
|
|
425
|
+
/**
|
|
426
|
+
* Validate the XML structure of a prompt file.
|
|
427
|
+
*/
|
|
428
|
+
function validatePromptStructure(text, fileType) {
|
|
429
|
+
if (!text || typeof text !== 'string') {
|
|
430
|
+
return { valid: true, violations: [] };
|
|
431
|
+
}
|
|
432
|
+
if (fileType !== 'agent' && fileType !== 'workflow') {
|
|
433
|
+
return { valid: true, violations: [] };
|
|
434
|
+
}
|
|
435
|
+
const violations = [];
|
|
436
|
+
const tagRegex = /<([A-Za-z][A-Za-z0-9_-]*)/g;
|
|
437
|
+
let match;
|
|
438
|
+
while ((match = tagRegex.exec(text)) !== null) {
|
|
439
|
+
const tag = match[1].toLowerCase();
|
|
440
|
+
if (!KNOWN_VALID_TAGS.has(tag)) {
|
|
441
|
+
violations.push(`Unknown XML tag in ${fileType} file: <${tag}>`);
|
|
442
|
+
}
|
|
443
|
+
}
|
|
444
|
+
return { valid: violations.length === 0, violations };
|
|
445
|
+
}
|
|
446
|
+
// ─── Layer 4: Paragraph-Level Entropy Anomaly Detection ─────────────────────────────────────────────────────────────────────
|
|
447
|
+
function shannonEntropy(text) {
|
|
448
|
+
if (!text || text.length === 0)
|
|
449
|
+
return 0;
|
|
450
|
+
const freq = {};
|
|
451
|
+
for (const ch of text) {
|
|
452
|
+
freq[ch] = (freq[ch] || 0) + 1;
|
|
453
|
+
}
|
|
454
|
+
const len = text.length;
|
|
455
|
+
let entropy = 0;
|
|
456
|
+
for (const count of Object.values(freq)) {
|
|
457
|
+
const p = count / len;
|
|
458
|
+
entropy -= p * Math.log2(p);
|
|
459
|
+
}
|
|
460
|
+
return entropy;
|
|
461
|
+
}
|
|
462
|
+
/**
|
|
463
|
+
* Scan text for paragraphs with anomalously high Shannon entropy.
|
|
464
|
+
*/
|
|
465
|
+
function scanEntropyAnomalies(text) {
|
|
466
|
+
if (!text || typeof text !== 'string') {
|
|
467
|
+
return { clean: true, findings: [] };
|
|
468
|
+
}
|
|
469
|
+
const findings = [];
|
|
470
|
+
const paragraphs = text.split(/\n\n+/);
|
|
471
|
+
for (const para of paragraphs) {
|
|
472
|
+
if (para.length <= 50)
|
|
473
|
+
continue;
|
|
474
|
+
const entropy = shannonEntropy(para);
|
|
475
|
+
if (entropy > 5.5) {
|
|
476
|
+
findings.push(`High-entropy paragraph detected (${entropy.toFixed(2)} bits/char) — possible encoded payload`);
|
|
477
|
+
}
|
|
478
|
+
}
|
|
479
|
+
return { clean: findings.length === 0, findings };
|
|
480
|
+
}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Shared semver comparison utility (ADR-457 pilot: first hand-written
|
|
4
|
+
* bin/lib/*.cjs collapsed to a TypeScript source of truth).
|
|
5
|
+
*
|
|
6
|
+
* Logic is preserved byte-for-behaviour from the prior hand-written
|
|
7
|
+
* `gsd-core/bin/lib/semver-compare.cjs`; only types are added. The
|
|
8
|
+
* normalization policy here is locked by `tests/semver-compare.test.cjs` and
|
|
9
|
+
* consumed by update-check, statusline dev-install detection, and changeset
|
|
10
|
+
* range compare (`scripts/changeset/cli.cjs`).
|
|
11
|
+
*/
|
|
12
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
13
|
+
exports.toNumericTuple = toNumericTuple;
|
|
14
|
+
exports.compareSemverCore = compareSemverCore;
|
|
15
|
+
exports.isSemverNewer = isSemverNewer;
|
|
16
|
+
exports.isStableTripletSemver = isStableTripletSemver;
|
|
17
|
+
function toNumericTuple(input) {
|
|
18
|
+
const cleaned = String(input == null ? '' : input).trim().replace(/^v/, '');
|
|
19
|
+
const base = cleaned.replace(/[-+].*$/, '');
|
|
20
|
+
const parts = base.split('.');
|
|
21
|
+
const major = Number.parseInt(parts[0], 10) || 0;
|
|
22
|
+
const minor = Number.parseInt(parts[1], 10) || 0;
|
|
23
|
+
const patch = Number.parseInt(parts[2], 10) || 0;
|
|
24
|
+
return [major, minor, patch];
|
|
25
|
+
}
|
|
26
|
+
function compareSemverCore(a, b) {
|
|
27
|
+
const [a0, a1, a2] = toNumericTuple(a);
|
|
28
|
+
const [b0, b1, b2] = toNumericTuple(b);
|
|
29
|
+
if (a0 !== b0)
|
|
30
|
+
return a0 > b0 ? 1 : -1;
|
|
31
|
+
if (a1 !== b1)
|
|
32
|
+
return a1 > b1 ? 1 : -1;
|
|
33
|
+
if (a2 !== b2)
|
|
34
|
+
return a2 > b2 ? 1 : -1;
|
|
35
|
+
return 0;
|
|
36
|
+
}
|
|
37
|
+
function isSemverNewer(a, b) {
|
|
38
|
+
return compareSemverCore(a, b) > 0;
|
|
39
|
+
}
|
|
40
|
+
function isStableTripletSemver(v) {
|
|
41
|
+
return /^\d+\.\d+\.\d+$/.test(String(v || '').replace(/^v/, ''));
|
|
42
|
+
}
|