@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,479 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Loop Resolver — ADR-857 phase 3c registry-consuming query
|
|
4
|
+
*
|
|
5
|
+
* Given a loop point (one of the 12 canonical points from loop-host-contract.cjs),
|
|
6
|
+
* filters the materialized Capability Registry by config activation and returns
|
|
7
|
+
* the active hooks as a JSON envelope with a rendered-markdown field.
|
|
8
|
+
*
|
|
9
|
+
* Consumed live by the landed phase-6 loop-hook cutovers: plan-phase.md / autonomous.md
|
|
10
|
+
* at plan:pre (ui-phase) and autonomous.md at verify:post (ui-review). Further per-feature
|
|
11
|
+
* cutovers are ongoing.
|
|
12
|
+
*
|
|
13
|
+
* Command surface: gsd-tools loop render-hooks <point>
|
|
14
|
+
*
|
|
15
|
+
* Exports (three things):
|
|
16
|
+
* resolveLoopHooks({ point, registry, config }) → { point, activeHooks }
|
|
17
|
+
* renderLoopHooks(resolved) → markdown string
|
|
18
|
+
* cmdLoopRenderHooks(cwd, point, raw, options) — I/O entry point
|
|
19
|
+
*
|
|
20
|
+
* Both pure functions (resolveLoopHooks, renderLoopHooks) take explicit
|
|
21
|
+
* registry/config arguments so they are trivially testable without I/O.
|
|
22
|
+
*
|
|
23
|
+
* Dependencies (leaf modules only — no circular risk):
|
|
24
|
+
* - ./config-loader.cjs (loadConfig)
|
|
25
|
+
* - ./io.cjs (output, error)
|
|
26
|
+
* - ./capability-activation.cjs (resolveConfigKey, _resolveActivationValue, _getNestedConfigValue, _readRawConfigKey)
|
|
27
|
+
* - loop-host-contract.cjs (CANONICAL_POINTS via LOOP_HOST_CONTRACT)
|
|
28
|
+
* - capability-registry.cjs (byLoopPoint, consumed at call time)
|
|
29
|
+
* - capability-state.cjs (resolveCapabilityRuntimeState — for capabilities list)
|
|
30
|
+
*/
|
|
31
|
+
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
32
|
+
const ioMod = require("./io.cjs");
|
|
33
|
+
const { output: coreOutput, error: coreError } = ioMod;
|
|
34
|
+
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
35
|
+
const configLoaderModule = require("./config-loader.cjs");
|
|
36
|
+
const { loadConfig } = configLoaderModule;
|
|
37
|
+
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
38
|
+
const capabilityStateModule = require("./capability-state.cjs");
|
|
39
|
+
const { resolveCapabilityRuntimeState } = capabilityStateModule;
|
|
40
|
+
// ─── Capability-activation engine (single owner for config-key precedence) ────
|
|
41
|
+
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
42
|
+
const capabilityActivationModule = require("./capability-activation.cjs");
|
|
43
|
+
const { _getNestedConfigValue, _readRawConfigKey, _resolveActivationValue, resolveConfigKey } = capabilityActivationModule;
|
|
44
|
+
// ─── Canonical points (derived from LOOP_HOST_CONTRACT — authoritative 12) ───
|
|
45
|
+
// FIX 2: Derive the authoritative canonical set from LOOP_HOST_CONTRACT so it
|
|
46
|
+
// cannot drift from the host contract. CANONICAL_POINTS_FALLBACK is kept as an
|
|
47
|
+
// alias for backward compatibility in tests and exports.
|
|
48
|
+
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
49
|
+
const _loopHostContract = require('./loop-host-contract.cjs');
|
|
50
|
+
const CANONICAL_POINTS = (() => {
|
|
51
|
+
try {
|
|
52
|
+
const contract = _loopHostContract.LOOP_HOST_CONTRACT;
|
|
53
|
+
if (Array.isArray(contract)) {
|
|
54
|
+
const pts = [];
|
|
55
|
+
for (const step of contract) {
|
|
56
|
+
if (step && Array.isArray(step.points)) {
|
|
57
|
+
for (const p of step.points) {
|
|
58
|
+
if (typeof p === 'string')
|
|
59
|
+
pts.push(p);
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
if (pts.length > 0)
|
|
64
|
+
return pts;
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
catch { /* fall through to hardcoded fallback */ }
|
|
68
|
+
return [
|
|
69
|
+
'discuss:pre',
|
|
70
|
+
'discuss:post',
|
|
71
|
+
'plan:pre',
|
|
72
|
+
'plan:post',
|
|
73
|
+
'execute:pre',
|
|
74
|
+
'execute:wave:pre',
|
|
75
|
+
'execute:wave:post',
|
|
76
|
+
'execute:post',
|
|
77
|
+
'verify:pre',
|
|
78
|
+
'verify:post',
|
|
79
|
+
'ship:pre',
|
|
80
|
+
'ship:post',
|
|
81
|
+
];
|
|
82
|
+
})();
|
|
83
|
+
// Alias for backward compatibility (tests import this name)
|
|
84
|
+
const CANONICAL_POINTS_FALLBACK = CANONICAL_POINTS;
|
|
85
|
+
// FIX 2: _getCanonicalPoints now returns the authoritative CANONICAL_POINTS set
|
|
86
|
+
// derived from LOOP_HOST_CONTRACT — not the registry's byLoopPoint keys.
|
|
87
|
+
// The registry's byLoopPoint is only used to READ hooks, not to define valid points.
|
|
88
|
+
function _getCanonicalPoints(_registry) {
|
|
89
|
+
return CANONICAL_POINTS;
|
|
90
|
+
}
|
|
91
|
+
// ─── Pure resolver ─────────────────────────────────────────────────────────────
|
|
92
|
+
/**
|
|
93
|
+
* Pure resolver: given a point, registry, and config, returns the active hooks.
|
|
94
|
+
*
|
|
95
|
+
* Throws if `point` is not one of the 12 canonical points (caller converts to
|
|
96
|
+
* io.error). Never throws for malformed registry/hook entries — skips and
|
|
97
|
+
* continues.
|
|
98
|
+
*
|
|
99
|
+
* Ordering: steps first, then contributions, then gates. Within each array,
|
|
100
|
+
* the materialized registry order is preserved.
|
|
101
|
+
*
|
|
102
|
+
* Activation: a hook with no `when` is always active. With `when` (dotted key),
|
|
103
|
+
* resolved against `config`; active iff truthy. Inactive hooks are filtered out.
|
|
104
|
+
*/
|
|
105
|
+
function resolveLoopHooks(input) {
|
|
106
|
+
const { point, registry, config, cwd, capabilityStatesById } = input;
|
|
107
|
+
// Validate point
|
|
108
|
+
const canonicalPoints = _getCanonicalPoints(registry);
|
|
109
|
+
if (!canonicalPoints.includes(point)) {
|
|
110
|
+
throw new Error(`Invalid loop point: "${point}". Valid points: ${canonicalPoints.join(', ')}`);
|
|
111
|
+
}
|
|
112
|
+
// Guard: registry missing byLoopPoint
|
|
113
|
+
const byLoopPoint = registry['byLoopPoint'];
|
|
114
|
+
if (!byLoopPoint || typeof byLoopPoint !== 'object' || Array.isArray(byLoopPoint)) {
|
|
115
|
+
return { point, activeHooks: [] };
|
|
116
|
+
}
|
|
117
|
+
const byLoopPointMap = byLoopPoint;
|
|
118
|
+
// Guard: point missing in registry
|
|
119
|
+
const entry = byLoopPointMap[point];
|
|
120
|
+
if (!entry || typeof entry !== 'object' || Array.isArray(entry)) {
|
|
121
|
+
return { point, activeHooks: [] };
|
|
122
|
+
}
|
|
123
|
+
const entryMap = entry;
|
|
124
|
+
const activeHooks = [];
|
|
125
|
+
// Helper: check activation using single-key precedence resolver (FIX 1 + FIX 3)
|
|
126
|
+
function isActive(hook) {
|
|
127
|
+
const when = hook['when'];
|
|
128
|
+
// No `when` → unconditional hook, always active
|
|
129
|
+
if (when === undefined || when === null)
|
|
130
|
+
return true;
|
|
131
|
+
// FIX 3: `when` present but not a non-empty string → malformed registry data → INACTIVE
|
|
132
|
+
if (typeof when !== 'string' || when.length === 0)
|
|
133
|
+
return false;
|
|
134
|
+
return _resolveActivationValue(when, config, cwd, registry);
|
|
135
|
+
}
|
|
136
|
+
function isCapabilityActive(capId) {
|
|
137
|
+
if (!capabilityStatesById)
|
|
138
|
+
return true;
|
|
139
|
+
const state = capabilityStatesById instanceof Map
|
|
140
|
+
? capabilityStatesById.get(capId)
|
|
141
|
+
: capabilityStatesById[capId];
|
|
142
|
+
if (!state)
|
|
143
|
+
return false;
|
|
144
|
+
// Fail-closed gate: only render the hook when active is explicitly true.
|
|
145
|
+
// A capability can be installed and surfaced (enabled=true) but config-disabled
|
|
146
|
+
// (active=false); in that case the hook must not render.
|
|
147
|
+
// Phase 4 tri-state alignment: `active` is now required (not optional), so
|
|
148
|
+
// `=== true` is the correct fail-closed check (not `!== false`).
|
|
149
|
+
return state.active === true;
|
|
150
|
+
}
|
|
151
|
+
// Helper: safe string array
|
|
152
|
+
function toStringArray(v) {
|
|
153
|
+
if (!Array.isArray(v))
|
|
154
|
+
return [];
|
|
155
|
+
return v.filter((x) => typeof x === 'string');
|
|
156
|
+
}
|
|
157
|
+
function toFragment(v) {
|
|
158
|
+
if (!v || typeof v !== 'object' || Array.isArray(v))
|
|
159
|
+
return undefined;
|
|
160
|
+
const raw = v;
|
|
161
|
+
const fragment = {};
|
|
162
|
+
if (typeof raw.inline === 'string')
|
|
163
|
+
fragment.inline = raw.inline;
|
|
164
|
+
if (typeof raw.path === 'string')
|
|
165
|
+
fragment.path = raw.path;
|
|
166
|
+
return Object.keys(fragment).length > 0 ? fragment : undefined;
|
|
167
|
+
}
|
|
168
|
+
/**
|
|
169
|
+
* Resolve declared configValues for a contribution hook.
|
|
170
|
+
* The hook may carry `configValues: { alias: "dotted.key", ... }`.
|
|
171
|
+
* Each key is resolved using the same four-level precedence as activation resolution,
|
|
172
|
+
* but returning the raw value (not coerced to boolean) so numeric/string config values
|
|
173
|
+
* are preserved (e.g. security_asvs_level: 2, security_block_on: "medium").
|
|
174
|
+
*/
|
|
175
|
+
function resolveConfigValues(hook) {
|
|
176
|
+
const raw = hook['configValues'];
|
|
177
|
+
if (!raw || typeof raw !== 'object' || Array.isArray(raw))
|
|
178
|
+
return undefined;
|
|
179
|
+
const rawMap = raw;
|
|
180
|
+
const resolved = {};
|
|
181
|
+
for (const [alias, dotKey] of Object.entries(rawMap)) {
|
|
182
|
+
// Prototype-pollution guard (inline literal, CodeQL barrier)
|
|
183
|
+
if (alias === '__proto__' || alias === 'constructor' || alias === 'prototype')
|
|
184
|
+
continue;
|
|
185
|
+
if (typeof dotKey !== 'string')
|
|
186
|
+
continue;
|
|
187
|
+
const r = resolveConfigKey(dotKey, { config, cwd, registry });
|
|
188
|
+
if (r.found)
|
|
189
|
+
resolved[alias] = r.value;
|
|
190
|
+
}
|
|
191
|
+
return Object.keys(resolved).length > 0 ? resolved : undefined;
|
|
192
|
+
}
|
|
193
|
+
// Process steps
|
|
194
|
+
const stepsRaw = entryMap['steps'];
|
|
195
|
+
const steps = Array.isArray(stepsRaw) ? stepsRaw : [];
|
|
196
|
+
for (const hook of steps) {
|
|
197
|
+
if (!hook || typeof hook !== 'object')
|
|
198
|
+
continue;
|
|
199
|
+
const capId = typeof hook['capId'] === 'string' ? hook['capId'] : '';
|
|
200
|
+
if (!isCapabilityActive(capId))
|
|
201
|
+
continue;
|
|
202
|
+
if (!isActive(hook))
|
|
203
|
+
continue;
|
|
204
|
+
const ref = (typeof hook['ref'] === 'object' && hook['ref'] !== null)
|
|
205
|
+
? hook['ref']
|
|
206
|
+
: undefined;
|
|
207
|
+
const when = typeof hook['when'] === 'string' ? hook['when'] : undefined;
|
|
208
|
+
const fragment = toFragment(hook['fragment']);
|
|
209
|
+
const produces = toStringArray(hook['produces']);
|
|
210
|
+
const consumes = toStringArray(hook['consumes']);
|
|
211
|
+
const onError = typeof hook['onError'] === 'string' ? hook['onError'] : undefined;
|
|
212
|
+
const active = { capId, kind: 'step' };
|
|
213
|
+
if (ref !== undefined)
|
|
214
|
+
active.ref = ref;
|
|
215
|
+
if (fragment !== undefined)
|
|
216
|
+
active.fragment = fragment;
|
|
217
|
+
if (when !== undefined)
|
|
218
|
+
active.when = when;
|
|
219
|
+
if (produces.length > 0)
|
|
220
|
+
active.produces = produces;
|
|
221
|
+
if (consumes.length > 0)
|
|
222
|
+
active.consumes = consumes;
|
|
223
|
+
if (onError !== undefined)
|
|
224
|
+
active.onError = onError;
|
|
225
|
+
activeHooks.push(active);
|
|
226
|
+
}
|
|
227
|
+
// Process contributions
|
|
228
|
+
const contributionsRaw = entryMap['contributions'];
|
|
229
|
+
const contributions = Array.isArray(contributionsRaw) ? contributionsRaw : [];
|
|
230
|
+
for (const hook of contributions) {
|
|
231
|
+
if (!hook || typeof hook !== 'object')
|
|
232
|
+
continue;
|
|
233
|
+
const capId = typeof hook['capId'] === 'string' ? hook['capId'] : '';
|
|
234
|
+
if (!isCapabilityActive(capId))
|
|
235
|
+
continue;
|
|
236
|
+
if (!isActive(hook))
|
|
237
|
+
continue;
|
|
238
|
+
const into = typeof hook['into'] === 'string' ? hook['into'] : undefined;
|
|
239
|
+
const fragment = toFragment(hook['fragment']);
|
|
240
|
+
const when = typeof hook['when'] === 'string' ? hook['when'] : undefined;
|
|
241
|
+
const produces = toStringArray(hook['produces']);
|
|
242
|
+
const consumes = toStringArray(hook['consumes']);
|
|
243
|
+
const onError = typeof hook['onError'] === 'string' ? hook['onError'] : undefined;
|
|
244
|
+
const configValuesResolved = resolveConfigValues(hook);
|
|
245
|
+
const active = { capId, kind: 'contribution' };
|
|
246
|
+
if (into !== undefined)
|
|
247
|
+
active.into = into;
|
|
248
|
+
if (fragment !== undefined)
|
|
249
|
+
active.fragment = fragment;
|
|
250
|
+
if (when !== undefined)
|
|
251
|
+
active.when = when;
|
|
252
|
+
if (produces.length > 0)
|
|
253
|
+
active.produces = produces;
|
|
254
|
+
if (consumes.length > 0)
|
|
255
|
+
active.consumes = consumes;
|
|
256
|
+
if (onError !== undefined)
|
|
257
|
+
active.onError = onError;
|
|
258
|
+
if (configValuesResolved !== undefined)
|
|
259
|
+
active.configValues = configValuesResolved;
|
|
260
|
+
activeHooks.push(active);
|
|
261
|
+
}
|
|
262
|
+
// Process gates
|
|
263
|
+
const gatesRaw = entryMap['gates'];
|
|
264
|
+
const gates = Array.isArray(gatesRaw) ? gatesRaw : [];
|
|
265
|
+
for (const hook of gates) {
|
|
266
|
+
if (!hook || typeof hook !== 'object')
|
|
267
|
+
continue;
|
|
268
|
+
const capId = typeof hook['capId'] === 'string' ? hook['capId'] : '';
|
|
269
|
+
if (!isCapabilityActive(capId))
|
|
270
|
+
continue;
|
|
271
|
+
if (!isActive(hook))
|
|
272
|
+
continue;
|
|
273
|
+
const when = typeof hook['when'] === 'string' ? hook['when'] : undefined;
|
|
274
|
+
const check = hook['check'] !== undefined ? hook['check'] : undefined;
|
|
275
|
+
const blocking = typeof hook['blocking'] === 'boolean' ? hook['blocking'] : undefined;
|
|
276
|
+
const onError = typeof hook['onError'] === 'string' ? hook['onError'] : undefined;
|
|
277
|
+
const active = { capId, kind: 'gate' };
|
|
278
|
+
if (when !== undefined)
|
|
279
|
+
active.when = when;
|
|
280
|
+
if (check !== undefined)
|
|
281
|
+
active.check = check;
|
|
282
|
+
if (blocking !== undefined)
|
|
283
|
+
active.blocking = blocking;
|
|
284
|
+
if (onError !== undefined)
|
|
285
|
+
active.onError = onError;
|
|
286
|
+
activeHooks.push(active);
|
|
287
|
+
}
|
|
288
|
+
return { point, activeHooks };
|
|
289
|
+
}
|
|
290
|
+
// ─── Pure renderer ─────────────────────────────────────────────────────────────
|
|
291
|
+
/**
|
|
292
|
+
* Pure renderer: given a resolved result, returns a deterministic markdown string.
|
|
293
|
+
*
|
|
294
|
+
* Empty active set → returns a "no active hooks" placeholder line.
|
|
295
|
+
* Steps: heading with ordinal + skill ref + capId, produces/consumes lines.
|
|
296
|
+
* Contributions: labeled block.
|
|
297
|
+
* Gates: check name, blocking flag, onError.
|
|
298
|
+
*/
|
|
299
|
+
function renderLoopHooks(resolved) {
|
|
300
|
+
const { point, activeHooks } = resolved;
|
|
301
|
+
if (activeHooks.length === 0) {
|
|
302
|
+
return `_No active hooks at ${point}._`;
|
|
303
|
+
}
|
|
304
|
+
const lines = [];
|
|
305
|
+
let stepOrdinal = 0;
|
|
306
|
+
for (const hook of activeHooks) {
|
|
307
|
+
if (hook.kind === 'step') {
|
|
308
|
+
stepOrdinal += 1;
|
|
309
|
+
const refStr = hook.ref?.skill
|
|
310
|
+
? `skill:${hook.ref.skill}`
|
|
311
|
+
: hook.ref?.agent
|
|
312
|
+
? `agent:${hook.ref.agent}`
|
|
313
|
+
: JSON.stringify(hook.ref ?? {});
|
|
314
|
+
lines.push(`### Step ${stepOrdinal}: ${refStr} (${hook.capId})`);
|
|
315
|
+
if (hook.produces && hook.produces.length > 0) {
|
|
316
|
+
lines.push(`- produces: ${hook.produces.join(', ')}`);
|
|
317
|
+
}
|
|
318
|
+
if (hook.consumes && hook.consumes.length > 0) {
|
|
319
|
+
lines.push(`- consumes: ${hook.consumes.join(', ')}`);
|
|
320
|
+
}
|
|
321
|
+
if (hook.when) {
|
|
322
|
+
lines.push(`- when: \`${hook.when}\``);
|
|
323
|
+
}
|
|
324
|
+
if (hook.onError) {
|
|
325
|
+
lines.push(`- onError: ${hook.onError}`);
|
|
326
|
+
}
|
|
327
|
+
if (hook.fragment?.inline) {
|
|
328
|
+
lines.push('');
|
|
329
|
+
lines.push(hook.fragment.inline);
|
|
330
|
+
}
|
|
331
|
+
else if (hook.fragment?.path) {
|
|
332
|
+
lines.push('');
|
|
333
|
+
lines.push(`_Step fragment path is declared but not rendered by loop-resolver: ${hook.fragment.path}_`);
|
|
334
|
+
}
|
|
335
|
+
lines.push('');
|
|
336
|
+
}
|
|
337
|
+
else if (hook.kind === 'contribution') {
|
|
338
|
+
lines.push(`<contribution from="${hook.capId}" into="${hook.into ?? '(unset)'}">`);
|
|
339
|
+
if (hook.fragment?.inline) {
|
|
340
|
+
lines.push(hook.fragment.inline);
|
|
341
|
+
}
|
|
342
|
+
else if (hook.fragment?.path) {
|
|
343
|
+
lines.push(`_Contribution fragment path is declared but not rendered by loop-resolver: ${hook.fragment.path}_`);
|
|
344
|
+
}
|
|
345
|
+
if (hook.produces && hook.produces.length > 0) {
|
|
346
|
+
lines.push(`- produces: ${hook.produces.join(', ')}`);
|
|
347
|
+
}
|
|
348
|
+
if (hook.consumes && hook.consumes.length > 0) {
|
|
349
|
+
lines.push(`- consumes: ${hook.consumes.join(', ')}`);
|
|
350
|
+
}
|
|
351
|
+
if (hook.when) {
|
|
352
|
+
lines.push(`- when: \`${hook.when}\``);
|
|
353
|
+
}
|
|
354
|
+
if (hook.onError) {
|
|
355
|
+
lines.push(`- onError: ${hook.onError}`);
|
|
356
|
+
}
|
|
357
|
+
lines.push('</contribution>');
|
|
358
|
+
lines.push('');
|
|
359
|
+
}
|
|
360
|
+
else if (hook.kind === 'gate') {
|
|
361
|
+
let checkStr = '(none)';
|
|
362
|
+
if (hook.check !== undefined && hook.check !== null) {
|
|
363
|
+
checkStr = typeof hook.check === 'object'
|
|
364
|
+
? JSON.stringify(hook.check)
|
|
365
|
+
: typeof hook.check === 'string' || typeof hook.check === 'number' || typeof hook.check === 'boolean'
|
|
366
|
+
? String(hook.check)
|
|
367
|
+
: '(complex)';
|
|
368
|
+
}
|
|
369
|
+
lines.push(`**Gate** (${hook.capId}): check=${checkStr}, blocking=${String(hook.blocking ?? false)}, onError=${hook.onError ?? 'skip'}`);
|
|
370
|
+
if (hook.when) {
|
|
371
|
+
lines.push(`- when: \`${hook.when}\``);
|
|
372
|
+
}
|
|
373
|
+
lines.push('');
|
|
374
|
+
}
|
|
375
|
+
}
|
|
376
|
+
// Trim trailing blank line
|
|
377
|
+
while (lines.length > 0 && lines[lines.length - 1] === '') {
|
|
378
|
+
lines.pop();
|
|
379
|
+
}
|
|
380
|
+
return lines.join('\n');
|
|
381
|
+
}
|
|
382
|
+
// ─── I/O command handler ───────────────────────────────────────────────────────
|
|
383
|
+
/**
|
|
384
|
+
* Command entry point: load registry + config, resolve + render, emit envelope.
|
|
385
|
+
*
|
|
386
|
+
* Envelope: { point, activeHooks, rendered }
|
|
387
|
+
* On invalid point, emits io.error instead of throwing.
|
|
388
|
+
*
|
|
389
|
+
* Config note: FIX 1 replaced _loadMergedConfig (whole-config deep-merge) with a
|
|
390
|
+
* per-hook single-key activation resolver (_resolveActivationValue). The resolver
|
|
391
|
+
* checks loadConfig result first, then raw config.json files directly (workstream
|
|
392
|
+
* then root), then the registry's configSchema default. This eliminates the
|
|
393
|
+
* merged-object-from-untrusted-keys security concern and correctly handles
|
|
394
|
+
* pre-cutover keys like `workflow.ui_phase` that live in config.json but are not
|
|
395
|
+
* yet exposed through loadConfig's whitelist.
|
|
396
|
+
*
|
|
397
|
+
* --active-cap <capId>: when present, resolves hooks for <point> exactly as the
|
|
398
|
+
* normal path does, then prints exactly `true` (if any resolved activeHook has
|
|
399
|
+
* capId === <capId>) or `false` followed by a single newline, and exits 0.
|
|
400
|
+
* No JSON envelope is emitted — output is clean for shell $(…) capture.
|
|
401
|
+
* Missing <capId> value → coreError + non-zero exit.
|
|
402
|
+
* Unknown/inactive capId → `false` (not an error).
|
|
403
|
+
*/
|
|
404
|
+
function cmdLoopRenderHooks(cwd, point, raw, options = {}) {
|
|
405
|
+
if (!point) {
|
|
406
|
+
coreError('loop render-hooks requires a <point> argument. Valid points: ' + CANONICAL_POINTS.join(', '));
|
|
407
|
+
return;
|
|
408
|
+
}
|
|
409
|
+
// --active-cap <capId> mode: emit 'true' or 'false' only (scanner-safe, no JSON envelope)
|
|
410
|
+
const activeCapId = typeof options['activeCap'] === 'string' ? options['activeCap'] : undefined;
|
|
411
|
+
if (activeCapId !== undefined && activeCapId === '') {
|
|
412
|
+
coreError('--active-cap requires a <capId> value (e.g. --active-cap tdd)');
|
|
413
|
+
return;
|
|
414
|
+
}
|
|
415
|
+
const runtimeConfigDir = typeof options['configDir'] === 'string'
|
|
416
|
+
? options['configDir']
|
|
417
|
+
: undefined;
|
|
418
|
+
// Load the config snapshot ONCE and share it with both the capability-state
|
|
419
|
+
// resolver (via configOverride) and loop-hook resolution, so federated keys
|
|
420
|
+
// present in loadConfig resolve identically for `active` and for hook when/
|
|
421
|
+
// configValues — eliminating the previous double loadConfig() call. Note: keys
|
|
422
|
+
// absent from loadConfig still fall through to raw .planning/config.json reads
|
|
423
|
+
// (precedence levels 2-3) in each pass; that residual re-read window is
|
|
424
|
+
// pre-existing (unchanged by this consolidation), not introduced here.
|
|
425
|
+
let config;
|
|
426
|
+
try {
|
|
427
|
+
config = loadConfig(cwd);
|
|
428
|
+
}
|
|
429
|
+
catch {
|
|
430
|
+
config = {};
|
|
431
|
+
}
|
|
432
|
+
const state = resolveCapabilityRuntimeState(cwd, runtimeConfigDir, config);
|
|
433
|
+
// Registry is the static generated module — same object capability-state uses internally.
|
|
434
|
+
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
435
|
+
const registry = require('./capability-registry.cjs');
|
|
436
|
+
const capabilityStatesById = new Map();
|
|
437
|
+
for (const cap of state.capabilities || []) {
|
|
438
|
+
capabilityStatesById.set(cap.id, cap);
|
|
439
|
+
}
|
|
440
|
+
let resolved;
|
|
441
|
+
try {
|
|
442
|
+
resolved = resolveLoopHooks({ point, registry, config, cwd, capabilityStatesById });
|
|
443
|
+
}
|
|
444
|
+
catch (err) {
|
|
445
|
+
const msg = (err instanceof Error) ? err.message : String(err);
|
|
446
|
+
coreError(msg);
|
|
447
|
+
return;
|
|
448
|
+
}
|
|
449
|
+
// --active-cap mode: print exactly 'true' or 'false' with no envelope
|
|
450
|
+
if (activeCapId !== undefined) {
|
|
451
|
+
const isActive = resolved.activeHooks.some((h) => h.capId === activeCapId);
|
|
452
|
+
process.stdout.write(isActive ? 'true\n' : 'false\n');
|
|
453
|
+
return;
|
|
454
|
+
}
|
|
455
|
+
const rendered = renderLoopHooks(resolved);
|
|
456
|
+
const envelope = {
|
|
457
|
+
point: resolved.point,
|
|
458
|
+
activeHooks: resolved.activeHooks,
|
|
459
|
+
rendered,
|
|
460
|
+
};
|
|
461
|
+
if (state.warnings && state.warnings.length > 0) {
|
|
462
|
+
envelope.warnings = state.warnings;
|
|
463
|
+
}
|
|
464
|
+
coreOutput(envelope, raw);
|
|
465
|
+
}
|
|
466
|
+
module.exports = {
|
|
467
|
+
resolveLoopHooks,
|
|
468
|
+
renderLoopHooks,
|
|
469
|
+
cmdLoopRenderHooks,
|
|
470
|
+
// Exported for tests
|
|
471
|
+
_getNestedConfigValue,
|
|
472
|
+
_resolveActivationValue,
|
|
473
|
+
_readRawConfigKey,
|
|
474
|
+
// Re-exported for identity parity guard (FIX 2: resolveConfigValues in this module
|
|
475
|
+
// calls resolveConfigKey; exporting it here makes the single-owner contract testable).
|
|
476
|
+
resolveConfigKey,
|
|
477
|
+
CANONICAL_POINTS_FALLBACK,
|
|
478
|
+
CANONICAL_POINTS,
|
|
479
|
+
};
|