@opengsd/gsd-core 1.10.0 → 1.11.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/marketplace.json +1 -1
- package/.claude-plugin/plugin.json +1 -1
- package/agents/gsd-debug-session-manager.md +11 -0
- package/agents/gsd-doc-synthesizer.md +2 -4
- package/agents/gsd-executor.md +5 -5
- package/agents/gsd-mempalace-curator.md +5 -2
- package/agents/gsd-phase-researcher.md +20 -1
- package/agents/gsd-plan-checker.md +37 -0
- package/agents/gsd-planner.md +44 -46
- package/agents/gsd-user-profiler.md +3 -0
- package/agents/gsd-verifier.md +12 -3
- package/bin/install.js +841 -971
- package/bin/lib/ui-safety-gate.cjs +2 -0
- package/commands/gsd/code-review.md +1 -1
- package/commands/gsd/execute-phase.md +1 -1
- package/commands/gsd/map-codebase.md +1 -1
- package/commands/gsd/mempalace-capture.md +1 -1
- package/commands/gsd/mempalace-recall.md +1 -1
- package/commands/gsd/new-milestone.md +1 -1
- package/commands/gsd/quick.md +1 -1
- package/commands/gsd/review-backlog.md +2 -1
- package/commands/gsd/verify-work.md +1 -1
- package/gsd-core/bin/gsd-tools.cjs +469 -88
- package/gsd-core/bin/lib/active-workstream-store.cjs +138 -22
- package/gsd-core/bin/lib/agent-install-check.cjs +230 -32
- package/gsd-core/bin/lib/api-coverage.cjs +3 -5
- package/gsd-core/bin/lib/artifacts.cjs +3 -0
- package/gsd-core/bin/lib/assumption-delta.cjs +2 -4
- package/gsd-core/bin/lib/audit-command-router.cjs +9 -2
- package/gsd-core/bin/lib/audit.cjs +876 -240
- package/gsd-core/bin/lib/broken-windows.cjs +1 -1
- package/gsd-core/bin/lib/capability-consent.cjs +149 -15
- package/gsd-core/bin/lib/capability-lifecycle.cjs +45 -0
- package/gsd-core/bin/lib/capability-registry.cjs +575 -101
- package/gsd-core/bin/lib/capability-source.cjs +92 -0
- package/gsd-core/bin/lib/capability-trust.cjs +444 -25
- package/gsd-core/bin/lib/capability-validator.cjs +495 -22
- package/gsd-core/bin/lib/capability-writer.cjs +3 -2
- package/gsd-core/bin/lib/check-command-router.cjs +71 -37
- package/gsd-core/bin/lib/claude-orchestration.cjs +56 -3
- package/gsd-core/bin/lib/codex-agent-toml.cjs +329 -0
- package/gsd-core/bin/lib/command-aliases.cjs +22 -0
- package/gsd-core/bin/lib/command-roster.cjs +44 -1
- package/gsd-core/bin/lib/commands.cjs +651 -86
- package/gsd-core/bin/lib/commonjs-marker.cjs +12 -6
- package/gsd-core/bin/lib/complexity-trigger.cjs +1172 -0
- package/gsd-core/bin/lib/config-loader.cjs +75 -0
- package/gsd-core/bin/lib/config.cjs +10 -1
- package/gsd-core/bin/lib/core-utils.cjs +127 -29
- package/gsd-core/bin/lib/decisions.cjs +23 -0
- package/gsd-core/bin/lib/fallow-runner.cjs +20 -44
- package/gsd-core/bin/lib/frontmatter.cjs +155 -20
- package/gsd-core/bin/lib/gap-checker.cjs +68 -7
- package/gsd-core/bin/lib/git-base-branch.cjs +102 -0
- package/gsd-core/bin/lib/gsd2-import.cjs +10 -1
- package/gsd-core/bin/lib/health-diagnostic-rules/agent-install.cjs +101 -0
- package/gsd-core/bin/lib/health-diagnostic-rules/config-validation.cjs +348 -0
- package/gsd-core/bin/lib/health-diagnostic-rules/consistency.cjs +145 -0
- package/gsd-core/bin/lib/health-diagnostic-rules/install-surface-shadowing.cjs +98 -0
- package/gsd-core/bin/lib/health-diagnostic-rules/milestone-archive-hygiene.cjs +100 -0
- package/gsd-core/bin/lib/health-diagnostic-rules/phase-structure.cjs +222 -0
- package/gsd-core/bin/lib/health-diagnostic-rules/roadmap-disk-consistency.cjs +265 -0
- package/gsd-core/bin/lib/health-diagnostic-rules/root-existence.cjs +161 -0
- package/gsd-core/bin/lib/health-diagnostic-rules/state-consistency.cjs +303 -0
- package/gsd-core/bin/lib/health-diagnostic-rules/worktree-health.cjs +173 -0
- package/gsd-core/bin/lib/health-diagnostic-types.cjs +68 -0
- package/gsd-core/bin/lib/health-diagnostic.cjs +431 -0
- package/gsd-core/bin/lib/host-runtime-detection.cjs +134 -0
- package/gsd-core/bin/lib/init.cjs +321 -129
- package/gsd-core/bin/lib/install-effort-resolver.cjs +73 -30
- package/gsd-core/bin/lib/install-engine.cjs +745 -258
- package/gsd-core/bin/lib/install-fs-adapter.cjs +262 -0
- package/gsd-core/bin/lib/install-model-override-resolver.cjs +203 -0
- package/gsd-core/bin/lib/install-profiles.cjs +134 -57
- package/gsd-core/bin/lib/install-scope.cjs +270 -0
- package/gsd-core/bin/lib/install-shadow-report.cjs +385 -0
- package/gsd-core/bin/lib/installed-surface-resolver.cjs +381 -0
- package/gsd-core/bin/lib/installer-migrations.cjs +138 -31
- package/gsd-core/bin/lib/io.cjs +10 -0
- package/gsd-core/bin/lib/markdown-sectionizer.cjs +2 -1
- package/gsd-core/bin/lib/markdown-table.cjs +133 -20
- package/gsd-core/bin/lib/milestone-lock.cjs +248 -0
- package/gsd-core/bin/lib/milestone.cjs +754 -70
- package/gsd-core/bin/lib/model-catalog.cjs +59 -1
- package/gsd-core/bin/lib/model-resolver.cjs +183 -40
- package/gsd-core/bin/lib/normalize-test-command.cjs +1 -1
- package/gsd-core/bin/lib/pattern.cjs +122 -0
- package/gsd-core/bin/lib/phase-estimation.cjs +1 -1
- package/gsd-core/bin/lib/phase-id.cjs +444 -36
- package/gsd-core/bin/lib/phase-lifecycle.cjs +28 -3
- package/gsd-core/bin/lib/phase-locator.cjs +125 -18
- package/gsd-core/bin/lib/phase.cjs +646 -143
- package/gsd-core/bin/lib/plan-dependency-graph.cjs +72 -1
- package/gsd-core/bin/lib/plan-drift-guard.cjs +120 -0
- package/gsd-core/bin/lib/plan-scan.cjs +86 -2
- package/gsd-core/bin/lib/planning-scope.cjs +31 -0
- package/gsd-core/bin/lib/planning-snapshot.cjs +890 -0
- package/gsd-core/bin/lib/planning-workspace.cjs +56 -6
- package/gsd-core/bin/lib/probe-core.cjs +1 -1
- package/gsd-core/bin/lib/profile-output.cjs +1 -1
- package/gsd-core/bin/lib/refactor-trigger-command-router.cjs +740 -0
- package/gsd-core/bin/lib/retired-artifact-cleanup.cjs +11 -6
- package/gsd-core/bin/lib/review-lane-descriptor.cjs +13 -4
- package/gsd-core/bin/lib/review-lane-invocation.cjs +30 -0
- package/gsd-core/bin/lib/review-lane-runner.cjs +421 -66
- package/gsd-core/bin/lib/review-reviewer-selection.cjs +13 -18
- package/gsd-core/bin/lib/roadmap-command-router.cjs +34 -0
- package/gsd-core/bin/lib/roadmap-parser.cjs +943 -184
- package/gsd-core/bin/lib/roadmap-upgrade.cjs +37 -10
- package/gsd-core/bin/lib/roadmap.cjs +385 -94
- package/gsd-core/bin/lib/runtime-artifact-conversion.cjs +608 -46
- package/gsd-core/bin/lib/runtime-artifact-install-plan.cjs +14 -2
- package/gsd-core/bin/lib/runtime-artifact-layout.cjs +426 -55
- package/gsd-core/bin/lib/runtime-config-adapter-registry.cjs +3 -2
- package/gsd-core/bin/lib/runtime-homes.cjs +69 -3
- package/gsd-core/bin/lib/runtime-hooks-surface.cjs +115 -3
- package/gsd-core/bin/lib/runtime-name-policy.cjs +3 -1
- package/gsd-core/bin/lib/runtime-slash.cjs +27 -9
- package/gsd-core/bin/lib/security.cjs +104 -5
- package/gsd-core/bin/lib/shell-command-projection.cjs +275 -3
- package/gsd-core/bin/lib/smart-entry.cjs +142 -22
- package/gsd-core/bin/lib/state-command-router.cjs +5 -1
- package/gsd-core/bin/lib/state-document.cjs +152 -8
- package/gsd-core/bin/lib/state-transition.cjs +371 -117
- package/gsd-core/bin/lib/state.cjs +1794 -357
- package/gsd-core/bin/lib/surface.cjs +23 -9
- package/gsd-core/bin/lib/text-lines.cjs +80 -0
- package/gsd-core/bin/lib/token-scanner.cjs +76 -0
- package/gsd-core/bin/lib/uat-predicate.cjs +9 -3
- package/gsd-core/bin/lib/uat.cjs +399 -56
- package/gsd-core/bin/lib/ui-frontend-evidence.cjs +157 -0
- package/gsd-core/bin/lib/ui-safety-gate.cjs +14 -5
- package/gsd-core/bin/lib/unusable-input.cjs +24 -0
- package/gsd-core/bin/lib/update-context.cjs +8 -2
- package/gsd-core/bin/lib/user-artifact-staging.cjs +705 -0
- package/gsd-core/bin/lib/validate.cjs +20 -6
- package/gsd-core/bin/lib/vendor/README.md +37 -0
- package/gsd-core/bin/lib/vendor/re2js.cjs +6480 -0
- package/gsd-core/bin/lib/vendor/re2js.d.cts +938 -0
- package/gsd-core/bin/lib/verification-command-router.cjs +2 -1
- package/gsd-core/bin/lib/verification.cjs +258 -8
- package/gsd-core/bin/lib/verify.cjs +368 -888
- package/gsd-core/bin/lib/workstream-inventory-builder.cjs +53 -32
- package/gsd-core/bin/lib/workstream-inventory.cjs +63 -10
- package/gsd-core/bin/lib/workstream.cjs +2 -2
- package/gsd-core/bin/lib/worktree-safety.cjs +176 -9
- package/gsd-core/bin/shared/config-defaults.manifest.json +1 -0
- package/gsd-core/bin/shared/config-schema.manifest.json +7 -1
- package/gsd-core/references/agent-contracts.md +43 -26
- package/gsd-core/references/checkpoints.md +2 -2
- package/gsd-core/references/context-budget.md +1 -1
- package/gsd-core/references/dispatch-isolation-gate.md +138 -0
- package/gsd-core/references/doc-conflict-engine.md +1 -1
- package/gsd-core/references/execute-mvp-tdd.md +3 -3
- package/gsd-core/references/execute-phase-between-wave-reset.md +6 -2
- package/gsd-core/references/execute-phase-context-guard.md +1 -1
- package/gsd-core/references/execute-phase-response-language.md +1 -1
- package/gsd-core/references/execute-phase-wave-guard.md +6 -2
- package/gsd-core/references/gate-prompts.md +1 -1
- package/gsd-core/references/git-planning-commit.md +2 -1
- package/gsd-core/references/loop-hook-dispatch.md +39 -2
- package/gsd-core/references/model-profiles.md +12 -4
- package/gsd-core/references/mvp-concepts.md +9 -9
- package/gsd-core/references/planner-guidance.md +3 -9
- package/gsd-core/references/planner-preconditions.md +1 -1
- package/gsd-core/references/planner-reviews.md +1 -1
- package/gsd-core/references/planning-config.md +8 -6
- package/gsd-core/references/revision-loop.md +1 -1
- package/gsd-core/references/specless-probe-fallback.md +1 -1
- package/gsd-core/references/universal-anti-patterns.md +3 -3
- package/gsd-core/references/verifier-phase-gates.md +192 -0
- package/gsd-core/references/verify-mvp-mode.md +1 -1
- package/gsd-core/references/workstream-flag.md +22 -6
- package/gsd-core/templates/discussion-log.md +1 -1
- package/gsd-core/templates/phase-prompt.md +2 -4
- package/gsd-core/templates/state.md +4 -4
- package/gsd-core/templates/verification-report.md +9 -1
- package/gsd-core/workflows/ai-integration-phase.md +9 -11
- package/gsd-core/workflows/autonomous.md +1 -1
- package/gsd-core/workflows/cleanup.md +62 -3
- package/gsd-core/workflows/code-review/steps/structural-pre-pass.md +13 -3
- package/gsd-core/workflows/code-review-fix.md +37 -10
- package/gsd-core/workflows/code-review.md +38 -12
- package/gsd-core/workflows/complete-milestone.md +141 -18
- package/gsd-core/workflows/debug.md +7 -5
- package/gsd-core/workflows/diagnose-issues.md +35 -9
- package/gsd-core/workflows/discuss-phase/modes/chain.md +2 -1
- package/gsd-core/workflows/discuss-phase/modes/default.md +1 -1
- package/gsd-core/workflows/discuss-phase-assumptions.md +2 -1
- package/gsd-core/workflows/edit-phase.md +26 -1
- package/gsd-core/workflows/eval-review.md +3 -5
- package/gsd-core/workflows/execute-phase/steps/executor-isolation-dispatch.md +31 -6
- package/gsd-core/workflows/execute-phase/steps/per-plan-executor-routing.md +77 -0
- package/gsd-core/workflows/execute-phase/steps/per-plan-worktree-gate.md +2 -0
- package/gsd-core/workflows/execute-phase.md +38 -50
- package/gsd-core/workflows/execute-plan.md +36 -4
- package/gsd-core/workflows/explore.md +131 -4
- package/gsd-core/workflows/fast.md +10 -2
- package/gsd-core/workflows/health.md +73 -4
- package/gsd-core/workflows/import.md +4 -4
- package/gsd-core/workflows/ingest-docs.md +5 -5
- package/gsd-core/workflows/mvp-phase.md +6 -3
- package/gsd-core/workflows/new-milestone.md +14 -9
- package/gsd-core/workflows/new-project.md +14 -14
- package/gsd-core/workflows/next.md +12 -0
- package/gsd-core/workflows/plan-phase.md +41 -17
- package/gsd-core/workflows/plan-review-convergence.md +50 -2
- package/gsd-core/workflows/progress.md +34 -6
- package/gsd-core/workflows/quick/steps/plan-checker-loop.md +4 -4
- package/gsd-core/workflows/quick/steps/quick-verification.md +27 -6
- package/gsd-core/workflows/quick/steps/research-phase.md +2 -2
- package/gsd-core/workflows/quick.md +35 -15
- package/gsd-core/workflows/review.md +26 -5
- package/gsd-core/workflows/secure-phase.md +1 -1
- package/gsd-core/workflows/session-report.md +2 -1
- package/gsd-core/workflows/settings.md +66 -2
- package/gsd-core/workflows/ship.md +104 -44
- package/gsd-core/workflows/spec-phase.md +30 -12
- package/gsd-core/workflows/sync-skills.md +63 -8
- package/gsd-core/workflows/transition.md +46 -11
- package/gsd-core/workflows/ui-phase.md +5 -5
- package/gsd-core/workflows/ui-review.md +2 -2
- package/gsd-core/workflows/update.md +1 -1
- package/gsd-core/workflows/validate-phase.md +1 -1
- package/gsd-core/workflows/verify-work.md +9 -7
- package/hooks/dist/gsd-agent-isolation-guard.js +103 -14
- package/hooks/dist/gsd-check-update-worker.js +56 -13
- package/hooks/dist/gsd-check-update.js +19 -1
- package/hooks/dist/gsd-cursor-pre-tool.js +0 -3
- package/hooks/dist/gsd-cursor-subagent-start.js +77 -2
- package/hooks/dist/gsd-cursor-subagent-stop.js +3 -2
- package/hooks/dist/gsd-prompt-guard.js +21 -20
- package/hooks/dist/gsd-read-injection-scanner.js +38 -24
- package/hooks/dist/gsd-statusline.js +18 -0
- package/hooks/dist/gsd-update-banner.js +22 -1
- package/hooks/dist/gsd-workflow-guard.js +134 -36
- package/hooks/dist/lib/git-cmd.js +92 -59
- package/hooks/dist/lib/injection-patterns.js +45 -0
- package/hooks/dist/lib/isolation-deny-reason.js +39 -0
- package/hooks/dist/lib/isolation-sentinel.js +9 -0
- package/hooks/gsd-agent-isolation-guard.js +103 -14
- package/hooks/gsd-check-update-worker.js +56 -13
- package/hooks/gsd-check-update.js +19 -1
- package/hooks/gsd-cursor-pre-tool.js +0 -3
- package/hooks/gsd-cursor-subagent-start.js +77 -2
- package/hooks/gsd-cursor-subagent-stop.js +3 -2
- package/hooks/gsd-prompt-guard.js +21 -20
- package/hooks/gsd-read-injection-scanner.js +38 -24
- package/hooks/gsd-statusline.js +18 -0
- package/hooks/gsd-update-banner.js +22 -1
- package/hooks/gsd-workflow-guard.js +134 -36
- package/hooks/lib/git-cmd.js +92 -59
- package/hooks/lib/injection-patterns.js +45 -0
- package/hooks/lib/isolation-deny-reason.js +39 -0
- package/hooks/lib/isolation-sentinel.js +9 -0
- package/package.json +21 -9
- package/pi/gsd.cjs +19 -5
- package/scripts/baselines/planning-prompt-drift-baseline.json +4 -0
- package/scripts/baselines/planning-snapshot-bypass-baseline.json +12 -0
- package/scripts/baselines/unreachable-guard-drift-baseline.json +4 -0
- package/scripts/changeset/lint.cjs +60 -5
- package/scripts/check-alias-drift.cjs +7 -43
- package/scripts/check-contract-drift.cjs +297 -0
- package/scripts/ci-test-scope.cjs +19 -2
- package/scripts/command-contract-helpers.cjs +903 -1
- package/scripts/gen-adr-index.cjs +728 -38
- package/scripts/gen-capability-registry.cjs +3 -15
- package/scripts/gen-context-index.cjs +2 -11
- package/scripts/gen-health-docs.cjs +390 -0
- package/scripts/gen-inventory-manifest.cjs +50 -4
- package/scripts/gen-loop-host-contract.cjs +4 -24
- package/scripts/gen-registry.cjs +3 -14
- package/scripts/lib/alias-drift-families.cjs +46 -0
- package/scripts/lib/drift-scan.cjs +278 -0
- package/scripts/lint-allow-test-rule-refs.allowlist.json +1 -26
- package/scripts/lint-allow-test-rule-refs.effective-ceiling.json +4 -0
- package/scripts/lint-allow-test-rule-refs.unverified-ceiling.json +3 -0
- package/scripts/lint-canary-version-leak.cjs +73 -0
- package/scripts/lint-command-contract.cjs +96 -13
- package/scripts/lint-completion-predicate-drift.cjs +933 -0
- package/scripts/lint-completion-ratio-drift.cjs +214 -0
- package/scripts/lint-default-flip-documentation.cjs +193 -0
- package/scripts/lint-eslint-glob-coverage.allowlist.json +34 -0
- package/scripts/lint-eslint-glob-coverage.cjs +340 -0
- package/scripts/lint-frontmatter-scalar-broad-grep.cjs +237 -0
- package/scripts/lint-health-diagnostic-rule-table.cjs +404 -0
- package/scripts/lint-hooks-runtime-build-seam.cjs +262 -0
- package/scripts/lint-milestone-window-drift.cjs +468 -0
- package/scripts/lint-phase-enumeration-drift.cjs +479 -0
- package/scripts/lint-plan-count-drift.cjs +318 -0
- package/scripts/lint-planning-artifact-writer-drift.cjs +398 -0
- package/scripts/lint-planning-prompt-drift.cjs +434 -0
- package/scripts/lint-planning-snapshot-bypass-drift.cjs +544 -0
- package/scripts/lint-regression-test-names.cjs +15 -13
- package/scripts/lint-removed-but-needed.cjs +320 -0
- package/scripts/lint-state-field-drift.cjs +805 -0
- package/scripts/lint-state-write-path-drift.cjs +1045 -0
- package/scripts/lint-test-file-count.allowlist.json +21 -10
- package/scripts/lint-unreachable-guard-drift.cjs +843 -0
- package/scripts/lint-vendored-deps.cjs +124 -0
- package/scripts/pr-changed-files.cjs +63 -0
- package/scripts/pr-template-policy.cjs +14 -4
- package/scripts/prompt-injection-scan.sh +25 -0
- package/scripts/require-issue-link-policy.cjs +192 -0
- package/scripts/state-write-path-drift-baseline.json +19 -0
- package/scripts/sync-runtime-launcher.cjs +2 -4
- package/skills/gsd-autonomous/SKILL.md +0 -1
- package/skills/gsd-code-review/SKILL.md +1 -1
- package/skills/gsd-execute-phase/SKILL.md +1 -2
- package/skills/gsd-map-codebase/SKILL.md +1 -1
- package/skills/gsd-mempalace-capture/SKILL.md +1 -1
- package/skills/gsd-mempalace-recall/SKILL.md +1 -1
- package/skills/gsd-new-milestone/SKILL.md +1 -1
- package/skills/gsd-next/SKILL.md +0 -1
- package/skills/gsd-plan-phase/SKILL.md +0 -1
- package/skills/gsd-progress/SKILL.md +0 -1
- package/skills/gsd-quick/SKILL.md +1 -1
- package/skills/gsd-review-backlog/SKILL.md +2 -1
- package/skills/gsd-stats/SKILL.md +0 -1
- package/skills/gsd-verify-work/SKILL.md +1 -1
- package/vscode/package.json +1 -1
- package/gsd-core/workflows/discovery-phase.md +0 -298
- package/gsd-core/workflows/plan-milestone-gaps.md +0 -281
- package/gsd-core/workflows/verify-phase.md +0 -574
- package/scripts/affected-tests-lib.cjs +0 -554
- package/scripts/lint-allow-test-rule-refs.cjs +0 -162
- package/scripts/run-affected-tests.cjs +0 -7
- package/scripts/run-tests.cjs +0 -1051
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
*
|
|
13
13
|
* Dependencies (leaf modules only — no loadConfig):
|
|
14
14
|
* - node:fs / node:path (stdlib)
|
|
15
|
-
* - ./phase-id.cjs (normalizePhaseName,
|
|
15
|
+
* - ./phase-id.cjs (normalizePhaseName, matchPhaseDirs, phaseNumberForMatch)
|
|
16
16
|
* - ./core-utils.cjs (readSubdirectories, getPhaseFileStats, extractCanonicalPlanId, toPosixPath)
|
|
17
17
|
* - ./planning-workspace.cjs (planningDir)
|
|
18
18
|
*/
|
|
@@ -23,10 +23,10 @@ const node_fs_1 = __importDefault(require("node:fs"));
|
|
|
23
23
|
const node_path_1 = __importDefault(require("node:path"));
|
|
24
24
|
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
25
25
|
const phaseIdModule = require("./phase-id.cjs");
|
|
26
|
-
const { normalizePhaseName,
|
|
26
|
+
const { normalizePhaseName, matchPhaseDirs, phaseNumberForMatch, isSentinelPhaseId, comparePhaseNum } = phaseIdModule;
|
|
27
27
|
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
28
28
|
const coreUtilsModule = require("./core-utils.cjs");
|
|
29
|
-
const { readSubdirectories, getPhaseFileStats, extractCanonicalPlanId, toPosixPath } = coreUtilsModule;
|
|
29
|
+
const { readSubdirectories, getPhaseFileStats, extractCanonicalPlanId, toPosixPath, findUnsummarizedPlans } = coreUtilsModule;
|
|
30
30
|
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
31
31
|
const planningWorkspace = require("./planning-workspace.cjs");
|
|
32
32
|
const { planningDir } = planningWorkspace;
|
|
@@ -36,6 +36,12 @@ const { extractFrontmatter } = frontmatterModule;
|
|
|
36
36
|
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
37
37
|
const planDependencyGraphModule = require("./plan-dependency-graph.cjs");
|
|
38
38
|
const { computeHaltPropagation, buildSummaryFileIndex, isSummaryFileHalted } = planDependencyGraphModule;
|
|
39
|
+
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
40
|
+
const roadmapParserModule = require("./roadmap-parser.cjs");
|
|
41
|
+
const { getMilestonePhaseFilter } = roadmapParserModule;
|
|
42
|
+
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
43
|
+
const planningScopeMod = require("./planning-scope.cjs");
|
|
44
|
+
const { SCOPE } = planningScopeMod;
|
|
39
45
|
/**
|
|
40
46
|
* #2830: parse a plan file's `depends_on` frontmatter. Returns [] — never
|
|
41
47
|
* throws — on a missing/unreadable/malformed plan or absent field, matching
|
|
@@ -68,9 +74,27 @@ function parsePlanDependsOn(phaseDir, planFile) {
|
|
|
68
74
|
* exactly the shape that let the original #2855 bug (hardcoded root path)
|
|
69
75
|
* exist in one copy and not the other. Sharing this seam means a future
|
|
70
76
|
* change to how the archive tree is located only needs to happen once.
|
|
71
|
-
* Most-recent-milestone-first order
|
|
77
|
+
* Most-recent-milestone-first order, compared numerically segment-by-segment
|
|
78
|
+
* on the version (e.g. `v1.10` before `v1.9`) — NOT lexicographically. A
|
|
79
|
+
* lexicographic `.sort().reverse()` (the prior implementation) ranks `v1.9`
|
|
80
|
+
* ahead of `v1.10` because the string `"1.9"` sorts after `"1.10"`; that is
|
|
81
|
+
* deterministic but wrong for every double-digit-or-higher minor/patch
|
|
82
|
+
* version, and #3458 is what first surfaces archived phases in audit output
|
|
83
|
+
* where the misordering becomes user-visible.
|
|
72
84
|
* Never throws: an absent/unreadable milestones/ dir yields [].
|
|
73
85
|
*/
|
|
86
|
+
function compareArchiveVersionDesc(aName, bName) {
|
|
87
|
+
const aParts = (aName.match(/^v([\d.]+)-phases$/)?.[1] ?? '').split('.').map(Number);
|
|
88
|
+
const bParts = (bName.match(/^v([\d.]+)-phases$/)?.[1] ?? '').split('.').map(Number);
|
|
89
|
+
const len = Math.max(aParts.length, bParts.length);
|
|
90
|
+
for (let i = 0; i < len; i++) {
|
|
91
|
+
const a = aParts[i] ?? 0;
|
|
92
|
+
const b = bParts[i] ?? 0;
|
|
93
|
+
if (a !== b)
|
|
94
|
+
return b - a; // descending: newest (numerically largest) first
|
|
95
|
+
}
|
|
96
|
+
return 0;
|
|
97
|
+
}
|
|
74
98
|
function listArchiveVersionDirs(cwd) {
|
|
75
99
|
const milestonesDir = node_path_1.default.join(planningDir(cwd), 'milestones');
|
|
76
100
|
if (!node_fs_1.default.existsSync(milestonesDir))
|
|
@@ -80,8 +104,7 @@ function listArchiveVersionDirs(cwd) {
|
|
|
80
104
|
return milestoneEntries
|
|
81
105
|
.filter(e => e.isDirectory() && /^v[\d.]+-phases$/.test(e.name))
|
|
82
106
|
.map(e => e.name)
|
|
83
|
-
.sort()
|
|
84
|
-
.reverse()
|
|
107
|
+
.sort(compareArchiveVersionDesc)
|
|
85
108
|
.map(archiveName => ({
|
|
86
109
|
version: archiveName.match(/^(v[\d.]+)-phases$/)[1],
|
|
87
110
|
archivePath: node_path_1.default.join(milestonesDir, archiveName),
|
|
@@ -94,7 +117,10 @@ function listArchiveVersionDirs(cwd) {
|
|
|
94
117
|
function searchPhaseInDir(baseDir, relBase, normalized) {
|
|
95
118
|
try {
|
|
96
119
|
const dirs = readSubdirectories(baseDir, true);
|
|
97
|
-
|
|
120
|
+
// #2528: canonical two-pass selection (exact token match, then the
|
|
121
|
+
// bare-integer leading-digit-run fallback) shared with the find-phase and
|
|
122
|
+
// phase-plan-index scans — see phase-id.cts::matchPhaseDirs.
|
|
123
|
+
const { matches, usedBareFallback } = matchPhaseDirs(dirs, normalized);
|
|
98
124
|
if (matches.length === 0)
|
|
99
125
|
return null;
|
|
100
126
|
// #2237: fail loud when multiple directories match the same bare phase
|
|
@@ -121,7 +147,7 @@ function searchPhaseInDir(baseDir, relBase, normalized) {
|
|
|
121
147
|
};
|
|
122
148
|
}
|
|
123
149
|
const match = matches[0];
|
|
124
|
-
const phaseToken =
|
|
150
|
+
const phaseToken = phaseNumberForMatch(match, usedBareFallback);
|
|
125
151
|
const phaseNumber = phaseToken || normalized;
|
|
126
152
|
const afterToken = match.slice(phaseToken ? phaseToken.length : 0).replace(/^-/, '');
|
|
127
153
|
const phaseName = afterToken || null;
|
|
@@ -129,16 +155,13 @@ function searchPhaseInDir(baseDir, relBase, normalized) {
|
|
|
129
155
|
const { plans: unsortedPlans, summaries: unsortedSummaries, hasResearch, hasContext, hasVerification, hasReviews } = getPhaseFileStats(phaseDir);
|
|
130
156
|
const plans = unsortedPlans.sort();
|
|
131
157
|
const summaries = unsortedSummaries.sort();
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
const canonical = extractCanonicalPlanId(p);
|
|
140
|
-
return !completedPlanIds.has(planId) && !completedPlanIds.has(canonical);
|
|
141
|
-
});
|
|
158
|
+
// #3183 (ADR-3180 Decision 2): the summary→plan pairing used to be a
|
|
159
|
+
// bespoke rule local to this function (a third pairing rule alongside
|
|
160
|
+
// scanPhasePlans's completion check and countMatchedSummaries). Routed
|
|
161
|
+
// through the canonical core-utils.findUnsummarizedPlans instead, which
|
|
162
|
+
// shares its `summaryCandidates` matching rule with countMatchedSummaries
|
|
163
|
+
// so the count and this named list can never disagree.
|
|
164
|
+
const incompletePlans = findUnsummarizedPlans(plans, summaries);
|
|
142
165
|
// #2830: reverse lookup from a completed plan's id (exact or canonical) to
|
|
143
166
|
// its actual summary filename. Shared builder (also used by phase.cts's
|
|
144
167
|
// cmdPhasePlanIndex) so the two can never disagree about which summary
|
|
@@ -233,6 +256,89 @@ function findPhaseInternal(cwd, phase) {
|
|
|
233
256
|
}
|
|
234
257
|
return null;
|
|
235
258
|
}
|
|
259
|
+
/**
|
|
260
|
+
* #3185 (epic #3180 Phase 3, ADR-3180 Decision 1 row "Phase enumeration"):
|
|
261
|
+
* the SINGLE canonical owner of "which phase directories belong to the current
|
|
262
|
+
* milestone". Applies the milestone window AND the sentinel filter, in that
|
|
263
|
+
* order, and returns the surviving directory names.
|
|
264
|
+
*
|
|
265
|
+
* Before this existed the derivation had four independent implementations and
|
|
266
|
+
* only `cmdRoadmapAnalyze` carried both halves; `cmdProgressRender`,
|
|
267
|
+
* `cmdStats` and `cmdPhasesList` each carried neither or one.
|
|
268
|
+
*
|
|
269
|
+
* TWO THINGS THIS GETS RIGHT THAT A HEADING-SIDE FILTER CANNOT:
|
|
270
|
+
*
|
|
271
|
+
* 1. The sentinel test runs against DIRECTORY NAMES and is UNCONDITIONAL.
|
|
272
|
+
* `getMilestonePhaseFilter` excludes sentinels from its ROADMAP HEADING
|
|
273
|
+
* set, but when that set is empty it degrades to a literal `() => true`
|
|
274
|
+
* pass-all predicate and never consults the heading set at all — so its
|
|
275
|
+
* own sentinel exclusion becomes unreachable exactly when it is needed,
|
|
276
|
+
* and every directory on disk (backlog included) is reported as a
|
|
277
|
+
* current-milestone phase. That degrade is the #3167 symptom path.
|
|
278
|
+
*
|
|
279
|
+
* 2. The sentinel predicate is the canonical `isSentinelPhaseId`
|
|
280
|
+
* (`src/phase-id.cts`, SENTINEL_RANGES [0, 999]), not a local literal.
|
|
281
|
+
* The rule had five copies and three different regexes before this phase,
|
|
282
|
+
* and they disagreed about Phase 0.
|
|
283
|
+
*
|
|
284
|
+
* The pass-all degrade is narrowed MINIMALLY: it stays over-inclusive for
|
|
285
|
+
* non-sentinel directories, so a project whose window declares no phases
|
|
286
|
+
* still sees its real phase directories. Only sentinels are refused.
|
|
287
|
+
*
|
|
288
|
+
* `scope` distinguishes a REAL empty from a NON-answer (ADR-3180 Decision 2):
|
|
289
|
+
* an absent `phasesDir` is a real empty (a new project genuinely has no
|
|
290
|
+
* phases) and inherits the window's scope, whereas a `phasesDir` that exists
|
|
291
|
+
* but cannot be read is UNREADABLE.
|
|
292
|
+
*
|
|
293
|
+
* `opts.ws` is tri-state, matching `planningDir`'s own contract: `undefined`
|
|
294
|
+
* (the default — do not pass `ws` at all) resolves the AMBIENT workstream
|
|
295
|
+
* from `GSD_WORKSTREAM`; `null` FORCES the project root regardless of any
|
|
296
|
+
* ambient workstream; a string forces that specific workstream.
|
|
297
|
+
*/
|
|
298
|
+
function listMilestonePhaseDirs(phasesDir, opts = {}) {
|
|
299
|
+
// #3597: `ws` must default to `undefined`, NOT `null`. `undefined` means
|
|
300
|
+
// "resolve the ambient workstream" (mirrors planningDir's own contract,
|
|
301
|
+
// src/planning-workspace.cts:124); `null` means "force the project root".
|
|
302
|
+
// Every cwd-bearing caller derives `phasesDir` ambiently (planningPaths(cwd)
|
|
303
|
+
// / planningDir(cwd) with no explicit ws), so defaulting `ws` to `null` here
|
|
304
|
+
// forced the milestone WINDOW to the root ROADMAP while the caller's
|
|
305
|
+
// `phasesDir` stayed workstream-scoped — numerator and denominator drawn
|
|
306
|
+
// from different scoped sets (ADR-3180 §7.6 rule 3 violation). That is what
|
|
307
|
+
// made `--ws <name> progress` read `phase_scope: "unreadable"` and withhold
|
|
308
|
+
// `percent` once `workstream create` migrated the root ROADMAP away.
|
|
309
|
+
const { cwd, ws, versionOverride = null, phaseIdConvention = null } = opts;
|
|
310
|
+
// Without a cwd there is nothing to scope AGAINST — the caller asked for an
|
|
311
|
+
// unscoped read, which is a real answer (mirrors extractCurrentMilestoneScoped's
|
|
312
|
+
// row 1). Sentinels are still refused: they are never milestone phases.
|
|
313
|
+
let inWindow = () => true;
|
|
314
|
+
let scope = SCOPE.COMPLETE;
|
|
315
|
+
if (cwd) {
|
|
316
|
+
const filter = getMilestonePhaseFilter(cwd, versionOverride, phaseIdConvention, ws);
|
|
317
|
+
inWindow = filter;
|
|
318
|
+
scope = filter.scope;
|
|
319
|
+
}
|
|
320
|
+
// An ABSENT phases dir is a real empty, not a failure: a freshly-created
|
|
321
|
+
// project genuinely has no phase directories yet. Distinguishing this from
|
|
322
|
+
// the unreadable case below is the whole point of the scope discriminator.
|
|
323
|
+
if (!node_fs_1.default.existsSync(phasesDir))
|
|
324
|
+
return { value: [], scope };
|
|
325
|
+
let names;
|
|
326
|
+
try {
|
|
327
|
+
names = node_fs_1.default.readdirSync(phasesDir, { withFileTypes: true })
|
|
328
|
+
.filter((e) => e.isDirectory())
|
|
329
|
+
.map((e) => e.name);
|
|
330
|
+
}
|
|
331
|
+
catch {
|
|
332
|
+
// The directory EXISTS but could not be read (EACCES/EIO). An empty list
|
|
333
|
+
// here is a NON-answer and must not be reported as "this milestone has no
|
|
334
|
+
// phases" — that collapse is the defect class this epic removes.
|
|
335
|
+
return { value: [], scope: SCOPE.UNREADABLE };
|
|
336
|
+
}
|
|
337
|
+
const value = names
|
|
338
|
+
.filter((name) => inWindow(name) && !isSentinelPhaseId(name, phaseIdConvention ?? undefined))
|
|
339
|
+
.sort((a, b) => comparePhaseNum(a, b));
|
|
340
|
+
return { value, scope };
|
|
341
|
+
}
|
|
236
342
|
function getArchivedPhaseDirs(cwd) {
|
|
237
343
|
// #2855: same workstream-scoped resolution as findPhaseInternal above, via
|
|
238
344
|
// the shared listArchiveVersionDirs helper. `phase.list --include-archived`
|
|
@@ -256,4 +362,5 @@ module.exports = {
|
|
|
256
362
|
searchPhaseInDir,
|
|
257
363
|
findPhaseInternal,
|
|
258
364
|
getArchivedPhaseDirs,
|
|
365
|
+
listMilestonePhaseDirs,
|
|
259
366
|
};
|