@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 +0,0 @@
|
|
|
1
|
-
_GSD_SHIM_NAME="gsd-tools.cjs"; _GSD_RUNTIME_ROOT="${RUNTIME_DIR:-$(git rev-parse --show-toplevel 2>/dev/null || pwd)}"; GSD_TOOLS="${_GSD_RUNTIME_ROOT}/get-shit-done/bin/${_GSD_SHIM_NAME}"; if [ -f "$GSD_TOOLS" ]; then gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${_GSD_RUNTIME_ROOT}/.claude/get-shit-done/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${_GSD_RUNTIME_ROOT}/.claude/get-shit-done/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif command -v gsd-tools >/dev/null 2>&1; then GSD_TOOLS="$(command -v gsd-tools)"; gsd_run() { "$GSD_TOOLS" "$@"; }; elif [ -f "$HOME/.claude/get-shit-done/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="$HOME/.claude/get-shit-done/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; else echo "ERROR: gsd-tools.cjs not found at $GSD_TOOLS and gsd-tools is not on PATH. Run: npx -y @opengsd/gsd-core@latest --claude --local" >&2; exit 1; fi
|
|
@@ -1,81 +0,0 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Extended detector for the no-source-grep rule (#2982).
|
|
5
|
-
*
|
|
6
|
-
* The base lint (scripts/lint-no-source-grep.cjs) only catches the
|
|
7
|
-
* direct-chain form: readFileSync(...).includes(...). The much more common
|
|
8
|
-
* var-binding form escapes it:
|
|
9
|
-
*
|
|
10
|
-
* const src = fs.readFileSync(p, 'utf8');
|
|
11
|
-
* // ... 50 lines later ...
|
|
12
|
-
* assert.ok(src.includes('foo')); // ← still source-grep, lint missed it
|
|
13
|
-
*
|
|
14
|
-
* This module exposes pure detectors that scan source text and return
|
|
15
|
-
* structured violation records. The CLI wrapper (in the base lint) calls
|
|
16
|
-
* these for each test file.
|
|
17
|
-
*
|
|
18
|
-
* Tests assert on the typed VIOLATION enum codes, not on prose messages.
|
|
19
|
-
*/
|
|
20
|
-
|
|
21
|
-
const VIOLATION = Object.freeze({
|
|
22
|
-
VAR_FROM_READFILE_USED_IN_TEXT_MATCH: 'var_from_readfile_used_in_text_match',
|
|
23
|
-
WRAPPED_ASSERT_OK_MATCH: 'wrapped_assert_ok_match',
|
|
24
|
-
});
|
|
25
|
-
|
|
26
|
-
const TEXT_MATCH_METHODS = ['includes', 'startsWith', 'endsWith', 'match', 'search'];
|
|
27
|
-
|
|
28
|
-
/**
|
|
29
|
-
* Single-pass scanner. Tracks variables bound from a readFileSync call,
|
|
30
|
-
* then flags any subsequent <var>.<method>( use where method is one of
|
|
31
|
-
* TEXT_MATCH_METHODS.
|
|
32
|
-
*/
|
|
33
|
-
function detectVarBindingViolations(src) {
|
|
34
|
-
// Pass 1: collect variables bound from readFileSync.
|
|
35
|
-
// Matches: const|let|var <name> = [fs.]readFileSync(
|
|
36
|
-
const bindRe = /(?:const|let|var)\s+([A-Za-z_$][\w$]*)\s*=\s*(?:[A-Za-z_$][\w$.]*\.)?readFileSync\s*\(/g;
|
|
37
|
-
const boundVars = new Set();
|
|
38
|
-
let m;
|
|
39
|
-
while ((m = bindRe.exec(src)) !== null) {
|
|
40
|
-
boundVars.add(m[1]);
|
|
41
|
-
}
|
|
42
|
-
if (boundVars.size === 0) return [];
|
|
43
|
-
|
|
44
|
-
// Pass 2: find <var>.<method>( on any bound var.
|
|
45
|
-
const findings = [];
|
|
46
|
-
// Build a regex alternation from the bound var names.
|
|
47
|
-
const alt = [...boundVars].map((v) => v.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')).join('|');
|
|
48
|
-
const useRe = new RegExp(
|
|
49
|
-
`\\b(${alt})\\s*\\.\\s*(${TEXT_MATCH_METHODS.join('|')})\\s*\\(`,
|
|
50
|
-
'g',
|
|
51
|
-
);
|
|
52
|
-
while ((m = useRe.exec(src)) !== null) {
|
|
53
|
-
findings.push({
|
|
54
|
-
kind: VIOLATION.VAR_FROM_READFILE_USED_IN_TEXT_MATCH,
|
|
55
|
-
variable: m[1],
|
|
56
|
-
method: m[2],
|
|
57
|
-
});
|
|
58
|
-
}
|
|
59
|
-
return findings;
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
/**
|
|
63
|
-
* Detects assert.ok(<expr>.match(/.../)) and assert.ok(<expr>.match(<expr>))
|
|
64
|
-
* which is the same anti-pattern as assert.match but escapes the simpler
|
|
65
|
-
* regex used by the base lint.
|
|
66
|
-
*/
|
|
67
|
-
function detectWrappedAssertOkMatch(src) {
|
|
68
|
-
const re = /assert\.ok\s*\(\s*[A-Za-z_$][\w$.]*\.match\s*\(/g;
|
|
69
|
-
const findings = [];
|
|
70
|
-
let m;
|
|
71
|
-
while ((m = re.exec(src)) !== null) {
|
|
72
|
-
findings.push({ kind: VIOLATION.WRAPPED_ASSERT_OK_MATCH });
|
|
73
|
-
}
|
|
74
|
-
return findings;
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
function detectAll(src) {
|
|
78
|
-
return [...detectVarBindingViolations(src), ...detectWrappedAssertOkMatch(src)];
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
module.exports = { detectVarBindingViolations, detectWrappedAssertOkMatch, detectAll, VIOLATION };
|
|
@@ -1,174 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
/**
|
|
3
|
-
* lint-no-source-grep.cjs
|
|
4
|
-
*
|
|
5
|
-
* Enforces the "no source-grep tests" rule:
|
|
6
|
-
* Tests must NOT read source-code .cjs files with readFileSync to assert string
|
|
7
|
-
* presence. That pattern (source-grep theater) proves a literal exists in source,
|
|
8
|
-
* not that the runtime behavior is correct.
|
|
9
|
-
*
|
|
10
|
-
* ALLOWED:
|
|
11
|
-
* - require('../get-shit-done/bin/lib/foo.cjs') -- runs the module, not text inspection
|
|
12
|
-
* - readFileSync on .md / .json / .txt files -- product-content or config output
|
|
13
|
-
* - Files annotated: // allow-test-rule: <reason>
|
|
14
|
-
*
|
|
15
|
-
* DISALLOWED (without allow-test-rule):
|
|
16
|
-
* - readFileSync where the path argument ends in a .cjs filename literal
|
|
17
|
-
* - A path constant (e.g. CONFIG_PATH) assigned to a .cjs lib file, used in readFileSync
|
|
18
|
-
*
|
|
19
|
-
* Exit 0 = clean. Exit 1 = violations found (with diagnostics).
|
|
20
|
-
*/
|
|
21
|
-
|
|
22
|
-
'use strict';
|
|
23
|
-
|
|
24
|
-
const fs = require('fs');
|
|
25
|
-
const path = require('path');
|
|
26
|
-
|
|
27
|
-
const TESTS_DIR = path.join(__dirname, '..', 'tests');
|
|
28
|
-
const ALLOW_ANNOTATION = /\/\/\s*allow-test-rule:\s*\S/;
|
|
29
|
-
|
|
30
|
-
// Matches constant definitions that hold a .cjs path in a SOURCE directory.
|
|
31
|
-
// Requires a source-dir indicator ('bin', 'lib', 'get-shit-done') to avoid
|
|
32
|
-
// flagging temp files like path.join(tmpDir, 'example.cjs').
|
|
33
|
-
// const CONFIG_PATH = path.join(__dirname, '..', 'get-shit-done', 'bin', 'lib', 'config-schema.cjs');
|
|
34
|
-
const CJS_PATH_CONST_RE = /(?:const|let|var)\s+(\w+)\s*=\s*path\.join\s*\([^)]*(?:'bin'|"bin"|'lib'|"lib"|'get-shit-done'|"get-shit-done")[^)]*['"][^'"]*\.cjs['"]/gm;
|
|
35
|
-
|
|
36
|
-
// Matches readFileSync with a named variable as first arg
|
|
37
|
-
const READ_WITH_CONST_RE = /readFileSync\s*\(\s*([A-Za-z_][A-Za-z0-9_]*)\s*,/gm;
|
|
38
|
-
|
|
39
|
-
// Matches readFileSync with an inline path.join(.cjs) as first arg
|
|
40
|
-
const READ_WITH_INLINE_CJS_RE = /readFileSync\s*\([^,)]*path\.join\s*\([^)]*(?:'bin'|"bin"|'lib'|"lib"|'get-shit-done'|"get-shit-done")[^)]*['"][^'"]*\.cjs['"]/;
|
|
41
|
-
|
|
42
|
-
/**
|
|
43
|
-
* #2962-class violations: raw text matching against process output or file
|
|
44
|
-
* content. The rule from CONTRIBUTING.md "Prohibited: Raw Text Matching on
|
|
45
|
-
* Test Outputs": tests assert on typed structured fields, never on rendered
|
|
46
|
-
* text. Patterns below are the obvious anti-patterns; subtler hidden forms
|
|
47
|
-
* (e.g. wrapping the same logic in a parser function) are still forbidden
|
|
48
|
-
* by the prose rule but cannot be detected lexically without an AST.
|
|
49
|
-
*/
|
|
50
|
-
const RAW_MATCH_PATTERNS = [
|
|
51
|
-
{
|
|
52
|
-
re: /assert\.(?:match|doesNotMatch)\s*\(\s*[A-Za-z_$][A-Za-z0-9_$]*\.(?:stdout|stderr)\b/,
|
|
53
|
-
label: 'assert.match/doesNotMatch on .stdout/.stderr (emit --json from the SUT and assert on typed fields)',
|
|
54
|
-
},
|
|
55
|
-
{
|
|
56
|
-
re: /\.(?:stdout|stderr)\.(?:includes|startsWith|endsWith)\s*\(/,
|
|
57
|
-
label: '.stdout/.stderr substring match (emit --json and assert on typed fields)',
|
|
58
|
-
},
|
|
59
|
-
{
|
|
60
|
-
re: /readFileSync\s*\([^)]*\)\s*\.(?:includes|startsWith|endsWith)\s*\(/,
|
|
61
|
-
label: 'readFileSync(...).<includes|startsWith|endsWith> (expose an IR from production code; assert on its fields)',
|
|
62
|
-
},
|
|
63
|
-
];
|
|
64
|
-
|
|
65
|
-
function setFromMatches(content, re) {
|
|
66
|
-
const found = new Set();
|
|
67
|
-
let m;
|
|
68
|
-
const cloned = new RegExp(re.source, re.flags);
|
|
69
|
-
while ((m = cloned.exec(content)) !== null) found.add(m[1]);
|
|
70
|
-
return found;
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
function check(filepath) {
|
|
74
|
-
const content = fs.readFileSync(filepath, 'utf-8');
|
|
75
|
-
const rel = path.relative(path.join(__dirname, '..'), filepath);
|
|
76
|
-
|
|
77
|
-
if (ALLOW_ANNOTATION.test(content)) return null;
|
|
78
|
-
|
|
79
|
-
const violations = [];
|
|
80
|
-
|
|
81
|
-
// Pattern A: readFileSync(path.join(..., 'foo.cjs'), ...)
|
|
82
|
-
if (READ_WITH_INLINE_CJS_RE.test(content)) {
|
|
83
|
-
violations.push({
|
|
84
|
-
reason: 'readFileSync with inline .cjs path literal',
|
|
85
|
-
fix: 'Replace with runGsdTools() behavioral test, or add // allow-test-rule: <reason>',
|
|
86
|
-
});
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
// Pattern B: const FOO_PATH = path.join(..., 'foo.cjs') + readFileSync(FOO_PATH, ...)
|
|
90
|
-
const cjsConsts = setFromMatches(content, CJS_PATH_CONST_RE);
|
|
91
|
-
if (cjsConsts.size > 0) {
|
|
92
|
-
const readConsts = setFromMatches(content, READ_WITH_CONST_RE);
|
|
93
|
-
const overlap = [...cjsConsts].filter(c => readConsts.has(c));
|
|
94
|
-
if (overlap.length > 0) {
|
|
95
|
-
violations.push({
|
|
96
|
-
reason: `source .cjs path constant(s) used in readFileSync: ${overlap.join(', ')}`,
|
|
97
|
-
fix: 'Replace with runGsdTools() behavioral test, or add // allow-test-rule: <reason>',
|
|
98
|
-
});
|
|
99
|
-
}
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
// Patterns C..E: raw text matching against process output or file content.
|
|
103
|
-
// See CONTRIBUTING.md "Prohibited: Raw Text Matching on Test Outputs".
|
|
104
|
-
for (const { re, label } of RAW_MATCH_PATTERNS) {
|
|
105
|
-
if (re.test(content)) {
|
|
106
|
-
violations.push({
|
|
107
|
-
reason: label,
|
|
108
|
-
fix: 'Expose typed IR from production code; assert on structured fields. Or add // allow-test-rule: <reason>',
|
|
109
|
-
});
|
|
110
|
-
}
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
// Patterns F..G (#2982): var-binding readFileSync().<text-method>() and
|
|
114
|
-
// assert.ok(<expr>.match(...)). These escape the simpler patterns above
|
|
115
|
-
// because the bind and the use are on different lines or wrapped.
|
|
116
|
-
const extras = require('./lint-no-source-grep-extras.cjs');
|
|
117
|
-
const varBindFindings = extras.detectVarBindingViolations(content);
|
|
118
|
-
if (varBindFindings.length > 0) {
|
|
119
|
-
const samples = varBindFindings.slice(0, 3)
|
|
120
|
-
.map((f) => `${f.variable}.${f.method}()`)
|
|
121
|
-
.join(', ');
|
|
122
|
-
violations.push({
|
|
123
|
-
reason: `readFileSync-bound variable used in text-match method: ${samples}${varBindFindings.length > 3 ? `, …+${varBindFindings.length - 3} more` : ''}`,
|
|
124
|
-
fix: 'Expose typed IR; assert on structured fields. Or // allow-test-rule: <reason>',
|
|
125
|
-
});
|
|
126
|
-
}
|
|
127
|
-
const wrappedFindings = extras.detectWrappedAssertOkMatch(content);
|
|
128
|
-
if (wrappedFindings.length > 0) {
|
|
129
|
-
violations.push({
|
|
130
|
-
reason: `assert.ok(<expr>.match(...)) — escapes assert.match rule (${wrappedFindings.length} occurrence${wrappedFindings.length > 1 ? 's' : ''})`,
|
|
131
|
-
fix: 'Use assert.equal on a typed field, not regex match on text. Or // allow-test-rule: <reason>',
|
|
132
|
-
});
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
if (violations.length === 0) return null;
|
|
136
|
-
return { file: rel, violations };
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
function findTestFiles(dir) {
|
|
140
|
-
const results = [];
|
|
141
|
-
for (const entry of fs.readdirSync(dir, { withFileTypes: true })) {
|
|
142
|
-
const full = path.join(dir, entry.name);
|
|
143
|
-
if (entry.isDirectory()) {
|
|
144
|
-
results.push(...findTestFiles(full));
|
|
145
|
-
} else if (entry.name.endsWith('.test.cjs')) {
|
|
146
|
-
results.push(full);
|
|
147
|
-
}
|
|
148
|
-
}
|
|
149
|
-
return results;
|
|
150
|
-
}
|
|
151
|
-
|
|
152
|
-
const testFiles = findTestFiles(TESTS_DIR);
|
|
153
|
-
|
|
154
|
-
const violations = testFiles.map(check).filter(Boolean);
|
|
155
|
-
|
|
156
|
-
if (violations.length === 0) {
|
|
157
|
-
console.log(`ok lint-no-source-grep: ${testFiles.length} test files checked, 0 violations`);
|
|
158
|
-
process.exit(0);
|
|
159
|
-
}
|
|
160
|
-
|
|
161
|
-
const totalIssues = violations.reduce((n, v) => n + v.violations.length, 0);
|
|
162
|
-
process.stderr.write(`\nERROR lint-no-source-grep: ${totalIssues} violation(s) across ${violations.length} file(s)\n\n`);
|
|
163
|
-
for (const f of violations) {
|
|
164
|
-
process.stderr.write(` ${f.file}\n`);
|
|
165
|
-
for (const v of f.violations) {
|
|
166
|
-
process.stderr.write(` Problem : ${v.reason}\n`);
|
|
167
|
-
process.stderr.write(` Fix : ${v.fix}\n`);
|
|
168
|
-
}
|
|
169
|
-
process.stderr.write('\n');
|
|
170
|
-
}
|
|
171
|
-
process.stderr.write('See CONTRIBUTING.md "Prohibited: Source-Grep Tests" and\n');
|
|
172
|
-
process.stderr.write('"Prohibited: Raw Text Matching on Test Outputs" for guidance.\n');
|
|
173
|
-
process.stderr.write('Structural tests that legitimately read source files: add // allow-test-rule: <reason>\n\n');
|
|
174
|
-
process.exit(1);
|
|
@@ -1,388 +0,0 @@
|
|
|
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();
|