@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,231 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# secret-scan-lint.sh — Lint governance policy for .secretscanignore exclusions
|
|
3
|
+
#
|
|
4
|
+
# Usage:
|
|
5
|
+
# scripts/secret-scan-lint.sh --file <path-to-.secretscanignore>
|
|
6
|
+
# scripts/secret-scan-lint.sh --file <path-to-.secretscanignore> --strict
|
|
7
|
+
#
|
|
8
|
+
# Exit codes:
|
|
9
|
+
# 0 = every exclusion has full annotation OR is grandfathered (with deprecation warning)
|
|
10
|
+
# 1 = annotation violation: missing required key, expired date, or unguarded wildcard
|
|
11
|
+
# without rule-id; OR (under --strict) any grandfathered entry is present
|
|
12
|
+
# 2 = usage/config error (file not found, invalid arguments)
|
|
13
|
+
#
|
|
14
|
+
# Annotation syntax (sidecar comment, must immediately precede the path line):
|
|
15
|
+
# # allow: <pattern> reason="..." owner="..." expires="YYYY-MM-DD" [rule-id="..."]
|
|
16
|
+
# <pattern>
|
|
17
|
+
#
|
|
18
|
+
# Required annotation keys: reason, owner, expires
|
|
19
|
+
# Optional annotation key: rule-id (REQUIRED when pattern contains '*' wildcards)
|
|
20
|
+
#
|
|
21
|
+
# Grandfathered entries: paths with any preceding plain comment (not a structured
|
|
22
|
+
# annotation) are treated as grandfathered in default mode — exit 0 with a
|
|
23
|
+
# deprecation warning to stderr. Under --strict, grandfathered entries cause exit 1.
|
|
24
|
+
#
|
|
25
|
+
# Design references:
|
|
26
|
+
# - GitGuardian exclusion annotation convention:
|
|
27
|
+
# https://docs.gitguardian.com/internal-repositories-monitoring/integrations/cli/secrets
|
|
28
|
+
# - CNCF Security TAG threat-model exception lifecycle:
|
|
29
|
+
# https://github.com/cncf/tag-security/blob/main/community/working-groups/threat-modeling/templates/threats.md
|
|
30
|
+
#
|
|
31
|
+
# Exit-code alignment with secret-scan.sh:
|
|
32
|
+
# Both scripts use 0=clean, 1=policy-violation/findings, 2=usage/config-error.
|
|
33
|
+
# The symmetry is intentional — CI can treat either non-zero as a gate failure.
|
|
34
|
+
|
|
35
|
+
set -euo pipefail
|
|
36
|
+
|
|
37
|
+
# ─── Argument Parsing ─────────────────────────────────────────────────────────
|
|
38
|
+
|
|
39
|
+
STRICT=false
|
|
40
|
+
IGNOREFILE=""
|
|
41
|
+
|
|
42
|
+
usage() {
|
|
43
|
+
echo "Usage: $0 --file <path-to-.secretscanignore> [--strict]" >&2
|
|
44
|
+
exit 2
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
while [[ $# -gt 0 ]]; do
|
|
48
|
+
case "$1" in
|
|
49
|
+
--file)
|
|
50
|
+
shift
|
|
51
|
+
[[ $# -eq 0 ]] && usage
|
|
52
|
+
IGNOREFILE="$1"
|
|
53
|
+
shift
|
|
54
|
+
;;
|
|
55
|
+
--strict)
|
|
56
|
+
STRICT=true
|
|
57
|
+
shift
|
|
58
|
+
;;
|
|
59
|
+
-h|--help)
|
|
60
|
+
usage
|
|
61
|
+
;;
|
|
62
|
+
*)
|
|
63
|
+
echo "Error: unknown argument: $1" >&2
|
|
64
|
+
usage
|
|
65
|
+
;;
|
|
66
|
+
esac
|
|
67
|
+
done
|
|
68
|
+
|
|
69
|
+
if [[ -z "$IGNOREFILE" ]]; then
|
|
70
|
+
usage
|
|
71
|
+
fi
|
|
72
|
+
|
|
73
|
+
if [[ ! -f "$IGNOREFILE" ]]; then
|
|
74
|
+
echo "Error: file not found: $IGNOREFILE" >&2
|
|
75
|
+
exit 2
|
|
76
|
+
fi
|
|
77
|
+
|
|
78
|
+
# ─── Date Helpers ─────────────────────────────────────────────────────────────
|
|
79
|
+
|
|
80
|
+
# Returns today's date as YYYY-MM-DD (portable across macOS and Linux)
|
|
81
|
+
today_date() {
|
|
82
|
+
date +%Y-%m-%d
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
# Returns true (0) if date1 < date2 (both YYYY-MM-DD strings)
|
|
86
|
+
date_is_past() {
|
|
87
|
+
local check_date="$1"
|
|
88
|
+
local today
|
|
89
|
+
today=$(today_date)
|
|
90
|
+
# Lexicographic comparison works for ISO-8601 dates
|
|
91
|
+
[[ "$check_date" < "$today" ]]
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
# ─── Annotation Parser ────────────────────────────────────────────────────────
|
|
95
|
+
|
|
96
|
+
# Returns value of a key="value" or key='value' pair from a string.
|
|
97
|
+
# Usage: extract_key <string> <key>
|
|
98
|
+
extract_key() {
|
|
99
|
+
local str="$1"
|
|
100
|
+
local key="$2"
|
|
101
|
+
# Match key="value" or key='value'
|
|
102
|
+
local val
|
|
103
|
+
val=$(echo "$str" | grep -oE "${key}=['\"][^'\"]+['\"]" | head -1 | sed "s/${key}=['\"]//;s/['\"]$//") || true
|
|
104
|
+
echo "$val"
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
# Returns true (0) if the string contains a wildcard glob character (* or **)
|
|
108
|
+
contains_wildcard() {
|
|
109
|
+
local pattern="$1"
|
|
110
|
+
[[ "$pattern" == *"*"* ]]
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
# Returns true (0) if a comment line is a structured annotation
|
|
114
|
+
# (must start with "# allow:" prefix)
|
|
115
|
+
is_structured_annotation() {
|
|
116
|
+
local comment="$1"
|
|
117
|
+
[[ "$comment" =~ ^#[[:space:]]+allow:[[:space:]] ]]
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
# ─── Main Lint Logic ──────────────────────────────────────────────────────────
|
|
121
|
+
|
|
122
|
+
VIOLATIONS=0
|
|
123
|
+
WARNINGS=0
|
|
124
|
+
|
|
125
|
+
# We process the file line-by-line, tracking the comment immediately preceding
|
|
126
|
+
# each path entry. If the preceding line was a comment, we inspect it.
|
|
127
|
+
|
|
128
|
+
prev_comment=""
|
|
129
|
+
lineno=0
|
|
130
|
+
|
|
131
|
+
while IFS= read -r line || [[ -n "$line" ]]; do
|
|
132
|
+
lineno=$((lineno + 1))
|
|
133
|
+
|
|
134
|
+
# Skip empty lines (reset prev_comment to avoid false association)
|
|
135
|
+
if [[ -z "${line// }" ]]; then
|
|
136
|
+
prev_comment=""
|
|
137
|
+
continue
|
|
138
|
+
fi
|
|
139
|
+
|
|
140
|
+
# Accumulate comment lines
|
|
141
|
+
if [[ "$line" =~ ^[[:space:]]*# ]]; then
|
|
142
|
+
prev_comment="$line"
|
|
143
|
+
continue
|
|
144
|
+
fi
|
|
145
|
+
|
|
146
|
+
# This is a path/pattern entry.
|
|
147
|
+
local_path="$line"
|
|
148
|
+
|
|
149
|
+
# ── Case 1: No preceding comment at all ────────────────────────────────────
|
|
150
|
+
if [[ -z "$prev_comment" ]]; then
|
|
151
|
+
echo "VIOLATION (line $lineno): '$local_path' has no annotation comment." >&2
|
|
152
|
+
echo " Required: # allow: <pattern> reason=\"...\" owner=\"...\" expires=\"YYYY-MM-DD\"" >&2
|
|
153
|
+
VIOLATIONS=$((VIOLATIONS + 1))
|
|
154
|
+
prev_comment=""
|
|
155
|
+
continue
|
|
156
|
+
fi
|
|
157
|
+
|
|
158
|
+
# ── Case 2: Preceding comment exists — check if it's a structured annotation ─
|
|
159
|
+
if is_structured_annotation "$prev_comment"; then
|
|
160
|
+
# Extract required keys
|
|
161
|
+
reason=$(extract_key "$prev_comment" "reason")
|
|
162
|
+
owner=$(extract_key "$prev_comment" "owner")
|
|
163
|
+
expires=$(extract_key "$prev_comment" "expires")
|
|
164
|
+
rule_id=$(extract_key "$prev_comment" "rule-id")
|
|
165
|
+
|
|
166
|
+
local_ok=true
|
|
167
|
+
|
|
168
|
+
if [[ -z "$reason" ]]; then
|
|
169
|
+
echo "VIOLATION (line $lineno): '$local_path' annotation missing required key: reason" >&2
|
|
170
|
+
local_ok=false
|
|
171
|
+
fi
|
|
172
|
+
|
|
173
|
+
if [[ -z "$owner" ]]; then
|
|
174
|
+
echo "VIOLATION (line $lineno): '$local_path' annotation missing required key: owner" >&2
|
|
175
|
+
local_ok=false
|
|
176
|
+
fi
|
|
177
|
+
|
|
178
|
+
if [[ -z "$expires" ]]; then
|
|
179
|
+
echo "VIOLATION (line $lineno): '$local_path' annotation missing required key: expires" >&2
|
|
180
|
+
local_ok=false
|
|
181
|
+
elif date_is_past "$expires"; then
|
|
182
|
+
echo "VIOLATION (line $lineno): '$local_path' annotation 'expires' date is in the past: $expires" >&2
|
|
183
|
+
echo " Review this exclusion and update or remove it." >&2
|
|
184
|
+
local_ok=false
|
|
185
|
+
fi
|
|
186
|
+
|
|
187
|
+
if contains_wildcard "$local_path" && [[ -z "$rule_id" ]]; then
|
|
188
|
+
echo "VIOLATION (line $lineno): '$local_path' uses a wildcard but is missing required key: rule-id" >&2
|
|
189
|
+
echo " Wildcard exclusions (** *.ext) require an explicit rule-id for auditability." >&2
|
|
190
|
+
local_ok=false
|
|
191
|
+
fi
|
|
192
|
+
|
|
193
|
+
if [[ "$local_ok" == false ]]; then
|
|
194
|
+
VIOLATIONS=$((VIOLATIONS + 1))
|
|
195
|
+
fi
|
|
196
|
+
|
|
197
|
+
else
|
|
198
|
+
# ── Case 3: Preceding comment is plain (not structured) — grandfathered ──
|
|
199
|
+
if [[ "$STRICT" == true ]]; then
|
|
200
|
+
echo "VIOLATION (line $lineno): '$local_path' is grandfathered (no structured annotation) — rejected under --strict mode." >&2
|
|
201
|
+
echo " Add: # allow: $local_path reason=\"...\" owner=\"...\" expires=\"YYYY-MM-DD\"" >&2
|
|
202
|
+
VIOLATIONS=$((VIOLATIONS + 1))
|
|
203
|
+
else
|
|
204
|
+
echo "WARNING (line $lineno): '$local_path' is grandfathered (missing structured annotation)." >&2
|
|
205
|
+
echo " DEPRECATION: migrate to structured annotation before removing grandfather status." >&2
|
|
206
|
+
echo " Required: # allow: $local_path reason=\"...\" owner=\"...\" expires=\"YYYY-MM-DD\"" >&2
|
|
207
|
+
echo " See: https://docs.gitguardian.com/internal-repositories-monitoring/integrations/cli/secrets" >&2
|
|
208
|
+
WARNINGS=$((WARNINGS + 1))
|
|
209
|
+
fi
|
|
210
|
+
fi
|
|
211
|
+
|
|
212
|
+
prev_comment=""
|
|
213
|
+
|
|
214
|
+
done < "$IGNOREFILE"
|
|
215
|
+
|
|
216
|
+
# ─── Summary ──────────────────────────────────────────────────────────────────
|
|
217
|
+
|
|
218
|
+
if [[ $VIOLATIONS -gt 0 ]]; then
|
|
219
|
+
echo "secret-scan-lint: $VIOLATIONS violation(s) found" >&2
|
|
220
|
+
if [[ $STRICT == true ]]; then
|
|
221
|
+
echo "secret-scan-lint: --strict mode active — grandfathered entries are not permitted" >&2
|
|
222
|
+
fi
|
|
223
|
+
exit 1
|
|
224
|
+
fi
|
|
225
|
+
|
|
226
|
+
if [[ $WARNINGS -gt 0 ]]; then
|
|
227
|
+
echo "secret-scan-lint: $WARNINGS grandfathered entry/entries (deprecation warning)" >&2
|
|
228
|
+
fi
|
|
229
|
+
|
|
230
|
+
echo "secret-scan-lint: OK"
|
|
231
|
+
exit 0
|
|
@@ -0,0 +1,358 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# secret-scan.sh — Check files for accidentally committed secrets/credentials
|
|
3
|
+
#
|
|
4
|
+
# Usage:
|
|
5
|
+
# scripts/secret-scan.sh --diff origin/main # CI mode: scan changed files
|
|
6
|
+
# scripts/secret-scan.sh --file path/to/file # Scan a single file
|
|
7
|
+
# scripts/secret-scan.sh --dir agents/ # Scan all files in a directory
|
|
8
|
+
# scripts/secret-scan.sh --diff origin/main --strict # Strict/release mode
|
|
9
|
+
#
|
|
10
|
+
# Flags:
|
|
11
|
+
# --strict Reduced-exclusion mode for release and security-audit CI lanes.
|
|
12
|
+
# Under --strict:
|
|
13
|
+
# - Grandfathered (un-annotated) .secretscanignore entries are
|
|
14
|
+
# treated as FAILURES rather than silently honoured.
|
|
15
|
+
# - Exclusions whose 'expires' date is in the past are ignored
|
|
16
|
+
# (the file IS scanned, not skipped).
|
|
17
|
+
# This flag does not change secret-detection logic — only which
|
|
18
|
+
# exclusions are applied.
|
|
19
|
+
#
|
|
20
|
+
# Exit codes:
|
|
21
|
+
# 0 = clean
|
|
22
|
+
# 1 = findings detected
|
|
23
|
+
# 2 = usage error
|
|
24
|
+
#
|
|
25
|
+
# Annotation format for .secretscanignore (required for --strict compliance):
|
|
26
|
+
# # allow: <pattern> reason="..." owner="..." expires="YYYY-MM-DD" [rule-id="..."]
|
|
27
|
+
# <pattern>
|
|
28
|
+
#
|
|
29
|
+
# Design references:
|
|
30
|
+
# - GitGuardian exclusion annotation convention:
|
|
31
|
+
# https://docs.gitguardian.com/internal-repositories-monitoring/integrations/cli/secrets
|
|
32
|
+
# - CNCF Security TAG threat-model exception lifecycle:
|
|
33
|
+
# https://github.com/cncf/tag-security/blob/main/community/working-groups/threat-modeling/templates/threats.md
|
|
34
|
+
#
|
|
35
|
+
# Periodic reduced-exclusion scan procedure:
|
|
36
|
+
# Run this script with --strict on every release branch and during scheduled
|
|
37
|
+
# security reviews. This mode intentionally skips grandfathered entries and
|
|
38
|
+
# expired exclusions so that accumulated technical debt in the ignore-list
|
|
39
|
+
# cannot permanently hide secrets. See SECURITY.md for the audit runbook.
|
|
40
|
+
set -euo pipefail
|
|
41
|
+
|
|
42
|
+
# ─── Global mode flag ─────────────────────────────────────────────────────────
|
|
43
|
+
STRICT_MODE=false
|
|
44
|
+
|
|
45
|
+
# ─── Secret Patterns ─────────────────────────────────────────────────────────
|
|
46
|
+
# Format: "LABEL:::REGEX"
|
|
47
|
+
# Each entry is a human label paired with a POSIX extended regex.
|
|
48
|
+
|
|
49
|
+
SECRET_PATTERNS=(
|
|
50
|
+
# AWS
|
|
51
|
+
"AWS Access Key:::AKIA[0-9A-Z]{16}"
|
|
52
|
+
"AWS Secret Key:::aws_secret_access_key[[:space:]]*=[[:space:]]*[A-Za-z0-9/+=]{40}"
|
|
53
|
+
|
|
54
|
+
# OpenAI / Anthropic / AI providers
|
|
55
|
+
"OpenAI API Key:::sk-[A-Za-z0-9]{20,}"
|
|
56
|
+
"Anthropic API Key:::sk-ant-[A-Za-z0-9_-]{20,}"
|
|
57
|
+
|
|
58
|
+
# GitHub
|
|
59
|
+
"GitHub PAT:::ghp_[A-Za-z0-9]{36}"
|
|
60
|
+
"GitHub OAuth:::gho_[A-Za-z0-9]{36}"
|
|
61
|
+
"GitHub App Token:::ghs_[A-Za-z0-9]{36}"
|
|
62
|
+
"GitHub Fine-grained PAT:::github_pat_[A-Za-z0-9_]{20,}"
|
|
63
|
+
|
|
64
|
+
# Stripe
|
|
65
|
+
"Stripe Secret Key:::sk_live_[A-Za-z0-9]{24,}"
|
|
66
|
+
"Stripe Publishable Key:::pk_live_[A-Za-z0-9]{24,}"
|
|
67
|
+
|
|
68
|
+
# Generic patterns
|
|
69
|
+
"Private Key Header:::-----BEGIN[[:space:]]+(RSA|EC|DSA|OPENSSH)?[[:space:]]*PRIVATE[[:space:]]+KEY-----"
|
|
70
|
+
"Generic API Key Assignment:::api[_-]?key[[:space:]]*[:=][[:space:]]*['\"][A-Za-z0-9_-]{20,}['\"]"
|
|
71
|
+
"Generic Secret Assignment:::secret[[:space:]]*[:=][[:space:]]*['\"][A-Za-z0-9_-]{20,}['\"]"
|
|
72
|
+
"Generic Token Assignment:::token[[:space:]]*[:=][[:space:]]*['\"][A-Za-z0-9_-]{20,}['\"]"
|
|
73
|
+
"Generic Password Assignment:::password[[:space:]]*[:=][[:space:]]*['\"][^'\"]{8,}['\"]"
|
|
74
|
+
|
|
75
|
+
# Slack
|
|
76
|
+
"Slack Bot Token:::xoxb-[0-9]{10,}-[A-Za-z0-9]{20,}"
|
|
77
|
+
"Slack Webhook:::hooks\.slack\.com/services/T[A-Z0-9]{8,}/B[A-Z0-9]{8,}/[A-Za-z0-9]{24}"
|
|
78
|
+
|
|
79
|
+
# Google
|
|
80
|
+
"Google API Key:::AIza[A-Za-z0-9_-]{35}"
|
|
81
|
+
|
|
82
|
+
# NPM
|
|
83
|
+
"NPM Token:::npm_[A-Za-z0-9]{36}"
|
|
84
|
+
|
|
85
|
+
# .env file content (key=value with sensitive-looking keys)
|
|
86
|
+
"Env Variable Leak:::(DATABASE_URL|DB_PASSWORD|REDIS_URL|MONGO_URI|JWT_SECRET|SESSION_SECRET|ENCRYPTION_KEY)[[:space:]]*=[[:space:]]*[^[:space:]]{8,}"
|
|
87
|
+
)
|
|
88
|
+
|
|
89
|
+
# ─── Ignorelist ──────────────────────────────────────────────────────────────
|
|
90
|
+
#
|
|
91
|
+
# Entries in IGNORED_FILES are loaded from .secretscanignore.
|
|
92
|
+
# In --strict mode, only fully-annotated entries with a future 'expires' date
|
|
93
|
+
# are loaded. Grandfathered entries and expired entries are skipped (the
|
|
94
|
+
# corresponding files ARE scanned, not excluded).
|
|
95
|
+
#
|
|
96
|
+
# Annotation format (structured comment must immediately precede the path):
|
|
97
|
+
# # allow: <pattern> reason="..." owner="..." expires="YYYY-MM-DD" [rule-id="..."]
|
|
98
|
+
# <pattern>
|
|
99
|
+
#
|
|
100
|
+
# Entries without a structured annotation are grandfathered:
|
|
101
|
+
# - Default mode: accepted (file excluded), deprecation warning emitted
|
|
102
|
+
# - Strict mode: rejected (file scanned, no exclusion applied)
|
|
103
|
+
|
|
104
|
+
IGNOREFILE=".secretscanignore"
|
|
105
|
+
IGNORED_FILES=()
|
|
106
|
+
|
|
107
|
+
# Returns value of key="value" annotation pair from a string
|
|
108
|
+
_extract_annotation_key() {
|
|
109
|
+
local str="$1"
|
|
110
|
+
local key="$2"
|
|
111
|
+
echo "$str" | grep -oE "${key}=['\"][^'\"]+['\"]" | head -1 | sed "s/${key}=['\"]//;s/['\"]$//" || true
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
# Returns today as YYYY-MM-DD
|
|
115
|
+
_today() {
|
|
116
|
+
date +%Y-%m-%d
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
# Returns 0 (true) if a date string YYYY-MM-DD is strictly in the past
|
|
120
|
+
_date_is_past() {
|
|
121
|
+
local d="$1"
|
|
122
|
+
[[ "$d" < "$(_today)" ]]
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
load_ignorelist() {
|
|
126
|
+
if [[ ! -f "$IGNOREFILE" ]]; then
|
|
127
|
+
return
|
|
128
|
+
fi
|
|
129
|
+
|
|
130
|
+
local prev_comment=""
|
|
131
|
+
|
|
132
|
+
while IFS= read -r line || [[ -n "$line" ]]; do
|
|
133
|
+
# Empty line resets context
|
|
134
|
+
if [[ -z "${line// }" ]]; then
|
|
135
|
+
prev_comment=""
|
|
136
|
+
continue
|
|
137
|
+
fi
|
|
138
|
+
|
|
139
|
+
# Accumulate comment
|
|
140
|
+
if [[ "$line" =~ ^[[:space:]]*# ]]; then
|
|
141
|
+
prev_comment="$line"
|
|
142
|
+
continue
|
|
143
|
+
fi
|
|
144
|
+
|
|
145
|
+
# This is a path entry
|
|
146
|
+
local pattern="$line"
|
|
147
|
+
|
|
148
|
+
# Determine if preceding comment is a structured annotation
|
|
149
|
+
local is_structured=false
|
|
150
|
+
if [[ "$prev_comment" =~ ^#[[:space:]]+allow:[[:space:]] ]]; then
|
|
151
|
+
is_structured=true
|
|
152
|
+
fi
|
|
153
|
+
|
|
154
|
+
if [[ "$is_structured" == true ]]; then
|
|
155
|
+
# Parse structured annotation
|
|
156
|
+
local expires
|
|
157
|
+
expires=$(_extract_annotation_key "$prev_comment" "expires")
|
|
158
|
+
|
|
159
|
+
if [[ -n "$expires" ]] && _date_is_past "$expires"; then
|
|
160
|
+
# Expired exclusion — never apply, regardless of mode
|
|
161
|
+
echo "secret-scan: WARNING: exclusion '$pattern' has expired (expires=$expires) — entry ignored" >&2
|
|
162
|
+
prev_comment=""
|
|
163
|
+
continue
|
|
164
|
+
fi
|
|
165
|
+
|
|
166
|
+
# Valid structured annotation — always apply
|
|
167
|
+
IGNORED_FILES+=("$pattern")
|
|
168
|
+
|
|
169
|
+
else
|
|
170
|
+
# Grandfathered (plain comment or no comment)
|
|
171
|
+
if [[ "$STRICT_MODE" == true ]]; then
|
|
172
|
+
# Strict mode: do NOT apply grandfathered exclusion
|
|
173
|
+
echo "secret-scan: WARNING (--strict): grandfathered exclusion '$pattern' not applied" >&2
|
|
174
|
+
else
|
|
175
|
+
# Default mode: apply but warn
|
|
176
|
+
echo "secret-scan: DEPRECATION WARNING: '$pattern' has no structured annotation — grandfather applied" >&2
|
|
177
|
+
echo " Migrate to: # allow: $pattern reason=\"...\" owner=\"...\" expires=\"YYYY-MM-DD\"" >&2
|
|
178
|
+
IGNORED_FILES+=("$pattern")
|
|
179
|
+
fi
|
|
180
|
+
fi
|
|
181
|
+
|
|
182
|
+
prev_comment=""
|
|
183
|
+
done < "$IGNOREFILE"
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
is_ignored() {
|
|
187
|
+
local file="$1"
|
|
188
|
+
if [[ ${#IGNORED_FILES[@]} -eq 0 ]]; then
|
|
189
|
+
return 1
|
|
190
|
+
fi
|
|
191
|
+
for pattern in "${IGNORED_FILES[@]}"; do
|
|
192
|
+
# Support glob-style matching
|
|
193
|
+
# shellcheck disable=SC2254
|
|
194
|
+
case "$file" in
|
|
195
|
+
$pattern) return 0 ;;
|
|
196
|
+
esac
|
|
197
|
+
done
|
|
198
|
+
return 1
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
# ─── Skip Rules ──────────────────────────────────────────────────────────────
|
|
202
|
+
|
|
203
|
+
should_skip_file() {
|
|
204
|
+
local file="$1"
|
|
205
|
+
# Skip binary files
|
|
206
|
+
case "$file" in
|
|
207
|
+
*.png|*.jpg|*.jpeg|*.gif|*.ico|*.woff|*.woff2|*.ttf|*.eot|*.otf) return 0 ;;
|
|
208
|
+
*.zip|*.tar|*.gz|*.bz2|*.xz|*.7z) return 0 ;;
|
|
209
|
+
*.pdf|*.doc|*.docx|*.xls|*.xlsx) return 0 ;;
|
|
210
|
+
esac
|
|
211
|
+
# Skip lockfiles and node_modules
|
|
212
|
+
case "$file" in
|
|
213
|
+
*/node_modules/*) return 0 ;;
|
|
214
|
+
*/package-lock.json) return 0 ;;
|
|
215
|
+
*/yarn.lock) return 0 ;;
|
|
216
|
+
*/pnpm-lock.yaml) return 0 ;;
|
|
217
|
+
esac
|
|
218
|
+
# Skip the scan scripts themselves and test files
|
|
219
|
+
case "$file" in
|
|
220
|
+
*/secret-scan.sh) return 0 ;;
|
|
221
|
+
*/secret-scan-lint.test.cjs) return 0 ;;
|
|
222
|
+
*/security-scan.test.cjs) return 0 ;;
|
|
223
|
+
*/security-prompt-injection.test.cjs) return 0 ;;
|
|
224
|
+
tests/fixtures/adversarial/security/*|*/tests/fixtures/adversarial/security/*) return 0 ;;
|
|
225
|
+
esac
|
|
226
|
+
return 1
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
# ─── File Collection ─────────────────────────────────────────────────────────
|
|
230
|
+
|
|
231
|
+
collect_files() {
|
|
232
|
+
local mode="$1"
|
|
233
|
+
shift
|
|
234
|
+
|
|
235
|
+
case "$mode" in
|
|
236
|
+
--diff)
|
|
237
|
+
local base="${1:-origin/main}"
|
|
238
|
+
git diff --name-only --diff-filter=ACMR "$base"...HEAD 2>/dev/null \
|
|
239
|
+
| grep -vE '\.(png|jpg|jpeg|gif|ico|woff|woff2|ttf|eot|otf|zip|tar|gz|pdf)$' || true
|
|
240
|
+
;;
|
|
241
|
+
--file)
|
|
242
|
+
if [[ -f "$1" ]]; then
|
|
243
|
+
echo "$1"
|
|
244
|
+
else
|
|
245
|
+
echo "Error: file not found: $1" >&2
|
|
246
|
+
exit 2
|
|
247
|
+
fi
|
|
248
|
+
;;
|
|
249
|
+
--dir)
|
|
250
|
+
local dir="$1"
|
|
251
|
+
if [[ ! -d "$dir" ]]; then
|
|
252
|
+
echo "Error: directory not found: $dir" >&2
|
|
253
|
+
exit 2
|
|
254
|
+
fi
|
|
255
|
+
find "$dir" -type f ! -path '*/node_modules/*' ! -path '*/.git/*' ! -path '*/dist/*' \
|
|
256
|
+
! -name '*.png' ! -name '*.jpg' ! -name '*.gif' ! -name '*.woff*' 2>/dev/null || true
|
|
257
|
+
;;
|
|
258
|
+
--stdin)
|
|
259
|
+
cat
|
|
260
|
+
;;
|
|
261
|
+
*)
|
|
262
|
+
echo "Usage: $0 --diff [base] | --file <path> | --dir <path> | --stdin" >&2
|
|
263
|
+
exit 2
|
|
264
|
+
;;
|
|
265
|
+
esac
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
# ─── Scanner ─────────────────────────────────────────────────────────────────
|
|
269
|
+
|
|
270
|
+
scan_file() {
|
|
271
|
+
local file="$1"
|
|
272
|
+
local found=0
|
|
273
|
+
|
|
274
|
+
if is_ignored "$file"; then
|
|
275
|
+
return 0
|
|
276
|
+
fi
|
|
277
|
+
|
|
278
|
+
for entry in "${SECRET_PATTERNS[@]}"; do
|
|
279
|
+
local label="${entry%%:::*}"
|
|
280
|
+
local pattern="${entry#*:::}"
|
|
281
|
+
|
|
282
|
+
local matches
|
|
283
|
+
matches=$(grep -nE -e "$pattern" "$file" 2>/dev/null || true)
|
|
284
|
+
if [[ -n "$matches" ]]; then
|
|
285
|
+
if [[ $found -eq 0 ]]; then
|
|
286
|
+
echo "FAIL: $file"
|
|
287
|
+
found=1
|
|
288
|
+
fi
|
|
289
|
+
echo "$matches" | while IFS= read -r line; do
|
|
290
|
+
echo " [$label] $line"
|
|
291
|
+
done
|
|
292
|
+
fi
|
|
293
|
+
done
|
|
294
|
+
|
|
295
|
+
return $found
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
# ─── Main ────────────────────────────────────────────────────────────────────
|
|
299
|
+
|
|
300
|
+
main() {
|
|
301
|
+
if [[ $# -eq 0 ]]; then
|
|
302
|
+
echo "Usage: $0 --diff [base] | --file <path> | --dir <path> [--strict]" >&2
|
|
303
|
+
exit 2
|
|
304
|
+
fi
|
|
305
|
+
|
|
306
|
+
# Parse --strict flag first (may appear anywhere in argv)
|
|
307
|
+
local remaining_args=()
|
|
308
|
+
for arg in "$@"; do
|
|
309
|
+
if [[ "$arg" == "--strict" ]]; then
|
|
310
|
+
STRICT_MODE=true
|
|
311
|
+
else
|
|
312
|
+
remaining_args+=("$arg")
|
|
313
|
+
fi
|
|
314
|
+
done
|
|
315
|
+
set -- "${remaining_args[@]}"
|
|
316
|
+
|
|
317
|
+
if [[ $# -eq 0 ]]; then
|
|
318
|
+
echo "Usage: $0 --diff [base] | --file <path> | --dir <path> [--strict]" >&2
|
|
319
|
+
exit 2
|
|
320
|
+
fi
|
|
321
|
+
|
|
322
|
+
load_ignorelist
|
|
323
|
+
|
|
324
|
+
local mode="$1"
|
|
325
|
+
shift
|
|
326
|
+
|
|
327
|
+
local files
|
|
328
|
+
files=$(collect_files "$mode" "$@")
|
|
329
|
+
|
|
330
|
+
if [[ -z "$files" ]]; then
|
|
331
|
+
echo "secret-scan: no files to scan"
|
|
332
|
+
exit 0
|
|
333
|
+
fi
|
|
334
|
+
|
|
335
|
+
local total=0
|
|
336
|
+
local failed=0
|
|
337
|
+
|
|
338
|
+
while IFS= read -r file; do
|
|
339
|
+
[[ -z "$file" ]] && continue
|
|
340
|
+
if should_skip_file "$file"; then
|
|
341
|
+
continue
|
|
342
|
+
fi
|
|
343
|
+
total=$((total + 1))
|
|
344
|
+
if ! scan_file "$file"; then
|
|
345
|
+
failed=$((failed + 1))
|
|
346
|
+
fi
|
|
347
|
+
done <<< "$files"
|
|
348
|
+
|
|
349
|
+
echo ""
|
|
350
|
+
echo "secret-scan: scanned $total files, $failed with findings"
|
|
351
|
+
|
|
352
|
+
if [[ $failed -gt 0 ]]; then
|
|
353
|
+
exit 1
|
|
354
|
+
fi
|
|
355
|
+
exit 0
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
main "$@"
|