@opengsd/gsd-core 1.2.0 → 1.3.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/README.ja-JP.md +46 -791
- package/README.ko-KR.md +44 -780
- package/README.md +42 -218
- package/README.pt-BR.md +47 -414
- package/README.zh-CN.md +46 -763
- package/agents/gsd-ai-researcher.md +2 -2
- package/agents/gsd-debug-session-manager.md +1 -1
- package/agents/gsd-debugger.md +8 -8
- package/agents/gsd-doc-writer.md +7 -6
- package/agents/gsd-domain-researcher.md +15 -2
- package/agents/gsd-eval-auditor.md +1 -1
- package/agents/gsd-eval-planner.md +2 -2
- package/agents/gsd-executor.md +21 -8
- package/agents/gsd-framework-selector.md +1 -1
- package/agents/gsd-intel-updater.md +4 -4
- package/agents/gsd-phase-researcher.md +19 -6
- package/agents/gsd-plan-checker.md +3 -3
- package/agents/gsd-planner.md +36 -23
- package/agents/gsd-project-researcher.md +13 -0
- package/agents/gsd-research-synthesizer.md +6 -2
- package/agents/gsd-roadmapper.md +6 -6
- package/agents/gsd-ui-researcher.md +16 -3
- package/agents/gsd-user-profiler.md +2 -2
- package/agents/gsd-verifier.md +8 -8
- 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 +255 -103
- package/commands/gsd/add-tests.md +1 -1
- package/commands/gsd/ai-integration-phase.md +3 -3
- package/commands/gsd/audit-fix.md +1 -1
- package/commands/gsd/audit-milestone.md +1 -1
- package/commands/gsd/audit-uat.md +1 -1
- package/commands/gsd/autonomous.md +2 -2
- package/commands/gsd/capture.md +6 -6
- package/commands/gsd/cleanup.md +1 -1
- package/commands/gsd/code-review.md +1 -1
- package/commands/gsd/complete-milestone.md +2 -2
- package/commands/gsd/config.md +3 -3
- package/commands/gsd/debug.md +1 -1
- package/commands/gsd/discuss-phase.md +5 -4
- package/commands/gsd/docs-update.md +1 -1
- package/commands/gsd/eval-review.md +2 -2
- package/commands/gsd/execute-phase.md +2 -2
- package/commands/gsd/explore.md +1 -1
- package/commands/gsd/extract-learnings.md +2 -2
- package/commands/gsd/fast.md +1 -1
- package/commands/gsd/forensics.md +1 -1
- package/commands/gsd/graphify.md +9 -9
- package/commands/gsd/health.md +1 -1
- package/commands/gsd/help.md +2 -2
- package/commands/gsd/import.md +5 -5
- package/commands/gsd/inbox.md +1 -1
- package/commands/gsd/ingest-docs.md +4 -4
- package/commands/gsd/manager.md +3 -3
- package/commands/gsd/map-codebase.md +1 -1
- package/commands/gsd/milestone-summary.md +1 -1
- package/commands/gsd/mvp-phase.md +4 -4
- package/commands/gsd/new-milestone.md +5 -5
- package/commands/gsd/new-project.md +5 -5
- package/commands/gsd/pause-work.md +2 -2
- package/commands/gsd/phase.md +4 -4
- package/commands/gsd/plan-phase.md +2 -2
- package/commands/gsd/plan-review-convergence.md +4 -4
- package/commands/gsd/pr-branch.md +1 -1
- package/commands/gsd/profile-user.md +2 -2
- package/commands/gsd/progress.md +4 -4
- package/commands/gsd/quick.md +1 -1
- package/commands/gsd/resume-work.md +1 -1
- package/commands/gsd/review.md +3 -2
- package/commands/gsd/secure-phase.md +1 -1
- package/commands/gsd/settings.md +1 -1
- package/commands/gsd/ship.md +2 -2
- package/commands/gsd/sketch.md +7 -7
- package/commands/gsd/spec-phase.md +2 -2
- package/commands/gsd/spike.md +3 -3
- package/commands/gsd/stats.md +1 -1
- package/commands/gsd/surface.md +4 -4
- package/commands/gsd/thread.md +1 -1
- package/commands/gsd/ui-phase.md +2 -2
- package/commands/gsd/ui-review.md +2 -2
- package/commands/gsd/ultraplan-phase.md +2 -2
- package/commands/gsd/undo.md +3 -3
- package/commands/gsd/update.md +3 -3
- package/commands/gsd/validate-phase.md +1 -1
- package/commands/gsd/verify-work.md +2 -2
- package/commands/gsd/workspace.md +4 -4
- package/{get-shit-done → gsd-core}/bin/check-latest-version.cjs +1 -1
- package/{get-shit-done → gsd-core}/bin/gsd-tools.cjs +50 -4
- 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 +342 -0
- package/gsd-core/bin/lib/cjs-command-router-adapter.cjs +81 -0
- package/gsd-core/bin/lib/clock.cjs +95 -0
- package/gsd-core/bin/lib/clusters.cjs +128 -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 +1202 -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 +714 -0
- package/{get-shit-done → gsd-core}/bin/lib/configuration.cjs +76 -85
- package/gsd-core/bin/lib/context-utilization.cjs +48 -0
- package/gsd-core/bin/lib/core.cjs +2007 -0
- package/{get-shit-done → gsd-core}/bin/lib/decisions.cjs +9 -7
- 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 +1799 -0
- package/gsd-core/bin/lib/install-profiles.cjs +526 -0
- package/gsd-core/bin/lib/installer-migration-authoring.cjs +122 -0
- package/gsd-core/bin/lib/installer-migration-report.cjs +347 -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 +784 -0
- package/gsd-core/bin/lib/intel.cjs +607 -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/{get-shit-done → gsd-core}/bin/lib/observability/redaction.cjs +19 -21
- package/{get-shit-done → gsd-core}/bin/lib/package-identity.cjs +5 -1
- 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/{get-shit-done → gsd-core}/bin/lib/plan-scan.cjs +18 -24
- 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/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 +491 -0
- package/gsd-core/bin/lib/roadmap.cjs +600 -0
- package/gsd-core/bin/lib/runtime-artifact-layout.cjs +254 -0
- package/gsd-core/bin/lib/runtime-homes.cjs +169 -0
- package/gsd-core/bin/lib/runtime-name-policy.cjs +96 -0
- package/gsd-core/bin/lib/runtime-slash.cjs +119 -0
- package/{get-shit-done → gsd-core}/bin/lib/schema-detect.cjs +20 -26
- package/gsd-core/bin/lib/secrets.cjs +34 -0
- package/gsd-core/bin/lib/security.cjs +407 -0
- package/gsd-core/bin/lib/semver-compare.cjs +42 -0
- package/gsd-core/bin/lib/shell-command-projection.cjs +524 -0
- package/gsd-core/bin/lib/state-command-router.cjs +160 -0
- package/{get-shit-done → gsd-core}/bin/lib/state-document.cjs +78 -82
- package/gsd-core/bin/lib/state.cjs +2010 -0
- package/gsd-core/bin/lib/surface.cjs +406 -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/verify-command-router.cjs +44 -0
- package/gsd-core/bin/lib/verify.cjs +1451 -0
- package/{get-shit-done → gsd-core}/bin/lib/workstream-inventory-builder.cjs +19 -12
- package/gsd-core/bin/lib/workstream-inventory.cjs +147 -0
- package/{get-shit-done → gsd-core}/bin/lib/workstream-name-policy.cjs +28 -31
- package/gsd-core/bin/lib/workstream.cjs +380 -0
- package/gsd-core/bin/lib/worktree-safety.cjs +912 -0
- package/{get-shit-done → gsd-core}/bin/shared/config-defaults.manifest.json +1 -0
- package/{get-shit-done → gsd-core}/bin/shared/config-schema.manifest.json +17 -1
- package/{get-shit-done → gsd-core}/bin/shared/model-catalog.json +27 -0
- package/{get-shit-done → gsd-core}/references/artifact-types.md +1 -1
- package/{get-shit-done → gsd-core}/references/checkpoints.md +1 -1
- package/{get-shit-done → gsd-core}/references/few-shot-examples/plan-checker.md +2 -2
- package/{get-shit-done → gsd-core}/references/few-shot-examples/verifier.md +12 -12
- package/{get-shit-done → gsd-core}/references/model-profile-resolution.md +1 -1
- package/{get-shit-done → gsd-core}/references/mvp-concepts.md +1 -1
- package/{get-shit-done → gsd-core}/references/planner-graphify-auto-update.md +2 -2
- package/{get-shit-done → gsd-core}/references/planner-human-verify-mode.md +1 -1
- package/{get-shit-done → gsd-core}/references/planner-mvp-mode.md +1 -1
- package/{get-shit-done → gsd-core}/references/ui-brand.md +4 -2
- package/{get-shit-done → gsd-core}/references/verification-patterns.md +1 -1
- package/gsd-core/references/worktree-branch-check.md +38 -0
- package/{get-shit-done → gsd-core}/references/worktree-path-safety.md +4 -26
- package/{get-shit-done → gsd-core}/templates/README.md +2 -2
- package/{get-shit-done → gsd-core}/templates/codebase/structure.md +10 -10
- package/{get-shit-done → gsd-core}/templates/copilot-instructions.md +1 -1
- package/{get-shit-done → gsd-core}/templates/phase-prompt.md +10 -10
- package/gsd-core/workflows/_runtime-launcher.snippet.sh +1 -0
- package/{get-shit-done → gsd-core}/workflows/add-backlog.md +1 -1
- package/{get-shit-done → gsd-core}/workflows/add-phase.md +1 -1
- package/{get-shit-done → gsd-core}/workflows/add-tests.md +1 -1
- package/{get-shit-done → gsd-core}/workflows/add-todo.md +1 -1
- package/{get-shit-done → gsd-core}/workflows/ai-integration-phase.md +4 -4
- package/{get-shit-done → gsd-core}/workflows/audit-fix.md +2 -2
- package/{get-shit-done → gsd-core}/workflows/audit-milestone.md +3 -1
- package/{get-shit-done → gsd-core}/workflows/audit-uat.md +1 -1
- package/{get-shit-done → gsd-core}/workflows/autonomous.md +10 -8
- package/{get-shit-done → gsd-core}/workflows/check-todos.md +1 -1
- package/{get-shit-done → gsd-core}/workflows/cleanup.md +44 -4
- package/{get-shit-done → gsd-core}/workflows/code-review-fix.md +4 -4
- package/{get-shit-done → gsd-core}/workflows/code-review.md +6 -4
- package/{get-shit-done → gsd-core}/workflows/complete-milestone.md +2 -2
- package/{get-shit-done → gsd-core}/workflows/debug.md +7 -2
- package/{get-shit-done → gsd-core}/workflows/diagnose-issues.md +6 -2
- package/{get-shit-done → gsd-core}/workflows/discovery-phase.md +5 -5
- package/{get-shit-done → gsd-core}/workflows/discuss-phase/modes/advisor.md +5 -5
- package/{get-shit-done → gsd-core}/workflows/discuss-phase/modes/auto.md +1 -1
- package/{get-shit-done → gsd-core}/workflows/discuss-phase/modes/chain.md +1 -1
- package/{get-shit-done → gsd-core}/workflows/discuss-phase/modes/power.md +1 -1
- package/{get-shit-done → gsd-core}/workflows/discuss-phase-assumptions.md +4 -4
- package/{get-shit-done → gsd-core}/workflows/discuss-phase.md +6 -6
- package/{get-shit-done → gsd-core}/workflows/do.md +1 -1
- package/{get-shit-done → gsd-core}/workflows/docs-update.md +19 -5
- package/{get-shit-done → gsd-core}/workflows/edit-phase.md +1 -1
- package/{get-shit-done → gsd-core}/workflows/eval-review.md +3 -3
- package/{get-shit-done → gsd-core}/workflows/execute-phase/steps/codebase-drift-gate.md +16 -3
- package/{get-shit-done → gsd-core}/workflows/execute-phase/steps/post-merge-gate.md +1 -1
- package/{get-shit-done → gsd-core}/workflows/execute-phase.md +89 -57
- package/{get-shit-done → gsd-core}/workflows/execute-plan.md +8 -8
- package/{get-shit-done → gsd-core}/workflows/explore.md +5 -3
- package/{get-shit-done → gsd-core}/workflows/extract-learnings.md +1 -1
- package/{get-shit-done → gsd-core}/workflows/forensics.md +1 -1
- package/{get-shit-done → gsd-core}/workflows/graduation.md +1 -1
- package/{get-shit-done → gsd-core}/workflows/health.md +1 -1
- package/{get-shit-done → gsd-core}/workflows/help/modes/default.md +3 -3
- package/{get-shit-done → gsd-core}/workflows/help/modes/full.md +6 -6
- package/{get-shit-done → gsd-core}/workflows/import.md +3 -1
- package/{get-shit-done → gsd-core}/workflows/ingest-docs.md +5 -5
- package/{get-shit-done → gsd-core}/workflows/insert-phase.md +1 -1
- package/{get-shit-done → gsd-core}/workflows/list-workspaces.md +1 -1
- package/{get-shit-done → gsd-core}/workflows/manager.md +3 -3
- package/{get-shit-done → gsd-core}/workflows/map-codebase.md +3 -1
- package/{get-shit-done → gsd-core}/workflows/milestone-summary.md +1 -1
- package/{get-shit-done → gsd-core}/workflows/mvp-phase.md +7 -7
- package/{get-shit-done → gsd-core}/workflows/new-milestone.md +5 -5
- package/{get-shit-done → gsd-core}/workflows/new-project.md +8 -8
- package/{get-shit-done → gsd-core}/workflows/new-workspace.md +1 -1
- package/{get-shit-done → gsd-core}/workflows/next.md +1 -1
- package/{get-shit-done → gsd-core}/workflows/pause-work.md +1 -1
- package/{get-shit-done → gsd-core}/workflows/plan-milestone-gaps.md +1 -1
- package/{get-shit-done → gsd-core}/workflows/plan-phase.md +29 -28
- package/{get-shit-done → gsd-core}/workflows/plan-review-convergence.md +10 -10
- package/{get-shit-done → gsd-core}/workflows/plant-seed.md +1 -1
- package/{get-shit-done → gsd-core}/workflows/profile-user.md +11 -11
- package/{get-shit-done → gsd-core}/workflows/progress.md +1 -1
- package/{get-shit-done → gsd-core}/workflows/quick.md +7 -29
- package/{get-shit-done → gsd-core}/workflows/reapply-patches.md +2 -2
- package/{get-shit-done → gsd-core}/workflows/remove-phase.md +1 -1
- package/{get-shit-done → gsd-core}/workflows/remove-workspace.md +1 -1
- package/{get-shit-done → gsd-core}/workflows/resume-project.md +2 -2
- package/{get-shit-done → gsd-core}/workflows/review.md +110 -2
- package/{get-shit-done → gsd-core}/workflows/scan.md +3 -1
- package/{get-shit-done → gsd-core}/workflows/secure-phase.md +5 -3
- package/{get-shit-done → gsd-core}/workflows/settings-advanced.md +196 -6
- package/{get-shit-done → gsd-core}/workflows/settings-integrations.md +2 -2
- package/{get-shit-done → gsd-core}/workflows/settings.md +16 -2
- package/{get-shit-done → gsd-core}/workflows/ship.md +56 -4
- package/{get-shit-done → gsd-core}/workflows/sketch-wrap-up.md +1 -1
- package/{get-shit-done → gsd-core}/workflows/sketch.md +5 -5
- package/{get-shit-done → gsd-core}/workflows/spec-phase.md +2 -2
- package/{get-shit-done → gsd-core}/workflows/spike-wrap-up.md +1 -1
- package/{get-shit-done → gsd-core}/workflows/spike.md +1 -1
- package/{get-shit-done → gsd-core}/workflows/stats.md +1 -1
- package/{get-shit-done → gsd-core}/workflows/sync-skills.md +3 -3
- package/{get-shit-done → gsd-core}/workflows/thread.md +1 -1
- package/{get-shit-done → gsd-core}/workflows/transition.md +2 -2
- package/{get-shit-done → gsd-core}/workflows/ui-phase.md +5 -5
- package/{get-shit-done → gsd-core}/workflows/ui-review.md +3 -3
- package/{get-shit-done → gsd-core}/workflows/ultraplan-phase.md +1 -1
- package/{get-shit-done → gsd-core}/workflows/undo.md +2 -2
- package/{get-shit-done → gsd-core}/workflows/update.md +41 -16
- package/{get-shit-done → gsd-core}/workflows/validate-phase.md +5 -3
- package/{get-shit-done → gsd-core}/workflows/verify-phase.md +4 -4
- package/{get-shit-done → gsd-core}/workflows/verify-work.md +7 -7
- package/hooks/dist/gsd-check-update-worker.js +16 -3
- package/hooks/dist/gsd-check-update.js +7 -5
- package/hooks/dist/gsd-context-monitor.js +2 -2
- package/hooks/dist/gsd-statusline.js +39 -21
- package/hooks/dist/gsd-update-banner.js +6 -2
- package/hooks/dist/gsd-worktree-path-guard.js +169 -0
- package/hooks/dist/managed-hooks-registry.cjs +35 -0
- package/hooks/gsd-check-update-worker.js +16 -3
- package/hooks/gsd-check-update.js +7 -5
- package/hooks/gsd-context-monitor.js +2 -2
- package/hooks/gsd-statusline.js +39 -21
- package/hooks/gsd-update-banner.js +6 -2
- package/hooks/gsd-worktree-path-guard.js +169 -0
- package/hooks/managed-hooks-registry.cjs +1 -0
- package/package.json +17 -11
- package/scripts/affected-tests-lib.cjs +1 -1
- package/scripts/base64-scan.sh +12 -0
- package/scripts/build-hooks.js +5 -1
- package/scripts/changeset/cli.cjs +2 -2
- package/scripts/changeset/github-release-notes.cjs +1 -1
- package/scripts/changeset/lint.cjs +1 -1
- package/scripts/check-alias-drift.cjs +8 -8
- package/scripts/check-env.cjs +5 -1
- package/scripts/ci-test-scope.cjs +34 -9
- package/scripts/command-contract-helpers.cjs +1 -1
- package/scripts/fix-slash-commands.cjs +5 -5
- package/scripts/gen-inventory-manifest.cjs +3 -3
- package/scripts/generate-package-identity.cjs +28 -7
- package/scripts/lib/allowlist-ratchet.cjs +136 -0
- package/scripts/lint-command-contract.cjs +1 -1
- package/scripts/lint-legacy-dir-name.cjs +156 -0
- package/scripts/lint-package-identity-drift.cjs +8 -8
- package/scripts/lint-pr-check-project-dir.cjs +0 -1
- package/scripts/lint-shell-command-projection-drift.cjs +1 -1
- package/scripts/lint-skill-deps.cjs +1 -1
- package/scripts/lint-test-file-count.allowlist.json +129 -32
- package/scripts/lint-test-file-count.cjs +85 -30
- package/scripts/mutation-matrix.cjs +219 -0
- package/scripts/prompt-injection-scan.sh +5 -1
- package/scripts/release-notes/format-github-release-notes.cjs +256 -0
- package/scripts/release-tarball-smoke.cjs +9 -9
- package/scripts/run-tests.cjs +34 -2
- package/scripts/strip-prose-atrefs.cjs +2 -2
- package/scripts/sync-runtime-launcher.cjs +2 -2
- package/scripts/verify-npm-publish.cjs +252 -0
- package/get-shit-done/bin/lib/active-workstream-store.cjs +0 -302
- package/get-shit-done/bin/lib/adr-parser.cjs +0 -394
- package/get-shit-done/bin/lib/agent-command-router.cjs +0 -65
- package/get-shit-done/bin/lib/artifacts.cjs +0 -53
- package/get-shit-done/bin/lib/audit.cjs +0 -755
- package/get-shit-done/bin/lib/check-command-router.cjs +0 -333
- package/get-shit-done/bin/lib/cjs-command-router-adapter.cjs +0 -118
- package/get-shit-done/bin/lib/clock.cjs +0 -96
- package/get-shit-done/bin/lib/clusters.cjs +0 -135
- package/get-shit-done/bin/lib/code-review-flags.cjs +0 -74
- package/get-shit-done/bin/lib/command-aliases.cjs +0 -815
- package/get-shit-done/bin/lib/command-arg-projection.cjs +0 -62
- package/get-shit-done/bin/lib/command-routing-hub.cjs +0 -388
- package/get-shit-done/bin/lib/commands.cjs +0 -1188
- package/get-shit-done/bin/lib/config-schema.cjs +0 -31
- package/get-shit-done/bin/lib/config.cjs +0 -728
- package/get-shit-done/bin/lib/context-utilization.cjs +0 -47
- package/get-shit-done/bin/lib/core.cjs +0 -2121
- package/get-shit-done/bin/lib/docs.cjs +0 -270
- package/get-shit-done/bin/lib/drift.cjs +0 -388
- package/get-shit-done/bin/lib/fallow-runner.cjs +0 -109
- package/get-shit-done/bin/lib/frontmatter.cjs +0 -389
- package/get-shit-done/bin/lib/gap-checker.cjs +0 -205
- package/get-shit-done/bin/lib/graphify.cjs +0 -592
- package/get-shit-done/bin/lib/gsd2-import.cjs +0 -514
- package/get-shit-done/bin/lib/init-command-router.cjs +0 -58
- package/get-shit-done/bin/lib/init.cjs +0 -2112
- package/get-shit-done/bin/lib/install-profiles.cjs +0 -603
- package/get-shit-done/bin/lib/installer-migration-authoring.cjs +0 -117
- package/get-shit-done/bin/lib/installer-migration-report.cjs +0 -354
- package/get-shit-done/bin/lib/installer-migrations/000-first-time-baseline.cjs +0 -220
- package/get-shit-done/bin/lib/installer-migrations/001-legacy-orphan-files.cjs +0 -41
- package/get-shit-done/bin/lib/installer-migrations/002-codex-legacy-hooks-json.cjs +0 -80
- package/get-shit-done/bin/lib/installer-migrations.cjs +0 -778
- package/get-shit-done/bin/lib/intel.cjs +0 -708
- package/get-shit-done/bin/lib/learnings.cjs +0 -421
- package/get-shit-done/bin/lib/milestone.cjs +0 -314
- package/get-shit-done/bin/lib/model-catalog.cjs +0 -212
- package/get-shit-done/bin/lib/model-profiles.cjs +0 -31
- package/get-shit-done/bin/lib/observability/event.cjs +0 -82
- package/get-shit-done/bin/lib/observability/logger.cjs +0 -174
- package/get-shit-done/bin/lib/phase-command-router.cjs +0 -191
- package/get-shit-done/bin/lib/phase-lifecycle.cjs +0 -80
- package/get-shit-done/bin/lib/phase.cjs +0 -1607
- package/get-shit-done/bin/lib/phases-command-router.cjs +0 -39
- package/get-shit-done/bin/lib/planning-workspace.cjs +0 -238
- package/get-shit-done/bin/lib/profile-output.cjs +0 -1141
- package/get-shit-done/bin/lib/profile-pipeline.cjs +0 -539
- package/get-shit-done/bin/lib/project-root.cjs +0 -112
- package/get-shit-done/bin/lib/prompt-budget.cjs +0 -399
- package/get-shit-done/bin/lib/review-reviewer-selection.cjs +0 -125
- package/get-shit-done/bin/lib/roadmap-command-router.cjs +0 -28
- package/get-shit-done/bin/lib/roadmap.cjs +0 -650
- package/get-shit-done/bin/lib/runtime-artifact-layout.cjs +0 -301
- package/get-shit-done/bin/lib/runtime-homes.cjs +0 -222
- package/get-shit-done/bin/lib/runtime-name-policy.cjs +0 -83
- package/get-shit-done/bin/lib/runtime-slash.cjs +0 -112
- package/get-shit-done/bin/lib/secrets.cjs +0 -32
- package/get-shit-done/bin/lib/security.cjs +0 -600
- package/get-shit-done/bin/lib/semver-compare.cjs +0 -35
- package/get-shit-done/bin/lib/shell-command-projection.cjs +0 -500
- package/get-shit-done/bin/lib/state-command-router.cjs +0 -252
- package/get-shit-done/bin/lib/state.cjs +0 -2038
- package/get-shit-done/bin/lib/surface.cjs +0 -470
- package/get-shit-done/bin/lib/task-command-router.cjs +0 -81
- package/get-shit-done/bin/lib/template.cjs +0 -228
- package/get-shit-done/bin/lib/uat.cjs +0 -289
- package/get-shit-done/bin/lib/update-context.cjs +0 -209
- package/get-shit-done/bin/lib/validate-command-router.cjs +0 -83
- package/get-shit-done/bin/lib/validate.cjs +0 -92
- package/get-shit-done/bin/lib/verify-command-router.cjs +0 -40
- package/get-shit-done/bin/lib/verify.cjs +0 -1511
- package/get-shit-done/bin/lib/workstream-inventory.cjs +0 -146
- package/get-shit-done/bin/lib/workstream.cjs +0 -389
- package/get-shit-done/bin/lib/worktree-safety.cjs +0 -985
- package/get-shit-done/workflows/_runtime-launcher.snippet.sh +0 -1
- package/scripts/lint-no-source-grep-extras.cjs +0 -81
- package/scripts/lint-no-source-grep.cjs +0 -174
- package/scripts/lint-shared-module-handsync.cjs +0 -388
- package/scripts/shared-module-handsync-allowlist.json +0 -183
- /package/{get-shit-done → gsd-core}/bin/shared/runtime-aliases.manifest.json +0 -0
- /package/{get-shit-done → gsd-core}/bin/verify-reapply-patches.cjs +0 -0
- /package/{get-shit-done → gsd-core}/contexts/dev.md +0 -0
- /package/{get-shit-done → gsd-core}/contexts/research.md +0 -0
- /package/{get-shit-done → gsd-core}/contexts/review.md +0 -0
- /package/{get-shit-done → gsd-core}/references/agent-contracts.md +0 -0
- /package/{get-shit-done → gsd-core}/references/ai-evals.md +0 -0
- /package/{get-shit-done → gsd-core}/references/ai-frameworks.md +0 -0
- /package/{get-shit-done → gsd-core}/references/autonomous-smart-discuss.md +0 -0
- /package/{get-shit-done → gsd-core}/references/common-bug-patterns.md +0 -0
- /package/{get-shit-done → gsd-core}/references/context-budget.md +0 -0
- /package/{get-shit-done → gsd-core}/references/continuation-format.md +0 -0
- /package/{get-shit-done → gsd-core}/references/debugger-philosophy.md +0 -0
- /package/{get-shit-done → gsd-core}/references/decimal-phase-calculation.md +0 -0
- /package/{get-shit-done → gsd-core}/references/doc-conflict-engine.md +0 -0
- /package/{get-shit-done → gsd-core}/references/domain-probes.md +0 -0
- /package/{get-shit-done → gsd-core}/references/execute-mvp-tdd.md +0 -0
- /package/{get-shit-done → gsd-core}/references/executor-examples.md +0 -0
- /package/{get-shit-done → gsd-core}/references/gate-prompts.md +0 -0
- /package/{get-shit-done → gsd-core}/references/gates.md +0 -0
- /package/{get-shit-done → gsd-core}/references/git-integration.md +0 -0
- /package/{get-shit-done → gsd-core}/references/git-planning-commit.md +0 -0
- /package/{get-shit-done → gsd-core}/references/ios-scaffold.md +0 -0
- /package/{get-shit-done → gsd-core}/references/mandatory-initial-read.md +0 -0
- /package/{get-shit-done → gsd-core}/references/model-profiles.md +0 -0
- /package/{get-shit-done → gsd-core}/references/phase-argument-parsing.md +0 -0
- /package/{get-shit-done → gsd-core}/references/planner-antipatterns.md +0 -0
- /package/{get-shit-done → gsd-core}/references/planner-chunked.md +0 -0
- /package/{get-shit-done → gsd-core}/references/planner-gap-closure.md +0 -0
- /package/{get-shit-done → gsd-core}/references/planner-interface-context.md +0 -0
- /package/{get-shit-done → gsd-core}/references/planner-reviews.md +0 -0
- /package/{get-shit-done → gsd-core}/references/planner-revision.md +0 -0
- /package/{get-shit-done → gsd-core}/references/planner-source-audit.md +0 -0
- /package/{get-shit-done → gsd-core}/references/planning-config.md +0 -0
- /package/{get-shit-done → gsd-core}/references/project-skills-discovery.md +0 -0
- /package/{get-shit-done → gsd-core}/references/questioning.md +0 -0
- /package/{get-shit-done → gsd-core}/references/revision-loop.md +0 -0
- /package/{get-shit-done → gsd-core}/references/scout-codebase.md +0 -0
- /package/{get-shit-done → gsd-core}/references/skeleton-template.md +0 -0
- /package/{get-shit-done → gsd-core}/references/sketch-interactivity.md +0 -0
- /package/{get-shit-done → gsd-core}/references/sketch-theme-system.md +0 -0
- /package/{get-shit-done → gsd-core}/references/sketch-tooling.md +0 -0
- /package/{get-shit-done → gsd-core}/references/sketch-variant-patterns.md +0 -0
- /package/{get-shit-done → gsd-core}/references/spidr-splitting.md +0 -0
- /package/{get-shit-done → gsd-core}/references/tdd.md +0 -0
- /package/{get-shit-done → gsd-core}/references/thinking-models-debug.md +0 -0
- /package/{get-shit-done → gsd-core}/references/thinking-models-execution.md +0 -0
- /package/{get-shit-done → gsd-core}/references/thinking-models-planning.md +0 -0
- /package/{get-shit-done → gsd-core}/references/thinking-models-research.md +0 -0
- /package/{get-shit-done → gsd-core}/references/thinking-models-verification.md +0 -0
- /package/{get-shit-done → gsd-core}/references/thinking-partner.md +0 -0
- /package/{get-shit-done → gsd-core}/references/universal-anti-patterns.md +0 -0
- /package/{get-shit-done → gsd-core}/references/user-profiling.md +0 -0
- /package/{get-shit-done → gsd-core}/references/user-story-template.md +0 -0
- /package/{get-shit-done → gsd-core}/references/verification-overrides.md +0 -0
- /package/{get-shit-done → gsd-core}/references/verify-mvp-mode.md +0 -0
- /package/{get-shit-done → gsd-core}/references/workstream-flag.md +0 -0
- /package/{get-shit-done → gsd-core}/templates/AI-SPEC.md +0 -0
- /package/{get-shit-done → gsd-core}/templates/DEBUG.md +0 -0
- /package/{get-shit-done → gsd-core}/templates/SECURITY.md +0 -0
- /package/{get-shit-done → gsd-core}/templates/UAT.md +0 -0
- /package/{get-shit-done → gsd-core}/templates/UI-SPEC.md +0 -0
- /package/{get-shit-done → gsd-core}/templates/VALIDATION.md +0 -0
- /package/{get-shit-done → gsd-core}/templates/claude-md.md +0 -0
- /package/{get-shit-done → gsd-core}/templates/codebase/architecture.md +0 -0
- /package/{get-shit-done → gsd-core}/templates/codebase/concerns.md +0 -0
- /package/{get-shit-done → gsd-core}/templates/codebase/conventions.md +0 -0
- /package/{get-shit-done → gsd-core}/templates/codebase/integrations.md +0 -0
- /package/{get-shit-done → gsd-core}/templates/codebase/stack.md +0 -0
- /package/{get-shit-done → gsd-core}/templates/codebase/testing.md +0 -0
- /package/{get-shit-done → gsd-core}/templates/config.json +0 -0
- /package/{get-shit-done → gsd-core}/templates/context.md +0 -0
- /package/{get-shit-done → gsd-core}/templates/continue-here.md +0 -0
- /package/{get-shit-done → gsd-core}/templates/debug-subagent-prompt.md +0 -0
- /package/{get-shit-done → gsd-core}/templates/dev-preferences.md +0 -0
- /package/{get-shit-done → gsd-core}/templates/discovery.md +0 -0
- /package/{get-shit-done → gsd-core}/templates/discussion-log.md +0 -0
- /package/{get-shit-done → gsd-core}/templates/milestone-archive.md +0 -0
- /package/{get-shit-done → gsd-core}/templates/milestone.md +0 -0
- /package/{get-shit-done → gsd-core}/templates/planner-subagent-prompt.md +0 -0
- /package/{get-shit-done → gsd-core}/templates/project.md +0 -0
- /package/{get-shit-done → gsd-core}/templates/requirements.md +0 -0
- /package/{get-shit-done → gsd-core}/templates/research-project/ARCHITECTURE.md +0 -0
- /package/{get-shit-done → gsd-core}/templates/research-project/FEATURES.md +0 -0
- /package/{get-shit-done → gsd-core}/templates/research-project/PITFALLS.md +0 -0
- /package/{get-shit-done → gsd-core}/templates/research-project/STACK.md +0 -0
- /package/{get-shit-done → gsd-core}/templates/research-project/SUMMARY.md +0 -0
- /package/{get-shit-done → gsd-core}/templates/research.md +0 -0
- /package/{get-shit-done → gsd-core}/templates/retrospective.md +0 -0
- /package/{get-shit-done → gsd-core}/templates/roadmap.md +0 -0
- /package/{get-shit-done → gsd-core}/templates/spec.md +0 -0
- /package/{get-shit-done → gsd-core}/templates/state.md +0 -0
- /package/{get-shit-done → gsd-core}/templates/summary-complex.md +0 -0
- /package/{get-shit-done → gsd-core}/templates/summary-minimal.md +0 -0
- /package/{get-shit-done → gsd-core}/templates/summary-standard.md +0 -0
- /package/{get-shit-done → gsd-core}/templates/summary.md +0 -0
- /package/{get-shit-done → gsd-core}/templates/user-profile.md +0 -0
- /package/{get-shit-done → gsd-core}/templates/user-setup.md +0 -0
- /package/{get-shit-done → gsd-core}/templates/verification-report.md +0 -0
- /package/{get-shit-done → gsd-core}/workflows/analyze-dependencies.md +0 -0
- /package/{get-shit-done → gsd-core}/workflows/discuss-phase/modes/all.md +0 -0
- /package/{get-shit-done → gsd-core}/workflows/discuss-phase/modes/analyze.md +0 -0
- /package/{get-shit-done → gsd-core}/workflows/discuss-phase/modes/batch.md +0 -0
- /package/{get-shit-done → gsd-core}/workflows/discuss-phase/modes/default.md +0 -0
- /package/{get-shit-done → gsd-core}/workflows/discuss-phase/modes/text.md +0 -0
- /package/{get-shit-done → gsd-core}/workflows/discuss-phase/templates/checkpoint.json +0 -0
- /package/{get-shit-done → gsd-core}/workflows/discuss-phase/templates/context.md +0 -0
- /package/{get-shit-done → gsd-core}/workflows/discuss-phase/templates/discussion-log.md +0 -0
- /package/{get-shit-done → gsd-core}/workflows/discuss-phase-power.md +0 -0
- /package/{get-shit-done → gsd-core}/workflows/execute-phase/steps/per-plan-worktree-gate.md +0 -0
- /package/{get-shit-done → gsd-core}/workflows/fast.md +0 -0
- /package/{get-shit-done → gsd-core}/workflows/help/modes/brief.md +0 -0
- /package/{get-shit-done → gsd-core}/workflows/help/modes/topic.md +0 -0
- /package/{get-shit-done → gsd-core}/workflows/help.md +0 -0
- /package/{get-shit-done → gsd-core}/workflows/inbox.md +0 -0
- /package/{get-shit-done → gsd-core}/workflows/list-phase-assumptions.md +0 -0
- /package/{get-shit-done → gsd-core}/workflows/node-repair.md +0 -0
- /package/{get-shit-done → gsd-core}/workflows/note.md +0 -0
- /package/{get-shit-done → gsd-core}/workflows/pr-branch.md +0 -0
- /package/{get-shit-done → gsd-core}/workflows/session-report.md +0 -0
|
@@ -1,13 +1,19 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
"use strict";
|
|
3
2
|
/**
|
|
4
3
|
* Schema Drift Detection — detects schema-relevant file changes and verifies
|
|
5
|
-
* that the appropriate database push command was executed during a phase
|
|
4
|
+
* that the appropriate database push command was executed during a phase
|
|
5
|
+
* (ADR-457 build-at-publish: the hand-written bin/lib/schema-detect.cjs
|
|
6
|
+
* collapsed to a TypeScript source of truth). Behaviour is preserved
|
|
7
|
+
* byte-for-behaviour from the prior hand-written .cjs; only types are added.
|
|
8
|
+
*
|
|
6
9
|
* This module does not read the filesystem directly.
|
|
7
10
|
*/
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
exports.ORM_INFO = exports.SCHEMA_PATTERNS = void 0;
|
|
13
|
+
exports.detectSchemaFiles = detectSchemaFiles;
|
|
14
|
+
exports.detectSchemaOrm = detectSchemaOrm;
|
|
15
|
+
exports.checkSchemaDrift = checkSchemaDrift;
|
|
16
|
+
exports.SCHEMA_PATTERNS = [
|
|
11
17
|
{ pattern: /^src\/collections\/.*\.ts$/, orm: 'payload' },
|
|
12
18
|
{ pattern: /^src\/globals\/.*\.ts$/, orm: 'payload' },
|
|
13
19
|
{ pattern: /^prisma\/schema\.prisma$/, orm: 'prisma' },
|
|
@@ -19,9 +25,7 @@ const SCHEMA_PATTERNS = [
|
|
|
19
25
|
{ pattern: /^src\/entities\/.*\.ts$/, orm: 'typeorm' },
|
|
20
26
|
{ pattern: /^src\/migrations\/.*\.ts$/, orm: 'typeorm' },
|
|
21
27
|
];
|
|
22
|
-
|
|
23
|
-
// ─── Push Commands & Evidence Patterns ──────────────────────────────────────
|
|
24
|
-
const ORM_INFO = {
|
|
28
|
+
exports.ORM_INFO = {
|
|
25
29
|
payload: {
|
|
26
30
|
pushCommand: 'npx payload migrate',
|
|
27
31
|
envHint: 'CI=true PAYLOAD_MIGRATING=true npx payload migrate',
|
|
@@ -53,14 +57,12 @@ const ORM_INFO = {
|
|
|
53
57
|
evidencePatterns: [/typeorm\s+migration:run/i, /typeorm\s+schema:sync/i],
|
|
54
58
|
},
|
|
55
59
|
};
|
|
56
|
-
|
|
57
|
-
// ─── Public API ──────────────────────────────────────────────────────────────
|
|
58
60
|
function detectSchemaFiles(files) {
|
|
59
61
|
const matches = [];
|
|
60
62
|
const orms = new Set();
|
|
61
63
|
for (const rawFile of files) {
|
|
62
64
|
const file = rawFile.replace(/\\/g, '/');
|
|
63
|
-
for (const { pattern, orm } of SCHEMA_PATTERNS) {
|
|
65
|
+
for (const { pattern, orm } of exports.SCHEMA_PATTERNS) {
|
|
64
66
|
if (pattern.test(file)) {
|
|
65
67
|
matches.push(rawFile);
|
|
66
68
|
orms.add(orm);
|
|
@@ -74,11 +76,9 @@ function detectSchemaFiles(files) {
|
|
|
74
76
|
orms: [...orms],
|
|
75
77
|
};
|
|
76
78
|
}
|
|
77
|
-
|
|
78
79
|
function detectSchemaOrm(ormName) {
|
|
79
|
-
|
|
80
|
+
return exports.ORM_INFO[ormName] || null;
|
|
80
81
|
}
|
|
81
|
-
|
|
82
82
|
function checkSchemaDrift(changedFiles, executionLog, options = {}) {
|
|
83
83
|
const { skipCheck = false } = options;
|
|
84
84
|
const detection = detectSchemaFiles(changedFiles);
|
|
@@ -95,7 +95,7 @@ function checkSchemaDrift(changedFiles, executionLog, options = {}) {
|
|
|
95
95
|
const pushedOrms = new Set();
|
|
96
96
|
const unpushedOrms = [];
|
|
97
97
|
for (const orm of detection.orms) {
|
|
98
|
-
const info = ORM_INFO[orm];
|
|
98
|
+
const info = exports.ORM_INFO[orm];
|
|
99
99
|
if (!info)
|
|
100
100
|
continue;
|
|
101
101
|
const hasPushEvidence = info.evidencePatterns.some(p => p.test(executionLog));
|
|
@@ -106,6 +106,8 @@ function checkSchemaDrift(changedFiles, executionLog, options = {}) {
|
|
|
106
106
|
unpushedOrms.push(orm);
|
|
107
107
|
}
|
|
108
108
|
}
|
|
109
|
+
// Suppress unused variable warning — pushedOrms tracks for conceptual clarity
|
|
110
|
+
void pushedOrms;
|
|
109
111
|
const driftDetected = unpushedOrms.length > 0;
|
|
110
112
|
if (!driftDetected) {
|
|
111
113
|
return {
|
|
@@ -119,10 +121,10 @@ function checkSchemaDrift(changedFiles, executionLog, options = {}) {
|
|
|
119
121
|
}
|
|
120
122
|
const pushCommands = unpushedOrms
|
|
121
123
|
.map(orm => {
|
|
122
|
-
const info = ORM_INFO[orm];
|
|
124
|
+
const info = exports.ORM_INFO[orm];
|
|
123
125
|
return info ? ` ${orm}: ${info.envHint || info.pushCommand}` : null;
|
|
124
126
|
})
|
|
125
|
-
.filter(
|
|
127
|
+
.filter((x) => x !== null)
|
|
126
128
|
.join('\n');
|
|
127
129
|
const message = [
|
|
128
130
|
'Schema drift detected: schema-relevant files changed but no database push was executed.',
|
|
@@ -155,11 +157,3 @@ function checkSchemaDrift(changedFiles, executionLog, options = {}) {
|
|
|
155
157
|
message,
|
|
156
158
|
};
|
|
157
159
|
}
|
|
158
|
-
|
|
159
|
-
module.exports = {
|
|
160
|
-
SCHEMA_PATTERNS,
|
|
161
|
-
ORM_INFO,
|
|
162
|
-
detectSchemaFiles,
|
|
163
|
-
detectSchemaOrm,
|
|
164
|
-
checkSchemaDrift,
|
|
165
|
-
};
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Secrets handling — masking convention for API keys and other
|
|
4
|
+
* credentials managed via /gsd-settings-integrations (ADR-457 build-at-publish:
|
|
5
|
+
* the hand-written bin/lib/secrets.cjs collapsed to a TypeScript source of
|
|
6
|
+
* truth). Behaviour is preserved byte-for-behaviour from the prior hand-written
|
|
7
|
+
* .cjs; only types are added.
|
|
8
|
+
*
|
|
9
|
+
* This module does not read the filesystem.
|
|
10
|
+
*/
|
|
11
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
exports.SECRET_CONFIG_KEYS = void 0;
|
|
13
|
+
exports.isSecretKey = isSecretKey;
|
|
14
|
+
exports.maskSecret = maskSecret;
|
|
15
|
+
exports.maskIfSecret = maskIfSecret;
|
|
16
|
+
exports.SECRET_CONFIG_KEYS = new Set([
|
|
17
|
+
'brave_search',
|
|
18
|
+
'firecrawl',
|
|
19
|
+
'exa_search',
|
|
20
|
+
]);
|
|
21
|
+
function isSecretKey(keyPath) {
|
|
22
|
+
return exports.SECRET_CONFIG_KEYS.has(keyPath);
|
|
23
|
+
}
|
|
24
|
+
function maskSecret(value) {
|
|
25
|
+
if (value === null || value === undefined || value === '')
|
|
26
|
+
return '(unset)';
|
|
27
|
+
const s = String(value);
|
|
28
|
+
if (s.length < 8)
|
|
29
|
+
return '****';
|
|
30
|
+
return '****' + s.slice(-4);
|
|
31
|
+
}
|
|
32
|
+
function maskIfSecret(keyPath, value) {
|
|
33
|
+
return isSecretKey(keyPath) ? maskSecret(value) : value;
|
|
34
|
+
}
|
|
@@ -0,0 +1,407 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Security — Input validation, path traversal prevention, and prompt injection guards
|
|
4
|
+
*
|
|
5
|
+
* This module centralizes security checks for GSD tooling. Because GSD generates
|
|
6
|
+
* markdown files that become LLM system prompts (agent instructions, workflow state,
|
|
7
|
+
* phase plans), any user-controlled text that flows into these files is a potential
|
|
8
|
+
* indirect prompt injection vector.
|
|
9
|
+
*
|
|
10
|
+
* Threat model:
|
|
11
|
+
* 1. Path traversal: user-supplied file paths escape the project directory
|
|
12
|
+
* 2. Prompt injection: malicious text in arguments/PRDs embeds LLM instructions
|
|
13
|
+
* 3. Shell metacharacter injection: user text interpreted by shell
|
|
14
|
+
* 4. JSON injection: malformed JSON crashes or corrupts state
|
|
15
|
+
* 5. Regex DoS: crafted input causes catastrophic backtracking
|
|
16
|
+
*
|
|
17
|
+
* ADR-457 build-at-publish: the hand-written bin/lib/security.cjs collapsed
|
|
18
|
+
* to a TypeScript source of truth. Behaviour is preserved byte-for-behaviour
|
|
19
|
+
* from the prior hand-written .cjs; only types are added.
|
|
20
|
+
*/
|
|
21
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
22
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
23
|
+
};
|
|
24
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
25
|
+
exports.MARKDOWN_LINK_PATTERNS = exports.INJECTION_PATTERNS = void 0;
|
|
26
|
+
exports.validatePath = validatePath;
|
|
27
|
+
exports.requireSafePath = requireSafePath;
|
|
28
|
+
exports.scanForInjection = scanForInjection;
|
|
29
|
+
exports.sanitizeForPrompt = sanitizeForPrompt;
|
|
30
|
+
exports.sanitizeForDisplay = sanitizeForDisplay;
|
|
31
|
+
exports.validateShellArg = validateShellArg;
|
|
32
|
+
exports.safeJsonParse = safeJsonParse;
|
|
33
|
+
exports.validatePhaseNumber = validatePhaseNumber;
|
|
34
|
+
exports.validateFieldName = validateFieldName;
|
|
35
|
+
exports.validatePromptStructure = validatePromptStructure;
|
|
36
|
+
exports.scanEntropyAnomalies = scanEntropyAnomalies;
|
|
37
|
+
const node_fs_1 = __importDefault(require("node:fs"));
|
|
38
|
+
const node_path_1 = __importDefault(require("node:path"));
|
|
39
|
+
// ─── Path Traversal Prevention ──────────────────────────────────────────────
|
|
40
|
+
/**
|
|
41
|
+
* Validate that a file path resolves within an allowed base directory.
|
|
42
|
+
* Prevents path traversal attacks via ../ sequences, symlinks, or absolute paths.
|
|
43
|
+
*/
|
|
44
|
+
function validatePath(filePath, baseDir, opts = {}) {
|
|
45
|
+
if (!filePath || typeof filePath !== 'string') {
|
|
46
|
+
return { safe: false, resolved: '', error: 'Empty or invalid file path' };
|
|
47
|
+
}
|
|
48
|
+
if (!baseDir || typeof baseDir !== 'string') {
|
|
49
|
+
return { safe: false, resolved: '', error: 'Empty or invalid base directory' };
|
|
50
|
+
}
|
|
51
|
+
if (filePath.includes('\0')) {
|
|
52
|
+
return { safe: false, resolved: '', error: 'Path contains null bytes' };
|
|
53
|
+
}
|
|
54
|
+
let resolvedBase;
|
|
55
|
+
try {
|
|
56
|
+
resolvedBase = node_fs_1.default.realpathSync(node_path_1.default.resolve(baseDir));
|
|
57
|
+
}
|
|
58
|
+
catch {
|
|
59
|
+
resolvedBase = node_path_1.default.resolve(baseDir);
|
|
60
|
+
}
|
|
61
|
+
let resolvedPath;
|
|
62
|
+
if (node_path_1.default.isAbsolute(filePath)) {
|
|
63
|
+
if (!opts.allowAbsolute) {
|
|
64
|
+
return { safe: false, resolved: '', error: 'Absolute paths not allowed' };
|
|
65
|
+
}
|
|
66
|
+
resolvedPath = node_path_1.default.resolve(filePath);
|
|
67
|
+
}
|
|
68
|
+
else {
|
|
69
|
+
resolvedPath = node_path_1.default.resolve(baseDir, filePath);
|
|
70
|
+
}
|
|
71
|
+
try {
|
|
72
|
+
resolvedPath = node_fs_1.default.realpathSync(resolvedPath);
|
|
73
|
+
}
|
|
74
|
+
catch {
|
|
75
|
+
const parentDir = node_path_1.default.dirname(resolvedPath);
|
|
76
|
+
try {
|
|
77
|
+
const realParent = node_fs_1.default.realpathSync(parentDir);
|
|
78
|
+
resolvedPath = node_path_1.default.join(realParent, node_path_1.default.basename(resolvedPath));
|
|
79
|
+
}
|
|
80
|
+
catch {
|
|
81
|
+
// Parent doesn't exist either — keep the resolved path as-is
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
const normalizedBase = resolvedBase + node_path_1.default.sep;
|
|
85
|
+
const normalizedPath = resolvedPath + node_path_1.default.sep;
|
|
86
|
+
if (resolvedPath !== resolvedBase && !normalizedPath.startsWith(normalizedBase)) {
|
|
87
|
+
return {
|
|
88
|
+
safe: false,
|
|
89
|
+
resolved: resolvedPath,
|
|
90
|
+
error: `Path escapes allowed directory: ${resolvedPath} is outside ${resolvedBase}`,
|
|
91
|
+
};
|
|
92
|
+
}
|
|
93
|
+
return { safe: true, resolved: resolvedPath };
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* Validate a file path and throw on traversal attempt.
|
|
97
|
+
* Convenience wrapper around validatePath for use in CLI commands.
|
|
98
|
+
*/
|
|
99
|
+
function requireSafePath(filePath, baseDir, label, opts = {}) {
|
|
100
|
+
const result = validatePath(filePath, baseDir, opts);
|
|
101
|
+
if (!result.safe) {
|
|
102
|
+
throw new Error(`${label || 'Path'} validation failed: ${result.error}`);
|
|
103
|
+
}
|
|
104
|
+
return result.resolved;
|
|
105
|
+
}
|
|
106
|
+
// ─── Prompt Injection Detection ────────────────────────────────────────────────────
|
|
107
|
+
/**
|
|
108
|
+
* Patterns that indicate prompt injection attempts in user-supplied text.
|
|
109
|
+
* These patterns catch common indirect prompt injection techniques where
|
|
110
|
+
* an attacker embeds LLM instructions in text that will be read by an agent.
|
|
111
|
+
*
|
|
112
|
+
* Note: This is defense-in-depth — not a complete solution. The primary defense
|
|
113
|
+
* is proper input/output boundaries in agent prompts.
|
|
114
|
+
*/
|
|
115
|
+
exports.INJECTION_PATTERNS = [
|
|
116
|
+
// Direct instruction override attempts
|
|
117
|
+
/ignore\s+(all\s+)?previous\s+instructions/i,
|
|
118
|
+
/ignore\s+(all\s+)?above\s+instructions/i,
|
|
119
|
+
/disregard\s+(all\s+)?previous/i,
|
|
120
|
+
/forget\s+(all\s+)?(your\s+)?instructions/i,
|
|
121
|
+
/override\s+(system|previous)\s+(prompt|instructions)/i,
|
|
122
|
+
// Role/identity manipulation
|
|
123
|
+
/you\s+are\s+now\s+(?:a|an|the)\s+/i,
|
|
124
|
+
/act\s+as\s+(?:a|an|the)\s+(?!plan|phase|wave)/i,
|
|
125
|
+
/pretend\s+(?:you(?:'re| are)\s+|to\s+be\s+)/i,
|
|
126
|
+
/from\s+now\s+on,?\s+you\s+(?:are|will|should|must)/i,
|
|
127
|
+
// System prompt extraction
|
|
128
|
+
/(?:print|output|reveal|show|display|repeat)\s+(?:your\s+)?(?:system\s+)?(?:prompt|instructions)/i,
|
|
129
|
+
/what\s+(?:are|is)\s+your\s+(?:system\s+)?(?:prompt|instructions)/i,
|
|
130
|
+
// Hidden instruction markers (XML/HTML tags that mimic system messages)
|
|
131
|
+
// Note: <instructions> is excluded — GSD uses it as legitimate prompt structure
|
|
132
|
+
// Requires > to close the tag (not just whitespace) to avoid matching generic types like Promise<User | null>
|
|
133
|
+
/<\/?(?:system|assistant|human)>/i,
|
|
134
|
+
/\[SYSTEM\]/i,
|
|
135
|
+
/\[\/?(INST)\]/i,
|
|
136
|
+
/<<\s*SYS\s*>>/i,
|
|
137
|
+
// Exfiltration attempts
|
|
138
|
+
/(?:send|post|fetch|curl|wget)\s+(?:to|from)\s+https?:\/\//i,
|
|
139
|
+
/(?:base64|btoa|encode)\s+(?:and\s+)?(?:send|exfiltrate|output)/i,
|
|
140
|
+
// Tool manipulation
|
|
141
|
+
/(?:run|execute|call|invoke)\s+(?:the\s+)?(?:bash|shell|exec|spawn)\s+(?:tool|command)/i,
|
|
142
|
+
];
|
|
143
|
+
// Explicit safe-list for data: MIME types that are benign in link targets.
|
|
144
|
+
// Note: image/svg+xml is intentionally NOT in this list (SVG can host <script>).
|
|
145
|
+
const DATA_URI_SAFE_MIME_RE = /^data:(image\/(png|jpe?g|gif|webp|bmp|ico|avif|heic)|font\/(woff2?|otf|ttf))(;[^,]*)?,/i;
|
|
146
|
+
exports.MARKDOWN_LINK_PATTERNS = [
|
|
147
|
+
{
|
|
148
|
+
pattern: /\]\(\s*javascript:/i,
|
|
149
|
+
ruleId: 'MD-LINK-JS-SCHEME',
|
|
150
|
+
},
|
|
151
|
+
{
|
|
152
|
+
pattern: /\]\(\s*data:/i,
|
|
153
|
+
ruleId: 'MD-LINK-DATA-SCHEME',
|
|
154
|
+
safePredicate: (line) => {
|
|
155
|
+
const m = line.match(/\]\(\s*(data:[^)]*)/i);
|
|
156
|
+
if (!m)
|
|
157
|
+
return false;
|
|
158
|
+
return DATA_URI_SAFE_MIME_RE.test(m[1]);
|
|
159
|
+
},
|
|
160
|
+
},
|
|
161
|
+
{
|
|
162
|
+
pattern: /\]\(\s*https?:\/\/[^/\s]+:[^/@\s]+@/i,
|
|
163
|
+
ruleId: 'MD-LINK-USERINFO',
|
|
164
|
+
},
|
|
165
|
+
{
|
|
166
|
+
pattern: /[?&](token|access_token|id_token|refresh_token|api_key|apikey|secret|password|client_secret|code)=/i,
|
|
167
|
+
ruleId: 'MD-LINK-TOKEN-IN-QUERY',
|
|
168
|
+
},
|
|
169
|
+
];
|
|
170
|
+
const OBFUSCATION_PATTERN_ENTRIES = [
|
|
171
|
+
{
|
|
172
|
+
pattern: /\b(\w\s){4,}\w\b/,
|
|
173
|
+
message: 'Character-spacing obfuscation pattern detected (e.g. "i g n o r e")',
|
|
174
|
+
},
|
|
175
|
+
{
|
|
176
|
+
pattern: /<\/?(system|human|assistant|user)\s*>/i,
|
|
177
|
+
message: 'Delimiter injection pattern: <system>/<human>/<assistant>/<user> tag detected',
|
|
178
|
+
},
|
|
179
|
+
{
|
|
180
|
+
pattern: /0x[0-9a-fA-F]{16,}/,
|
|
181
|
+
message: 'Long hex sequence detected — possible encoded payload',
|
|
182
|
+
},
|
|
183
|
+
];
|
|
184
|
+
/**
|
|
185
|
+
* Scan text for potential prompt injection patterns.
|
|
186
|
+
* Returns an array of findings (empty = clean).
|
|
187
|
+
*/
|
|
188
|
+
function scanForInjection(text, opts = {}) {
|
|
189
|
+
if (!text || typeof text !== 'string') {
|
|
190
|
+
return { clean: true, findings: [], structuredFindings: [] };
|
|
191
|
+
}
|
|
192
|
+
const findings = [];
|
|
193
|
+
const structuredFindings = [];
|
|
194
|
+
for (const pattern of exports.INJECTION_PATTERNS) {
|
|
195
|
+
if (pattern.test(text)) {
|
|
196
|
+
findings.push(`Matched injection pattern: ${pattern.source}`);
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
for (const entry of OBFUSCATION_PATTERN_ENTRIES) {
|
|
200
|
+
if (entry.pattern.test(text)) {
|
|
201
|
+
findings.push(entry.message);
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
const lines = text.split('\n');
|
|
205
|
+
for (const entry of exports.MARKDOWN_LINK_PATTERNS) {
|
|
206
|
+
for (let i = 0; i < lines.length; i++) {
|
|
207
|
+
const line = lines[i];
|
|
208
|
+
const m = line.match(entry.pattern);
|
|
209
|
+
if (!m)
|
|
210
|
+
continue;
|
|
211
|
+
if (entry.safePredicate && entry.safePredicate(line))
|
|
212
|
+
continue;
|
|
213
|
+
const matchText = m[0];
|
|
214
|
+
findings.push(`Matched markdown link pattern [${entry.ruleId}]: ${matchText}`);
|
|
215
|
+
structuredFindings.push({
|
|
216
|
+
ruleId: entry.ruleId,
|
|
217
|
+
file: opts.file,
|
|
218
|
+
line: i + 1,
|
|
219
|
+
match: matchText,
|
|
220
|
+
});
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
if (opts.strict) {
|
|
224
|
+
// Check for suspicious Unicode that could hide instructions
|
|
225
|
+
// (zero-width chars, RTL override, homoglyph attacks)
|
|
226
|
+
if (/[\u200B-\u200F\u2028-\u202F\uFEFF\u00AD]/.test(text)) {
|
|
227
|
+
findings.push('Contains suspicious zero-width or invisible Unicode characters');
|
|
228
|
+
}
|
|
229
|
+
// Layer 1: Unicode tag block U+E0000–E007F (2025 supply-chain attack vector)
|
|
230
|
+
// These characters are invisible and can embed hidden instructions
|
|
231
|
+
if (/[\uDB40\uDC00-\uDB40\uDC7F]/u.test(text) || /[\u{E0000}-\u{E007F}]/u.test(text)) {
|
|
232
|
+
findings.push('Contains Unicode tag block characters (U+E0000–E007F) — invisible instruction injection vector');
|
|
233
|
+
}
|
|
234
|
+
// Check for extremely long strings that could be prompt stuffing.
|
|
235
|
+
// Normalize CRLF → LF before measuring so Windows checkouts don't inflate the count.
|
|
236
|
+
const normalizedLength = text.replace(/\r\n/g, '\n').replace(/\r/g, '\n').length;
|
|
237
|
+
if (normalizedLength > 50000) {
|
|
238
|
+
findings.push(`Suspicious text length: ${normalizedLength} chars (potential prompt stuffing)`);
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
return { clean: findings.length === 0, findings, structuredFindings };
|
|
242
|
+
}
|
|
243
|
+
/**
|
|
244
|
+
* Sanitize text that will be embedded in agent prompts or planning documents.
|
|
245
|
+
* Strips known injection markers while preserving legitimate content.
|
|
246
|
+
*/
|
|
247
|
+
function sanitizeForPrompt(text) {
|
|
248
|
+
if (!text || typeof text !== 'string')
|
|
249
|
+
return text;
|
|
250
|
+
let sanitized = text;
|
|
251
|
+
// Strip zero-width characters that could hide instructions
|
|
252
|
+
sanitized = sanitized.replace(/[\u200B-\u200F\u2028-\u202F\uFEFF\u00AD]/g, '');
|
|
253
|
+
// Neutralize XML/HTML tags that mimic system boundaries
|
|
254
|
+
// Note: <instructions> is excluded — GSD uses it as legitimate prompt structure
|
|
255
|
+
sanitized = sanitized.replace(/<(\/?)\s*(?:system|assistant|human|user)\s*>/gi, (_, slash) => `<${slash || ''}system-text>`);
|
|
256
|
+
// Neutralize [SYSTEM] / [INST] / [/INST] markers
|
|
257
|
+
sanitized = sanitized.replace(/\[(\/?)(SYSTEM|INST)\]/gi, (_, slash, tag) => `[${slash}${tag.toUpperCase()}-TEXT]`);
|
|
258
|
+
// Neutralize <<SYS>> and <</SYS>> markers (Llama-style delimiters)
|
|
259
|
+
sanitized = sanitized.replace(/<<\/?\s*SYS\s*>>/gi, '«SYS-TEXT»');
|
|
260
|
+
return sanitized;
|
|
261
|
+
}
|
|
262
|
+
/**
|
|
263
|
+
* Sanitize text that will be displayed back to the user.
|
|
264
|
+
* Removes protocol-like leak markers that should never surface in checkpoints.
|
|
265
|
+
*/
|
|
266
|
+
function sanitizeForDisplay(text) {
|
|
267
|
+
if (!text || typeof text !== 'string')
|
|
268
|
+
return text;
|
|
269
|
+
let sanitized = sanitizeForPrompt(text);
|
|
270
|
+
const protocolLeakPatterns = [
|
|
271
|
+
/^\s*(?:assistant|user|system)\s+to=[^:\s]+:[^\n]+$/i,
|
|
272
|
+
/^\s*<\|(?:assistant|user|system)[^|]*\|>\s*$/i,
|
|
273
|
+
];
|
|
274
|
+
sanitized = sanitized
|
|
275
|
+
.split('\n')
|
|
276
|
+
.filter(line => !protocolLeakPatterns.some(pattern => pattern.test(line)))
|
|
277
|
+
.join('\n');
|
|
278
|
+
return sanitized;
|
|
279
|
+
}
|
|
280
|
+
// ─── Shell Safety ───────────────────────────────────────────────────────────────────────
|
|
281
|
+
/**
|
|
282
|
+
* Validate that a string is safe to use as a shell argument when quoted.
|
|
283
|
+
*/
|
|
284
|
+
function validateShellArg(value, label) {
|
|
285
|
+
if (!value || typeof value !== 'string') {
|
|
286
|
+
throw new Error(`${label || 'Argument'}: empty or invalid value`);
|
|
287
|
+
}
|
|
288
|
+
if (value.includes('\0')) {
|
|
289
|
+
throw new Error(`${label || 'Argument'}: contains null bytes`);
|
|
290
|
+
}
|
|
291
|
+
if (/[$`]/.test(value) && /\$\(|`/.test(value)) {
|
|
292
|
+
throw new Error(`${label || 'Argument'}: contains potential command substitution`);
|
|
293
|
+
}
|
|
294
|
+
return value;
|
|
295
|
+
}
|
|
296
|
+
// ─── JSON Safety ──────────────────────────────────────────────────────────────────────────
|
|
297
|
+
/**
|
|
298
|
+
* Safely parse JSON with error handling and optional size limits.
|
|
299
|
+
*/
|
|
300
|
+
function safeJsonParse(text, opts = {}) {
|
|
301
|
+
const maxLength = opts.maxLength || 1048576;
|
|
302
|
+
const label = opts.label || 'JSON';
|
|
303
|
+
if (!text || typeof text !== 'string') {
|
|
304
|
+
return { ok: false, error: `${label}: empty or invalid input` };
|
|
305
|
+
}
|
|
306
|
+
if (text.length > maxLength) {
|
|
307
|
+
return { ok: false, error: `${label}: input exceeds ${maxLength} byte limit (got ${text.length})` };
|
|
308
|
+
}
|
|
309
|
+
try {
|
|
310
|
+
const value = JSON.parse(text);
|
|
311
|
+
return { ok: true, value };
|
|
312
|
+
}
|
|
313
|
+
catch (err) {
|
|
314
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
315
|
+
return { ok: false, error: `${label}: parse error — ${msg}` };
|
|
316
|
+
}
|
|
317
|
+
}
|
|
318
|
+
// ─── Phase/Argument Validation ─────────────────────────────────────────────────────────
|
|
319
|
+
/**
|
|
320
|
+
* Validate a phase number argument.
|
|
321
|
+
*/
|
|
322
|
+
function validatePhaseNumber(phase) {
|
|
323
|
+
if (!phase || typeof phase !== 'string') {
|
|
324
|
+
return { valid: false, error: 'Phase number is required' };
|
|
325
|
+
}
|
|
326
|
+
const trimmed = phase.trim();
|
|
327
|
+
if (/^\d{1,4}[A-Z]?(?:\.\d{1,3})*$/i.test(trimmed)) {
|
|
328
|
+
return { valid: true, normalized: trimmed };
|
|
329
|
+
}
|
|
330
|
+
if (/^[A-Z][A-Z0-9]*(?:-[A-Z0-9]+){1,4}$/i.test(trimmed) && trimmed.length <= 30) {
|
|
331
|
+
return { valid: true, normalized: trimmed };
|
|
332
|
+
}
|
|
333
|
+
return { valid: false, error: `Invalid phase number format: "${trimmed}"` };
|
|
334
|
+
}
|
|
335
|
+
/**
|
|
336
|
+
* Validate a STATE.md field name to prevent injection into regex patterns.
|
|
337
|
+
*/
|
|
338
|
+
function validateFieldName(field) {
|
|
339
|
+
if (!field || typeof field !== 'string') {
|
|
340
|
+
return { valid: false, error: 'Field name is required' };
|
|
341
|
+
}
|
|
342
|
+
if (/^[A-Za-z][A-Za-z0-9 _.\-/]{0,60}$/.test(field)) {
|
|
343
|
+
return { valid: true };
|
|
344
|
+
}
|
|
345
|
+
return { valid: false, error: `Invalid field name: "${field}"` };
|
|
346
|
+
}
|
|
347
|
+
// ─── Layer 3: Structural Schema Validation ──────────────────────────────────────────────────────────────────────────
|
|
348
|
+
const KNOWN_VALID_TAGS = new Set([
|
|
349
|
+
'objective', 'process', 'step', 'success_criteria', 'critical_rules',
|
|
350
|
+
'available_agent_types', 'purpose', 'required_reading',
|
|
351
|
+
]);
|
|
352
|
+
/**
|
|
353
|
+
* Validate the XML structure of a prompt file.
|
|
354
|
+
*/
|
|
355
|
+
function validatePromptStructure(text, fileType) {
|
|
356
|
+
if (!text || typeof text !== 'string') {
|
|
357
|
+
return { valid: true, violations: [] };
|
|
358
|
+
}
|
|
359
|
+
if (fileType !== 'agent' && fileType !== 'workflow') {
|
|
360
|
+
return { valid: true, violations: [] };
|
|
361
|
+
}
|
|
362
|
+
const violations = [];
|
|
363
|
+
const tagRegex = /<([A-Za-z][A-Za-z0-9_-]*)/g;
|
|
364
|
+
let match;
|
|
365
|
+
while ((match = tagRegex.exec(text)) !== null) {
|
|
366
|
+
const tag = match[1].toLowerCase();
|
|
367
|
+
if (!KNOWN_VALID_TAGS.has(tag)) {
|
|
368
|
+
violations.push(`Unknown XML tag in ${fileType} file: <${tag}>`);
|
|
369
|
+
}
|
|
370
|
+
}
|
|
371
|
+
return { valid: violations.length === 0, violations };
|
|
372
|
+
}
|
|
373
|
+
// ─── Layer 4: Paragraph-Level Entropy Anomaly Detection ─────────────────────────────────────────────────────────────────────
|
|
374
|
+
function shannonEntropy(text) {
|
|
375
|
+
if (!text || text.length === 0)
|
|
376
|
+
return 0;
|
|
377
|
+
const freq = {};
|
|
378
|
+
for (const ch of text) {
|
|
379
|
+
freq[ch] = (freq[ch] || 0) + 1;
|
|
380
|
+
}
|
|
381
|
+
const len = text.length;
|
|
382
|
+
let entropy = 0;
|
|
383
|
+
for (const count of Object.values(freq)) {
|
|
384
|
+
const p = count / len;
|
|
385
|
+
entropy -= p * Math.log2(p);
|
|
386
|
+
}
|
|
387
|
+
return entropy;
|
|
388
|
+
}
|
|
389
|
+
/**
|
|
390
|
+
* Scan text for paragraphs with anomalously high Shannon entropy.
|
|
391
|
+
*/
|
|
392
|
+
function scanEntropyAnomalies(text) {
|
|
393
|
+
if (!text || typeof text !== 'string') {
|
|
394
|
+
return { clean: true, findings: [] };
|
|
395
|
+
}
|
|
396
|
+
const findings = [];
|
|
397
|
+
const paragraphs = text.split(/\n\n+/);
|
|
398
|
+
for (const para of paragraphs) {
|
|
399
|
+
if (para.length <= 50)
|
|
400
|
+
continue;
|
|
401
|
+
const entropy = shannonEntropy(para);
|
|
402
|
+
if (entropy > 5.5) {
|
|
403
|
+
findings.push(`High-entropy paragraph detected (${entropy.toFixed(2)} bits/char) — possible encoded payload`);
|
|
404
|
+
}
|
|
405
|
+
}
|
|
406
|
+
return { clean: findings.length === 0, findings };
|
|
407
|
+
}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Shared semver comparison utility (ADR-457 pilot: first hand-written
|
|
4
|
+
* bin/lib/*.cjs collapsed to a TypeScript source of truth).
|
|
5
|
+
*
|
|
6
|
+
* Logic is preserved byte-for-behaviour from the prior hand-written
|
|
7
|
+
* `gsd-core/bin/lib/semver-compare.cjs`; only types are added. The
|
|
8
|
+
* normalization policy here is locked by `tests/semver-compare.test.cjs` and
|
|
9
|
+
* consumed by update-check, statusline dev-install detection, and changeset
|
|
10
|
+
* range compare (`scripts/changeset/cli.cjs`).
|
|
11
|
+
*/
|
|
12
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
13
|
+
exports.toNumericTuple = toNumericTuple;
|
|
14
|
+
exports.compareSemverCore = compareSemverCore;
|
|
15
|
+
exports.isSemverNewer = isSemverNewer;
|
|
16
|
+
exports.isStableTripletSemver = isStableTripletSemver;
|
|
17
|
+
function toNumericTuple(input) {
|
|
18
|
+
const cleaned = String(input == null ? '' : input).trim().replace(/^v/, '');
|
|
19
|
+
const base = cleaned.replace(/[-+].*$/, '');
|
|
20
|
+
const parts = base.split('.');
|
|
21
|
+
const major = Number.parseInt(parts[0], 10) || 0;
|
|
22
|
+
const minor = Number.parseInt(parts[1], 10) || 0;
|
|
23
|
+
const patch = Number.parseInt(parts[2], 10) || 0;
|
|
24
|
+
return [major, minor, patch];
|
|
25
|
+
}
|
|
26
|
+
function compareSemverCore(a, b) {
|
|
27
|
+
const [a0, a1, a2] = toNumericTuple(a);
|
|
28
|
+
const [b0, b1, b2] = toNumericTuple(b);
|
|
29
|
+
if (a0 !== b0)
|
|
30
|
+
return a0 > b0 ? 1 : -1;
|
|
31
|
+
if (a1 !== b1)
|
|
32
|
+
return a1 > b1 ? 1 : -1;
|
|
33
|
+
if (a2 !== b2)
|
|
34
|
+
return a2 > b2 ? 1 : -1;
|
|
35
|
+
return 0;
|
|
36
|
+
}
|
|
37
|
+
function isSemverNewer(a, b) {
|
|
38
|
+
return compareSemverCore(a, b) > 0;
|
|
39
|
+
}
|
|
40
|
+
function isStableTripletSemver(v) {
|
|
41
|
+
return /^\d+\.\d+\.\d+$/.test(String(v || '').replace(/^v/, ''));
|
|
42
|
+
}
|