@opengsd/gsd-core 1.2.0-rc.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.ja-JP.md +870 -0
- package/README.ko-KR.md +861 -0
- package/README.md +301 -0
- package/README.pt-BR.md +492 -0
- package/README.zh-CN.md +842 -0
- package/agents/gsd-advisor-researcher.md +127 -0
- package/agents/gsd-ai-researcher.md +133 -0
- package/agents/gsd-assumptions-analyzer.md +105 -0
- package/agents/gsd-code-fixer.md +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 +615 -0
- package/agents/gsd-domain-researcher.md +153 -0
- package/agents/gsd-eval-auditor.md +191 -0
- package/agents/gsd-eval-planner.md +154 -0
- package/agents/gsd-executor.md +772 -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 +928 -0
- package/agents/gsd-plan-checker.md +978 -0
- package/agents/gsd-planner.md +1218 -0
- package/agents/gsd-project-researcher.md +677 -0
- package/agents/gsd-research-synthesizer.md +255 -0
- package/agents/gsd-roadmapper.md +688 -0
- package/agents/gsd-security-auditor.md +155 -0
- package/agents/gsd-ui-auditor.md +495 -0
- package/agents/gsd-ui-checker.md +309 -0
- package/agents/gsd-ui-researcher.md +380 -0
- package/agents/gsd-user-profiler.md +171 -0
- package/agents/gsd-verifier.md +917 -0
- package/bin/install.js +10936 -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 +46 -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/discuss-phase.md +76 -0
- package/commands/gsd/docs-update.md +49 -0
- package/commands/gsd/eval-review.md +33 -0
- package/commands/gsd/execute-phase.md +64 -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 +199 -0
- package/commands/gsd/health.md +31 -0
- package/commands/gsd/help.md +28 -0
- package/commands/gsd/import.md +41 -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/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 +62 -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 +47 -0
- package/commands/gsd/quick.md +174 -0
- package/commands/gsd/resume-work.md +30 -0
- package/commands/gsd/review-backlog.md +63 -0
- package/commands/gsd/review.md +41 -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 +19 -0
- package/commands/gsd/surface.md +155 -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 +48 -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/get-shit-done/bin/check-latest-version.cjs +106 -0
- package/get-shit-done/bin/gsd-tools.cjs +1676 -0
- package/get-shit-done/bin/lib/active-workstream-store.cjs +302 -0
- package/get-shit-done/bin/lib/adr-parser.cjs +394 -0
- package/get-shit-done/bin/lib/agent-command-router.cjs +65 -0
- package/get-shit-done/bin/lib/artifacts.cjs +53 -0
- package/get-shit-done/bin/lib/audit.cjs +755 -0
- package/get-shit-done/bin/lib/check-command-router.cjs +333 -0
- package/get-shit-done/bin/lib/cjs-command-router-adapter.cjs +118 -0
- package/get-shit-done/bin/lib/clock.cjs +96 -0
- package/get-shit-done/bin/lib/clusters.cjs +135 -0
- package/get-shit-done/bin/lib/code-review-flags.cjs +74 -0
- package/get-shit-done/bin/lib/command-aliases.cjs +815 -0
- package/get-shit-done/bin/lib/command-arg-projection.cjs +62 -0
- package/get-shit-done/bin/lib/command-routing-hub.cjs +388 -0
- package/get-shit-done/bin/lib/commands.cjs +1188 -0
- package/get-shit-done/bin/lib/config-schema.cjs +31 -0
- package/get-shit-done/bin/lib/config.cjs +728 -0
- package/get-shit-done/bin/lib/configuration.cjs +248 -0
- package/get-shit-done/bin/lib/context-utilization.cjs +47 -0
- package/get-shit-done/bin/lib/core.cjs +2121 -0
- package/get-shit-done/bin/lib/decisions.cjs +116 -0
- package/get-shit-done/bin/lib/docs.cjs +270 -0
- package/get-shit-done/bin/lib/drift.cjs +388 -0
- package/get-shit-done/bin/lib/fallow-runner.cjs +109 -0
- package/get-shit-done/bin/lib/frontmatter.cjs +389 -0
- package/get-shit-done/bin/lib/gap-checker.cjs +205 -0
- package/get-shit-done/bin/lib/graphify.cjs +592 -0
- package/get-shit-done/bin/lib/gsd2-import.cjs +514 -0
- package/get-shit-done/bin/lib/init-command-router.cjs +58 -0
- package/get-shit-done/bin/lib/init.cjs +2112 -0
- package/get-shit-done/bin/lib/install-profiles.cjs +603 -0
- package/get-shit-done/bin/lib/installer-migration-authoring.cjs +117 -0
- package/get-shit-done/bin/lib/installer-migration-report.cjs +354 -0
- package/get-shit-done/bin/lib/installer-migrations/000-first-time-baseline.cjs +220 -0
- package/get-shit-done/bin/lib/installer-migrations/001-legacy-orphan-files.cjs +41 -0
- package/get-shit-done/bin/lib/installer-migrations/002-codex-legacy-hooks-json.cjs +80 -0
- package/get-shit-done/bin/lib/installer-migrations.cjs +778 -0
- package/get-shit-done/bin/lib/intel.cjs +708 -0
- package/get-shit-done/bin/lib/learnings.cjs +421 -0
- package/get-shit-done/bin/lib/milestone.cjs +314 -0
- package/get-shit-done/bin/lib/model-catalog.cjs +212 -0
- package/get-shit-done/bin/lib/model-profiles.cjs +31 -0
- package/get-shit-done/bin/lib/observability/event.cjs +82 -0
- package/get-shit-done/bin/lib/observability/logger.cjs +174 -0
- package/get-shit-done/bin/lib/observability/redaction.cjs +50 -0
- package/get-shit-done/bin/lib/package-identity.cjs +31 -0
- package/get-shit-done/bin/lib/phase-command-router.cjs +191 -0
- package/get-shit-done/bin/lib/phase-lifecycle.cjs +80 -0
- package/get-shit-done/bin/lib/phase.cjs +1607 -0
- package/get-shit-done/bin/lib/phases-command-router.cjs +39 -0
- package/get-shit-done/bin/lib/plan-scan.cjs +97 -0
- package/get-shit-done/bin/lib/planning-workspace.cjs +238 -0
- package/get-shit-done/bin/lib/profile-output.cjs +1141 -0
- package/get-shit-done/bin/lib/profile-pipeline.cjs +539 -0
- package/get-shit-done/bin/lib/project-root.cjs +112 -0
- package/get-shit-done/bin/lib/prompt-budget.cjs +399 -0
- package/get-shit-done/bin/lib/review-reviewer-selection.cjs +125 -0
- package/get-shit-done/bin/lib/roadmap-command-router.cjs +28 -0
- package/get-shit-done/bin/lib/roadmap.cjs +650 -0
- package/get-shit-done/bin/lib/runtime-artifact-layout.cjs +301 -0
- package/get-shit-done/bin/lib/runtime-homes.cjs +222 -0
- package/get-shit-done/bin/lib/runtime-name-policy.cjs +83 -0
- package/get-shit-done/bin/lib/runtime-slash.cjs +112 -0
- package/get-shit-done/bin/lib/schema-detect.cjs +165 -0
- package/get-shit-done/bin/lib/secrets.cjs +32 -0
- package/get-shit-done/bin/lib/security.cjs +600 -0
- package/get-shit-done/bin/lib/semver-compare.cjs +35 -0
- package/get-shit-done/bin/lib/shell-command-projection.cjs +500 -0
- package/get-shit-done/bin/lib/state-command-router.cjs +252 -0
- package/get-shit-done/bin/lib/state-document.cjs +263 -0
- package/get-shit-done/bin/lib/state.cjs +2038 -0
- package/get-shit-done/bin/lib/surface.cjs +470 -0
- package/get-shit-done/bin/lib/task-command-router.cjs +81 -0
- package/get-shit-done/bin/lib/template.cjs +228 -0
- package/get-shit-done/bin/lib/uat.cjs +289 -0
- package/get-shit-done/bin/lib/update-context.cjs +209 -0
- package/get-shit-done/bin/lib/validate-command-router.cjs +83 -0
- package/get-shit-done/bin/lib/validate.cjs +92 -0
- package/get-shit-done/bin/lib/verify-command-router.cjs +40 -0
- package/get-shit-done/bin/lib/verify.cjs +1511 -0
- package/get-shit-done/bin/lib/workstream-inventory-builder.cjs +74 -0
- package/get-shit-done/bin/lib/workstream-inventory.cjs +146 -0
- package/get-shit-done/bin/lib/workstream-name-policy.cjs +94 -0
- package/get-shit-done/bin/lib/workstream.cjs +389 -0
- package/get-shit-done/bin/lib/worktree-safety.cjs +985 -0
- package/get-shit-done/bin/shared/config-defaults.manifest.json +97 -0
- package/get-shit-done/bin/shared/config-schema.manifest.json +175 -0
- package/get-shit-done/bin/shared/model-catalog.json +122 -0
- package/get-shit-done/bin/shared/runtime-aliases.manifest.json +75 -0
- package/get-shit-done/bin/verify-reapply-patches.cjs +352 -0
- package/get-shit-done/contexts/dev.md +21 -0
- package/get-shit-done/contexts/research.md +22 -0
- package/get-shit-done/contexts/review.md +23 -0
- package/get-shit-done/references/agent-contracts.md +79 -0
- package/get-shit-done/references/ai-evals.md +156 -0
- package/get-shit-done/references/ai-frameworks.md +186 -0
- package/get-shit-done/references/artifact-types.md +131 -0
- package/get-shit-done/references/autonomous-smart-discuss.md +277 -0
- package/get-shit-done/references/checkpoints.md +814 -0
- package/get-shit-done/references/common-bug-patterns.md +114 -0
- package/get-shit-done/references/context-budget.md +85 -0
- package/get-shit-done/references/continuation-format.md +253 -0
- package/get-shit-done/references/debugger-philosophy.md +76 -0
- package/get-shit-done/references/decimal-phase-calculation.md +64 -0
- package/get-shit-done/references/doc-conflict-engine.md +91 -0
- package/get-shit-done/references/domain-probes.md +125 -0
- package/get-shit-done/references/execute-mvp-tdd.md +81 -0
- package/get-shit-done/references/executor-examples.md +110 -0
- package/get-shit-done/references/few-shot-examples/plan-checker.md +73 -0
- package/get-shit-done/references/few-shot-examples/verifier.md +109 -0
- package/get-shit-done/references/gate-prompts.md +100 -0
- package/get-shit-done/references/gates.md +70 -0
- package/get-shit-done/references/git-integration.md +298 -0
- package/get-shit-done/references/git-planning-commit.md +40 -0
- package/get-shit-done/references/ios-scaffold.md +123 -0
- package/get-shit-done/references/mandatory-initial-read.md +2 -0
- package/get-shit-done/references/model-profile-resolution.md +38 -0
- package/get-shit-done/references/model-profiles.md +245 -0
- package/get-shit-done/references/mvp-concepts.md +49 -0
- package/get-shit-done/references/phase-argument-parsing.md +61 -0
- package/get-shit-done/references/planner-antipatterns.md +89 -0
- package/get-shit-done/references/planner-chunked.md +49 -0
- package/get-shit-done/references/planner-gap-closure.md +62 -0
- package/get-shit-done/references/planner-graphify-auto-update.md +67 -0
- package/get-shit-done/references/planner-human-verify-mode.md +57 -0
- package/get-shit-done/references/planner-interface-context.md +62 -0
- package/get-shit-done/references/planner-mvp-mode.md +53 -0
- package/get-shit-done/references/planner-reviews.md +39 -0
- package/get-shit-done/references/planner-revision.md +87 -0
- package/get-shit-done/references/planner-source-audit.md +73 -0
- package/get-shit-done/references/planning-config.md +471 -0
- package/get-shit-done/references/project-skills-discovery.md +19 -0
- package/get-shit-done/references/questioning.md +162 -0
- package/get-shit-done/references/revision-loop.md +97 -0
- package/get-shit-done/references/scout-codebase.md +51 -0
- package/get-shit-done/references/skeleton-template.md +48 -0
- package/get-shit-done/references/sketch-interactivity.md +41 -0
- package/get-shit-done/references/sketch-theme-system.md +94 -0
- package/get-shit-done/references/sketch-tooling.md +45 -0
- package/get-shit-done/references/sketch-variant-patterns.md +81 -0
- package/get-shit-done/references/spidr-splitting.md +69 -0
- package/get-shit-done/references/tdd.md +330 -0
- package/get-shit-done/references/thinking-models-debug.md +44 -0
- package/get-shit-done/references/thinking-models-execution.md +50 -0
- package/get-shit-done/references/thinking-models-planning.md +62 -0
- package/get-shit-done/references/thinking-models-research.md +50 -0
- package/get-shit-done/references/thinking-models-verification.md +55 -0
- package/get-shit-done/references/thinking-partner.md +96 -0
- package/get-shit-done/references/ui-brand.md +160 -0
- package/get-shit-done/references/universal-anti-patterns.md +63 -0
- package/get-shit-done/references/user-profiling.md +681 -0
- package/get-shit-done/references/user-story-template.md +58 -0
- package/get-shit-done/references/verification-overrides.md +227 -0
- package/get-shit-done/references/verification-patterns.md +612 -0
- package/get-shit-done/references/verify-mvp-mode.md +85 -0
- package/get-shit-done/references/workstream-flag.md +111 -0
- package/get-shit-done/references/worktree-path-safety.md +89 -0
- package/get-shit-done/templates/AI-SPEC.md +246 -0
- package/get-shit-done/templates/DEBUG.md +169 -0
- package/get-shit-done/templates/README.md +77 -0
- package/get-shit-done/templates/SECURITY.md +61 -0
- package/get-shit-done/templates/UAT.md +265 -0
- package/get-shit-done/templates/UI-SPEC.md +100 -0
- package/get-shit-done/templates/VALIDATION.md +76 -0
- package/get-shit-done/templates/claude-md.md +145 -0
- package/get-shit-done/templates/codebase/architecture.md +255 -0
- package/get-shit-done/templates/codebase/concerns.md +310 -0
- package/get-shit-done/templates/codebase/conventions.md +307 -0
- package/get-shit-done/templates/codebase/integrations.md +280 -0
- package/get-shit-done/templates/codebase/stack.md +186 -0
- package/get-shit-done/templates/codebase/structure.md +285 -0
- package/get-shit-done/templates/codebase/testing.md +480 -0
- package/get-shit-done/templates/config.json +62 -0
- package/get-shit-done/templates/context.md +352 -0
- package/get-shit-done/templates/continue-here.md +78 -0
- package/get-shit-done/templates/copilot-instructions.md +7 -0
- package/get-shit-done/templates/debug-subagent-prompt.md +91 -0
- package/get-shit-done/templates/dev-preferences.md +21 -0
- package/get-shit-done/templates/discovery.md +146 -0
- package/get-shit-done/templates/discussion-log.md +63 -0
- package/get-shit-done/templates/milestone-archive.md +123 -0
- package/get-shit-done/templates/milestone.md +115 -0
- package/get-shit-done/templates/phase-prompt.md +610 -0
- package/get-shit-done/templates/planner-subagent-prompt.md +117 -0
- package/get-shit-done/templates/project.md +186 -0
- package/get-shit-done/templates/requirements.md +231 -0
- package/get-shit-done/templates/research-project/ARCHITECTURE.md +204 -0
- package/get-shit-done/templates/research-project/FEATURES.md +147 -0
- package/get-shit-done/templates/research-project/PITFALLS.md +200 -0
- package/get-shit-done/templates/research-project/STACK.md +120 -0
- package/get-shit-done/templates/research-project/SUMMARY.md +170 -0
- package/get-shit-done/templates/research.md +592 -0
- package/get-shit-done/templates/retrospective.md +54 -0
- package/get-shit-done/templates/roadmap.md +202 -0
- package/get-shit-done/templates/spec.md +307 -0
- package/get-shit-done/templates/state.md +195 -0
- package/get-shit-done/templates/summary-complex.md +59 -0
- package/get-shit-done/templates/summary-minimal.md +41 -0
- package/get-shit-done/templates/summary-standard.md +48 -0
- package/get-shit-done/templates/summary.md +248 -0
- package/get-shit-done/templates/user-profile.md +146 -0
- package/get-shit-done/templates/user-setup.md +311 -0
- package/get-shit-done/templates/verification-report.md +322 -0
- package/get-shit-done/workflows/_runtime-launcher.snippet.sh +1 -0
- package/get-shit-done/workflows/add-backlog.md +91 -0
- package/get-shit-done/workflows/add-phase.md +113 -0
- package/get-shit-done/workflows/add-tests.md +355 -0
- package/get-shit-done/workflows/add-todo.md +161 -0
- package/get-shit-done/workflows/ai-integration-phase.md +295 -0
- package/get-shit-done/workflows/analyze-dependencies.md +96 -0
- package/get-shit-done/workflows/audit-fix.md +178 -0
- package/get-shit-done/workflows/audit-milestone.md +358 -0
- package/get-shit-done/workflows/audit-uat.md +110 -0
- package/get-shit-done/workflows/autonomous.md +795 -0
- package/get-shit-done/workflows/check-todos.md +180 -0
- package/get-shit-done/workflows/cleanup.md +155 -0
- package/get-shit-done/workflows/code-review-fix.md +502 -0
- package/get-shit-done/workflows/code-review.md +656 -0
- package/get-shit-done/workflows/complete-milestone.md +855 -0
- package/get-shit-done/workflows/debug.md +232 -0
- package/get-shit-done/workflows/diagnose-issues.md +241 -0
- package/get-shit-done/workflows/discovery-phase.md +291 -0
- package/get-shit-done/workflows/discuss-phase/modes/advisor.md +176 -0
- package/get-shit-done/workflows/discuss-phase/modes/all.md +28 -0
- package/get-shit-done/workflows/discuss-phase/modes/analyze.md +44 -0
- package/get-shit-done/workflows/discuss-phase/modes/auto.md +57 -0
- package/get-shit-done/workflows/discuss-phase/modes/batch.md +52 -0
- package/get-shit-done/workflows/discuss-phase/modes/chain.md +98 -0
- package/get-shit-done/workflows/discuss-phase/modes/default.md +141 -0
- package/get-shit-done/workflows/discuss-phase/modes/power.md +44 -0
- package/get-shit-done/workflows/discuss-phase/modes/text.md +55 -0
- package/get-shit-done/workflows/discuss-phase/templates/checkpoint.json +18 -0
- package/get-shit-done/workflows/discuss-phase/templates/context.md +136 -0
- package/get-shit-done/workflows/discuss-phase/templates/discussion-log.md +50 -0
- package/get-shit-done/workflows/discuss-phase-assumptions.md +675 -0
- package/get-shit-done/workflows/discuss-phase-power.md +291 -0
- package/get-shit-done/workflows/discuss-phase.md +499 -0
- package/get-shit-done/workflows/do.md +111 -0
- package/get-shit-done/workflows/docs-update.md +1162 -0
- package/get-shit-done/workflows/edit-phase.md +295 -0
- package/get-shit-done/workflows/eval-review.md +156 -0
- package/get-shit-done/workflows/execute-phase/steps/codebase-drift-gate.md +82 -0
- package/get-shit-done/workflows/execute-phase/steps/per-plan-worktree-gate.md +94 -0
- package/get-shit-done/workflows/execute-phase/steps/post-merge-gate.md +117 -0
- package/get-shit-done/workflows/execute-phase.md +1709 -0
- package/get-shit-done/workflows/execute-plan.md +526 -0
- package/get-shit-done/workflows/explore.md +144 -0
- package/get-shit-done/workflows/extract-learnings.md +243 -0
- package/get-shit-done/workflows/fast.md +124 -0
- package/get-shit-done/workflows/forensics.md +279 -0
- package/get-shit-done/workflows/graduation.md +196 -0
- package/get-shit-done/workflows/health.md +224 -0
- package/get-shit-done/workflows/help/modes/brief.md +22 -0
- package/get-shit-done/workflows/help/modes/default.md +50 -0
- package/get-shit-done/workflows/help/modes/full.md +784 -0
- package/get-shit-done/workflows/help/modes/topic.md +74 -0
- package/get-shit-done/workflows/help.md +24 -0
- package/get-shit-done/workflows/import.md +254 -0
- package/get-shit-done/workflows/inbox.md +387 -0
- package/get-shit-done/workflows/ingest-docs.md +339 -0
- package/get-shit-done/workflows/insert-phase.md +152 -0
- package/get-shit-done/workflows/list-phase-assumptions.md +178 -0
- package/get-shit-done/workflows/list-workspaces.md +57 -0
- package/get-shit-done/workflows/manager.md +393 -0
- package/get-shit-done/workflows/map-codebase.md +444 -0
- package/get-shit-done/workflows/milestone-summary.md +224 -0
- package/get-shit-done/workflows/mvp-phase.md +222 -0
- package/get-shit-done/workflows/new-milestone.md +635 -0
- package/get-shit-done/workflows/new-project.md +1555 -0
- package/get-shit-done/workflows/new-workspace.md +240 -0
- package/get-shit-done/workflows/next.md +299 -0
- package/get-shit-done/workflows/node-repair.md +92 -0
- package/get-shit-done/workflows/note.md +158 -0
- package/get-shit-done/workflows/pause-work.md +244 -0
- package/get-shit-done/workflows/plan-milestone-gaps.md +281 -0
- package/get-shit-done/workflows/plan-phase.md +1809 -0
- package/get-shit-done/workflows/plan-review-convergence.md +346 -0
- package/get-shit-done/workflows/plant-seed.md +230 -0
- package/get-shit-done/workflows/pr-branch.md +157 -0
- package/get-shit-done/workflows/profile-user.md +453 -0
- package/get-shit-done/workflows/progress.md +699 -0
- package/get-shit-done/workflows/quick.md +1039 -0
- package/get-shit-done/workflows/reapply-patches.md +426 -0
- package/get-shit-done/workflows/remove-phase.md +156 -0
- package/get-shit-done/workflows/remove-workspace.md +108 -0
- package/get-shit-done/workflows/resume-project.md +332 -0
- package/get-shit-done/workflows/review.md +623 -0
- package/get-shit-done/workflows/scan.md +105 -0
- package/get-shit-done/workflows/secure-phase.md +180 -0
- package/get-shit-done/workflows/session-report.md +146 -0
- package/get-shit-done/workflows/settings-advanced.md +620 -0
- package/get-shit-done/workflows/settings-integrations.md +312 -0
- package/get-shit-done/workflows/settings.md +552 -0
- package/get-shit-done/workflows/ship.md +356 -0
- package/get-shit-done/workflows/sketch-wrap-up.md +286 -0
- package/get-shit-done/workflows/sketch.md +361 -0
- package/get-shit-done/workflows/spec-phase.md +262 -0
- package/get-shit-done/workflows/spike-wrap-up.md +307 -0
- package/get-shit-done/workflows/spike.md +453 -0
- package/get-shit-done/workflows/stats.md +80 -0
- package/get-shit-done/workflows/sync-skills.md +182 -0
- package/get-shit-done/workflows/thread.md +222 -0
- package/get-shit-done/workflows/transition.md +694 -0
- package/get-shit-done/workflows/ui-phase.md +328 -0
- package/get-shit-done/workflows/ui-review.md +193 -0
- package/get-shit-done/workflows/ultraplan-phase.md +199 -0
- package/get-shit-done/workflows/undo.md +314 -0
- package/get-shit-done/workflows/update.md +443 -0
- package/get-shit-done/workflows/validate-phase.md +179 -0
- package/get-shit-done/workflows/verify-phase.md +544 -0
- package/get-shit-done/workflows/verify-work.md +781 -0
- package/hooks/dist/gsd-check-update-worker.js +95 -0
- package/hooks/dist/gsd-check-update.js +64 -0
- package/hooks/dist/gsd-context-monitor.js +195 -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 +548 -0
- package/hooks/dist/gsd-update-banner.js +134 -0
- package/hooks/dist/gsd-validate-commit.sh +57 -0
- package/hooks/dist/gsd-workflow-guard.js +166 -0
- package/hooks/dist/lib/git-cmd.js +150 -0
- package/hooks/dist/lib/gsd-graphify-rebuild.sh +65 -0
- package/hooks/gsd-check-update-worker.js +95 -0
- package/hooks/gsd-check-update.js +64 -0
- package/hooks/gsd-context-monitor.js +195 -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 +548 -0
- package/hooks/gsd-update-banner.js +134 -0
- package/hooks/gsd-validate-commit.sh +57 -0
- package/hooks/gsd-workflow-guard.js +166 -0
- package/hooks/lib/git-cmd.js +150 -0
- package/hooks/lib/gsd-graphify-rebuild.sh +65 -0
- package/hooks/managed-hooks-registry.cjs +34 -0
- package/package.json +102 -0
- package/scripts/affected-tests-lib.cjs +541 -0
- package/scripts/audit-workflow-script-paths.cjs +73 -0
- package/scripts/base64-scan.sh +339 -0
- package/scripts/build-hooks.js +236 -0
- package/scripts/changeset/README.md +129 -0
- package/scripts/changeset/cli.cjs +392 -0
- package/scripts/changeset/github-release-notes.cjs +199 -0
- package/scripts/changeset/lint.cjs +110 -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 +108 -0
- package/scripts/check-env.cjs +302 -0
- package/scripts/check-npm-integrity.cjs +209 -0
- package/scripts/ci-guard-runner.cjs +16 -0
- package/scripts/ci-prepare-test-scope.cjs +46 -0
- package/scripts/ci-rebase-check.cjs +85 -0
- package/scripts/ci-test-scope.cjs +302 -0
- package/scripts/command-contract-helpers.cjs +64 -0
- package/scripts/diff-touches-shipped-paths.cjs +147 -0
- package/scripts/fix-slash-commands.cjs +147 -0
- package/scripts/gen-inventory-manifest.cjs +109 -0
- package/scripts/generate-package-identity.cjs +104 -0
- package/scripts/lint-command-contract.cjs +108 -0
- package/scripts/lint-descriptions.cjs +83 -0
- package/scripts/lint-docs-required.cjs +222 -0
- package/scripts/lint-no-source-grep-extras.cjs +81 -0
- package/scripts/lint-no-source-grep.cjs +174 -0
- package/scripts/lint-package-identity-drift.cjs +141 -0
- package/scripts/lint-pr-check-project-dir.cjs +98 -0
- package/scripts/lint-shared-module-handsync.cjs +388 -0
- package/scripts/lint-shell-command-projection-drift.cjs +57 -0
- package/scripts/lint-skill-deps.cjs +180 -0
- package/scripts/lint-test-file-count.allowlist.json +36 -0
- package/scripts/lint-test-file-count.cjs +190 -0
- package/scripts/pr-template-policy.cjs +268 -0
- package/scripts/prompt-injection-scan.sh +203 -0
- package/scripts/release-tarball-smoke.cjs +627 -0
- package/scripts/run-affected-tests.cjs +6 -0
- package/scripts/run-cross-platform-tests.cjs +63 -0
- package/scripts/run-tests.cjs +282 -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/shared-module-handsync-allowlist.json +183 -0
- package/scripts/strip-prose-atrefs.cjs +106 -0
- package/scripts/sync-rulesets.sh +34 -0
- package/scripts/sync-runtime-launcher.cjs +402 -0
- package/scripts/test-failure-reasons.cjs +34 -0
- package/scripts/workflow-policy.cjs +450 -0
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
'use strict';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Drift-guard lint for the Package Identity seam (issue #498).
|
|
6
|
+
*
|
|
7
|
+
* The seam (`get-shit-done/bin/lib/package-identity.cjs`, derived from
|
|
8
|
+
* package.json) is the single source of GSD's published coordinates. Many
|
|
9
|
+
* runtime surfaces still carry a literal copy of those coordinates because
|
|
10
|
+
* they cannot `require()` the seam at runtime: the bash launcher snippet (and
|
|
11
|
+
* its byte-equal copies across ~85 workflows, kept in lockstep by the
|
|
12
|
+
* runtime-launcher parity test) and the installer's user-facing install/help
|
|
13
|
+
* strings.
|
|
14
|
+
*
|
|
15
|
+
* This lint makes those literals *value-checked*: every GSD package/repo
|
|
16
|
+
* coordinate that appears as a literal must equal the seam's current value.
|
|
17
|
+
* It passes today (the literals are correct) and FAILS the moment a repoint is
|
|
18
|
+
* not propagated — rename package.json, regenerate the seam, and every stale
|
|
19
|
+
* literal is reported until updated. That is what turns a repoint into a
|
|
20
|
+
* one-line change with mechanical enforcement.
|
|
21
|
+
*
|
|
22
|
+
* Scope: the runtime/code surface (bin/, hooks/, scripts/, get-shit-done/).
|
|
23
|
+
* Pure-prose docs and localized READMEs are intentionally out of scope.
|
|
24
|
+
*/
|
|
25
|
+
|
|
26
|
+
const fs = require('node:fs');
|
|
27
|
+
const path = require('node:path');
|
|
28
|
+
|
|
29
|
+
// A GSD package coordinate: a scoped npm name whose package part contains
|
|
30
|
+
// "get-shit-done" (so @opengsd/gsd-sdk and unrelated scopes never match).
|
|
31
|
+
const PACKAGE_RE = /@[A-Za-z0-9._-]+\/[A-Za-z0-9._-]*get-shit-done[A-Za-z0-9._-]*/g;
|
|
32
|
+
// A GSD repo slug, only inside a GitHub URL context so it never overlaps the
|
|
33
|
+
// scoped package literal above. The `.git` suffix is trimmed before compare.
|
|
34
|
+
const SLUG_RE = /(?:github\.com[/:]|raw\.githubusercontent\.com\/)([A-Za-z0-9._-]+\/[A-Za-z0-9._-]*get-shit-done[A-Za-z0-9._-]*)/g;
|
|
35
|
+
|
|
36
|
+
function lineOf(text, index) {
|
|
37
|
+
let line = 1;
|
|
38
|
+
for (let i = 0; i < index && i < text.length; i++) {
|
|
39
|
+
if (text[i] === '\n') line++;
|
|
40
|
+
}
|
|
41
|
+
return line;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Pure: find every GSD coordinate literal in `text` that does not match the
|
|
46
|
+
* expected seam values. Returns [{ kind, found, expected, line }].
|
|
47
|
+
*/
|
|
48
|
+
function findCoordinateDrift(text, { packageName, repoSlug }) {
|
|
49
|
+
const out = [];
|
|
50
|
+
for (const m of text.matchAll(PACKAGE_RE)) {
|
|
51
|
+
if (m[0] !== packageName) {
|
|
52
|
+
out.push({ kind: 'package', found: m[0], expected: packageName, line: lineOf(text, m.index) });
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
for (const m of text.matchAll(SLUG_RE)) {
|
|
56
|
+
const slug = m[1].replace(/\.git$/, '');
|
|
57
|
+
if (slug !== repoSlug) {
|
|
58
|
+
out.push({ kind: 'slug', found: slug, expected: repoSlug, line: lineOf(text, m.index) });
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
return out;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
// Directories scanned, relative to repo root.
|
|
65
|
+
const SCAN_DIRS = ['bin', 'hooks', 'scripts', 'get-shit-done'];
|
|
66
|
+
const SCAN_EXT = new Set(['.js', '.cjs', '.sh', '.md']);
|
|
67
|
+
// Files exempt because they ARE the source of truth / the tooling that defines
|
|
68
|
+
// the coordinate patterns. The generated seam holds the correct value by
|
|
69
|
+
// construction; the generator and this lint carry regex/templates, not stray
|
|
70
|
+
// literals.
|
|
71
|
+
const EXEMPT = new Set([
|
|
72
|
+
path.join('get-shit-done', 'bin', 'lib', 'package-identity.cjs'),
|
|
73
|
+
path.join('scripts', 'generate-package-identity.cjs'),
|
|
74
|
+
path.join('scripts', 'lint-package-identity-drift.cjs'),
|
|
75
|
+
]);
|
|
76
|
+
|
|
77
|
+
function walk(dir, acc) {
|
|
78
|
+
let entries;
|
|
79
|
+
try {
|
|
80
|
+
entries = fs.readdirSync(dir, { withFileTypes: true });
|
|
81
|
+
} catch (e) {
|
|
82
|
+
return acc;
|
|
83
|
+
}
|
|
84
|
+
for (const entry of entries) {
|
|
85
|
+
const full = path.join(dir, entry.name);
|
|
86
|
+
if (entry.isDirectory()) {
|
|
87
|
+
if (entry.name === 'node_modules' || entry.name === 'dist' || entry.name === '.git') continue;
|
|
88
|
+
walk(full, acc);
|
|
89
|
+
} else if (entry.isFile() && SCAN_EXT.has(path.extname(entry.name))) {
|
|
90
|
+
acc.push(full);
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
return acc;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
/**
|
|
97
|
+
* Scan the repo's runtime/code surface and return all coordinate drift, each
|
|
98
|
+
* annotated with the repo-relative file path.
|
|
99
|
+
*/
|
|
100
|
+
function scanRepo(root) {
|
|
101
|
+
const seam = require(path.join(root, 'get-shit-done', 'bin', 'lib', 'package-identity.cjs'));
|
|
102
|
+
const expected = { packageName: seam.packageName, repoSlug: seam.repoSlug };
|
|
103
|
+
const violations = [];
|
|
104
|
+
for (const dir of SCAN_DIRS) {
|
|
105
|
+
const files = walk(path.join(root, dir), []);
|
|
106
|
+
for (const file of files) {
|
|
107
|
+
const rel = path.relative(root, file);
|
|
108
|
+
if (EXEMPT.has(rel)) continue;
|
|
109
|
+
let text;
|
|
110
|
+
try {
|
|
111
|
+
text = fs.readFileSync(file, 'utf8');
|
|
112
|
+
} catch (e) {
|
|
113
|
+
continue;
|
|
114
|
+
}
|
|
115
|
+
for (const d of findCoordinateDrift(text, expected)) {
|
|
116
|
+
violations.push({ file: rel, ...d });
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
return violations;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
function main() {
|
|
124
|
+
const root = path.join(__dirname, '..');
|
|
125
|
+
const violations = scanRepo(root);
|
|
126
|
+
if (violations.length === 0) {
|
|
127
|
+
process.stdout.write('ok identity-drift: all GSD coordinate literals match the seam\n');
|
|
128
|
+
return;
|
|
129
|
+
}
|
|
130
|
+
process.stderr.write('identity-drift: stale GSD coordinate literal(s) found.\n');
|
|
131
|
+
process.stderr.write('Repoint by editing package.json, then `node scripts/generate-package-identity.cjs`,\n');
|
|
132
|
+
process.stderr.write('and update the value-checked materialization sites below:\n');
|
|
133
|
+
for (const d of violations) {
|
|
134
|
+
process.stderr.write(` ${d.file}:${d.line} ${d.kind} '${d.found}' != '${d.expected}'\n`);
|
|
135
|
+
}
|
|
136
|
+
process.exitCode = 1;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
if (require.main === module) main();
|
|
140
|
+
|
|
141
|
+
module.exports = { findCoordinateDrift, scanRepo };
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
'use strict';
|
|
3
|
+
|
|
4
|
+
const fs = require('fs');
|
|
5
|
+
const path = require('path');
|
|
6
|
+
|
|
7
|
+
const ROOT = path.join(__dirname, '..');
|
|
8
|
+
|
|
9
|
+
const DEFAULT_RELATIVE_FILES = [
|
|
10
|
+
'.github/workflows/test.yml',
|
|
11
|
+
'.github/workflows/pr-template-format.yml',
|
|
12
|
+
'.github/workflows/changeset-required.yml',
|
|
13
|
+
'scripts/lint-no-source-grep.cjs',
|
|
14
|
+
'scripts/lint-command-contract.cjs',
|
|
15
|
+
'scripts/lint-skill-deps.cjs',
|
|
16
|
+
'scripts/lint-descriptions.cjs',
|
|
17
|
+
'scripts/lint-shell-command-projection-drift.cjs',
|
|
18
|
+
'scripts/pr-template-policy.cjs',
|
|
19
|
+
'scripts/changeset/lint.cjs',
|
|
20
|
+
];
|
|
21
|
+
|
|
22
|
+
function defaultFiles(rootDir = ROOT) {
|
|
23
|
+
return DEFAULT_RELATIVE_FILES
|
|
24
|
+
.map((file) => path.join(rootDir, file))
|
|
25
|
+
.filter((file) => fs.existsSync(file));
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
function findForbiddenCwd(content, file = '<inline>') {
|
|
29
|
+
const findings = [];
|
|
30
|
+
const lines = content.split(/\r?\n/);
|
|
31
|
+
|
|
32
|
+
lines.forEach((line, index) => {
|
|
33
|
+
const pattern = /\bcwd\b/g;
|
|
34
|
+
let match;
|
|
35
|
+
while ((match = pattern.exec(line)) !== null) {
|
|
36
|
+
findings.push({
|
|
37
|
+
file,
|
|
38
|
+
line: index + 1,
|
|
39
|
+
column: match.index + 1,
|
|
40
|
+
source: line.trim(),
|
|
41
|
+
});
|
|
42
|
+
}
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
return findings;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
function checkFiles(files, { rootDir = ROOT } = {}) {
|
|
49
|
+
const findings = [];
|
|
50
|
+
for (const file of files) {
|
|
51
|
+
const content = fs.readFileSync(file, 'utf8');
|
|
52
|
+
const rel = path.relative(rootDir, file);
|
|
53
|
+
findings.push(...findForbiddenCwd(content, rel));
|
|
54
|
+
}
|
|
55
|
+
return findings;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
function formatFindings(findings) {
|
|
59
|
+
const lines = [
|
|
60
|
+
`ERROR lint-pr-check-project-dir: ${findings.length} forbidden cwd reference(s) found`,
|
|
61
|
+
'',
|
|
62
|
+
'PR checkers must use projectDir for project roots; cwd is forbidden in this layer.',
|
|
63
|
+
'',
|
|
64
|
+
];
|
|
65
|
+
|
|
66
|
+
for (const finding of findings) {
|
|
67
|
+
lines.push(` ${finding.file}:${finding.line}:${finding.column}`);
|
|
68
|
+
lines.push(` ${finding.source}`);
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
return `${lines.join('\n')}\n`;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
function main(argv = process.argv.slice(2)) {
|
|
75
|
+
const files = argv.length > 0 ? argv.map((file) => path.resolve(file)) : defaultFiles();
|
|
76
|
+
const findings = checkFiles(files);
|
|
77
|
+
|
|
78
|
+
if (findings.length === 0) {
|
|
79
|
+
console.log(`ok lint-pr-check-project-dir: ${files.length} PR check files checked`);
|
|
80
|
+
return 0;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
process.stderr.write(formatFindings(findings));
|
|
84
|
+
return 1;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
if (require.main === module) {
|
|
88
|
+
process.exit(main());
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
module.exports = {
|
|
92
|
+
DEFAULT_RELATIVE_FILES,
|
|
93
|
+
checkFiles,
|
|
94
|
+
defaultFiles,
|
|
95
|
+
findForbiddenCwd,
|
|
96
|
+
formatFindings,
|
|
97
|
+
main,
|
|
98
|
+
};
|
|
@@ -0,0 +1,388 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
'use strict';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Shared Module hand-sync drift lint — Phase 6 of #3524 (#3575).
|
|
6
|
+
*
|
|
7
|
+
* Scans get-shit-done/bin/lib/ for .cjs files and checks whether a matching
|
|
8
|
+
* TypeScript file exists in sdk/src/<name>.ts, sdk/src/query/<name>.ts, or
|
|
9
|
+
* sdk/src/<name>/index.ts (excluding *.generated.ts and *.test.ts).
|
|
10
|
+
*
|
|
11
|
+
* Allowlist entries are keyed by the (cjs, ts) PAIR. An entry with cjs
|
|
12
|
+
* `bin/lib/foo.cjs` and ts `sdk/src/foo.ts` only allow-throughs that exact
|
|
13
|
+
* pair — a sibling at `sdk/src/query/foo.ts` is still flagged.
|
|
14
|
+
*
|
|
15
|
+
* Cross-name pairs are also supported when declared in the allowlist
|
|
16
|
+
* (for example `verify.cjs` <-> `validate.ts`), so cooperating siblings are
|
|
17
|
+
* observable even when basenames differ.
|
|
18
|
+
*
|
|
19
|
+
* If a pair is found:
|
|
20
|
+
* - cooperatingSiblings (matching cjs + ts): accepted silently (exit 0).
|
|
21
|
+
* - migrateMeBacklog (matching cjs + ts): emits a WARNING only when
|
|
22
|
+
* --warn-all is set; otherwise the pair passes silently. Backlog
|
|
23
|
+
* pairs never fail CI.
|
|
24
|
+
* - Unlisted pairs (cjs or ts not on either list): ERROR — exit 1.
|
|
25
|
+
*
|
|
26
|
+
* Usage:
|
|
27
|
+
* node scripts/lint-shared-module-handsync.cjs
|
|
28
|
+
* node scripts/lint-shared-module-handsync.cjs --root /path/to/repo
|
|
29
|
+
* node scripts/lint-shared-module-handsync.cjs --warn-all
|
|
30
|
+
* node scripts/lint-shared-module-handsync.cjs --cjs-dir custom/bin/lib --sdk-src custom/sdk/src
|
|
31
|
+
*/
|
|
32
|
+
|
|
33
|
+
const fs = require('fs');
|
|
34
|
+
const path = require('path');
|
|
35
|
+
|
|
36
|
+
// ---------------------------------------------------------------------------
|
|
37
|
+
// Argument parsing
|
|
38
|
+
// ---------------------------------------------------------------------------
|
|
39
|
+
const args = process.argv.slice(2);
|
|
40
|
+
let ROOT = path.resolve(__dirname, '..');
|
|
41
|
+
let CJS_DIR = null; // resolved below
|
|
42
|
+
let SDK_SRC = null; // resolved below
|
|
43
|
+
let SDK_SRC_EXPLICIT = false;
|
|
44
|
+
let ALLOWLIST_OVERRIDE = null; // resolved below
|
|
45
|
+
let WARN_ALL = false;
|
|
46
|
+
let JSON_OUTPUT = false;
|
|
47
|
+
|
|
48
|
+
for (let i = 0; i < args.length; i++) {
|
|
49
|
+
if (args[i] === '--root' && args[i + 1]) {
|
|
50
|
+
ROOT = path.resolve(args[++i]);
|
|
51
|
+
} else if (args[i] === '--cjs-dir' && args[i + 1]) {
|
|
52
|
+
CJS_DIR = path.resolve(args[++i]);
|
|
53
|
+
} else if (args[i] === '--sdk-src' && args[i + 1]) {
|
|
54
|
+
SDK_SRC = path.resolve(args[++i]);
|
|
55
|
+
SDK_SRC_EXPLICIT = true;
|
|
56
|
+
} else if (args[i] === '--allowlist' && args[i + 1]) {
|
|
57
|
+
ALLOWLIST_OVERRIDE = path.resolve(args[++i]);
|
|
58
|
+
} else if (args[i] === '--warn-all') {
|
|
59
|
+
WARN_ALL = true;
|
|
60
|
+
} else if (args[i] === '--json') {
|
|
61
|
+
JSON_OUTPUT = true;
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
if (!CJS_DIR) CJS_DIR = path.join(ROOT, 'get-shit-done', 'bin', 'lib');
|
|
66
|
+
if (!SDK_SRC) SDK_SRC = path.join(ROOT, 'sdk', 'src');
|
|
67
|
+
|
|
68
|
+
// ---------------------------------------------------------------------------
|
|
69
|
+
// Load allowlist
|
|
70
|
+
// When --root is given (e.g. in tests), prefer <ROOT>/scripts/allowlist.json
|
|
71
|
+
// so fixture trees can supply their own allowlist. Fall back to the copy
|
|
72
|
+
// co-located with this script (default production path).
|
|
73
|
+
// ---------------------------------------------------------------------------
|
|
74
|
+
const ALLOWLIST_PATH = ALLOWLIST_OVERRIDE
|
|
75
|
+
? ALLOWLIST_OVERRIDE
|
|
76
|
+
: fs.existsSync(path.join(ROOT, 'scripts', 'shared-module-handsync-allowlist.json'))
|
|
77
|
+
? path.join(ROOT, 'scripts', 'shared-module-handsync-allowlist.json')
|
|
78
|
+
: path.join(__dirname, 'shared-module-handsync-allowlist.json');
|
|
79
|
+
let allowlist;
|
|
80
|
+
try {
|
|
81
|
+
allowlist = JSON.parse(fs.readFileSync(ALLOWLIST_PATH, 'utf8'));
|
|
82
|
+
} catch (err) {
|
|
83
|
+
process.stderr.write(
|
|
84
|
+
`lint-shared-module-handsync: failed to read allowlist at ${ALLOWLIST_PATH}: ${err.message}\n`
|
|
85
|
+
);
|
|
86
|
+
process.exit(1);
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* Pair identity = `${cjs}::${ts}`. Keying on the pair (not just cjs)
|
|
91
|
+
* prevents an allowlisted entry from silently passing an unintended
|
|
92
|
+
* sibling at a different ts path with the same basename.
|
|
93
|
+
*
|
|
94
|
+
* @type {Set<string>} pair identities in cooperatingSiblings
|
|
95
|
+
*/
|
|
96
|
+
const cooperatingPairs = new Set(
|
|
97
|
+
(allowlist.cooperatingSiblings || []).map((e) => `${e.cjs}::${e.ts}`)
|
|
98
|
+
);
|
|
99
|
+
|
|
100
|
+
/** @type {Map<string, object>} pair identity -> entry for migrateMeBacklog */
|
|
101
|
+
const migrateMap = new Map(
|
|
102
|
+
(allowlist.migrateMeBacklog || []).map((e) => [`${e.cjs}::${e.ts}`, e])
|
|
103
|
+
);
|
|
104
|
+
|
|
105
|
+
/** @type {Map<string, Set<string>>} cjs rel path -> explicit declared ts rel paths */
|
|
106
|
+
const explicitTsByCjs = new Map();
|
|
107
|
+
for (const entry of [
|
|
108
|
+
...(allowlist.cooperatingSiblings || []),
|
|
109
|
+
...(allowlist.migrateMeBacklog || []),
|
|
110
|
+
]) {
|
|
111
|
+
if (!entry || typeof entry.cjs !== 'string' || typeof entry.ts !== 'string') continue;
|
|
112
|
+
if (!explicitTsByCjs.has(entry.cjs)) explicitTsByCjs.set(entry.cjs, new Set());
|
|
113
|
+
explicitTsByCjs.get(entry.cjs).add(entry.ts);
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
// ---------------------------------------------------------------------------
|
|
117
|
+
// Build SDK name index: name -> array of absolute TS paths
|
|
118
|
+
// (excludes *.generated.ts and *.test.ts)
|
|
119
|
+
// ---------------------------------------------------------------------------
|
|
120
|
+
function buildSdkIndex(sdkSrc) {
|
|
121
|
+
const index = new Map(); // name -> [absPath, ...]
|
|
122
|
+
|
|
123
|
+
function addEntry(name, absPath) {
|
|
124
|
+
if (!index.has(name)) index.set(name, []);
|
|
125
|
+
index.get(name).push(absPath);
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
function walk(dir) {
|
|
129
|
+
let entries;
|
|
130
|
+
try {
|
|
131
|
+
entries = fs.readdirSync(dir, { withFileTypes: true });
|
|
132
|
+
} catch (_) {
|
|
133
|
+
return;
|
|
134
|
+
}
|
|
135
|
+
for (const ent of entries) {
|
|
136
|
+
const abs = path.join(dir, ent.name);
|
|
137
|
+
if (ent.isDirectory()) {
|
|
138
|
+
walk(abs);
|
|
139
|
+
} else if (ent.isFile() && ent.name.endsWith('.ts') &&
|
|
140
|
+
!ent.name.endsWith('.generated.ts') &&
|
|
141
|
+
!ent.name.endsWith('.test.ts')) {
|
|
142
|
+
const rel = path.relative(sdkSrc, abs);
|
|
143
|
+
const parts = rel.split(path.sep);
|
|
144
|
+
|
|
145
|
+
// sdk/src/<name>.ts (direct child, not in a subdir)
|
|
146
|
+
if (parts.length === 1) {
|
|
147
|
+
const name = parts[0].slice(0, -3); // strip .ts
|
|
148
|
+
addEntry(name, abs);
|
|
149
|
+
}
|
|
150
|
+
// sdk/src/<name>/index.ts (one subdir deep, file is index.ts)
|
|
151
|
+
else if (parts.length === 2 && parts[1] === 'index.ts') {
|
|
152
|
+
const name = parts[0];
|
|
153
|
+
addEntry(name, abs);
|
|
154
|
+
}
|
|
155
|
+
// sdk/src/query/<name>.ts (exactly: query/<something>.ts)
|
|
156
|
+
else if (parts.length === 2 && parts[0] === 'query' && parts[1] !== 'index.ts') {
|
|
157
|
+
const name = parts[1].slice(0, -3); // strip .ts
|
|
158
|
+
addEntry(name, abs);
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
walk(sdkSrc);
|
|
165
|
+
return index;
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
// ---------------------------------------------------------------------------
|
|
169
|
+
// Scan CJS files (direct children only; exclude *.generated.cjs)
|
|
170
|
+
// ---------------------------------------------------------------------------
|
|
171
|
+
function scanCjsFiles(cjsDir) {
|
|
172
|
+
let entries;
|
|
173
|
+
try {
|
|
174
|
+
entries = fs.readdirSync(cjsDir, { withFileTypes: true });
|
|
175
|
+
} catch (err) {
|
|
176
|
+
process.stderr.write(
|
|
177
|
+
`lint-shared-module-handsync: cannot read CJS dir ${cjsDir}: ${err.message}\n`
|
|
178
|
+
);
|
|
179
|
+
process.exit(1);
|
|
180
|
+
}
|
|
181
|
+
return entries
|
|
182
|
+
.filter(
|
|
183
|
+
(e) =>
|
|
184
|
+
e.isFile() &&
|
|
185
|
+
e.name.endsWith('.cjs') &&
|
|
186
|
+
!e.name.endsWith('.generated.cjs')
|
|
187
|
+
)
|
|
188
|
+
.map((e) => ({
|
|
189
|
+
name: e.name.slice(0, -4), // strip .cjs
|
|
190
|
+
absPath: path.join(cjsDir, e.name),
|
|
191
|
+
}));
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
// ---------------------------------------------------------------------------
|
|
195
|
+
// Main
|
|
196
|
+
// ---------------------------------------------------------------------------
|
|
197
|
+
function emitJson(payload) {
|
|
198
|
+
process.stdout.write(JSON.stringify(payload) + '\n');
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
function main() {
|
|
202
|
+
// Check that the directories exist
|
|
203
|
+
if (!fs.existsSync(CJS_DIR)) {
|
|
204
|
+
if (JSON_OUTPUT) {
|
|
205
|
+
emitJson({ ok: false, reason: 'cjs_dir_missing', path: CJS_DIR });
|
|
206
|
+
} else {
|
|
207
|
+
process.stderr.write(
|
|
208
|
+
`lint-shared-module-handsync: CJS dir not found: ${CJS_DIR}\n` +
|
|
209
|
+
` Pass --root <repo-root> or --cjs-dir <path> to override.\n`
|
|
210
|
+
);
|
|
211
|
+
}
|
|
212
|
+
process.exit(1);
|
|
213
|
+
}
|
|
214
|
+
if (!fs.existsSync(SDK_SRC)) {
|
|
215
|
+
// SDK tree was retired in ADR-0174 Phase 5.2. In default repo mode this
|
|
216
|
+
// lint becomes a no-op success; explicit --sdk-src remains fail-loud.
|
|
217
|
+
if (SDK_SRC_EXPLICIT) {
|
|
218
|
+
if (JSON_OUTPUT) {
|
|
219
|
+
emitJson({ ok: false, reason: 'sdk_src_missing', path: SDK_SRC });
|
|
220
|
+
} else {
|
|
221
|
+
process.stderr.write(
|
|
222
|
+
`lint-shared-module-handsync: SDK src dir not found: ${SDK_SRC}\n` +
|
|
223
|
+
` Pass --root <repo-root> or --sdk-src <path> to override.\n`
|
|
224
|
+
);
|
|
225
|
+
}
|
|
226
|
+
process.exit(1);
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
if (JSON_OUTPUT) {
|
|
230
|
+
emitJson({
|
|
231
|
+
ok: true,
|
|
232
|
+
reason: 'sdk_retired',
|
|
233
|
+
cooperatingCount: 0,
|
|
234
|
+
backlogCount: 0,
|
|
235
|
+
warnings: [],
|
|
236
|
+
});
|
|
237
|
+
} else {
|
|
238
|
+
process.stdout.write(
|
|
239
|
+
'ok lint-shared-module-handsync: SDK source tree retired; no hand-sync pairs to lint.\n'
|
|
240
|
+
);
|
|
241
|
+
}
|
|
242
|
+
process.exit(0);
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
const sdkIndex = buildSdkIndex(SDK_SRC);
|
|
246
|
+
const cjsFiles = scanCjsFiles(CJS_DIR);
|
|
247
|
+
|
|
248
|
+
const errors = [];
|
|
249
|
+
const warnings = [];
|
|
250
|
+
|
|
251
|
+
function candidateTsPathsFor(relCjs, name) {
|
|
252
|
+
const byName = sdkIndex.has(name)
|
|
253
|
+
? sdkIndex
|
|
254
|
+
.get(name)
|
|
255
|
+
.map((p) => path.relative(ROOT, p).replace(/\\/g, '/'))
|
|
256
|
+
: [];
|
|
257
|
+
|
|
258
|
+
const declared = explicitTsByCjs.has(relCjs)
|
|
259
|
+
? Array.from(explicitTsByCjs.get(relCjs))
|
|
260
|
+
: [];
|
|
261
|
+
|
|
262
|
+
const declaredExisting = declared.filter((relTs) => {
|
|
263
|
+
const abs = path.join(ROOT, relTs);
|
|
264
|
+
return (
|
|
265
|
+
relTs.endsWith('.ts') &&
|
|
266
|
+
!relTs.endsWith('.generated.ts') &&
|
|
267
|
+
!relTs.endsWith('.test.ts') &&
|
|
268
|
+
fs.existsSync(abs) &&
|
|
269
|
+
fs.statSync(abs).isFile()
|
|
270
|
+
);
|
|
271
|
+
});
|
|
272
|
+
|
|
273
|
+
return Array.from(new Set([...byName, ...declaredExisting]));
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
for (const { name, absPath } of cjsFiles) {
|
|
277
|
+
// Compute relative CJS path and all declared/discovered TS candidates.
|
|
278
|
+
const relCjs = path.relative(ROOT, absPath).replace(/\\/g, '/');
|
|
279
|
+
const tsPaths = candidateTsPathsFor(relCjs, name);
|
|
280
|
+
if (tsPaths.length === 0) continue;
|
|
281
|
+
|
|
282
|
+
// Pair-aware matching, per ts sibling. Each ts candidate is classified
|
|
283
|
+
// independently against the allowlist so a partially-allowlisted set of
|
|
284
|
+
// siblings still surfaces the unauthorized ones. See #3632.
|
|
285
|
+
const unauthorizedTs = [];
|
|
286
|
+
const backlogTsForCjs = [];
|
|
287
|
+
for (const relTs of tsPaths) {
|
|
288
|
+
const pairKey = `${relCjs}::${relTs}`;
|
|
289
|
+
if (cooperatingPairs.has(pairKey)) continue;
|
|
290
|
+
if (migrateMap.has(pairKey)) {
|
|
291
|
+
backlogTsForCjs.push(relTs);
|
|
292
|
+
continue;
|
|
293
|
+
}
|
|
294
|
+
unauthorizedTs.push(relTs);
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
if (unauthorizedTs.length > 0) {
|
|
298
|
+
errors.push({ relCjs, tsPaths: unauthorizedTs });
|
|
299
|
+
}
|
|
300
|
+
if (backlogTsForCjs.length > 0) {
|
|
301
|
+
const entry = migrateMap.get(`${relCjs}::${backlogTsForCjs[0]}`);
|
|
302
|
+
warnings.push({ relCjs, tsPaths: backlogTsForCjs, entry });
|
|
303
|
+
}
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
// Count cjs files whose pair identity (cjs+ts) is on cooperatingSiblings.
|
|
307
|
+
// A file with multiple ts candidates is counted once if any pair matches.
|
|
308
|
+
const cooperatingCount = cjsFiles.filter((f) => {
|
|
309
|
+
const relCjs = path.relative(ROOT, f.absPath).replace(/\\/g, '/');
|
|
310
|
+
return candidateTsPathsFor(relCjs, f.name).some((relTs) =>
|
|
311
|
+
cooperatingPairs.has(`${relCjs}::${relTs}`)
|
|
312
|
+
);
|
|
313
|
+
}).length;
|
|
314
|
+
|
|
315
|
+
// -------------------------------------------------------------------------
|
|
316
|
+
// Report errors (exit 1)
|
|
317
|
+
// -------------------------------------------------------------------------
|
|
318
|
+
if (errors.length > 0) {
|
|
319
|
+
if (JSON_OUTPUT) {
|
|
320
|
+
emitJson({
|
|
321
|
+
ok: false,
|
|
322
|
+
reason: 'unauthorized_pairs',
|
|
323
|
+
errors,
|
|
324
|
+
warnings,
|
|
325
|
+
cooperatingCount,
|
|
326
|
+
});
|
|
327
|
+
} else {
|
|
328
|
+
process.stderr.write(
|
|
329
|
+
`\nERROR lint-shared-module-handsync: ${errors.length} unauthorized hand-sync pair(s) found.\n\n`
|
|
330
|
+
);
|
|
331
|
+
for (const { relCjs, tsPaths } of errors) {
|
|
332
|
+
process.stderr.write(` CJS: ${relCjs}\n`);
|
|
333
|
+
for (const ts of tsPaths) {
|
|
334
|
+
process.stderr.write(` TS: ${ts}\n`);
|
|
335
|
+
}
|
|
336
|
+
process.stderr.write('\n');
|
|
337
|
+
}
|
|
338
|
+
process.stderr.write(
|
|
339
|
+
'To resolve, choose one of:\n' +
|
|
340
|
+
' 1. Migrate to a Shared Module (preferred): create sdk/src/<name>/index.ts as the\n' +
|
|
341
|
+
' source-of-truth, write a generator script (sdk/scripts/gen-<name>.mjs), add a\n' +
|
|
342
|
+
' freshness check, and update CI. See docs/agents/cjs-sdk-seam.md for the pattern.\n' +
|
|
343
|
+
' 2. Add an explicit allowlist entry to scripts/shared-module-handsync-allowlist.json\n' +
|
|
344
|
+
' with a justification explaining why this pair is a legitimate cooperating sibling\n' +
|
|
345
|
+
' rather than a drift anti-pattern. Requires maintainer review via CODEOWNERS.\n\n'
|
|
346
|
+
);
|
|
347
|
+
}
|
|
348
|
+
process.exit(1);
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
// -------------------------------------------------------------------------
|
|
352
|
+
// Report warnings (no exit code change)
|
|
353
|
+
// -------------------------------------------------------------------------
|
|
354
|
+
if (warnings.length > 0 && WARN_ALL && !JSON_OUTPUT) {
|
|
355
|
+
process.stderr.write(
|
|
356
|
+
`\nWARNING lint-shared-module-handsync: ${warnings.length} known drift anti-pattern pair(s) in migrateMeBacklog.\n` +
|
|
357
|
+
`These are tracked for future Shared Module migration but do not block CI.\n\n`
|
|
358
|
+
);
|
|
359
|
+
for (const { relCjs, tsPaths, entry } of warnings) {
|
|
360
|
+
process.stderr.write(` CJS: ${relCjs}\n`);
|
|
361
|
+
for (const ts of tsPaths) {
|
|
362
|
+
process.stderr.write(` TS: ${ts}\n`);
|
|
363
|
+
}
|
|
364
|
+
process.stderr.write(` Tracked: ${entry.trackedIn}\n`);
|
|
365
|
+
process.stderr.write(` Hint: ${entry.justification}\n\n`);
|
|
366
|
+
}
|
|
367
|
+
}
|
|
368
|
+
|
|
369
|
+
// -------------------------------------------------------------------------
|
|
370
|
+
// Success
|
|
371
|
+
// -------------------------------------------------------------------------
|
|
372
|
+
if (JSON_OUTPUT) {
|
|
373
|
+
emitJson({
|
|
374
|
+
ok: true,
|
|
375
|
+
cooperatingCount,
|
|
376
|
+
backlogCount: warnings.length,
|
|
377
|
+
warnings,
|
|
378
|
+
});
|
|
379
|
+
} else {
|
|
380
|
+
process.stdout.write(
|
|
381
|
+
`ok lint-shared-module-handsync: no unauthorized hand-sync pairs found` +
|
|
382
|
+
` (${cooperatingCount} cooperating sibling(s), ${warnings.length} backlog pair(s))\n`
|
|
383
|
+
);
|
|
384
|
+
}
|
|
385
|
+
process.exit(0);
|
|
386
|
+
}
|
|
387
|
+
|
|
388
|
+
main();
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
'use strict';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Focused drift guard for issue #3442:
|
|
6
|
+
* prevent installer-owned inline shim/wrapper text builders from bypassing the
|
|
7
|
+
* Shell Command Projection Module seam.
|
|
8
|
+
*
|
|
9
|
+
* Scope intentionally excludes subprocess execution helpers (spawnSync /
|
|
10
|
+
* execFileSync) because those are safe internal execution primitives, not
|
|
11
|
+
* serialized shell-command rendering.
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
const fs = require('fs');
|
|
15
|
+
const path = require('path');
|
|
16
|
+
|
|
17
|
+
const ROOT = path.resolve(__dirname, '..');
|
|
18
|
+
const targetArg = process.argv[2] || path.join(ROOT, 'bin', 'install.js');
|
|
19
|
+
const target = path.resolve(targetArg);
|
|
20
|
+
const rel = path.relative(ROOT, target);
|
|
21
|
+
|
|
22
|
+
let content;
|
|
23
|
+
try {
|
|
24
|
+
content = fs.readFileSync(target, 'utf8');
|
|
25
|
+
} catch (error) {
|
|
26
|
+
process.stderr.write(`lint-shell-command-projection-drift: failed to read ${target}: ${error.message}\n`);
|
|
27
|
+
process.exit(1);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
const forbidden = [
|
|
31
|
+
{
|
|
32
|
+
label: 'inline cmd shim builder',
|
|
33
|
+
pattern: /@ECHO OFF\\r\\n@SETLOCAL\\r\\n@node /,
|
|
34
|
+
},
|
|
35
|
+
{
|
|
36
|
+
label: 'inline pwsh shim builder',
|
|
37
|
+
pattern: /#!\/usr\/bin\/env pwsh\\n& node /,
|
|
38
|
+
},
|
|
39
|
+
{
|
|
40
|
+
label: 'inline sh shim builder',
|
|
41
|
+
pattern: /#!\/usr\/bin\/env sh\\nexec node /,
|
|
42
|
+
},
|
|
43
|
+
];
|
|
44
|
+
|
|
45
|
+
const matches = forbidden.filter((rule) => rule.pattern.test(content));
|
|
46
|
+
if (matches.length === 0) {
|
|
47
|
+
process.stdout.write(`ok shell-projection-drift: ${rel}\n`);
|
|
48
|
+
process.exit(0);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
process.stderr.write(`ERROR shell-projection-drift: inline serialized shim builders found in ${rel}\n`);
|
|
52
|
+
for (const match of matches) {
|
|
53
|
+
process.stderr.write(` - ${match.label}\n`);
|
|
54
|
+
}
|
|
55
|
+
process.stderr.write('Route shim/wrapper rendering through get-shit-done/bin/lib/shell-command-projection.cjs\n');
|
|
56
|
+
process.stderr.write('Safe subprocess execution via spawnSync/execFileSync is intentionally allowed.\n');
|
|
57
|
+
process.exit(1);
|