@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,505 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Runtime surface module — ADR-0011 Phase 2 (Option B).
|
|
4
|
+
*
|
|
5
|
+
* Manages the runtime enable/disable surface state (the `.gsd-surface.json` marker in
|
|
6
|
+
* each runtime's config dir root (e.g., ~/.claude)) independently of the install-time profile marker
|
|
7
|
+
* (`.gsd-profile`). Runtime config locations are resolved by callers.
|
|
8
|
+
*
|
|
9
|
+
* Effective skill set = base profile ∪ explicitAdds − disabledClusters − explicitRemoves,
|
|
10
|
+
* then transitively closed via the manifest.
|
|
11
|
+
*
|
|
12
|
+
* Exports:
|
|
13
|
+
* readSurface(runtimeConfigDir)
|
|
14
|
+
* writeSurface(runtimeConfigDir, surfaceState)
|
|
15
|
+
* resolveSurface(runtimeConfigDir, manifest, clusterMap?, registry?)
|
|
16
|
+
* applySurface(runtimeConfigDir, layout, manifest, clusterMap?, registry?)
|
|
17
|
+
* listSurface(runtimeConfigDir, manifest, clusterMap?, registry?)
|
|
18
|
+
* pruneSkillDirs(skillsDir, retainedNames, prefix, manifest)
|
|
19
|
+
*
|
|
20
|
+
* The optional `registry` param (ADR-857 phase 4c) accepts the capability-registry
|
|
21
|
+
* object. When present, capability clusters are merged into the effective cluster
|
|
22
|
+
* map and the registry is threaded into resolveProfile so capability-contributed
|
|
23
|
+
* skills participate in the base set and disable-ability. Absent or undefined
|
|
24
|
+
* leaves behaviour identical to the pre-registry path (no-op for current registry
|
|
25
|
+
* where UI=full and the full profile returns '*' regardless).
|
|
26
|
+
*
|
|
27
|
+
* ADR-457 build-at-publish: the hand-written bin/lib/surface.cjs collapsed
|
|
28
|
+
* to a TypeScript source of truth. Behaviour is preserved byte-for-behaviour
|
|
29
|
+
* from the prior hand-written .cjs; only types are added.
|
|
30
|
+
*/
|
|
31
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
32
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
33
|
+
};
|
|
34
|
+
const node_fs_1 = __importDefault(require("node:fs"));
|
|
35
|
+
const node_path_1 = __importDefault(require("node:path"));
|
|
36
|
+
const node_os_1 = __importDefault(require("node:os"));
|
|
37
|
+
const shell_command_projection_cjs_1 = require("./shell-command-projection.cjs");
|
|
38
|
+
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
39
|
+
const installProfiles = require("./install-profiles.cjs");
|
|
40
|
+
const { readActiveProfile, resolveProfile, loadSkillsManifest, } = installProfiles;
|
|
41
|
+
const clusters_cjs_1 = require("./clusters.cjs");
|
|
42
|
+
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
43
|
+
const runtimeArtifactLayout = require("./runtime-artifact-layout.cjs");
|
|
44
|
+
const { findInstallSourceRoot, getInstallExports } = runtimeArtifactLayout;
|
|
45
|
+
const SURFACE_FILE_NAME = '.gsd-surface.json';
|
|
46
|
+
/**
|
|
47
|
+
* Read the surface state from a runtime config directory.
|
|
48
|
+
*
|
|
49
|
+
* @param runtimeConfigDir
|
|
50
|
+
* @returns null if file missing or corrupt
|
|
51
|
+
*/
|
|
52
|
+
function readSurface(runtimeConfigDir) {
|
|
53
|
+
const filePath = node_path_1.default.join(runtimeConfigDir, SURFACE_FILE_NAME);
|
|
54
|
+
try {
|
|
55
|
+
const raw = node_fs_1.default.readFileSync(filePath, 'utf8');
|
|
56
|
+
const parsed = JSON.parse(raw);
|
|
57
|
+
// Structural validation — must have these fields with expected types
|
|
58
|
+
if (typeof parsed !== 'object' || parsed === null)
|
|
59
|
+
return null;
|
|
60
|
+
const p = parsed;
|
|
61
|
+
if (typeof p['baseProfile'] !== 'string')
|
|
62
|
+
return null;
|
|
63
|
+
if (!Array.isArray(p['disabledClusters']))
|
|
64
|
+
return null;
|
|
65
|
+
if (!Array.isArray(p['explicitAdds']))
|
|
66
|
+
return null;
|
|
67
|
+
if (!Array.isArray(p['explicitRemoves']))
|
|
68
|
+
return null;
|
|
69
|
+
return {
|
|
70
|
+
baseProfile: p['baseProfile'],
|
|
71
|
+
disabledClusters: p['disabledClusters'],
|
|
72
|
+
explicitAdds: p['explicitAdds'],
|
|
73
|
+
explicitRemoves: p['explicitRemoves'],
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
catch {
|
|
77
|
+
return null;
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* Write the surface state atomically via the platform seam (mkdir + tmp+rename).
|
|
82
|
+
*/
|
|
83
|
+
function writeSurface(runtimeConfigDir, surfaceState) {
|
|
84
|
+
(0, shell_command_projection_cjs_1.platformWriteSync)(node_path_1.default.join(runtimeConfigDir, SURFACE_FILE_NAME), JSON.stringify(surfaceState, null, 2) + '\n');
|
|
85
|
+
}
|
|
86
|
+
// ---------------------------------------------------------------------------
|
|
87
|
+
// Resolution
|
|
88
|
+
// ---------------------------------------------------------------------------
|
|
89
|
+
/**
|
|
90
|
+
* Expand cluster names to skill stems using the provided clusterMap.
|
|
91
|
+
*/
|
|
92
|
+
function clustersToSkills(clusterNames, clusterMap) {
|
|
93
|
+
const result = new Set();
|
|
94
|
+
for (const name of clusterNames) {
|
|
95
|
+
const members = clusterMap[name];
|
|
96
|
+
// FIX 5: guard against non-iterable members — malformed registry must never throw
|
|
97
|
+
if (!Array.isArray(members))
|
|
98
|
+
continue;
|
|
99
|
+
for (const s of members)
|
|
100
|
+
result.add(s);
|
|
101
|
+
}
|
|
102
|
+
return result;
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* Normalize manifest inputs to the skill-dependency Map shape expected by
|
|
106
|
+
* resolveProfile/computeClosure.
|
|
107
|
+
*
|
|
108
|
+
* Supports:
|
|
109
|
+
* - canonical Map<string, string[]>
|
|
110
|
+
* - legacy plain object map: { [stem]: string[] }
|
|
111
|
+
* - parsed gsd-file-manifest.json object ({ files: { ... } }) by rebuilding
|
|
112
|
+
* the dependency manifest from the install source tree
|
|
113
|
+
*/
|
|
114
|
+
function normalizeSkillManifest(runtimeConfigDir, manifest) {
|
|
115
|
+
if (manifest instanceof Map) {
|
|
116
|
+
return manifest;
|
|
117
|
+
}
|
|
118
|
+
if (!manifest || typeof manifest !== 'object') {
|
|
119
|
+
return new Map();
|
|
120
|
+
}
|
|
121
|
+
// Legacy/ad-hoc object map: stem -> requires[]
|
|
122
|
+
const arrayEntries = Object.entries(manifest).filter(([, value]) => Array.isArray(value));
|
|
123
|
+
if (arrayEntries.length > 0) {
|
|
124
|
+
return new Map(arrayEntries.map(([stem, deps]) => [stem, deps]));
|
|
125
|
+
}
|
|
126
|
+
// Parsed gsd-file-manifest.json shape: rebuild the dependency map from source.
|
|
127
|
+
const manifestObj = manifest;
|
|
128
|
+
if (manifestObj['files'] && typeof manifestObj['files'] === 'object') {
|
|
129
|
+
const srcCommandsDir = findInstallSourceRoot(runtimeConfigDir);
|
|
130
|
+
return loadSkillsManifest(srcCommandsDir);
|
|
131
|
+
}
|
|
132
|
+
return new Map();
|
|
133
|
+
}
|
|
134
|
+
/**
|
|
135
|
+
* Resolve the effective surface to a typed profile-like object.
|
|
136
|
+
* Shape: { name, skills: Set<string>|'*', agents: Set<string> }
|
|
137
|
+
*
|
|
138
|
+
* Resolution order:
|
|
139
|
+
* 1. Start with base profile resolved via resolveProfile()
|
|
140
|
+
* 2. Remove skills in disabled clusters
|
|
141
|
+
* 3. Add explicitAdds (and their transitive closure)
|
|
142
|
+
* 4. Remove explicitRemoves (only the stem itself, no cascade)
|
|
143
|
+
*
|
|
144
|
+
* ADR-857 phase 4c: optional registry param. When present:
|
|
145
|
+
* - capability clusters are merged into the effective cluster map so
|
|
146
|
+
* capability-owned skill groups are disable-able.
|
|
147
|
+
* - registry is threaded into resolveProfile so capability skills
|
|
148
|
+
* participate in the base skill set and their requires: chains expand.
|
|
149
|
+
*/
|
|
150
|
+
function resolveSurface(runtimeConfigDir, manifest, clusterMap, registry) {
|
|
151
|
+
// Merge capability clusters into the cluster map when registry is provided.
|
|
152
|
+
// The ADR-857 phase 4a HARD gate guarantees that when a capId matches a CLUSTERS
|
|
153
|
+
// key, the values are EQUAL — so the spread is idempotent for matching names.
|
|
154
|
+
// Defense-in-depth: if a capId collides with a hand-authored CLUSTERS key AND
|
|
155
|
+
// the values DIFFER (future drift bypassing the gate), prefer the hand-authored
|
|
156
|
+
// value so disable behavior is never silently changed by a stale registry entry.
|
|
157
|
+
// Also guard: skip entries whose value is not a string[] (malformed registry).
|
|
158
|
+
let cm = clusterMap || clusters_cjs_1.CLUSTERS;
|
|
159
|
+
if (registry && registry.capabilityClusters && typeof registry.capabilityClusters === 'object') {
|
|
160
|
+
const baseCm = cm;
|
|
161
|
+
const capClusters = registry.capabilityClusters;
|
|
162
|
+
const merged = { ...baseCm };
|
|
163
|
+
for (const capId of Object.keys(capClusters)) {
|
|
164
|
+
const val = capClusters[capId];
|
|
165
|
+
// FIX 5: skip malformed (non-array) entries — never throw on bad registry
|
|
166
|
+
if (!Array.isArray(val))
|
|
167
|
+
continue;
|
|
168
|
+
// FIX 4: if the capId matches an existing cluster key, only override when
|
|
169
|
+
// the values are identical (guaranteed by 4a gate). If they differ, the
|
|
170
|
+
// hand-authored value wins — prefer known-correct disable behavior over
|
|
171
|
+
// a potentially stale registry entry.
|
|
172
|
+
if (Object.prototype.hasOwnProperty.call(baseCm, capId)) {
|
|
173
|
+
const existing = baseCm[capId];
|
|
174
|
+
if (!Array.isArray(existing)) {
|
|
175
|
+
merged[capId] = val;
|
|
176
|
+
continue;
|
|
177
|
+
}
|
|
178
|
+
// Values differ → hand-authored wins (skip the override)
|
|
179
|
+
if (existing.length !== val.length || existing.some((v, i) => v !== val[i]))
|
|
180
|
+
continue;
|
|
181
|
+
}
|
|
182
|
+
// Prototype-pollution guard (parity with _capabilitySkillsForMode in install-profiles.cts)
|
|
183
|
+
if (capId === '__proto__' || capId === 'constructor' || capId === 'prototype')
|
|
184
|
+
continue;
|
|
185
|
+
merged[capId] = val;
|
|
186
|
+
}
|
|
187
|
+
cm = merged;
|
|
188
|
+
}
|
|
189
|
+
const skillManifest = normalizeSkillManifest(runtimeConfigDir, manifest);
|
|
190
|
+
const surface = readSurface(runtimeConfigDir);
|
|
191
|
+
// Determine base profile name: from surface state or from .gsd-profile marker
|
|
192
|
+
const baseProfileName = (surface && surface.baseProfile)
|
|
193
|
+
? surface.baseProfile
|
|
194
|
+
: (readActiveProfile(runtimeConfigDir) || 'full');
|
|
195
|
+
// Resolve base profile — thread registry so capability skills are included.
|
|
196
|
+
const baseResolved = resolveProfile({
|
|
197
|
+
modes: baseProfileName.split(',').map((s) => s.trim()),
|
|
198
|
+
manifest: skillManifest,
|
|
199
|
+
registry,
|
|
200
|
+
});
|
|
201
|
+
// If full, we need to enumerate all skills from the manifest
|
|
202
|
+
let skills;
|
|
203
|
+
if (baseResolved.skills === '*') {
|
|
204
|
+
// Materialize all skill stems from manifest
|
|
205
|
+
skills = new Set();
|
|
206
|
+
for (const [key] of skillManifest) {
|
|
207
|
+
if (!key.startsWith('_calls_agents_'))
|
|
208
|
+
skills.add(key);
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
else {
|
|
212
|
+
skills = new Set(baseResolved.skills);
|
|
213
|
+
}
|
|
214
|
+
if (surface) {
|
|
215
|
+
// Step 2: remove disabled cluster members
|
|
216
|
+
const disabledSkills = clustersToSkills(surface.disabledClusters, cm);
|
|
217
|
+
for (const s of disabledSkills)
|
|
218
|
+
skills.delete(s);
|
|
219
|
+
// Step 3: add explicitAdds with transitive closure
|
|
220
|
+
if (surface.explicitAdds.length > 0) {
|
|
221
|
+
const addSet = new Set(surface.explicitAdds);
|
|
222
|
+
// Compute closure of adds
|
|
223
|
+
const queue = [...addSet];
|
|
224
|
+
const visited = new Set(addSet);
|
|
225
|
+
while (queue.length > 0) {
|
|
226
|
+
const stem = queue.pop();
|
|
227
|
+
const deps = skillManifest.get(stem) || [];
|
|
228
|
+
for (const dep of deps) {
|
|
229
|
+
if (!visited.has(dep)) {
|
|
230
|
+
visited.add(dep);
|
|
231
|
+
queue.push(dep);
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
for (const s of visited)
|
|
236
|
+
skills.add(s);
|
|
237
|
+
}
|
|
238
|
+
// Step 4: remove explicitRemoves (stem only, no cascade)
|
|
239
|
+
for (const s of surface.explicitRemoves) {
|
|
240
|
+
skills.delete(s);
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
// Derive agents from skills
|
|
244
|
+
const agents = new Set();
|
|
245
|
+
for (const skillStem of skills) {
|
|
246
|
+
const agentRefs = skillManifest.get(`_calls_agents_${skillStem}`) || [];
|
|
247
|
+
for (const agentStem of agentRefs)
|
|
248
|
+
agents.add(agentStem);
|
|
249
|
+
}
|
|
250
|
+
const name = surface ? `surface:${surface.baseProfile}` : `profile:${baseProfileName}`;
|
|
251
|
+
return { name, skills, agents };
|
|
252
|
+
}
|
|
253
|
+
// ---------------------------------------------------------------------------
|
|
254
|
+
// Apply
|
|
255
|
+
// ---------------------------------------------------------------------------
|
|
256
|
+
/**
|
|
257
|
+
* Re-stage the active surface using the resolved layout.
|
|
258
|
+
* Iterates layout.kinds and syncs each artifact kind to its destination.
|
|
259
|
+
*/
|
|
260
|
+
function applySurface(runtimeConfigDir, layout, manifest, clusterMap, registry) {
|
|
261
|
+
if (node_path_1.default.resolve(runtimeConfigDir) !== node_path_1.default.resolve(layout.configDir)) {
|
|
262
|
+
throw new TypeError('applySurface runtimeConfigDir must match layout.configDir');
|
|
263
|
+
}
|
|
264
|
+
const skillManifest = normalizeSkillManifest(layout.configDir, manifest);
|
|
265
|
+
const resolved = resolveSurface(layout.configDir, skillManifest, clusterMap, registry);
|
|
266
|
+
// Mirror installRuntimeArtifacts: skills kinds get per-runtime path rewrites
|
|
267
|
+
// so SKILL.md bodies reference the install target (pathPrefix), not the
|
|
268
|
+
// converter's default ~/.claude paths (#813). Computed lazily so command-only
|
|
269
|
+
// runtimes do not trigger the install.js require.
|
|
270
|
+
let pathPrefix = null;
|
|
271
|
+
for (const kind of layout.kinds) {
|
|
272
|
+
const staged = kind.stage(resolved);
|
|
273
|
+
if (kind.kind === 'skills') {
|
|
274
|
+
const installExports = getInstallExports();
|
|
275
|
+
if (pathPrefix === null) {
|
|
276
|
+
const scope = layout.scope ?? 'global';
|
|
277
|
+
const resolvedTarget = node_path_1.default.resolve(layout.configDir).replace(/\\/g, '/');
|
|
278
|
+
const homeDir = node_os_1.default.homedir().replace(/\\/g, '/');
|
|
279
|
+
pathPrefix = installExports.computePathPrefix({
|
|
280
|
+
isGlobal: scope === 'global',
|
|
281
|
+
isOpencode: layout.runtime === 'opencode',
|
|
282
|
+
isWindowsHost: process.platform === 'win32',
|
|
283
|
+
resolvedTarget,
|
|
284
|
+
homeDir,
|
|
285
|
+
});
|
|
286
|
+
}
|
|
287
|
+
installExports.applyRuntimeContentRewritesInPlace(staged, layout.runtime, pathPrefix);
|
|
288
|
+
}
|
|
289
|
+
const dest = node_path_1.default.join(layout.configDir, kind.destSubpath);
|
|
290
|
+
_syncGsdDir(staged, dest, kind, skillManifest);
|
|
291
|
+
}
|
|
292
|
+
return resolved;
|
|
293
|
+
}
|
|
294
|
+
/**
|
|
295
|
+
* Prune GSD-managed skill directories from a skills directory.
|
|
296
|
+
*
|
|
297
|
+
* Removes every directory in `skillsDir` that is GSD-owned but NOT listed
|
|
298
|
+
* in `retainedNames`. User-owned dirs (not matching the GSD ownership criteria)
|
|
299
|
+
* are always preserved.
|
|
300
|
+
*
|
|
301
|
+
* Ownership criteria:
|
|
302
|
+
* - Non-empty prefix (e.g. 'gsd-'): dir name starts with that prefix AND
|
|
303
|
+
* appears in the manifest (manifest membership is required). Dirs that match
|
|
304
|
+
* the prefix but are NOT in the manifest are treated as user-owned and
|
|
305
|
+
* preserved — this prevents data loss for user-created gsd-* directories.
|
|
306
|
+
* A warning is written to stderr when such a dir is encountered.
|
|
307
|
+
* - Empty prefix (Hermes): dir name appears as a canonical skill stem in the
|
|
308
|
+
* manifest. User dirs not in the manifest are preserved.
|
|
309
|
+
* - Empty prefix without manifest, or manifest not a Map: conservative; no
|
|
310
|
+
* dirs are removed.
|
|
311
|
+
*
|
|
312
|
+
* This is the single point of truth for skill-dir pruning. Both _syncGsdDir
|
|
313
|
+
* (surface apply) and callers that need stand-alone pruning use this function.
|
|
314
|
+
*
|
|
315
|
+
* @param skillsDir directory that contains the gsd-STEM sub-dirs
|
|
316
|
+
* @param retainedNames set of directory names to keep (e.g. 'gsd-help')
|
|
317
|
+
* @param prefix GSD dir prefix, e.g. 'gsd-' (or '' for Hermes)
|
|
318
|
+
* @param manifest optional; required for Hermes empty-prefix case
|
|
319
|
+
* and for manifest-membership gate in prefixed case.
|
|
320
|
+
* Must be a Map; any other type is treated as missing.
|
|
321
|
+
*/
|
|
322
|
+
function pruneSkillDirs(skillsDir, retainedNames, prefix, manifest) {
|
|
323
|
+
if (!node_fs_1.default.existsSync(skillsDir))
|
|
324
|
+
return;
|
|
325
|
+
// Finding 2: guard against callers passing a truthy non-Map as manifest.
|
|
326
|
+
// A non-Map manifest would throw on .keys(); treat it as absent and be conservative.
|
|
327
|
+
const safeManifest = (manifest instanceof Map) ? manifest : null;
|
|
328
|
+
// Build the canonical stem set from the manifest (used for both prefixed and Hermes paths).
|
|
329
|
+
// Deletion requires manifest membership — without a valid manifest, be conservative.
|
|
330
|
+
const canonicalStems = safeManifest
|
|
331
|
+
? new Set([...safeManifest.keys()].filter(k => !k.startsWith('_calls_agents_')))
|
|
332
|
+
: null;
|
|
333
|
+
for (const entry of node_fs_1.default.readdirSync(skillsDir)) {
|
|
334
|
+
const entryPath = node_path_1.default.join(skillsDir, entry);
|
|
335
|
+
if (!node_fs_1.default.statSync(entryPath).isDirectory())
|
|
336
|
+
continue;
|
|
337
|
+
let isGsdOwned;
|
|
338
|
+
if (prefix !== '') {
|
|
339
|
+
if (!entry.startsWith(prefix)) {
|
|
340
|
+
// Does not match prefix at all — user-owned, preserve.
|
|
341
|
+
continue;
|
|
342
|
+
}
|
|
343
|
+
if (!canonicalStems) {
|
|
344
|
+
// No manifest available: cannot confirm ownership — preserve conservatively.
|
|
345
|
+
continue;
|
|
346
|
+
}
|
|
347
|
+
// Finding 1 fix: prefix match is necessary but NOT sufficient.
|
|
348
|
+
// The dir must also be in the manifest to be considered GSD-owned.
|
|
349
|
+
// A user-created gsd-* dir that isn't in the manifest is preserved with a warning.
|
|
350
|
+
if (!canonicalStems.has(entry.slice(prefix.length))) {
|
|
351
|
+
process.stderr.write(`[gsd] Warning: ${entry} matches GSD prefix '${prefix}' but is not in the manifest — preserving (user-owned or unknown)\n`);
|
|
352
|
+
continue;
|
|
353
|
+
}
|
|
354
|
+
isGsdOwned = true;
|
|
355
|
+
}
|
|
356
|
+
else if (canonicalStems) {
|
|
357
|
+
// Hermes: GSD-owned iff the directory name appears in the canonical manifest.
|
|
358
|
+
isGsdOwned = canonicalStems.has(entry);
|
|
359
|
+
}
|
|
360
|
+
else {
|
|
361
|
+
// No manifest available: be conservative, don't remove anything.
|
|
362
|
+
continue;
|
|
363
|
+
}
|
|
364
|
+
if (!isGsdOwned)
|
|
365
|
+
continue; // Hermes path only: preserve user-owned dirs not in manifest
|
|
366
|
+
if (retainedNames.has(entry))
|
|
367
|
+
continue; // GSD-owned and in retain set
|
|
368
|
+
try {
|
|
369
|
+
node_fs_1.default.rmSync(entryPath, { recursive: true, force: true });
|
|
370
|
+
}
|
|
371
|
+
catch (err) {
|
|
372
|
+
process.stderr.write(`surface: failed to prune ${entryPath}: ${err.message}\n`);
|
|
373
|
+
}
|
|
374
|
+
}
|
|
375
|
+
}
|
|
376
|
+
/**
|
|
377
|
+
* Sync destination directory from staged source.
|
|
378
|
+
*
|
|
379
|
+
* For 'commands' kind: iterate *.md files in destDir, remove if not in staged set.
|
|
380
|
+
* For 'agents' kind: same, but only remove files starting with 'gsd-' prefix.
|
|
381
|
+
* For 'skills' kind: iterate directories in destDir matching kind.prefix; add missing
|
|
382
|
+
* by copying recursively; remove dirs not in staged set. Preserves dirs not matching
|
|
383
|
+
* the prefix (user-owned skills). Pruning is delegated to pruneSkillDirs().
|
|
384
|
+
*
|
|
385
|
+
* For Hermes (empty prefix): uses manifest membership to discriminate GSD-owned vs
|
|
386
|
+
* user-owned dirs. GSD-owned = stem in manifest; removal targets = in manifest AND
|
|
387
|
+
* not in staged set. User-owned (not in manifest) are always preserved.
|
|
388
|
+
*/
|
|
389
|
+
function _syncGsdDir(stagedDir, destDir, kind, manifest) {
|
|
390
|
+
if (!node_fs_1.default.existsSync(stagedDir))
|
|
391
|
+
return;
|
|
392
|
+
node_fs_1.default.mkdirSync(destDir, { recursive: true });
|
|
393
|
+
// Normalize: allow legacy string context for backward-compat with internal callers
|
|
394
|
+
const kindName = (typeof kind === 'string') ? kind : kind.kind;
|
|
395
|
+
const kindPrefix = (typeof kind === 'object' && kind !== null) ? kind.prefix : 'gsd-';
|
|
396
|
+
if (kindName === 'skills') {
|
|
397
|
+
// Skills kind: work with directories, not files.
|
|
398
|
+
// Each staged entry is a directory named ${prefix}${stem}.
|
|
399
|
+
const stagedDirs = new Set(node_fs_1.default.readdirSync(stagedDir).filter(entry => {
|
|
400
|
+
return node_fs_1.default.statSync(node_path_1.default.join(stagedDir, entry)).isDirectory();
|
|
401
|
+
}));
|
|
402
|
+
// Copy missing dirs from staged to dest (always overwrite to ensure content is current)
|
|
403
|
+
for (const dirName of stagedDirs) {
|
|
404
|
+
const destSubDir = node_path_1.default.join(destDir, dirName);
|
|
405
|
+
node_fs_1.default.cpSync(node_path_1.default.join(stagedDir, dirName), destSubDir, { recursive: true });
|
|
406
|
+
}
|
|
407
|
+
// Prune GSD-owned dirs that are no longer in the staged set.
|
|
408
|
+
// pruneSkillDirs() is the single point of truth for this logic.
|
|
409
|
+
pruneSkillDirs(destDir, stagedDirs, kindPrefix, manifest);
|
|
410
|
+
}
|
|
411
|
+
else {
|
|
412
|
+
// commands / agents kind: mirror installRuntimeArtifacts (_copyStaged /
|
|
413
|
+
// _removeGsdEntries in bin/install.js) so surface produces the SAME files as a
|
|
414
|
+
// fresh install (#816). Flat command dirs (opencode/cursor/augment/kilo) take
|
|
415
|
+
// the gsd- prefix on copy; namespaced command dirs (commands/gsd) and agents
|
|
416
|
+
// keep their staged names. Copying staged names verbatim previously diverged
|
|
417
|
+
// from install and orphaned the installed gsd-*.md files, and the unscoped
|
|
418
|
+
// prune deleted user-owned command files.
|
|
419
|
+
//
|
|
420
|
+
// NOTE: the destName rule below intentionally mirrors bin/install.js
|
|
421
|
+
// `_copyStaged` (the `namespacedByDir` decision). Keep them in sync.
|
|
422
|
+
const destLast = (typeof kind === 'object' && kind !== null && kind.destSubpath)
|
|
423
|
+
? node_path_1.default.basename(kind.destSubpath)
|
|
424
|
+
: '';
|
|
425
|
+
const prefixStem = kindPrefix ? kindPrefix.replace(/-$/, '') : '';
|
|
426
|
+
const namespacedByDir = kindName === 'commands' && destLast === prefixStem;
|
|
427
|
+
const stagedFiles = node_fs_1.default.readdirSync(stagedDir).filter(f => f.endsWith('.md'));
|
|
428
|
+
const stagedDestNames = new Set();
|
|
429
|
+
for (const file of stagedFiles) {
|
|
430
|
+
// Flat-hyphen (D-12): staged command files already carry the `${kindPrefix}`
|
|
431
|
+
// prefix (e.g. `pp-progress.md`, preserved by stageSkillsForProfile). Re-prepending
|
|
432
|
+
// it here would double it (`pp-pp-progress.md`). Keep verbatim when already prefixed.
|
|
433
|
+
const alreadyPrefixed = kindPrefix && file.startsWith(kindPrefix);
|
|
434
|
+
const destName = (kindName === 'agents' || namespacedByDir || alreadyPrefixed)
|
|
435
|
+
? file
|
|
436
|
+
: `${kindPrefix}${file.slice(0, -3)}.md`;
|
|
437
|
+
node_fs_1.default.copyFileSync(node_path_1.default.join(stagedDir, file), node_path_1.default.join(destDir, destName));
|
|
438
|
+
stagedDestNames.add(destName);
|
|
439
|
+
}
|
|
440
|
+
// Prune stale GSD-owned files not in the staged set, preserving user-owned files
|
|
441
|
+
// (mirrors install's prefix-scoped _removeGsdEntries):
|
|
442
|
+
// - agents: only gsd-* are GSD-owned
|
|
443
|
+
// - flat command dirs: only `${kindPrefix}`-prefixed are GSD-owned
|
|
444
|
+
// - namespaced command dirs: the whole dir is GSD-owned
|
|
445
|
+
for (const file of node_fs_1.default.readdirSync(destDir).filter(f => f.endsWith('.md'))) {
|
|
446
|
+
if (kindName === 'agents' && !file.startsWith('gsd-'))
|
|
447
|
+
continue;
|
|
448
|
+
if (kindName === 'commands' && !namespacedByDir && kindPrefix && !file.startsWith(kindPrefix))
|
|
449
|
+
continue;
|
|
450
|
+
if (!stagedDestNames.has(file)) {
|
|
451
|
+
try {
|
|
452
|
+
node_fs_1.default.unlinkSync(node_path_1.default.join(destDir, file));
|
|
453
|
+
}
|
|
454
|
+
catch { /* ignore */ }
|
|
455
|
+
}
|
|
456
|
+
}
|
|
457
|
+
}
|
|
458
|
+
}
|
|
459
|
+
// ---------------------------------------------------------------------------
|
|
460
|
+
// List
|
|
461
|
+
// ---------------------------------------------------------------------------
|
|
462
|
+
/**
|
|
463
|
+
* List the currently enabled and disabled skills with token cost.
|
|
464
|
+
*
|
|
465
|
+
* Token cost = sum of description lengths ÷ 4 (mirrors audit script).
|
|
466
|
+
* Descriptions are read from the install source (findInstallSourceRoot).
|
|
467
|
+
*/
|
|
468
|
+
function listSurface(runtimeConfigDir, manifest, clusterMap, registry) {
|
|
469
|
+
const skillManifest = normalizeSkillManifest(runtimeConfigDir, manifest);
|
|
470
|
+
const resolved = resolveSurface(runtimeConfigDir, skillManifest, clusterMap, registry);
|
|
471
|
+
// All known stems from manifest (exclude _calls_agents_ meta keys)
|
|
472
|
+
const allStems = [];
|
|
473
|
+
for (const [key] of skillManifest) {
|
|
474
|
+
if (!key.startsWith('_calls_agents_'))
|
|
475
|
+
allStems.push(key);
|
|
476
|
+
}
|
|
477
|
+
const enabledSet = resolved.skills instanceof Set ? resolved.skills : new Set(allStems);
|
|
478
|
+
const enabled = allStems.filter(s => enabledSet.has(s)).sort();
|
|
479
|
+
const disabled = allStems.filter(s => !enabledSet.has(s)).sort();
|
|
480
|
+
// Compute token cost by reading descriptions from the install source
|
|
481
|
+
const srcCommandsDir = findInstallSourceRoot(runtimeConfigDir);
|
|
482
|
+
let tokenCost = 0;
|
|
483
|
+
for (const stem of enabled) {
|
|
484
|
+
const filePath = node_path_1.default.join(srcCommandsDir, `${stem}.md`);
|
|
485
|
+
try {
|
|
486
|
+
const content = node_fs_1.default.readFileSync(filePath, 'utf8');
|
|
487
|
+
const descMatch = content.match(/^description:\s*(.+)$/m);
|
|
488
|
+
if (descMatch) {
|
|
489
|
+
tokenCost += Math.ceil(descMatch[1].trim().length / 4);
|
|
490
|
+
}
|
|
491
|
+
}
|
|
492
|
+
catch { /* ignore */ }
|
|
493
|
+
}
|
|
494
|
+
return { enabled, disabled, tokenCost };
|
|
495
|
+
}
|
|
496
|
+
module.exports = {
|
|
497
|
+
readSurface,
|
|
498
|
+
writeSurface,
|
|
499
|
+
resolveSurface,
|
|
500
|
+
applySurface,
|
|
501
|
+
listSurface,
|
|
502
|
+
// Exported for testing and for callers that need stand-alone pruning
|
|
503
|
+
pruneSkillDirs,
|
|
504
|
+
_syncGsdDir,
|
|
505
|
+
};
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Task command router — is-behavior-adding subcommand handler.
|
|
4
|
+
*
|
|
5
|
+
* ADR-457 build-at-publish: the hand-written bin/lib/task-command-router.cjs
|
|
6
|
+
* collapsed to a TypeScript source of truth. Behaviour is preserved byte-for-behaviour
|
|
7
|
+
* from the prior hand-written .cjs; only types are added.
|
|
8
|
+
*/
|
|
9
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
10
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
11
|
+
};
|
|
12
|
+
const node_fs_1 = __importDefault(require("node:fs"));
|
|
13
|
+
const node_path_1 = __importDefault(require("node:path"));
|
|
14
|
+
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
15
|
+
const ioMod = require("./io.cjs");
|
|
16
|
+
const { output, error, ERROR_REASON } = ioMod;
|
|
17
|
+
// ─── Implementation ───────────────────────────────────────────────────────────
|
|
18
|
+
function isBehaviorAddingTaskContent(content) {
|
|
19
|
+
const tddTrue = /\btdd\s*=\s*["']true["']/i.test(content);
|
|
20
|
+
const behaviorMatch = content.match(/<behavior>([\s\S]*?)<\/behavior>/i);
|
|
21
|
+
const hasBehaviorBlock = Boolean(behaviorMatch && behaviorMatch[1].trim().length > 0);
|
|
22
|
+
const filesMatch = content.match(/<files>([\s\S]*?)<\/files>/i);
|
|
23
|
+
let hasSourceFiles = false;
|
|
24
|
+
if (filesMatch) {
|
|
25
|
+
const fileLines = filesMatch[1]
|
|
26
|
+
.split(/[\n,]/)
|
|
27
|
+
.map((line) => line.trim().replace(/^[-*]\s*/, ''))
|
|
28
|
+
.filter(Boolean);
|
|
29
|
+
hasSourceFiles = fileLines.some((file) => !/\.md$/i.test(file) &&
|
|
30
|
+
!/\.json$/i.test(file) &&
|
|
31
|
+
!/\.test\.[^.]+$/i.test(file) &&
|
|
32
|
+
!/\.spec\.[^.]+$/i.test(file) &&
|
|
33
|
+
!/(^|[\\/])tests?[\\/]/i.test(file) &&
|
|
34
|
+
!/\.(yml|yaml|toml|ini|cfg|conf|properties)$/i.test(file) &&
|
|
35
|
+
!/(^|[\\/])\.env(\..+)?$/i.test(file));
|
|
36
|
+
}
|
|
37
|
+
const isBehaviorAdding = tddTrue && hasBehaviorBlock && hasSourceFiles;
|
|
38
|
+
const missing = [];
|
|
39
|
+
if (!tddTrue)
|
|
40
|
+
missing.push('tdd="true" frontmatter absent');
|
|
41
|
+
if (!hasBehaviorBlock)
|
|
42
|
+
missing.push('<behavior> block missing or empty');
|
|
43
|
+
if (!hasSourceFiles)
|
|
44
|
+
missing.push('<files> has no non-test source file');
|
|
45
|
+
return {
|
|
46
|
+
is_behavior_adding: isBehaviorAdding,
|
|
47
|
+
checks: {
|
|
48
|
+
tdd_true: tddTrue,
|
|
49
|
+
has_behavior_block: hasBehaviorBlock,
|
|
50
|
+
has_source_files: hasSourceFiles,
|
|
51
|
+
},
|
|
52
|
+
reason: isBehaviorAdding ? null : `Not behavior-adding: ${missing.join('; ')}`,
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
function routeTaskCommand({ args, cwd, raw }) {
|
|
56
|
+
const subcommand = args[1];
|
|
57
|
+
if (subcommand !== 'is-behavior-adding') {
|
|
58
|
+
error('Unknown task subcommand. Available: is-behavior-adding', ERROR_REASON.SDK_UNKNOWN_COMMAND);
|
|
59
|
+
}
|
|
60
|
+
let content = null;
|
|
61
|
+
if (args[2] === '--task-content') {
|
|
62
|
+
content = args[3] || null;
|
|
63
|
+
}
|
|
64
|
+
else if (args[2]) {
|
|
65
|
+
const projectRoot = node_path_1.default.resolve(cwd || process.cwd());
|
|
66
|
+
const requestedPath = args[2];
|
|
67
|
+
const resolvedTaskPath = node_path_1.default.resolve(projectRoot, requestedPath);
|
|
68
|
+
const rel = node_path_1.default.relative(projectRoot, resolvedTaskPath);
|
|
69
|
+
if (rel === '..' || rel.startsWith(`..${node_path_1.default.sep}`)) {
|
|
70
|
+
error(`Task file is outside project scope: ${requestedPath}`, ERROR_REASON.USAGE);
|
|
71
|
+
}
|
|
72
|
+
if (!node_fs_1.default.existsSync(resolvedTaskPath)) {
|
|
73
|
+
error(`Task file not found: ${requestedPath}`, ERROR_REASON.USAGE);
|
|
74
|
+
}
|
|
75
|
+
content = node_fs_1.default.readFileSync(resolvedTaskPath, 'utf-8');
|
|
76
|
+
}
|
|
77
|
+
if (!content) {
|
|
78
|
+
error('Usage: task.is-behavior-adding <plan-file-path> | --task-content "<xml>"', ERROR_REASON.USAGE);
|
|
79
|
+
}
|
|
80
|
+
output(isBehaviorAddingTaskContent(content), raw, undefined);
|
|
81
|
+
}
|
|
82
|
+
module.exports = {
|
|
83
|
+
isBehaviorAddingTaskContent,
|
|
84
|
+
routeTaskCommand,
|
|
85
|
+
};
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Teams Status Module — issue #1355
|
|
4
|
+
*
|
|
5
|
+
* Read-only detector for claude-code's experimental agent-teams feature.
|
|
6
|
+
* Exposes a PURE core function (env injected, no process.env/disk inside) and
|
|
7
|
+
* a thin CLI wrapper that reuses resolveRuntime from runtime-slash.cjs.
|
|
8
|
+
*
|
|
9
|
+
* Exports:
|
|
10
|
+
* resolveTeamsStatus({ runtime, env }) → TeamsStatus
|
|
11
|
+
* cmdTeamsStatus(cwd, opts) — I/O entry point
|
|
12
|
+
*
|
|
13
|
+
* resolveTeamsStatus is PURE: env and runtime are injected, no process.env or
|
|
14
|
+
* disk access inside the function. Pass process.env explicitly at call sites.
|
|
15
|
+
*
|
|
16
|
+
* cmdTeamsStatus is the I/O handler. It reads process.env, resolves the
|
|
17
|
+
* runtime via resolveRuntime(cwd) from runtime-slash.cjs (GSD_RUNTIME →
|
|
18
|
+
* config.runtime → 'claude' precedence), then:
|
|
19
|
+
* - default: prints JSON.stringify(status) to stdout via io.output, exits 0.
|
|
20
|
+
* - --active: prints nothing, exits 0 if status.active, exit 1 otherwise.
|
|
21
|
+
*
|
|
22
|
+
* Strictly read-only — no config writes, no disk mutation.
|
|
23
|
+
*
|
|
24
|
+
* Dependencies:
|
|
25
|
+
* - ./io.cjs (output)
|
|
26
|
+
* - ./runtime-slash.cjs (resolveRuntime)
|
|
27
|
+
*/
|
|
28
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
29
|
+
exports.resolveTeamsStatus = resolveTeamsStatus;
|
|
30
|
+
exports.cmdTeamsStatus = cmdTeamsStatus;
|
|
31
|
+
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
32
|
+
const ioMod = require("./io.cjs");
|
|
33
|
+
const { output: coreOutput } = ioMod;
|
|
34
|
+
// ─── Pure core ────────────────────────────────────────────────────────────────
|
|
35
|
+
/**
|
|
36
|
+
* Resolve the agent-teams status from injected runtime and env.
|
|
37
|
+
*
|
|
38
|
+
* Strict truthiness: only '1' and 'true' (case-insensitive, trimmed) are on.
|
|
39
|
+
* '0', 'false', '', and unset are all off.
|
|
40
|
+
*
|
|
41
|
+
* @param opts.runtime The resolved runtime name (e.g. 'claude', 'codex')
|
|
42
|
+
* @param opts.env The environment map to read from (typically process.env)
|
|
43
|
+
*/
|
|
44
|
+
function resolveTeamsStatus(opts) {
|
|
45
|
+
const raw = (opts.env['CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS'] ?? '').trim().toLowerCase();
|
|
46
|
+
const envOn = raw === '1' || raw === 'true'; // strict: never '0'/'false'/'' as on
|
|
47
|
+
const isClaude = opts.runtime === 'claude';
|
|
48
|
+
const source = !isClaude ? 'off: non-claude' : (envOn ? 'on: env' : 'off: flag absent');
|
|
49
|
+
return { active: envOn && isClaude, runtime: opts.runtime, env_present: envOn, source };
|
|
50
|
+
}
|
|
51
|
+
// ─── CLI command handler ──────────────────────────────────────────────────────
|
|
52
|
+
/**
|
|
53
|
+
* Command entry point: resolve runtime via resolveRuntime(cwd), read process.env,
|
|
54
|
+
* call resolveTeamsStatus, and emit the result.
|
|
55
|
+
*
|
|
56
|
+
* @param cwd Project root directory (used by resolveRuntime for config.json)
|
|
57
|
+
* @param opts Command options
|
|
58
|
+
* @param opts.active When true: print nothing, exit 0 if active, exit 1 otherwise
|
|
59
|
+
*/
|
|
60
|
+
function cmdTeamsStatus(cwd, opts) {
|
|
61
|
+
// Resolve runtime via the canonical precedence:
|
|
62
|
+
// GSD_RUNTIME → config.runtime → 'claude'
|
|
63
|
+
// Reuses resolveRuntime from runtime-slash.cjs — no reimplementation.
|
|
64
|
+
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
65
|
+
const runtimeSlash = require('./runtime-slash.cjs');
|
|
66
|
+
const runtime = runtimeSlash.resolveRuntime(cwd);
|
|
67
|
+
const status = resolveTeamsStatus({ runtime, env: process.env });
|
|
68
|
+
if (opts.active) {
|
|
69
|
+
// --active mode: no output, exit code encodes the boolean
|
|
70
|
+
process.exit(status.active ? 0 : 1);
|
|
71
|
+
}
|
|
72
|
+
// Default: emit JSON to stdout via io.output, exit 0
|
|
73
|
+
coreOutput(status, false);
|
|
74
|
+
}
|