@pareto4/pp-core 1.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude-plugin/plugin.json +23 -0
- package/GEMINI.md +53 -0
- package/LICENSE +22 -0
- package/README.md +100 -0
- package/agents/pp-advisor-researcher.md +108 -0
- package/agents/pp-ai-researcher.md +114 -0
- package/agents/pp-assumptions-analyzer.md +105 -0
- package/agents/pp-code-fixer.md +669 -0
- package/agents/pp-code-reviewer.md +387 -0
- package/agents/pp-codebase-mapper.md +853 -0
- package/agents/pp-debug-session-manager.md +315 -0
- package/agents/pp-debugger.md +1453 -0
- package/agents/pp-doc-classifier.md +168 -0
- package/agents/pp-doc-synthesizer.md +204 -0
- package/agents/pp-doc-verifier.md +217 -0
- package/agents/pp-doc-writer.md +616 -0
- package/agents/pp-domain-researcher.md +147 -0
- package/agents/pp-eval-auditor.md +191 -0
- package/agents/pp-eval-planner.md +154 -0
- package/agents/pp-executor.md +808 -0
- package/agents/pp-framework-selector.md +160 -0
- package/agents/pp-integration-checker.md +470 -0
- package/agents/pp-intel-updater.md +339 -0
- package/agents/pp-mempalace-curator.md +47 -0
- package/agents/pp-nyquist-auditor.md +204 -0
- package/agents/pp-pattern-mapper.md +335 -0
- package/agents/pp-phase-researcher.md +867 -0
- package/agents/pp-plan-checker.md +988 -0
- package/agents/pp-planner.md +1052 -0
- package/agents/pp-project-researcher.md +612 -0
- package/agents/pp-research-synthesizer.md +260 -0
- package/agents/pp-roadmapper.md +741 -0
- package/agents/pp-security-auditor.md +156 -0
- package/agents/pp-ui-auditor.md +495 -0
- package/agents/pp-ui-checker.md +309 -0
- package/agents/pp-ui-researcher.md +375 -0
- package/agents/pp-user-profiler.md +171 -0
- package/agents/pp-verifier.md +967 -0
- package/assets/gsd-logo-2000-transparent.png +0 -0
- package/assets/gsd-logo-2000-transparent.svg +17 -0
- package/assets/gsd-logo-2000.png +0 -0
- package/assets/gsd-logo-2000.svg +21 -0
- package/assets/terminal.svg +68 -0
- package/bin/install.js +12370 -0
- package/bin/lib/ui-safety-gate.cjs +107 -0
- package/commands/pp-add-tests.md +42 -0
- package/commands/pp-ai-integration-phase.md +37 -0
- package/commands/pp-audit-fix.md +34 -0
- package/commands/pp-audit-milestone.md +37 -0
- package/commands/pp-audit-uat.md +24 -0
- package/commands/pp-autonomous.md +51 -0
- package/commands/pp-capture.md +62 -0
- package/commands/pp-cleanup.md +24 -0
- package/commands/pp-code-review.md +59 -0
- package/commands/pp-complete-milestone.md +143 -0
- package/commands/pp-config.md +56 -0
- package/commands/pp-debug.md +52 -0
- package/commands/pp-discovery.md +34 -0
- package/commands/pp-discuss-phase.md +77 -0
- package/commands/pp-docs-update.md +49 -0
- package/commands/pp-eval-review.md +33 -0
- package/commands/pp-execute-phase.md +65 -0
- package/commands/pp-explore.md +27 -0
- package/commands/pp-extract-learnings.md +23 -0
- package/commands/pp-fast.md +31 -0
- package/commands/pp-forensics.md +57 -0
- package/commands/pp-graphify.md +204 -0
- package/commands/pp-health.md +31 -0
- package/commands/pp-help.md +28 -0
- package/commands/pp-import.md +45 -0
- package/commands/pp-inbox.md +39 -0
- package/commands/pp-ingest-docs.md +42 -0
- package/commands/pp-manager.md +45 -0
- package/commands/pp-map-codebase.md +83 -0
- package/commands/pp-mempalace-capture.md +71 -0
- package/commands/pp-mempalace-recall.md +102 -0
- package/commands/pp-milestone-summary.md +51 -0
- package/commands/pp-mvp-phase.md +45 -0
- package/commands/pp-new-milestone.md +45 -0
- package/commands/pp-new-project.md +47 -0
- package/commands/pp-ns-context.md +25 -0
- package/commands/pp-ns-ideate.md +24 -0
- package/commands/pp-ns-manage.md +36 -0
- package/commands/pp-ns-project.md +27 -0
- package/commands/pp-ns-review.md +29 -0
- package/commands/pp-ns-workflow.md +35 -0
- package/commands/pp-pause-work.md +43 -0
- package/commands/pp-phase.md +56 -0
- package/commands/pp-plan-phase.md +63 -0
- package/commands/pp-plan-review-convergence.md +60 -0
- package/commands/pp-pr-branch.md +26 -0
- package/commands/pp-profile-user.md +46 -0
- package/commands/pp-progress.md +49 -0
- package/commands/pp-quick.md +174 -0
- package/commands/pp-resume-work.md +30 -0
- package/commands/pp-review-backlog.md +63 -0
- package/commands/pp-review.md +42 -0
- package/commands/pp-secure-phase.md +36 -0
- package/commands/pp-settings.md +29 -0
- package/commands/pp-ship.md +24 -0
- package/commands/pp-sketch.md +60 -0
- package/commands/pp-spec-phase.md +63 -0
- package/commands/pp-spike.md +57 -0
- package/commands/pp-stats.md +20 -0
- package/commands/pp-surface.md +162 -0
- package/commands/pp-thread.md +24 -0
- package/commands/pp-ui-phase.md +35 -0
- package/commands/pp-ui-review.md +33 -0
- package/commands/pp-ultraplan-phase.md +34 -0
- package/commands/pp-undo.md +35 -0
- package/commands/pp-update.md +49 -0
- package/commands/pp-validate-phase.md +36 -0
- package/commands/pp-verify-work.md +39 -0
- package/commands/pp-workspace.md +52 -0
- package/commands/pp-workstreams.md +70 -0
- package/gemini-extension.json +6 -0
- package/hooks/dist/lib/git-cmd.js +150 -0
- package/hooks/dist/lib/pp-graphify-rebuild.sh +65 -0
- package/hooks/dist/managed-hooks-registry.cjs +39 -0
- package/hooks/dist/pp-check-update-worker.js +108 -0
- package/hooks/dist/pp-check-update.js +66 -0
- package/hooks/dist/pp-config-reload.js +133 -0
- package/hooks/dist/pp-context-monitor.js +196 -0
- package/hooks/dist/pp-cursor-post-tool.js +75 -0
- package/hooks/dist/pp-cursor-session-start.js +52 -0
- package/hooks/dist/pp-ensure-canonical-path.js +305 -0
- package/hooks/dist/pp-graphify-update.sh +158 -0
- package/hooks/dist/pp-phase-boundary.sh +47 -0
- package/hooks/dist/pp-prompt-guard.js +97 -0
- package/hooks/dist/pp-read-guard.js +101 -0
- package/hooks/dist/pp-read-injection-scanner.js +203 -0
- package/hooks/dist/pp-session-state.sh +59 -0
- package/hooks/dist/pp-statusline.js +566 -0
- package/hooks/dist/pp-update-banner.js +138 -0
- package/hooks/dist/pp-validate-commit.sh +57 -0
- package/hooks/dist/pp-workflow-guard.js +167 -0
- package/hooks/dist/pp-worktree-path-guard.js +185 -0
- package/hooks/hooks.json +70 -0
- package/hooks/lib/git-cmd.js +150 -0
- package/hooks/lib/pp-graphify-rebuild.sh +65 -0
- package/hooks/managed-hooks-registry.cjs +39 -0
- package/hooks/pp-check-update-worker.js +108 -0
- package/hooks/pp-check-update.js +66 -0
- package/hooks/pp-config-reload.js +133 -0
- package/hooks/pp-context-monitor.js +196 -0
- package/hooks/pp-cursor-post-tool.js +75 -0
- package/hooks/pp-cursor-session-start.js +52 -0
- package/hooks/pp-ensure-canonical-path.js +305 -0
- package/hooks/pp-graphify-update.sh +158 -0
- package/hooks/pp-phase-boundary.sh +47 -0
- package/hooks/pp-prompt-guard.js +97 -0
- package/hooks/pp-read-guard.js +101 -0
- package/hooks/pp-read-injection-scanner.js +203 -0
- package/hooks/pp-session-state.sh +59 -0
- package/hooks/pp-statusline.js +566 -0
- package/hooks/pp-update-banner.js +138 -0
- package/hooks/pp-validate-commit.sh +57 -0
- package/hooks/pp-workflow-guard.js +167 -0
- package/hooks/pp-worktree-path-guard.js +185 -0
- package/package.json +125 -0
- package/pp-core/bin/check-latest-version.cjs +161 -0
- package/pp-core/bin/lib/active-workstream-store.cjs +297 -0
- package/pp-core/bin/lib/adr-parser.cjs +399 -0
- package/pp-core/bin/lib/agent-command-router.cjs +68 -0
- package/pp-core/bin/lib/agent-install-check.cjs +143 -0
- package/pp-core/bin/lib/artifacts.cjs +51 -0
- package/pp-core/bin/lib/audit-command-router.cjs +61 -0
- package/pp-core/bin/lib/audit.cjs +743 -0
- package/pp-core/bin/lib/capability-activation.cjs +113 -0
- package/pp-core/bin/lib/capability-registry.cjs +3727 -0
- package/pp-core/bin/lib/capability-state.cjs +497 -0
- package/pp-core/bin/lib/capability-writer.cjs +355 -0
- package/pp-core/bin/lib/check-command-router.cjs +800 -0
- package/pp-core/bin/lib/cjs-command-router-adapter.cjs +81 -0
- package/pp-core/bin/lib/cli-exit.cjs +61 -0
- package/pp-core/bin/lib/clock.cjs +95 -0
- package/pp-core/bin/lib/clusters.cjs +131 -0
- package/pp-core/bin/lib/code-review-flags.cjs +59 -0
- package/pp-core/bin/lib/command-aliases.cjs +809 -0
- package/pp-core/bin/lib/command-arg-projection.cjs +55 -0
- package/pp-core/bin/lib/command-roster.cjs +19 -0
- package/pp-core/bin/lib/command-routing-hub.cjs +300 -0
- package/pp-core/bin/lib/commands.cjs +1244 -0
- package/pp-core/bin/lib/config-loader.cjs +714 -0
- package/pp-core/bin/lib/config-schema.cjs +58 -0
- package/pp-core/bin/lib/config-types.cjs +20 -0
- package/pp-core/bin/lib/config.cjs +796 -0
- package/pp-core/bin/lib/configuration.cjs +209 -0
- package/pp-core/bin/lib/context-utilization.cjs +48 -0
- package/pp-core/bin/lib/core-utils.cjs +198 -0
- package/pp-core/bin/lib/decisions.cjs +136 -0
- package/pp-core/bin/lib/docs.cjs +264 -0
- package/pp-core/bin/lib/drift.cjs +364 -0
- package/pp-core/bin/lib/edge-probe.cjs +196 -0
- package/pp-core/bin/lib/fallow-runner.cjs +153 -0
- package/pp-core/bin/lib/federated-config.cjs +182 -0
- package/pp-core/bin/lib/frontmatter.cjs +494 -0
- package/pp-core/bin/lib/gap-checker.cjs +260 -0
- package/pp-core/bin/lib/git-base-branch.cjs +220 -0
- package/pp-core/bin/lib/graphify-command-router.cjs +72 -0
- package/pp-core/bin/lib/graphify.cjs +472 -0
- package/pp-core/bin/lib/gsd2-import.cjs +456 -0
- package/pp-core/bin/lib/init-command-router.cjs +62 -0
- package/pp-core/bin/lib/init.cjs +1912 -0
- package/pp-core/bin/lib/install-profiles.cjs +814 -0
- package/pp-core/bin/lib/installer-migration-authoring.cjs +122 -0
- package/pp-core/bin/lib/installer-migration-report.cjs +351 -0
- package/pp-core/bin/lib/installer-migrations/000-first-time-baseline.cjs +225 -0
- package/pp-core/bin/lib/installer-migrations/001-legacy-orphan-files.cjs +48 -0
- package/pp-core/bin/lib/installer-migrations/002-codex-legacy-hooks-json.cjs +94 -0
- package/pp-core/bin/lib/installer-migrations/003-rename-get-shit-done-to-gsd-core.cjs +108 -0
- package/pp-core/bin/lib/installer-migrations/004-prune-stale-pristine-snapshots.cjs +123 -0
- package/pp-core/bin/lib/installer-migrations/005-rename-gsd-core-to-pp-core.cjs +109 -0
- package/pp-core/bin/lib/installer-migrations/006-rename-gsd-command-namespace.cjs +135 -0
- package/pp-core/bin/lib/installer-migrations.cjs +823 -0
- package/pp-core/bin/lib/intel-command-router.cjs +119 -0
- package/pp-core/bin/lib/intel.cjs +584 -0
- package/pp-core/bin/lib/io.cjs +220 -0
- package/pp-core/bin/lib/learnings.cjs +270 -0
- package/pp-core/bin/lib/legacy-cleanup.cjs +253 -0
- package/pp-core/bin/lib/loop-host-contract.cjs +105 -0
- package/pp-core/bin/lib/loop-resolver.cjs +479 -0
- package/pp-core/bin/lib/milestone.cjs +381 -0
- package/pp-core/bin/lib/model-catalog.cjs +154 -0
- package/pp-core/bin/lib/model-profiles.cjs +24 -0
- package/pp-core/bin/lib/model-resolver.cjs +467 -0
- package/pp-core/bin/lib/observability/event.cjs +51 -0
- package/pp-core/bin/lib/observability/logger.cjs +146 -0
- package/pp-core/bin/lib/observability/redaction.cjs +48 -0
- package/pp-core/bin/lib/package-identity.cjs +35 -0
- package/pp-core/bin/lib/package-legitimacy.cjs +368 -0
- package/pp-core/bin/lib/phase-command-router.cjs +209 -0
- package/pp-core/bin/lib/phase-id.cjs +213 -0
- package/pp-core/bin/lib/phase-lifecycle.cjs +74 -0
- package/pp-core/bin/lib/phase-locator.cjs +145 -0
- package/pp-core/bin/lib/phase.cjs +1446 -0
- package/pp-core/bin/lib/phases-command-router.cjs +43 -0
- package/pp-core/bin/lib/plan-drift-guard.cjs +117 -0
- package/pp-core/bin/lib/plan-scan.cjs +91 -0
- package/pp-core/bin/lib/planning-workspace.cjs +245 -0
- package/pp-core/bin/lib/probe-core.cjs +402 -0
- package/pp-core/bin/lib/profile-output.cjs +1164 -0
- package/pp-core/bin/lib/profile-pipeline-command-router.cjs +138 -0
- package/pp-core/bin/lib/profile-pipeline.cjs +519 -0
- package/pp-core/bin/lib/prohibition-enforcement.cjs +660 -0
- package/pp-core/bin/lib/project-root.cjs +119 -0
- package/pp-core/bin/lib/prompt-budget.cjs +305 -0
- package/pp-core/bin/lib/research-provider.cjs +137 -0
- package/pp-core/bin/lib/research-store.cjs +167 -0
- package/pp-core/bin/lib/review-reviewer-selection.cjs +121 -0
- package/pp-core/bin/lib/roadmap-command-router.cjs +166 -0
- package/pp-core/bin/lib/roadmap-parser.cjs +456 -0
- package/pp-core/bin/lib/roadmap-upgrade.cjs +476 -0
- package/pp-core/bin/lib/roadmap.cjs +738 -0
- package/pp-core/bin/lib/runtime-artifact-conversion.cjs +1966 -0
- package/pp-core/bin/lib/runtime-artifact-layout.cjs +342 -0
- package/pp-core/bin/lib/runtime-config-adapter-registry.cjs +103 -0
- package/pp-core/bin/lib/runtime-homes.cjs +272 -0
- package/pp-core/bin/lib/runtime-hooks-surface.cjs +1460 -0
- package/pp-core/bin/lib/runtime-name-policy.cjs +97 -0
- package/pp-core/bin/lib/runtime-slash.cjs +137 -0
- package/pp-core/bin/lib/schema-detect.cjs +159 -0
- package/pp-core/bin/lib/secrets.cjs +34 -0
- package/pp-core/bin/lib/security.cjs +480 -0
- package/pp-core/bin/lib/semver-compare.cjs +42 -0
- package/pp-core/bin/lib/shell-command-projection.cjs +550 -0
- package/pp-core/bin/lib/state-command-router.cjs +172 -0
- package/pp-core/bin/lib/state-document.cjs +312 -0
- package/pp-core/bin/lib/state.cjs +2587 -0
- package/pp-core/bin/lib/surface.cjs +505 -0
- package/pp-core/bin/lib/task-command-router.cjs +85 -0
- package/pp-core/bin/lib/teams-status.cjs +74 -0
- package/pp-core/bin/lib/template.cjs +246 -0
- package/pp-core/bin/lib/uat-predicate.cjs +329 -0
- package/pp-core/bin/lib/uat.cjs +359 -0
- package/pp-core/bin/lib/ui-safety-gate.cjs +98 -0
- package/pp-core/bin/lib/update-context.cjs +221 -0
- package/pp-core/bin/lib/validate-command-router.cjs +91 -0
- package/pp-core/bin/lib/validate.cjs +122 -0
- package/pp-core/bin/lib/verification-command-router.cjs +31 -0
- package/pp-core/bin/lib/verification.cjs +196 -0
- package/pp-core/bin/lib/verify-command-router.cjs +44 -0
- package/pp-core/bin/lib/verify.cjs +1932 -0
- package/pp-core/bin/lib/workstream-inventory-builder.cjs +81 -0
- package/pp-core/bin/lib/workstream-inventory.cjs +147 -0
- package/pp-core/bin/lib/workstream-name-policy.cjs +91 -0
- package/pp-core/bin/lib/workstream.cjs +386 -0
- package/pp-core/bin/lib/worktree-base-ref.cjs +350 -0
- package/pp-core/bin/lib/worktree-safety.cjs +985 -0
- package/pp-core/bin/pp-tools.cjs +2239 -0
- package/pp-core/bin/pp_run +20 -0
- package/pp-core/bin/shared/config-defaults.manifest.json +97 -0
- package/pp-core/bin/shared/config-schema.manifest.json +176 -0
- package/pp-core/bin/shared/model-catalog.json +160 -0
- package/pp-core/bin/shared/runtime-aliases.manifest.json +79 -0
- package/pp-core/bin/verify-reapply-patches.cjs +400 -0
- package/pp-core/contexts/dev.md +21 -0
- package/pp-core/contexts/research.md +22 -0
- package/pp-core/contexts/review.md +23 -0
- package/pp-core/references/agent-contracts.md +79 -0
- package/pp-core/references/ai-evals.md +156 -0
- package/pp-core/references/ai-frameworks.md +186 -0
- package/pp-core/references/artifact-types.md +131 -0
- package/pp-core/references/autonomous-smart-discuss.md +277 -0
- package/pp-core/references/checkpoints.md +814 -0
- package/pp-core/references/common-bug-patterns.md +114 -0
- package/pp-core/references/context-budget.md +85 -0
- package/pp-core/references/continuation-format.md +253 -0
- package/pp-core/references/debugger-philosophy.md +76 -0
- package/pp-core/references/decimal-phase-calculation.md +64 -0
- package/pp-core/references/doc-conflict-engine.md +91 -0
- package/pp-core/references/domain-probes.md +125 -0
- package/pp-core/references/edge-probe-fixtures/01-round-half-even/expected-coverage.json +7 -0
- package/pp-core/references/edge-probe-fixtures/01-round-half-even/requirements.json +1 -0
- package/pp-core/references/edge-probe-fixtures/02-merge-intervals/expected-coverage.json +8 -0
- package/pp-core/references/edge-probe-fixtures/02-merge-intervals/requirements.json +1 -0
- package/pp-core/references/edge-probe-fixtures/03-truncate-graphemes/expected-coverage.json +7 -0
- package/pp-core/references/edge-probe-fixtures/03-truncate-graphemes/requirements.json +1 -0
- package/pp-core/references/edge-probe-fixtures/04-money-rounding/expected-coverage.json +7 -0
- package/pp-core/references/edge-probe-fixtures/04-money-rounding/requirements.json +1 -0
- package/pp-core/references/edge-probe-fixtures/05-list-dedupe/expected-coverage.json +8 -0
- package/pp-core/references/edge-probe-fixtures/05-list-dedupe/requirements.json +1 -0
- package/pp-core/references/edge-probe-fixtures/06-resolved-mixed/expected-coverage.json +8 -0
- package/pp-core/references/edge-probe-fixtures/06-resolved-mixed/requirements.json +1 -0
- package/pp-core/references/edge-probe-fixtures/06-resolved-mixed/resolutions.json +4 -0
- package/pp-core/references/edge-probe.md +272 -0
- package/pp-core/references/execute-mvp-tdd.md +81 -0
- package/pp-core/references/executor-examples.md +110 -0
- package/pp-core/references/few-shot-examples/plan-checker.md +73 -0
- package/pp-core/references/few-shot-examples/verifier.md +109 -0
- package/pp-core/references/gate-prompts.md +100 -0
- package/pp-core/references/gates.md +70 -0
- package/pp-core/references/git-integration.md +298 -0
- package/pp-core/references/git-planning-commit.md +40 -0
- package/pp-core/references/ios-scaffold.md +123 -0
- package/pp-core/references/loop-hook-dispatch.md +61 -0
- package/pp-core/references/mandatory-initial-read.md +2 -0
- package/pp-core/references/model-profile-resolution.md +38 -0
- package/pp-core/references/model-profiles.md +245 -0
- package/pp-core/references/mvp-concepts.md +49 -0
- package/pp-core/references/phase-argument-parsing.md +61 -0
- package/pp-core/references/planner-antipatterns.md +176 -0
- package/pp-core/references/planner-chunked.md +49 -0
- package/pp-core/references/planner-gap-closure.md +62 -0
- package/pp-core/references/planner-graphify-auto-update.md +67 -0
- package/pp-core/references/planner-guidance.md +186 -0
- package/pp-core/references/planner-human-verify-mode.md +57 -0
- package/pp-core/references/planner-interface-context.md +62 -0
- package/pp-core/references/planner-load-graph-context.md +36 -0
- package/pp-core/references/planner-mvp-mode.md +53 -0
- package/pp-core/references/planner-reviews.md +42 -0
- package/pp-core/references/planner-revision.md +87 -0
- package/pp-core/references/planner-source-audit.md +73 -0
- package/pp-core/references/planning-config.md +477 -0
- package/pp-core/references/prohibition-probe-fixtures/01-streak-reminder/expected.json +14 -0
- package/pp-core/references/prohibition-probe-fixtures/02-clean-utility/expected.json +4 -0
- package/pp-core/references/prohibition-probe-fixtures/03-multi-prohibition/expected.json +32 -0
- package/pp-core/references/prohibition-probe.md +326 -0
- package/pp-core/references/project-skills-discovery.md +19 -0
- package/pp-core/references/questioning.md +162 -0
- package/pp-core/references/research-documentation-lookup.md +29 -0
- package/pp-core/references/research-philosophy.md +29 -0
- package/pp-core/references/research-verification-protocol.md +27 -0
- package/pp-core/references/revision-loop.md +97 -0
- package/pp-core/references/scout-codebase.md +51 -0
- package/pp-core/references/skeleton-template.md +48 -0
- package/pp-core/references/sketch-interactivity.md +41 -0
- package/pp-core/references/sketch-theme-system.md +94 -0
- package/pp-core/references/sketch-tooling.md +45 -0
- package/pp-core/references/sketch-variant-patterns.md +81 -0
- package/pp-core/references/spidr-splitting.md +69 -0
- package/pp-core/references/tdd.md +330 -0
- package/pp-core/references/thinking-models-debug.md +44 -0
- package/pp-core/references/thinking-models-execution.md +50 -0
- package/pp-core/references/thinking-models-planning.md +62 -0
- package/pp-core/references/thinking-models-research.md +50 -0
- package/pp-core/references/thinking-models-verification.md +55 -0
- package/pp-core/references/thinking-partner.md +96 -0
- package/pp-core/references/ui-brand.md +162 -0
- package/pp-core/references/universal-anti-patterns.md +63 -0
- package/pp-core/references/user-profiling.md +681 -0
- package/pp-core/references/user-story-template.md +58 -0
- package/pp-core/references/verification-overrides.md +227 -0
- package/pp-core/references/verification-patterns.md +612 -0
- package/pp-core/references/verify-mvp-mode.md +85 -0
- package/pp-core/references/workstream-flag.md +111 -0
- package/pp-core/references/worktree-branch-check.md +44 -0
- package/pp-core/references/worktree-path-safety.md +67 -0
- package/pp-core/templates/AI-SPEC.md +246 -0
- package/pp-core/templates/DEBUG.md +169 -0
- package/pp-core/templates/README.md +77 -0
- package/pp-core/templates/SECURITY.md +61 -0
- package/pp-core/templates/UAT.md +265 -0
- package/pp-core/templates/UI-SPEC.md +100 -0
- package/pp-core/templates/VALIDATION.md +76 -0
- package/pp-core/templates/claude-md.md +145 -0
- package/pp-core/templates/codebase/architecture.md +255 -0
- package/pp-core/templates/codebase/concerns.md +310 -0
- package/pp-core/templates/codebase/conventions.md +307 -0
- package/pp-core/templates/codebase/integrations.md +280 -0
- package/pp-core/templates/codebase/stack.md +186 -0
- package/pp-core/templates/codebase/structure.md +285 -0
- package/pp-core/templates/codebase/testing.md +480 -0
- package/pp-core/templates/config.json +62 -0
- package/pp-core/templates/context.md +352 -0
- package/pp-core/templates/continue-here.md +78 -0
- package/pp-core/templates/copilot-instructions.md +7 -0
- package/pp-core/templates/debug-subagent-prompt.md +91 -0
- package/pp-core/templates/dev-preferences.md +21 -0
- package/pp-core/templates/discovery.md +146 -0
- package/pp-core/templates/discussion-log.md +63 -0
- package/pp-core/templates/milestone-archive.md +123 -0
- package/pp-core/templates/milestone.md +115 -0
- package/pp-core/templates/phase-prompt.md +610 -0
- package/pp-core/templates/planner-subagent-prompt.md +117 -0
- package/pp-core/templates/project.md +203 -0
- package/pp-core/templates/requirements.md +231 -0
- package/pp-core/templates/research-project/ARCHITECTURE.md +204 -0
- package/pp-core/templates/research-project/FEATURES.md +147 -0
- package/pp-core/templates/research-project/PITFALLS.md +200 -0
- package/pp-core/templates/research-project/STACK.md +120 -0
- package/pp-core/templates/research-project/SUMMARY.md +170 -0
- package/pp-core/templates/research.md +592 -0
- package/pp-core/templates/retrospective.md +54 -0
- package/pp-core/templates/roadmap.md +202 -0
- package/pp-core/templates/spec.md +333 -0
- package/pp-core/templates/state.md +195 -0
- package/pp-core/templates/summary-complex.md +60 -0
- package/pp-core/templates/summary-minimal.md +42 -0
- package/pp-core/templates/summary-standard.md +49 -0
- package/pp-core/templates/summary.md +249 -0
- package/pp-core/templates/user-profile.md +146 -0
- package/pp-core/templates/user-setup.md +311 -0
- package/pp-core/templates/verification-report.md +335 -0
- package/pp-core/workflows/_runtime-launcher.snippet.sh +1 -0
- package/pp-core/workflows/add-backlog.md +91 -0
- package/pp-core/workflows/add-phase.md +113 -0
- package/pp-core/workflows/add-tests.md +355 -0
- package/pp-core/workflows/add-todo.md +161 -0
- package/pp-core/workflows/ai-integration-phase.md +295 -0
- package/pp-core/workflows/analyze-dependencies.md +96 -0
- package/pp-core/workflows/audit-fix.md +178 -0
- package/pp-core/workflows/audit-milestone.md +362 -0
- package/pp-core/workflows/audit-uat.md +110 -0
- package/pp-core/workflows/autonomous.md +886 -0
- package/pp-core/workflows/check-todos.md +180 -0
- package/pp-core/workflows/cleanup.md +195 -0
- package/pp-core/workflows/code-review-fix.md +506 -0
- package/pp-core/workflows/code-review.md +696 -0
- package/pp-core/workflows/complete-milestone.md +857 -0
- package/pp-core/workflows/debug.md +237 -0
- package/pp-core/workflows/diagnose-issues.md +245 -0
- package/pp-core/workflows/discovery-phase.md +291 -0
- package/pp-core/workflows/discovery-sprint.md +1546 -0
- package/pp-core/workflows/discuss-phase/modes/advisor.md +176 -0
- package/pp-core/workflows/discuss-phase/modes/all.md +28 -0
- package/pp-core/workflows/discuss-phase/modes/analyze.md +44 -0
- package/pp-core/workflows/discuss-phase/modes/auto.md +57 -0
- package/pp-core/workflows/discuss-phase/modes/batch.md +52 -0
- package/pp-core/workflows/discuss-phase/modes/chain.md +98 -0
- package/pp-core/workflows/discuss-phase/modes/default.md +141 -0
- package/pp-core/workflows/discuss-phase/modes/power.md +44 -0
- package/pp-core/workflows/discuss-phase/modes/text.md +55 -0
- package/pp-core/workflows/discuss-phase/templates/checkpoint.json +18 -0
- package/pp-core/workflows/discuss-phase/templates/context.md +136 -0
- package/pp-core/workflows/discuss-phase/templates/discussion-log.md +50 -0
- package/pp-core/workflows/discuss-phase-assumptions.md +675 -0
- package/pp-core/workflows/discuss-phase-power.md +291 -0
- package/pp-core/workflows/discuss-phase.md +520 -0
- package/pp-core/workflows/do.md +111 -0
- package/pp-core/workflows/docs-update.md +1168 -0
- package/pp-core/workflows/edit-phase.md +295 -0
- package/pp-core/workflows/eval-review.md +159 -0
- package/pp-core/workflows/execute-phase/steps/codebase-drift-gate.md +95 -0
- package/pp-core/workflows/execute-phase/steps/per-plan-worktree-gate.md +94 -0
- package/pp-core/workflows/execute-phase/steps/post-merge-gate.md +117 -0
- package/pp-core/workflows/execute-phase/steps/worktree-recovery-policy.md +9 -0
- package/pp-core/workflows/execute-phase.md +1707 -0
- package/pp-core/workflows/execute-plan.md +541 -0
- package/pp-core/workflows/explore.md +146 -0
- package/pp-core/workflows/extract-learnings.md +243 -0
- package/pp-core/workflows/fast.md +124 -0
- package/pp-core/workflows/forensics.md +279 -0
- package/pp-core/workflows/graduation.md +196 -0
- package/pp-core/workflows/health.md +224 -0
- package/pp-core/workflows/help/modes/brief.md +22 -0
- package/pp-core/workflows/help/modes/default.md +50 -0
- package/pp-core/workflows/help/modes/full.md +791 -0
- package/pp-core/workflows/help/modes/topic.md +74 -0
- package/pp-core/workflows/help.md +24 -0
- package/pp-core/workflows/import.md +256 -0
- package/pp-core/workflows/inbox.md +387 -0
- package/pp-core/workflows/ingest-docs.md +340 -0
- package/pp-core/workflows/insert-phase.md +152 -0
- package/pp-core/workflows/list-phase-assumptions.md +178 -0
- package/pp-core/workflows/list-workspaces.md +57 -0
- package/pp-core/workflows/manager.md +435 -0
- package/pp-core/workflows/map-codebase.md +444 -0
- package/pp-core/workflows/milestone-summary.md +224 -0
- package/pp-core/workflows/mvp-phase.md +222 -0
- package/pp-core/workflows/new-milestone.md +643 -0
- package/pp-core/workflows/new-project.md +1563 -0
- package/pp-core/workflows/new-workspace.md +240 -0
- package/pp-core/workflows/next.md +347 -0
- package/pp-core/workflows/node-repair.md +92 -0
- package/pp-core/workflows/note.md +158 -0
- package/pp-core/workflows/pause-work.md +250 -0
- package/pp-core/workflows/plan-milestone-gaps.md +281 -0
- package/pp-core/workflows/plan-phase.md +1755 -0
- package/pp-core/workflows/plan-review-convergence.md +369 -0
- package/pp-core/workflows/plant-seed.md +230 -0
- package/pp-core/workflows/pr-branch.md +159 -0
- package/pp-core/workflows/profile-user.md +455 -0
- package/pp-core/workflows/progress.md +756 -0
- package/pp-core/workflows/quick.md +1045 -0
- package/pp-core/workflows/reapply-patches.md +443 -0
- package/pp-core/workflows/remove-phase.md +156 -0
- package/pp-core/workflows/remove-workspace.md +108 -0
- package/pp-core/workflows/resume-project.md +348 -0
- package/pp-core/workflows/review.md +765 -0
- package/pp-core/workflows/scan.md +107 -0
- package/pp-core/workflows/secure-phase.md +184 -0
- package/pp-core/workflows/session-report.md +146 -0
- package/pp-core/workflows/settings-advanced.md +816 -0
- package/pp-core/workflows/settings-integrations.md +312 -0
- package/pp-core/workflows/settings.md +592 -0
- package/pp-core/workflows/ship.md +465 -0
- package/pp-core/workflows/sketch-wrap-up.md +286 -0
- package/pp-core/workflows/sketch.md +361 -0
- package/pp-core/workflows/spec-phase.md +495 -0
- package/pp-core/workflows/spike-wrap-up.md +307 -0
- package/pp-core/workflows/spike.md +453 -0
- package/pp-core/workflows/stats.md +80 -0
- package/pp-core/workflows/sync-skills.md +182 -0
- package/pp-core/workflows/thread.md +222 -0
- package/pp-core/workflows/transition.md +694 -0
- package/pp-core/workflows/ui-phase.md +328 -0
- package/pp-core/workflows/ui-review.md +193 -0
- package/pp-core/workflows/ultraplan-phase.md +199 -0
- package/pp-core/workflows/undo.md +314 -0
- package/pp-core/workflows/update.md +501 -0
- package/pp-core/workflows/validate-phase.md +183 -0
- package/pp-core/workflows/verify-phase.md +569 -0
- package/pp-core/workflows/verify-work.md +804 -0
- package/scripts/affected-tests-lib.cjs +554 -0
- package/scripts/audit-workflow-script-paths.cjs +73 -0
- package/scripts/base64-scan.sh +351 -0
- package/scripts/build-hooks.js +254 -0
- package/scripts/changeset/README.md +129 -0
- package/scripts/changeset/cli.cjs +597 -0
- package/scripts/changeset/github-release-notes.cjs +199 -0
- package/scripts/changeset/lint.cjs +147 -0
- package/scripts/changeset/new.cjs +151 -0
- package/scripts/changeset/parse.cjs +114 -0
- package/scripts/changeset/render.cjs +34 -0
- package/scripts/changeset/serialize.cjs +130 -0
- package/scripts/check-alias-drift.cjs +114 -0
- package/scripts/check-env.cjs +312 -0
- package/scripts/check-npm-integrity.cjs +215 -0
- package/scripts/ci-guard-runner.cjs +22 -0
- package/scripts/ci-prepare-test-scope.cjs +93 -0
- package/scripts/ci-rebase-check.cjs +86 -0
- package/scripts/ci-test-scope.cjs +441 -0
- package/scripts/command-contract-helpers.cjs +64 -0
- package/scripts/diff-touches-shipped-paths.cjs +149 -0
- package/scripts/fix-slash-commands.cjs +161 -0
- package/scripts/gen-capability-registry.cjs +2646 -0
- package/scripts/gen-commands-reference.cjs +139 -0
- package/scripts/gen-inventory-manifest.cjs +114 -0
- package/scripts/gen-loop-host-contract.cjs +526 -0
- package/scripts/gen-research-agents.cjs +276 -0
- package/scripts/generate-package-identity.cjs +134 -0
- package/scripts/issue-dedupe.cjs +278 -0
- package/scripts/issue-version-gate.cjs +140 -0
- package/scripts/lib/allowlist-ratchet.cjs +236 -0
- package/scripts/lib/cli-exit.cjs +56 -0
- package/scripts/lint-allow-test-rule-refs.allowlist.json +328 -0
- package/scripts/lint-allow-test-rule-refs.cjs +162 -0
- package/scripts/lint-command-contract.cjs +118 -0
- package/scripts/lint-descriptions.cjs +87 -0
- package/scripts/lint-docs-required.cjs +222 -0
- package/scripts/lint-legacy-dir-name.cjs +166 -0
- package/scripts/lint-package-identity-drift.cjs +141 -0
- package/scripts/lint-pr-check-project-dir.cjs +99 -0
- package/scripts/lint-regression-test-names.allowlist.json +269 -0
- package/scripts/lint-regression-test-names.cjs +117 -0
- package/scripts/lint-shell-command-projection-drift.cjs +62 -0
- package/scripts/lint-skill-deps.cjs +185 -0
- package/scripts/lint-test-file-count.allowlist.json +181 -0
- package/scripts/lint-test-file-count.cjs +246 -0
- package/scripts/lint-windows-test-portability.cjs +178 -0
- package/scripts/mutation-matrix.cjs +323 -0
- package/scripts/pr-target-policy.cjs +63 -0
- package/scripts/pr-template-policy.cjs +268 -0
- package/scripts/prompt-injection-scan.sh +207 -0
- package/scripts/registry-smoke.cjs +337 -0
- package/scripts/release-notes/discord-release-summary.cjs +373 -0
- package/scripts/release-notes/format-github-release-notes.cjs +261 -0
- package/scripts/release-tarball-smoke.cjs +763 -0
- package/scripts/research-profiles.cjs +149 -0
- package/scripts/run-affected-tests.cjs +7 -0
- package/scripts/run-tests.cjs +589 -0
- package/scripts/secret-scan-lint.sh +231 -0
- package/scripts/secret-scan.sh +358 -0
- package/scripts/setup-branch-protection.sh +234 -0
- package/scripts/strip-prose-atrefs.cjs +106 -0
- package/scripts/sync-manifest-versions.cjs +119 -0
- package/scripts/sync-next-version.cjs +133 -0
- package/scripts/sync-rulesets.sh +34 -0
- package/scripts/sync-runtime-launcher.cjs +425 -0
- package/scripts/test-failure-reasons.cjs +34 -0
- package/scripts/update-size-baseline.cjs +68 -0
- package/scripts/verify-npm-publish.cjs +240 -0
- package/scripts/verify-opengsd-sweep.cjs +288 -0
- package/scripts/verify-phase-02-rename.sh +258 -0
- package/scripts/verify-phase-03-rename.sh +376 -0
- package/scripts/workflow-policy.cjs +483 -0
- package/scripts/workflow-size.cjs +90 -0
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Arg redaction policy — issue #177 (ADR-457 build-at-publish: the
|
|
4
|
+
* hand-written bin/lib/observability/redaction.cjs collapsed to a TypeScript
|
|
5
|
+
* source of truth). Behaviour is preserved byte-for-behaviour from the prior
|
|
6
|
+
* hand-written .cjs; only types are added.
|
|
7
|
+
*
|
|
8
|
+
* Privacy default: args are OMITTED from every emitted event (both stderr
|
|
9
|
+
* and file audit). Opt-in: set GSD_AUDIT_ARGS=1 to include args verbatim.
|
|
10
|
+
*
|
|
11
|
+
* This module is deliberately simple and has no side effects — redaction
|
|
12
|
+
* decisions are stateless reads of process.env at call time so that tests
|
|
13
|
+
* can toggle the env var without module-level caching issues.
|
|
14
|
+
*/
|
|
15
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
16
|
+
exports.shouldIncludeArgs = shouldIncludeArgs;
|
|
17
|
+
exports.redactEvent = redactEvent;
|
|
18
|
+
/**
|
|
19
|
+
* Returns true when the caller has opted in to including args in events.
|
|
20
|
+
* Only GSD_AUDIT_ARGS === '1' enables inclusion; any other value (including
|
|
21
|
+
* empty string, 'true', 'yes') keeps the default of omitting args.
|
|
22
|
+
*/
|
|
23
|
+
function shouldIncludeArgs() {
|
|
24
|
+
return process.env.GSD_AUDIT_ARGS === '1';
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Return a redacted copy of a DispatchEvent.
|
|
28
|
+
*
|
|
29
|
+
* If args should be omitted (default), strips the `args` field entirely.
|
|
30
|
+
* If args should be included (GSD_AUDIT_ARGS=1), passes the event through
|
|
31
|
+
* unchanged (args were already set by makeDispatchEvent with includeArgs:true,
|
|
32
|
+
* or absent — in which case they stay absent).
|
|
33
|
+
*
|
|
34
|
+
* The original event object is never mutated (it is frozen by makeDispatchEvent).
|
|
35
|
+
*
|
|
36
|
+
* @param event - A DispatchEvent (frozen or plain).
|
|
37
|
+
* @returns A new plain object with the same fields, minus args when redacted.
|
|
38
|
+
*/
|
|
39
|
+
function redactEvent(event) {
|
|
40
|
+
if (shouldIncludeArgs()) {
|
|
41
|
+
// Include path: return a shallow copy with args preserved if present
|
|
42
|
+
const copy = Object.assign({}, event);
|
|
43
|
+
return copy;
|
|
44
|
+
}
|
|
45
|
+
// Exclude path: build a copy omitting `args`
|
|
46
|
+
const { args: _dropped, ...rest } = event;
|
|
47
|
+
return rest;
|
|
48
|
+
}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
// @generated by scripts/generate-package-identity.cjs from package.json — DO NOT EDIT.
|
|
2
|
+
// Single source for PP package coordinates (issue #498). Regenerate with:
|
|
3
|
+
// node scripts/generate-package-identity.cjs
|
|
4
|
+
'use strict';
|
|
5
|
+
|
|
6
|
+
const packageName = "@pareto4/pp-core";
|
|
7
|
+
const binName = "pp-core";
|
|
8
|
+
const repoSlug = "pareto4/pp-core";
|
|
9
|
+
const repoUrl = "https://gitlab.com/pareto4/pp-core";
|
|
10
|
+
const changelogRawUrl = "https://gitlab.com/pareto4/pp-core/-/raw/main/CHANGELOG.md";
|
|
11
|
+
const cacheSlug = "pareto4-pp-core";
|
|
12
|
+
const updateCacheFileName = "pp-update-check-pareto4-pp-core.json";
|
|
13
|
+
|
|
14
|
+
function formatManualInstall({ packageName, binName, scope, runtime } = {}) {
|
|
15
|
+
const runtimeFlag = runtime ? ` --${runtime}` : '';
|
|
16
|
+
return `npx -y --package=${packageName}@latest -- ${binName}${runtimeFlag} --${scope}`;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
function manualInstallCommand(opts = {}) {
|
|
20
|
+
return formatManualInstall({ packageName, binName, scope: opts.scope, runtime: opts.runtime });
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
module.exports = Object.freeze({
|
|
24
|
+
packageName,
|
|
25
|
+
// PACKAGE_NAME: back-compat alias for #516-era consumers. Baked here, so it
|
|
26
|
+
// survives the installed tree's synthetic package.json (fixes the #378 undefined).
|
|
27
|
+
PACKAGE_NAME: packageName,
|
|
28
|
+
binName,
|
|
29
|
+
repoSlug,
|
|
30
|
+
repoUrl,
|
|
31
|
+
changelogRawUrl,
|
|
32
|
+
cacheSlug,
|
|
33
|
+
updateCacheFileName,
|
|
34
|
+
manualInstallCommand,
|
|
35
|
+
});
|
|
@@ -0,0 +1,368 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Package Legitimacy Module
|
|
4
|
+
*
|
|
5
|
+
* Replaces the bolt-on prose slopcheck gate (which pip-installed `slopcheck`
|
|
6
|
+
* and degraded ALL packages to [ASSUMED] when pip failed) with registry-API
|
|
7
|
+
* verdicts computed in code.
|
|
8
|
+
*
|
|
9
|
+
* Public interface:
|
|
10
|
+
* DEFAULT_THRESHOLDS — baseline thresholds
|
|
11
|
+
* classifyPackage — pure function: signals → { verdict, reasons }
|
|
12
|
+
* checkPackages — async: resolves registry signals and classifies
|
|
13
|
+
* _setHttpGet — test seam: override the HTTP transport (pass null to restore)
|
|
14
|
+
*
|
|
15
|
+
* All network IO is injected via a `registry` client option so that tests
|
|
16
|
+
* never touch the real network (same seam pattern as clock injection).
|
|
17
|
+
*
|
|
18
|
+
* ADR-457 build-at-publish: authored as TypeScript .cts → emits .cjs via tsc.
|
|
19
|
+
*/
|
|
20
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
21
|
+
if (k2 === undefined) k2 = k;
|
|
22
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
23
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
24
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
25
|
+
}
|
|
26
|
+
Object.defineProperty(o, k2, desc);
|
|
27
|
+
}) : (function(o, m, k, k2) {
|
|
28
|
+
if (k2 === undefined) k2 = k;
|
|
29
|
+
o[k2] = m[k];
|
|
30
|
+
}));
|
|
31
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
32
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
33
|
+
}) : function(o, v) {
|
|
34
|
+
o["default"] = v;
|
|
35
|
+
});
|
|
36
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
37
|
+
var ownKeys = function(o) {
|
|
38
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
39
|
+
var ar = [];
|
|
40
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
41
|
+
return ar;
|
|
42
|
+
};
|
|
43
|
+
return ownKeys(o);
|
|
44
|
+
};
|
|
45
|
+
return function (mod) {
|
|
46
|
+
if (mod && mod.__esModule) return mod;
|
|
47
|
+
var result = {};
|
|
48
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
49
|
+
__setModuleDefault(result, mod);
|
|
50
|
+
return result;
|
|
51
|
+
};
|
|
52
|
+
})();
|
|
53
|
+
const https = __importStar(require("node:https"));
|
|
54
|
+
// ---------------------------------------------------------------------------
|
|
55
|
+
// Constants
|
|
56
|
+
// ---------------------------------------------------------------------------
|
|
57
|
+
const DEFAULT_THRESHOLDS = {
|
|
58
|
+
minAgeDays: 30,
|
|
59
|
+
minWeeklyDownloads: 1000,
|
|
60
|
+
requireRepo: true,
|
|
61
|
+
};
|
|
62
|
+
// Matches common dangerous postinstall execution patterns.
|
|
63
|
+
// Deliberately EXCLUDES bare https?:// (over-fires on legit packages like
|
|
64
|
+
// esbuild/sharp/node-gyp that reference download URLs without executing them).
|
|
65
|
+
// Shell-execution / download-and-exec signatures only:
|
|
66
|
+
const SUSPICIOUS_POSTINSTALL_RE = /(curl |wget |\|\s*(ba)?sh|bash -c|sh -c|node -e|eval|base64 -d|\/etc\/|\.\.\/|~\/|nc |>\s*\/)/i;
|
|
67
|
+
// ---------------------------------------------------------------------------
|
|
68
|
+
// Severity ordering for verdict merging (SLOP > SUS > OK)
|
|
69
|
+
// ---------------------------------------------------------------------------
|
|
70
|
+
const SEVERITY = { OK: 0, SUS: 1, SLOP: 2 };
|
|
71
|
+
function moreSevereVerdict(a, b) {
|
|
72
|
+
return SEVERITY[a] >= SEVERITY[b] ? a : b;
|
|
73
|
+
}
|
|
74
|
+
// ---------------------------------------------------------------------------
|
|
75
|
+
// classifyPackage — pure, no IO
|
|
76
|
+
// ---------------------------------------------------------------------------
|
|
77
|
+
function classifyPackage(signals, { thresholds = DEFAULT_THRESHOLDS, clock = Date } = {}) {
|
|
78
|
+
const reasons = [];
|
|
79
|
+
// Terminal: package does not exist
|
|
80
|
+
if (signals.exists === false) {
|
|
81
|
+
return { verdict: 'SLOP', reasons: ['does-not-exist'] };
|
|
82
|
+
}
|
|
83
|
+
// Age check
|
|
84
|
+
if (signals.publishedAt == null) {
|
|
85
|
+
reasons.push('unknown-age');
|
|
86
|
+
}
|
|
87
|
+
else {
|
|
88
|
+
const parsed = Date.parse(String(signals.publishedAt));
|
|
89
|
+
if (!Number.isFinite(parsed)) {
|
|
90
|
+
// Unparseable date — treat as unknown
|
|
91
|
+
reasons.push('unknown-age');
|
|
92
|
+
}
|
|
93
|
+
else {
|
|
94
|
+
const ageDays = Math.floor((clock.now() - parsed) / 86_400_000);
|
|
95
|
+
if (ageDays < thresholds.minAgeDays) {
|
|
96
|
+
reasons.push('too-new');
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
// Downloads check
|
|
101
|
+
const downloads = signals.weeklyDownloads;
|
|
102
|
+
if (downloads == null) {
|
|
103
|
+
reasons.push('unknown-downloads');
|
|
104
|
+
}
|
|
105
|
+
else if (typeof downloads !== 'number' || !Number.isFinite(downloads)) {
|
|
106
|
+
// Odd type / NaN — treat as unknown
|
|
107
|
+
reasons.push('unknown-downloads');
|
|
108
|
+
}
|
|
109
|
+
else if (downloads < thresholds.minWeeklyDownloads) {
|
|
110
|
+
reasons.push('low-downloads');
|
|
111
|
+
}
|
|
112
|
+
// Repository check
|
|
113
|
+
if (thresholds.requireRepo && !signals.repoUrl) {
|
|
114
|
+
reasons.push('no-repository');
|
|
115
|
+
}
|
|
116
|
+
// Deprecated check
|
|
117
|
+
if (signals.deprecated === true) {
|
|
118
|
+
reasons.push('deprecated');
|
|
119
|
+
}
|
|
120
|
+
// Suspicious postinstall (npm only — but apply whenever postinstall is present)
|
|
121
|
+
if (signals.postinstall != null && typeof signals.postinstall === 'string') {
|
|
122
|
+
if (SUSPICIOUS_POSTINSTALL_RE.test(signals.postinstall)) {
|
|
123
|
+
reasons.push('suspicious-postinstall');
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
// Terminal: suspicious postinstall is a slopsquatting execution risk
|
|
127
|
+
if (reasons.includes('suspicious-postinstall')) {
|
|
128
|
+
return { verdict: 'SLOP', reasons };
|
|
129
|
+
}
|
|
130
|
+
const verdict = reasons.length > 0 ? 'SUS' : 'OK';
|
|
131
|
+
return { verdict, reasons };
|
|
132
|
+
}
|
|
133
|
+
// ---------------------------------------------------------------------------
|
|
134
|
+
// Injectable HTTP transport (test seam — W1)
|
|
135
|
+
// ---------------------------------------------------------------------------
|
|
136
|
+
/** The real HTTPS transport — resolves { statusCode, body } */
|
|
137
|
+
function realHttpsGet(url, timeoutMs) {
|
|
138
|
+
return new Promise((resolve, reject) => {
|
|
139
|
+
const req = https.get(url, { headers: { 'User-Agent': 'gsd-core-package-legitimacy/1.0' } }, (res) => {
|
|
140
|
+
const chunks = [];
|
|
141
|
+
res.on('data', (c) => chunks.push(c));
|
|
142
|
+
res.on('end', () => resolve({
|
|
143
|
+
statusCode: res.statusCode ?? 0,
|
|
144
|
+
body: Buffer.concat(chunks).toString('utf8'),
|
|
145
|
+
}));
|
|
146
|
+
res.on('error', reject);
|
|
147
|
+
});
|
|
148
|
+
req.setTimeout(timeoutMs, () => {
|
|
149
|
+
req.destroy(new Error(`timeout after ${timeoutMs}ms`));
|
|
150
|
+
});
|
|
151
|
+
req.on('error', reject);
|
|
152
|
+
});
|
|
153
|
+
}
|
|
154
|
+
/** Module-level transport pointer — overrideable via _setHttpGet for tests */
|
|
155
|
+
let httpsGet = realHttpsGet;
|
|
156
|
+
/**
|
|
157
|
+
* Test seam: replace the HTTP transport. Pass null to restore the real transport.
|
|
158
|
+
* Tests call this before exercising a real-adapter code path; always restore in finally.
|
|
159
|
+
*/
|
|
160
|
+
function _setHttpGet(fn) {
|
|
161
|
+
httpsGet = fn ?? realHttpsGet;
|
|
162
|
+
}
|
|
163
|
+
// ---------------------------------------------------------------------------
|
|
164
|
+
// Real registry adapters (not exercised by tests — tests inject fakes)
|
|
165
|
+
// ---------------------------------------------------------------------------
|
|
166
|
+
function degradedSignals() {
|
|
167
|
+
return {
|
|
168
|
+
exists: null,
|
|
169
|
+
publishedAt: null,
|
|
170
|
+
weeklyDownloads: null,
|
|
171
|
+
repoUrl: null,
|
|
172
|
+
deprecated: false,
|
|
173
|
+
postinstall: null,
|
|
174
|
+
};
|
|
175
|
+
}
|
|
176
|
+
async function lookupNpm(name, version) {
|
|
177
|
+
try {
|
|
178
|
+
const resp = await httpsGet(`https://registry.npmjs.org/${encodeURIComponent(name)}`, 5000);
|
|
179
|
+
if (resp.statusCode === 404)
|
|
180
|
+
return { ...degradedSignals(), exists: false };
|
|
181
|
+
if (resp.statusCode < 200 || resp.statusCode >= 300)
|
|
182
|
+
return degradedSignals();
|
|
183
|
+
const data = JSON.parse(resp.body);
|
|
184
|
+
if (data.error)
|
|
185
|
+
return { ...degradedSignals(), exists: false };
|
|
186
|
+
const time = data.time ?? {};
|
|
187
|
+
const allVersions = data.versions ?? {};
|
|
188
|
+
// I3: when a specific version is requested, verify it exists
|
|
189
|
+
if (version !== undefined) {
|
|
190
|
+
if (!(version in allVersions)) {
|
|
191
|
+
return { ...degradedSignals(), exists: false };
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
const latestVersion = data['dist-tags']?.latest ?? '';
|
|
195
|
+
const resolvedVersion = version !== undefined ? version : latestVersion;
|
|
196
|
+
const versionMeta = allVersions[resolvedVersion] ?? {};
|
|
197
|
+
const scripts = versionMeta.scripts ??
|
|
198
|
+
{};
|
|
199
|
+
const postinstall = scripts.postinstall ?? null;
|
|
200
|
+
const repoField = versionMeta.repository;
|
|
201
|
+
let repoUrl = null;
|
|
202
|
+
if (typeof repoField === 'string')
|
|
203
|
+
repoUrl = repoField;
|
|
204
|
+
else if (repoField && typeof repoField.url === 'string') {
|
|
205
|
+
repoUrl = repoField.url;
|
|
206
|
+
}
|
|
207
|
+
const deprecated = typeof versionMeta.deprecated === 'string' ? true : false;
|
|
208
|
+
// Fetch weekly download count from the npm downloads API
|
|
209
|
+
let weeklyDownloads = null;
|
|
210
|
+
try {
|
|
211
|
+
const dlResp = await httpsGet(`https://api.npmjs.org/downloads/point/last-week/${encodeURIComponent(name)}`, 5000);
|
|
212
|
+
if (dlResp.statusCode >= 200 && dlResp.statusCode < 300) {
|
|
213
|
+
const dlData = JSON.parse(dlResp.body);
|
|
214
|
+
if (typeof dlData.downloads === 'number') {
|
|
215
|
+
weeklyDownloads = dlData.downloads;
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
catch {
|
|
220
|
+
// Degraded: leave weeklyDownloads as null, never throw
|
|
221
|
+
}
|
|
222
|
+
return {
|
|
223
|
+
exists: true,
|
|
224
|
+
publishedAt: time[resolvedVersion] ?? time.created ?? null,
|
|
225
|
+
weeklyDownloads,
|
|
226
|
+
repoUrl,
|
|
227
|
+
deprecated,
|
|
228
|
+
postinstall,
|
|
229
|
+
ecosystem: 'npm',
|
|
230
|
+
};
|
|
231
|
+
}
|
|
232
|
+
catch {
|
|
233
|
+
return degradedSignals();
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
async function lookupPypi(name, version) {
|
|
237
|
+
try {
|
|
238
|
+
const resp = await httpsGet(`https://pypi.org/pypi/${encodeURIComponent(name)}/json`, 5000);
|
|
239
|
+
if (resp.statusCode === 404)
|
|
240
|
+
return { ...degradedSignals(), exists: false };
|
|
241
|
+
if (resp.statusCode < 200 || resp.statusCode >= 300)
|
|
242
|
+
return degradedSignals();
|
|
243
|
+
const data = JSON.parse(resp.body);
|
|
244
|
+
const info = data.info ?? {};
|
|
245
|
+
// I3: when a specific version is requested, verify it exists in releases
|
|
246
|
+
const releases = data.releases ?? {};
|
|
247
|
+
if (version !== undefined) {
|
|
248
|
+
if (!(version in releases)) {
|
|
249
|
+
return { ...degradedSignals(), exists: false };
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
// Finding 2: when version is provided, derive publishedAt from the
|
|
253
|
+
// version-specific release record rather than the package-level urls[] array
|
|
254
|
+
// (which reflects the latest release, not the requested version).
|
|
255
|
+
let uploadTime = null;
|
|
256
|
+
if (version !== undefined) {
|
|
257
|
+
const versionFiles = releases[version] ?? [];
|
|
258
|
+
uploadTime =
|
|
259
|
+
versionFiles.length > 0
|
|
260
|
+
? versionFiles[0].upload_time_iso_8601 ?? null
|
|
261
|
+
: null;
|
|
262
|
+
}
|
|
263
|
+
else {
|
|
264
|
+
const urls = data.urls ?? [];
|
|
265
|
+
uploadTime =
|
|
266
|
+
urls.length > 0 ? urls[0].upload_time_iso_8601 ?? null : null;
|
|
267
|
+
}
|
|
268
|
+
const projectUrls = info.project_urls;
|
|
269
|
+
const repoUrl = projectUrls?.['Source'] ??
|
|
270
|
+
projectUrls?.['Homepage'] ??
|
|
271
|
+
info.home_page ??
|
|
272
|
+
null;
|
|
273
|
+
return {
|
|
274
|
+
exists: true,
|
|
275
|
+
publishedAt: uploadTime,
|
|
276
|
+
weeklyDownloads: null, // PyPI weekly downloads require a separate API
|
|
277
|
+
repoUrl: repoUrl || null,
|
|
278
|
+
deprecated: false, // PyPI doesn't have a first-class deprecated field
|
|
279
|
+
postinstall: null, // Not applicable for PyPI
|
|
280
|
+
ecosystem: 'pypi',
|
|
281
|
+
};
|
|
282
|
+
}
|
|
283
|
+
catch {
|
|
284
|
+
return degradedSignals();
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
async function lookupCrates(name, version) {
|
|
288
|
+
try {
|
|
289
|
+
const resp = await httpsGet(`https://crates.io/api/v1/crates/${encodeURIComponent(name)}`, 5000);
|
|
290
|
+
if (resp.statusCode === 404)
|
|
291
|
+
return { ...degradedSignals(), exists: false };
|
|
292
|
+
if (resp.statusCode < 200 || resp.statusCode >= 300)
|
|
293
|
+
return degradedSignals();
|
|
294
|
+
const data = JSON.parse(resp.body);
|
|
295
|
+
const krate = data.crate ?? {};
|
|
296
|
+
// I3: when a specific version is requested, verify it exists in versions list
|
|
297
|
+
const versions = data.versions ?? [];
|
|
298
|
+
if (version !== undefined) {
|
|
299
|
+
const found = versions.some((v) => v.num === version);
|
|
300
|
+
if (!found) {
|
|
301
|
+
return { ...degradedSignals(), exists: false };
|
|
302
|
+
}
|
|
303
|
+
}
|
|
304
|
+
const repoUrl = krate.repository ?? null;
|
|
305
|
+
// Finding 2: when version is provided, use the version-specific created_at
|
|
306
|
+
// rather than the package-level crate.created_at (first-ever publish date).
|
|
307
|
+
let created;
|
|
308
|
+
if (version !== undefined) {
|
|
309
|
+
const versionObj = versions.find((v) => v.num === version);
|
|
310
|
+
created = versionObj?.created_at ?? null;
|
|
311
|
+
}
|
|
312
|
+
else {
|
|
313
|
+
created = krate.created_at ?? null;
|
|
314
|
+
}
|
|
315
|
+
// recent_downloads is a 90-day count; normalize to a weekly figure for comparison
|
|
316
|
+
// against minWeeklyDownloads (which is a weekly threshold).
|
|
317
|
+
const rawDownloads = krate.recent_downloads;
|
|
318
|
+
const downloads = (rawDownloads != null && typeof Number(rawDownloads) === 'number' && !isNaN(Number(rawDownloads)))
|
|
319
|
+
? Math.round(Number(rawDownloads) * 7 / 90)
|
|
320
|
+
: null;
|
|
321
|
+
return {
|
|
322
|
+
exists: true,
|
|
323
|
+
publishedAt: created,
|
|
324
|
+
weeklyDownloads: downloads,
|
|
325
|
+
repoUrl,
|
|
326
|
+
deprecated: false,
|
|
327
|
+
postinstall: null,
|
|
328
|
+
ecosystem: 'crates',
|
|
329
|
+
};
|
|
330
|
+
}
|
|
331
|
+
catch {
|
|
332
|
+
return degradedSignals();
|
|
333
|
+
}
|
|
334
|
+
}
|
|
335
|
+
const realRegistry = {
|
|
336
|
+
async lookup(ecosystem, name, version) {
|
|
337
|
+
switch (ecosystem) {
|
|
338
|
+
case 'npm':
|
|
339
|
+
return lookupNpm(name, version);
|
|
340
|
+
case 'pypi':
|
|
341
|
+
return lookupPypi(name, version);
|
|
342
|
+
case 'crates':
|
|
343
|
+
return lookupCrates(name, version);
|
|
344
|
+
default:
|
|
345
|
+
return degradedSignals();
|
|
346
|
+
}
|
|
347
|
+
},
|
|
348
|
+
};
|
|
349
|
+
// ---------------------------------------------------------------------------
|
|
350
|
+
// checkPackages — orchestrates lookup + classify + slopcheck merge
|
|
351
|
+
// ---------------------------------------------------------------------------
|
|
352
|
+
async function checkPackages({ ecosystem, packages, version }, { registry = realRegistry, clock = Date, thresholds = DEFAULT_THRESHOLDS, slopcheck = null, } = {}) {
|
|
353
|
+
const results = [];
|
|
354
|
+
for (const name of packages) {
|
|
355
|
+
const signals = await registry.lookup(ecosystem, name, version);
|
|
356
|
+
const { verdict: registryVerdict, reasons } = classifyPackage(signals, { thresholds, clock });
|
|
357
|
+
let finalVerdict = registryVerdict;
|
|
358
|
+
if (slopcheck != null) {
|
|
359
|
+
const slopVerdict = await slopcheck.check(ecosystem, name);
|
|
360
|
+
if (slopVerdict != null) {
|
|
361
|
+
finalVerdict = moreSevereVerdict(finalVerdict, slopVerdict);
|
|
362
|
+
}
|
|
363
|
+
}
|
|
364
|
+
results.push({ name, verdict: finalVerdict, signals, reasons });
|
|
365
|
+
}
|
|
366
|
+
return results;
|
|
367
|
+
}
|
|
368
|
+
module.exports = { DEFAULT_THRESHOLDS, classifyPackage, checkPackages, _setHttpGet };
|
|
@@ -0,0 +1,209 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Manifest-backed phase subcommand router.
|
|
4
|
+
* Keeps gsd-tools.cjs thin while preserving existing command semantics.
|
|
5
|
+
*
|
|
6
|
+
* Unsupported in this router:
|
|
7
|
+
* - scaffold: routed through top-level scaffold command.
|
|
8
|
+
*
|
|
9
|
+
* CJS-only subcommands: mvp-mode (dispatched directly, before hub).
|
|
10
|
+
*
|
|
11
|
+
* #3788: dispatch is mediated by CommandRoutingHub. The public entry point
|
|
12
|
+
* and observable CLI behaviour are unchanged.
|
|
13
|
+
*
|
|
14
|
+
* ADR-457 build-at-publish: the hand-written bin/lib/phase-command-router.cjs
|
|
15
|
+
* collapsed to a TypeScript source of truth. Behaviour is preserved byte-for-behaviour
|
|
16
|
+
* from the prior hand-written .cjs; only types are added.
|
|
17
|
+
*/
|
|
18
|
+
const command_aliases_cjs_1 = require("./command-aliases.cjs");
|
|
19
|
+
// ─── CommandRoutingHub (issue #3788, simplified in #175, typed in #176) ───────
|
|
20
|
+
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
21
|
+
const commandRoutingHub = require("./command-routing-hub.cjs");
|
|
22
|
+
const { createHub, ERROR_KINDS, makeInvalidArgs } = commandRoutingHub;
|
|
23
|
+
// ─── Implementation ───────────────────────────────────────────────────────────
|
|
24
|
+
function routePhaseCommand({ phase, args, cwd, raw, error }) {
|
|
25
|
+
// ── Unsupported subcommands ─────────────────────────────────────────────────
|
|
26
|
+
// Resolved before dispatch so the error message stays deterministic.
|
|
27
|
+
const UNSUPPORTED = {
|
|
28
|
+
scaffold: 'phase scaffold is routed through the top-level scaffold command.',
|
|
29
|
+
};
|
|
30
|
+
const subcommand = args[1];
|
|
31
|
+
if (subcommand && UNSUPPORTED[subcommand]) {
|
|
32
|
+
error(UNSUPPORTED[subcommand]);
|
|
33
|
+
return;
|
|
34
|
+
}
|
|
35
|
+
// ── No subcommand → reject early with helpful error ────────────────────────
|
|
36
|
+
// Pre-#3788 code resolved unknown subcommands via routeCjsCommandFamily which
|
|
37
|
+
// fell through to error() when no handler matched (including undefined).
|
|
38
|
+
// Post-#3788 the hub's manifest check is skipped for falsy subcommand, so we
|
|
39
|
+
// must guard here to preserve the deterministic "Available: ..." error message.
|
|
40
|
+
if (!subcommand) {
|
|
41
|
+
const available = command_aliases_cjs_1.PHASE_SUBCOMMANDS.filter(s => !UNSUPPORTED[s]).join(', ');
|
|
42
|
+
error(`Unknown phase subcommand. Available: ${available}`);
|
|
43
|
+
return;
|
|
44
|
+
}
|
|
45
|
+
// ── CJS-only subcommands (dispatched directly, before hub) ─────────────────
|
|
46
|
+
// `mvp-mode` has a CJS-native implementation in phase.cmdPhaseMvpMode that
|
|
47
|
+
// differs from the SDK query layer (different ROADMAP scan + error codes).
|
|
48
|
+
// Dispatch it early to preserve pre-migration observable behaviour (correct
|
|
49
|
+
// exit code, correct JSON error reason code, correct ROADMAP scan).
|
|
50
|
+
if (subcommand === 'mvp-mode') {
|
|
51
|
+
phase.cmdPhaseMvpMode(cwd, args.slice(2), raw);
|
|
52
|
+
return;
|
|
53
|
+
}
|
|
54
|
+
// ── Build the CJS registry ──────────────────────────────────────────────────
|
|
55
|
+
// Each handler receives a ctx object from the hub and must return a HubResult.
|
|
56
|
+
const cjsRegistry = {
|
|
57
|
+
phase: {
|
|
58
|
+
'next-decimal': (_ctx) => {
|
|
59
|
+
phase.cmdPhaseNextDecimal(cwd, args[2], raw);
|
|
60
|
+
return { ok: true, data: null };
|
|
61
|
+
},
|
|
62
|
+
add: (_ctx) => {
|
|
63
|
+
let customId = null;
|
|
64
|
+
const descArgs = [];
|
|
65
|
+
for (let i = 2; i < args.length; i++) {
|
|
66
|
+
const token = args[i];
|
|
67
|
+
if (token === '--raw') {
|
|
68
|
+
continue;
|
|
69
|
+
}
|
|
70
|
+
if (token === '--id') {
|
|
71
|
+
const id = args[i + 1];
|
|
72
|
+
if (!id || id.startsWith('--')) {
|
|
73
|
+
return makeInvalidArgs('--id', '--id requires a value');
|
|
74
|
+
}
|
|
75
|
+
customId = id;
|
|
76
|
+
i++;
|
|
77
|
+
}
|
|
78
|
+
else if (token.startsWith('--')) {
|
|
79
|
+
return makeInvalidArgs(token, `phase add does not support ${token}`);
|
|
80
|
+
}
|
|
81
|
+
else {
|
|
82
|
+
descArgs.push(token);
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
phase.cmdPhaseAdd(cwd, descArgs.join(' '), raw, customId);
|
|
86
|
+
return { ok: true, data: null };
|
|
87
|
+
},
|
|
88
|
+
'add-batch': (_ctx) => {
|
|
89
|
+
const descFlagIdx = args.indexOf('--descriptions');
|
|
90
|
+
let descriptions;
|
|
91
|
+
if (descFlagIdx !== -1) {
|
|
92
|
+
const rawDescriptions = args[descFlagIdx + 1];
|
|
93
|
+
if (!rawDescriptions || rawDescriptions.startsWith('--')) {
|
|
94
|
+
return makeInvalidArgs('--descriptions', '--descriptions must be a JSON array');
|
|
95
|
+
}
|
|
96
|
+
try {
|
|
97
|
+
descriptions = JSON.parse(rawDescriptions);
|
|
98
|
+
}
|
|
99
|
+
catch {
|
|
100
|
+
return makeInvalidArgs('--descriptions', '--descriptions must be a JSON array');
|
|
101
|
+
}
|
|
102
|
+
if (!Array.isArray(descriptions)) {
|
|
103
|
+
return makeInvalidArgs('--descriptions', '--descriptions must be a JSON array');
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
else {
|
|
107
|
+
descriptions = args.slice(2).filter(a => a !== '--raw');
|
|
108
|
+
}
|
|
109
|
+
phase.cmdPhaseAddBatch(cwd, descriptions, raw);
|
|
110
|
+
return { ok: true, data: null };
|
|
111
|
+
},
|
|
112
|
+
insert: (_ctx) => {
|
|
113
|
+
if (args.includes('--dry-run')) {
|
|
114
|
+
return makeInvalidArgs('--dry-run', 'phase insert does not support --dry-run');
|
|
115
|
+
}
|
|
116
|
+
phase.cmdPhaseInsert(cwd, args[2], args.slice(3).join(' '), raw);
|
|
117
|
+
return { ok: true, data: null };
|
|
118
|
+
},
|
|
119
|
+
remove: (_ctx) => {
|
|
120
|
+
const removeArgs = args.slice(2).filter(token => token !== '--raw');
|
|
121
|
+
let forceFlag = false;
|
|
122
|
+
const positional = [];
|
|
123
|
+
for (const token of removeArgs) {
|
|
124
|
+
if (token === '--force') {
|
|
125
|
+
forceFlag = true;
|
|
126
|
+
continue;
|
|
127
|
+
}
|
|
128
|
+
if (token.startsWith('--')) {
|
|
129
|
+
return makeInvalidArgs(token, `phase remove does not support ${token}`);
|
|
130
|
+
}
|
|
131
|
+
positional.push(token);
|
|
132
|
+
}
|
|
133
|
+
if (positional.length !== 1) {
|
|
134
|
+
return makeInvalidArgs('<phase-number>', 'phase remove accepts exactly one phase number');
|
|
135
|
+
}
|
|
136
|
+
phase.cmdPhaseRemove(cwd, positional[0], { force: forceFlag }, raw);
|
|
137
|
+
return { ok: true, data: null };
|
|
138
|
+
},
|
|
139
|
+
complete: (_ctx) => {
|
|
140
|
+
phase.cmdPhaseComplete(cwd, args[2], raw);
|
|
141
|
+
return { ok: true, data: null };
|
|
142
|
+
},
|
|
143
|
+
'uat-passed': (_ctx) => {
|
|
144
|
+
let requireVerification = false;
|
|
145
|
+
const positional = [];
|
|
146
|
+
for (const token of args.slice(2)) {
|
|
147
|
+
if (token === '--require-verification') {
|
|
148
|
+
requireVerification = true;
|
|
149
|
+
}
|
|
150
|
+
else if (token === '--raw') {
|
|
151
|
+
// --raw is handled by the outer CLI layer; accepted here silently
|
|
152
|
+
}
|
|
153
|
+
else if (token.startsWith('--')) {
|
|
154
|
+
return makeInvalidArgs(token, `phase uat-passed does not support ${token}`);
|
|
155
|
+
}
|
|
156
|
+
else {
|
|
157
|
+
positional.push(token);
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
phase.cmdPhaseUatPassed(cwd, positional[0], raw, { policy: { requireVerification } });
|
|
161
|
+
return { ok: true, data: null };
|
|
162
|
+
},
|
|
163
|
+
},
|
|
164
|
+
};
|
|
165
|
+
// ── Build manifest (available subcommands for UnknownCommand detection) ─────
|
|
166
|
+
// `availableSubcommands` is what the error message shows. It excludes
|
|
167
|
+
// unsupported commands (already handled above) but does NOT include 'mvp-mode'
|
|
168
|
+
// because it was absent from PHASE_SUBCOMMANDS in the original and was not
|
|
169
|
+
// shown in the "Available:" list there either.
|
|
170
|
+
//
|
|
171
|
+
// `manifestSubcommands` is the full routing set for the hub — it includes
|
|
172
|
+
// 'mvp-mode' (which the original code routed via a handler even without a
|
|
173
|
+
// manifest entry) so the hub's UnknownCommand check passes for it.
|
|
174
|
+
const availableSubcommands = command_aliases_cjs_1.PHASE_SUBCOMMANDS.filter(s => !UNSUPPORTED[s]);
|
|
175
|
+
const manifestSubcommands = ['mvp-mode', ...availableSubcommands];
|
|
176
|
+
const manifest = { phase: manifestSubcommands };
|
|
177
|
+
// ── Construct hub ──────────────────────────────────────────────────────────
|
|
178
|
+
// #175: Hub is CJS-only — no mode param, no sdkLoader.
|
|
179
|
+
const hub = createHub({ cjsRegistry, manifest });
|
|
180
|
+
// ── Dispatch ────────────────────────────────────────────────────────────────
|
|
181
|
+
const result = hub.dispatch({
|
|
182
|
+
family: 'phase',
|
|
183
|
+
subcommand,
|
|
184
|
+
args: args.slice(2),
|
|
185
|
+
cwd,
|
|
186
|
+
raw,
|
|
187
|
+
});
|
|
188
|
+
// ── Translate result → CLI output / error (adapter responsibility) ──────────
|
|
189
|
+
// CJS handlers call output() themselves (inside phase.cmdPhase*()).
|
|
190
|
+
// No further output call is needed here.
|
|
191
|
+
if (!result.ok) {
|
|
192
|
+
if (result.kind === ERROR_KINDS.UnknownCommand) {
|
|
193
|
+
const available = availableSubcommands.join(', ');
|
|
194
|
+
error(`Unknown phase subcommand. Available: ${available}`);
|
|
195
|
+
return;
|
|
196
|
+
}
|
|
197
|
+
if (result.kind === ERROR_KINDS.InvalidArgs || result.kind === ERROR_KINDS.HandlerRefusal) {
|
|
198
|
+
// #176: typed payload — reason holds the human-readable message
|
|
199
|
+
error(result.reason);
|
|
200
|
+
return;
|
|
201
|
+
}
|
|
202
|
+
// HandlerFailure: message field
|
|
203
|
+
error(result.message);
|
|
204
|
+
return;
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
module.exports = {
|
|
208
|
+
routePhaseCommand,
|
|
209
|
+
};
|