@opengsd/gsd-core 1.18.0 → 1.20.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 +2 -1
- package/.opencode/plugins/gsd-core.js +2 -3
- package/agents/gsd-code-fixer.compact.md +7 -7
- package/agents/gsd-code-fixer.md +13 -7
- package/agents/gsd-code-reviewer.compact.md +49 -8
- package/agents/gsd-code-reviewer.md +53 -14
- package/agents/gsd-executor.md +8 -4
- package/agents/gsd-verifier.md +1 -1
- package/bin/install.js +422 -103
- package/commands/gsd/update.md +5 -2
- package/gsd-core/bin/gsd-tools.cjs +179 -30
- package/gsd-core/bin/lib/agent-install-check.cjs +29 -3
- package/gsd-core/bin/lib/args-terminator.cjs +114 -0
- package/gsd-core/bin/lib/broken-windows.cjs +59 -1
- package/gsd-core/bin/lib/capability-lifecycle.cjs +1 -12
- package/gsd-core/bin/lib/capability-lock.cjs +13 -2
- package/gsd-core/bin/lib/capability-registry.cjs +376 -103
- package/gsd-core/bin/lib/capability-state.cjs +14 -8
- package/gsd-core/bin/lib/capability-validator.cjs +32 -0
- package/gsd-core/bin/lib/commands.cjs +27 -17
- package/gsd-core/bin/lib/config-loader.cjs +13 -3
- package/gsd-core/bin/lib/config.cjs +256 -58
- package/gsd-core/bin/lib/core-utils.cjs +45 -0
- package/gsd-core/bin/lib/decision-coverage-support.cjs +74 -0
- package/gsd-core/bin/lib/frontmatter.cjs +21 -3
- package/gsd-core/bin/lib/gate-api-coverage-verify-pre.cjs +2 -2
- package/gsd-core/bin/lib/gate-context-drift.cjs +9 -4
- package/gsd-core/bin/lib/gate-decision-coverage-plan.cjs +6 -1
- package/gsd-core/bin/lib/gate-decision-coverage-verify.cjs +6 -1
- package/gsd-core/bin/lib/gate-evaluation-scope.cjs +134 -13
- package/gsd-core/bin/lib/gate-phase-context.cjs +7 -8
- package/gsd-core/bin/lib/gate-schema-drift.cjs +1 -1
- package/gsd-core/bin/lib/gate-tdd-review-checkpoint.cjs +63 -22
- package/gsd-core/bin/lib/gate-ui-safety.cjs +23 -5
- package/gsd-core/bin/lib/git-info-exclude.cjs +52 -0
- package/gsd-core/bin/lib/health-diagnostic-rules/phase-structure.cjs +31 -12
- package/gsd-core/bin/lib/health-diagnostic-rules/roadmap-disk-consistency.cjs +9 -7
- package/gsd-core/bin/lib/health-diagnostic-rules/state-consistency.cjs +3 -3
- package/gsd-core/bin/lib/health-diagnostic-types.cjs +4 -0
- package/gsd-core/bin/lib/health-diagnostic.cjs +52 -1
- package/gsd-core/bin/lib/host-integration.cjs +13 -6
- package/gsd-core/bin/lib/init.cjs +245 -68
- package/gsd-core/bin/lib/install-engine.cjs +246 -32
- package/gsd-core/bin/lib/install-profiles.cjs +9 -4
- package/gsd-core/bin/lib/installer-migration-report.cjs +2 -0
- package/gsd-core/bin/lib/io.cjs +6 -0
- package/gsd-core/bin/lib/markdown-line-diff.cjs +147 -0
- package/gsd-core/bin/lib/markdown-sectionizer.cjs +147 -1
- package/gsd-core/bin/lib/markdown-table.cjs +23 -0
- package/gsd-core/bin/lib/mcp-server.cjs +8 -5
- package/gsd-core/bin/lib/milestone-lock.cjs +8 -1
- package/gsd-core/bin/lib/milestone-release-map.cjs +244 -0
- package/gsd-core/bin/lib/milestone-release-tags.cjs +440 -0
- package/gsd-core/bin/lib/milestone.cjs +61 -51
- package/gsd-core/bin/lib/model-catalog.cjs +8 -0
- package/gsd-core/bin/lib/normalize-test-command.cjs +67 -0
- package/gsd-core/bin/lib/phase-entry-grammar.cjs +119 -0
- package/gsd-core/bin/lib/phase-id-display.cjs +2 -0
- package/gsd-core/bin/lib/phase-id.cjs +629 -38
- package/gsd-core/bin/lib/phase-lifecycle.cjs +12 -44
- package/gsd-core/bin/lib/phase-locator.cjs +328 -19
- package/gsd-core/bin/lib/phase.cjs +3066 -653
- package/gsd-core/bin/lib/planning-document.cjs +26 -5
- package/gsd-core/bin/lib/planning-inspect.cjs +27 -35
- package/gsd-core/bin/lib/planning-snapshot.cjs +15 -8
- package/gsd-core/bin/lib/planning-workspace.cjs +21 -3
- package/gsd-core/bin/lib/pristine-baseline.cjs +11 -3
- package/gsd-core/bin/lib/read-only-git-env.cjs +79 -0
- package/gsd-core/bin/lib/refactor-trigger-command-router.cjs +2 -2
- package/gsd-core/bin/lib/review-lane-descriptor.cjs +57 -2
- package/gsd-core/bin/lib/review-lane-invocation.cjs +125 -18
- package/gsd-core/bin/lib/review-lane-runner.cjs +33 -4
- package/gsd-core/bin/lib/reviewer-step-dispatch.cjs +11 -9
- package/gsd-core/bin/lib/roadmap-parser.cjs +735 -137
- package/gsd-core/bin/lib/roadmap-progress.cjs +136 -0
- package/gsd-core/bin/lib/roadmap-upgrade.cjs +47 -7
- package/gsd-core/bin/lib/roadmap.cjs +383 -123
- package/gsd-core/bin/lib/runtime-artifact-conversion.cjs +381 -14
- package/gsd-core/bin/lib/runtime-artifact-layout.cjs +8 -4
- package/gsd-core/bin/lib/runtime-hooks-surface.cjs +60 -16
- package/gsd-core/bin/lib/shell-command-projection.cjs +151 -19
- package/gsd-core/bin/lib/smart-entry.cjs +35 -11
- package/gsd-core/bin/lib/state-contract.cjs +39 -15
- package/gsd-core/bin/lib/state-document.cjs +344 -27
- package/gsd-core/bin/lib/state-transition.cjs +156 -32
- package/gsd-core/bin/lib/state.cjs +527 -186
- package/gsd-core/bin/lib/surface.cjs +9 -0
- package/gsd-core/bin/lib/task-command-router.cjs +5 -25
- package/gsd-core/bin/lib/task-content-resolution.cjs +46 -1
- package/gsd-core/bin/lib/template.cjs +2 -2
- package/gsd-core/bin/lib/validate.cjs +3 -2
- package/gsd-core/bin/lib/vendor/re2js.cjs +863 -577
- package/gsd-core/bin/lib/vendor/re2js.d.cts +284 -219
- package/gsd-core/bin/lib/verification.cjs +96 -9
- package/gsd-core/bin/lib/verify.cjs +4 -2
- package/gsd-core/bin/lib/workstream-inventory.cjs +26 -20
- package/gsd-core/bin/lib/worktree-safety.cjs +22 -1
- package/gsd-core/bin/shared/config-defaults.manifest.json +1 -0
- package/gsd-core/bin/shared/config-schema.manifest.json +1 -0
- package/gsd-core/bin/verify-reapply-patches.cjs +411 -10
- package/gsd-core/references/cicd-review-patterns.md +45 -0
- package/gsd-core/references/git-integration.md +11 -0
- package/gsd-core/references/loop-hook-dispatch.md +13 -6
- package/gsd-core/references/necessity-review.md +48 -0
- package/gsd-core/references/planning-config.md +2 -0
- package/gsd-core/references/tdd.md +2 -2
- package/gsd-core/templates/DEBUG.md +16 -0
- package/gsd-core/templates/config.json +2 -1
- package/gsd-core/templates/verification-report.md +1 -1
- package/gsd-core/workflows/audit-fix.md +2 -1
- package/gsd-core/workflows/code-review/steps/structural-pre-pass.md +10 -1
- package/gsd-core/workflows/code-review-fix.md +46 -5
- package/gsd-core/workflows/code-review.md +64 -7
- package/gsd-core/workflows/complete-milestone/steps/project-md-evolution-review.md +145 -0
- package/gsd-core/workflows/complete-milestone/steps/release-map.md +80 -0
- package/gsd-core/workflows/complete-milestone.md +37 -150
- package/gsd-core/workflows/diagnose-issues.md +29 -5
- package/gsd-core/workflows/discuss-phase/modes/power.md +1 -1
- package/gsd-core/workflows/discuss-phase-assumptions.md +33 -2
- package/gsd-core/workflows/discuss-phase-power.md +19 -2
- package/gsd-core/workflows/discuss-phase.md +6 -10
- package/gsd-core/workflows/execute-phase/steps/per-plan-worktree-gate.md +13 -7
- package/gsd-core/workflows/execute-phase/steps/post-merge-gate.md +7 -2
- package/gsd-core/workflows/execute-phase/steps/regression-gate-run.md +2 -1
- package/gsd-core/workflows/execute-phase/steps/verify-phase-goal.md +2 -2
- package/gsd-core/workflows/execute-phase/steps/wave-post-gate-hooks.md +11 -2
- package/gsd-core/workflows/execute-phase.md +10 -6
- package/gsd-core/workflows/execute-plan.md +1 -1
- package/gsd-core/workflows/health.md +2 -1
- package/gsd-core/workflows/import.md +1 -1
- package/gsd-core/workflows/plan-phase/steps/chunked-planning-mode.md +2 -2
- package/gsd-core/workflows/plan-phase/steps/stall-detection-helpers.md +13 -9
- package/gsd-core/workflows/plan-phase.md +14 -14
- package/gsd-core/workflows/pr-branch.md +2 -0
- package/gsd-core/workflows/quick/steps/plan-checker-loop.md +1 -1
- package/gsd-core/workflows/quick/steps/worktree-pre-dispatch-commit.md +8 -1
- package/gsd-core/workflows/quick-batch/steps/plan-checker-loop.md +2 -1
- package/gsd-core/workflows/quick.md +1 -1
- package/gsd-core/workflows/reapply-patches.md +104 -0
- package/gsd-core/workflows/review.md +70 -154
- package/gsd-core/workflows/section-manifest.json +5 -0
- package/gsd-core/workflows/secure-phase.md +1 -1
- package/gsd-core/workflows/settings-advanced.md +57 -9
- package/gsd-core/workflows/settings.md +1 -0
- package/gsd-core/workflows/ship.md +15 -4
- package/gsd-core/workflows/spec-phase.md +3 -6
- package/gsd-core/workflows/verify-work.md +4 -3
- package/hooks/dist/gsd-agent-isolation-guard.js +11 -1
- package/hooks/dist/gsd-cursor-subagent-start.js +6 -2
- package/hooks/dist/gsd-graphify-update.sh +6 -0
- package/hooks/dist/gsd-path-export.js +95 -0
- package/hooks/dist/gsd-secret-read-guard.js +172 -39
- package/hooks/dist/gsd-statusline.js +37 -3
- package/hooks/dist/gsd-windsurf-pre-write.js +29 -2
- package/hooks/dist/gsd-workflow-guard.js +3 -2
- package/hooks/dist/gsd-worktree-path-guard.js +29 -2
- package/hooks/dist/lib/git-probe.js +16 -0
- package/hooks/dist/lib/isolation-sentinel.js +44 -0
- package/hooks/dist/managed-hooks-registry.cjs +1 -0
- package/hooks/gsd-agent-isolation-guard.js +11 -1
- package/hooks/gsd-cursor-subagent-start.js +6 -2
- package/hooks/gsd-graphify-update.sh +6 -0
- package/hooks/gsd-path-export.js +95 -0
- package/hooks/gsd-secret-read-guard.js +172 -39
- package/hooks/gsd-statusline.js +37 -3
- package/hooks/gsd-windsurf-pre-write.js +29 -2
- package/hooks/gsd-workflow-guard.js +3 -2
- package/hooks/gsd-worktree-path-guard.js +29 -2
- package/hooks/hooks.json +1 -0
- package/hooks/lib/git-probe.js +16 -0
- package/hooks/lib/isolation-sentinel.js +44 -0
- package/hooks/managed-hooks-registry.cjs +1 -0
- package/package.json +15 -8
- package/pi/gsd.cjs +1047 -10
- package/pi/package-agents/gsd-advisor-researcher.md +113 -0
- package/pi/package-agents/gsd-ai-researcher.md +111 -0
- package/pi/package-agents/gsd-assumptions-analyzer.md +110 -0
- package/pi/package-agents/gsd-code-fixer.md +774 -0
- package/pi/package-agents/gsd-code-reviewer.md +441 -0
- package/pi/package-agents/gsd-codebase-mapper.md +850 -0
- package/pi/package-agents/gsd-debug-session-manager.md +416 -0
- package/pi/package-agents/gsd-debugger.md +1274 -0
- package/pi/package-agents/gsd-doc-classifier.md +269 -0
- package/pi/package-agents/gsd-doc-synthesizer.md +259 -0
- package/pi/package-agents/gsd-doc-verifier.md +212 -0
- package/pi/package-agents/gsd-doc-writer.md +626 -0
- package/pi/package-agents/gsd-dom-verifier.md +164 -0
- package/pi/package-agents/gsd-domain-researcher.md +144 -0
- package/pi/package-agents/gsd-eval-auditor.md +185 -0
- package/pi/package-agents/gsd-eval-planner.md +149 -0
- package/pi/package-agents/gsd-executor.md +898 -0
- package/pi/package-agents/gsd-framework-selector.md +159 -0
- package/pi/package-agents/gsd-integration-checker.md +476 -0
- package/pi/package-agents/gsd-intel-updater.md +338 -0
- package/pi/package-agents/gsd-mempalace-curator.md +49 -0
- package/pi/package-agents/gsd-nyquist-auditor.md +200 -0
- package/pi/package-agents/gsd-pattern-mapper.md +340 -0
- package/pi/package-agents/gsd-phase-researcher.md +897 -0
- package/pi/package-agents/gsd-plan-checker.md +1077 -0
- package/pi/package-agents/gsd-planner.md +1003 -0
- package/pi/package-agents/gsd-project-researcher.md +611 -0
- package/pi/package-agents/gsd-research-synthesizer.md +259 -0
- package/pi/package-agents/gsd-roadmapper.md +779 -0
- package/pi/package-agents/gsd-security-auditor.md +171 -0
- package/pi/package-agents/gsd-ui-auditor.md +581 -0
- package/pi/package-agents/gsd-ui-checker.md +417 -0
- package/pi/package-agents/gsd-ui-researcher.md +469 -0
- package/pi/package-agents/gsd-user-profiler.md +174 -0
- package/pi/package-agents/gsd-verifier.md +963 -0
- package/pi/package-agents/manifest.json +39 -0
- package/pi/package-skills/gsd-add-tests/SKILL.md +39 -0
- package/pi/package-skills/gsd-ai-integration-phase/SKILL.md +36 -0
- package/pi/package-skills/gsd-audit-fix/SKILL.md +34 -0
- package/pi/package-skills/gsd-audit-milestone/SKILL.md +40 -0
- package/pi/package-skills/gsd-audit-uat/SKILL.md +26 -0
- package/pi/package-skills/gsd-autonomous/SKILL.md +52 -0
- package/pi/package-skills/gsd-capture/SKILL.md +68 -0
- package/pi/package-skills/gsd-cleanup/SKILL.md +25 -0
- package/pi/package-skills/gsd-code-review/SKILL.md +71 -0
- package/pi/package-skills/gsd-complete-milestone/SKILL.md +147 -0
- package/pi/package-skills/gsd-config/SKILL.md +60 -0
- package/pi/package-skills/gsd-debug/SKILL.md +64 -0
- package/pi/package-skills/gsd-discuss-phase/SKILL.md +74 -0
- package/pi/package-skills/gsd-docs-update/SKILL.md +50 -0
- package/pi/package-skills/gsd-eval-review/SKILL.md +35 -0
- package/pi/package-skills/gsd-execute-phase/SKILL.md +62 -0
- package/pi/package-skills/gsd-explore/SKILL.md +26 -0
- package/pi/package-skills/gsd-extract-learnings/SKILL.md +25 -0
- package/pi/package-skills/gsd-fast/SKILL.md +33 -0
- package/pi/package-skills/gsd-forensics/SKILL.md +59 -0
- package/pi/package-skills/gsd-graphify/SKILL.md +210 -0
- package/pi/package-skills/gsd-health/SKILL.md +36 -0
- package/pi/package-skills/gsd-help/SKILL.md +37 -0
- package/pi/package-skills/gsd-import/SKILL.md +46 -0
- package/pi/package-skills/gsd-inbox/SKILL.md +42 -0
- package/pi/package-skills/gsd-ingest-docs/SKILL.md +43 -0
- package/pi/package-skills/gsd-manager/SKILL.md +46 -0
- package/pi/package-skills/gsd-map-codebase/SKILL.md +85 -0
- package/pi/package-skills/gsd-mempalace-capture/SKILL.md +111 -0
- package/pi/package-skills/gsd-mempalace-recall/SKILL.md +111 -0
- package/pi/package-skills/gsd-milestone-summary/SKILL.md +54 -0
- package/pi/package-skills/gsd-mvp-phase/SKILL.md +45 -0
- package/pi/package-skills/gsd-new-milestone/SKILL.md +49 -0
- package/pi/package-skills/gsd-new-project/SKILL.md +49 -0
- package/pi/package-skills/gsd-next/SKILL.md +34 -0
- package/pi/package-skills/gsd-ns-context/SKILL.md +31 -0
- package/pi/package-skills/gsd-ns-ideate/SKILL.md +30 -0
- package/pi/package-skills/gsd-ns-manage/SKILL.md +42 -0
- package/pi/package-skills/gsd-ns-project/SKILL.md +34 -0
- package/pi/package-skills/gsd-ns-review/SKILL.md +35 -0
- package/pi/package-skills/gsd-ns-workflow/SKILL.md +44 -0
- package/pi/package-skills/gsd-onboard/SKILL.md +46 -0
- package/pi/package-skills/gsd-pause-work/SKILL.md +48 -0
- package/pi/package-skills/gsd-phase/SKILL.md +61 -0
- package/pi/package-skills/gsd-plan-phase/SKILL.md +62 -0
- package/pi/package-skills/gsd-plan-review-convergence/SKILL.md +63 -0
- package/pi/package-skills/gsd-pr-branch/SKILL.md +31 -0
- package/pi/package-skills/gsd-profile-user/SKILL.md +48 -0
- package/pi/package-skills/gsd-progress/SKILL.md +51 -0
- package/pi/package-skills/gsd-quick/SKILL.md +179 -0
- package/pi/package-skills/gsd-quick-batch/SKILL.md +114 -0
- package/pi/package-skills/gsd-resume-work/SKILL.md +31 -0
- package/pi/package-skills/gsd-review/SKILL.md +50 -0
- package/pi/package-skills/gsd-review-backlog/SKILL.md +65 -0
- package/pi/package-skills/gsd-secure-phase/SKILL.md +37 -0
- package/pi/package-skills/gsd-settings/SKILL.md +30 -0
- package/pi/package-skills/gsd-ship/SKILL.md +27 -0
- package/pi/package-skills/gsd-sketch/SKILL.md +56 -0
- package/pi/package-skills/gsd-spec-phase/SKILL.md +63 -0
- package/pi/package-skills/gsd-spike/SKILL.md +53 -0
- package/pi/package-skills/gsd-stats/SKILL.md +22 -0
- package/pi/package-skills/gsd-surface/SKILL.md +177 -0
- package/pi/package-skills/gsd-thread/SKILL.md +29 -0
- package/pi/package-skills/gsd-ui-phase/SKILL.md +35 -0
- package/pi/package-skills/gsd-ui-review/SKILL.md +35 -0
- package/pi/package-skills/gsd-ultraplan-phase/SKILL.md +38 -0
- package/pi/package-skills/gsd-undo/SKILL.md +38 -0
- package/pi/package-skills/gsd-update/SKILL.md +54 -0
- package/pi/package-skills/gsd-validate-phase/SKILL.md +37 -0
- package/pi/package-skills/gsd-verify-work/SKILL.md +41 -0
- package/pi/package-skills/gsd-workspace/SKILL.md +57 -0
- package/pi/package-skills/gsd-workstreams/SKILL.md +73 -0
- package/scripts/build-hooks.js +4 -0
- package/scripts/ci-next-health.cjs +246 -23
- package/scripts/command-contract-helpers.cjs +1 -1
- package/scripts/docs-guard-registry.cjs +22 -7
- package/scripts/gen-features.cjs +14 -2
- package/scripts/gen-health-docs.cjs +13 -1
- package/scripts/gen-pi-package-skills.cjs +217 -0
- package/scripts/lib/drift-scan.cjs +27 -0
- package/scripts/lib/macos-conformance-tier.generated.cjs +17 -1
- package/scripts/lib/platform-conformance-tier.generated.cjs +37 -1
- package/scripts/lint-docs-guard-registration.exempt-baseline.cjs +3 -3
- package/scripts/lint-phase-enumeration-drift.cjs +8 -4
- package/scripts/lint-retired-runtime-name.cjs +5 -0
- package/scripts/lint-roadmap-progress-drift.cjs +421 -0
- package/scripts/mutation-matrix.cjs +23 -1
- package/scripts/npm-audit-baseline.cjs +41 -7
- package/scripts/reviewed-or-maintainer-policy.cjs +181 -0
- package/scripts/select-docs-guards.cjs +1 -1
- package/scripts/self-test-report-policy.cjs +350 -0
- package/scripts/sync-next-version.cjs +38 -6
- package/skills/gsd-update/SKILL.md +5 -2
- package/vscode/package.json +1 -1
- package/scripts/diagnose-validate-commit-in-tier.cjs +0 -270
- package/scripts/diagnose-validate-commit-phases.cjs +0 -348
- package/scripts/xtrace-phase-timing.cjs +0 -205
|
@@ -47,6 +47,8 @@ const coreUtilsMod = require("./core-utils.cjs");
|
|
|
47
47
|
// eslint-disable-next-line @typescript-eslint/no-require-imports -- planning-scope.cjs is an export= CommonJS module
|
|
48
48
|
const planningScopeMod = require("./planning-scope.cjs");
|
|
49
49
|
const shell_command_projection_cjs_1 = require("./shell-command-projection.cjs");
|
|
50
|
+
const text_lines_cjs_1 = require("./text-lines.cjs");
|
|
51
|
+
const frontmatter_fence_cjs_1 = require("./frontmatter-fence.cjs");
|
|
50
52
|
const runtime_slash_cjs_1 = require("./runtime-slash.cjs");
|
|
51
53
|
const security_cjs_1 = require("./security.cjs");
|
|
52
54
|
const pattern_cjs_1 = require("./pattern.cjs");
|
|
@@ -607,17 +609,19 @@ function phaseArtifactPaths(phaseDir, projectRoot) {
|
|
|
607
609
|
* `.planning/<project>/workstreams/<ws>`), covering a
|
|
608
610
|
* per-project/per-workstream store symlink (amendment 1,
|
|
609
611
|
* revised R7).
|
|
612
|
+
* v4 (#5351) — v3 with each CRLF byte pair hashed as LF. Every other
|
|
613
|
+
* byte, including a lone CR and non-UTF-8 input, is preserved.
|
|
610
614
|
*
|
|
611
615
|
* A stored digest names its own version (`v<N>:sha256:…`), and
|
|
612
616
|
* `readVerificationStatus` recomputes under the STORED version rather than
|
|
613
617
|
* this constant — so bumping it does not flip every already-verified phase
|
|
614
|
-
* to `stale` on upgrade. A legacy v1/v2 report keeps its own
|
|
615
|
-
* (shared documents included for v1; no report filter or artifact
|
|
616
|
-
*
|
|
618
|
+
* to `stale` on upgrade. A legacy v1/v2/v3 report keeps its own raw-byte
|
|
619
|
+
* semantics (shared documents included for v1; no report filter or artifact
|
|
620
|
+
* union for v1/v2) until it is re-fingerprinted; only a version outside
|
|
617
621
|
* `KNOWN_FINGERPRINT_VERSIONS` is unrecomputable and fails closed.
|
|
618
622
|
*/
|
|
619
|
-
const FINGERPRINT_VERSION =
|
|
620
|
-
const KNOWN_FINGERPRINT_VERSIONS = new Set([1, 2, 3]);
|
|
623
|
+
const FINGERPRINT_VERSION = 4;
|
|
624
|
+
const KNOWN_FINGERPRINT_VERSIONS = new Set([1, 2, 3, 4]);
|
|
621
625
|
/**
|
|
622
626
|
* #4623: the planning roots whose DIRECT children are repo-wide planning
|
|
623
627
|
* documents, as project-root-relative posix paths. Always `.planning`; plus
|
|
@@ -815,7 +819,22 @@ function deriveCoveredDigest(projectRoot, coveredFiles, version = FINGERPRINT_VE
|
|
|
815
819
|
catch {
|
|
816
820
|
return { ok: true, digest: null, files: declared, mappedPhaseDir: artifactMappedPhaseDir };
|
|
817
821
|
}
|
|
818
|
-
const
|
|
822
|
+
const hash = node_crypto_1.default.createHash('sha256');
|
|
823
|
+
if (version >= 4) {
|
|
824
|
+
// #5351: drop only the CR in each CRLF pair without decoding the
|
|
825
|
+
// covered input — binary files and lone CR bytes keep their meaning.
|
|
826
|
+
// Hash Buffer slices directly, retaining the LF at each new start.
|
|
827
|
+
let start = 0;
|
|
828
|
+
for (let crlf = bytes.indexOf('\r\n'); crlf !== -1; crlf = bytes.indexOf('\r\n', start)) {
|
|
829
|
+
hash.update(bytes.subarray(start, crlf));
|
|
830
|
+
start = crlf + 1;
|
|
831
|
+
}
|
|
832
|
+
hash.update(bytes.subarray(start));
|
|
833
|
+
}
|
|
834
|
+
else {
|
|
835
|
+
hash.update(bytes);
|
|
836
|
+
}
|
|
837
|
+
const fileHash = hash.digest('hex');
|
|
819
838
|
parts.push(`${rel}\n${fileHash}\n`);
|
|
820
839
|
hashed++;
|
|
821
840
|
}
|
|
@@ -1175,6 +1194,72 @@ function findVerificationStatusError(phaseDirs, deps = {}) {
|
|
|
1175
1194
|
}
|
|
1176
1195
|
return null;
|
|
1177
1196
|
}
|
|
1197
|
+
/**
|
|
1198
|
+
* #5291: legacy report statuses `validate health --repair` may rewrite, and the
|
|
1199
|
+
* closed-set status each becomes. Deliberately minimal — only the value the
|
|
1200
|
+
* maintainer ruled on (`pass_with_caveats` -> `passed`). Every other status
|
|
1201
|
+
* outside the closed set (`pending`, `partial`, …) has NO mapping: it stays
|
|
1202
|
+
* refused and its W030 stays advise-only (fail closed; only `passed` satisfies
|
|
1203
|
+
* the gate). The original value is preserved in `legacy_status`.
|
|
1204
|
+
*/
|
|
1205
|
+
const LEGACY_STATUS_REPAIRS = Object.freeze({
|
|
1206
|
+
pass_with_caveats: VERIFICATION_STATUS.PASSED,
|
|
1207
|
+
});
|
|
1208
|
+
/** The closed-set status a known legacy `raw` status repairs to, or `null` when it has no mapping. */
|
|
1209
|
+
function legacyStatusRepairTarget(raw) {
|
|
1210
|
+
return typeof raw === 'string' && Object.prototype.hasOwnProperty.call(LEGACY_STATUS_REPAIRS, raw)
|
|
1211
|
+
? LEGACY_STATUS_REPAIRS[raw]
|
|
1212
|
+
: null;
|
|
1213
|
+
}
|
|
1214
|
+
/**
|
|
1215
|
+
* #5291: rewrite one report's frontmatter `status:` from a known legacy value
|
|
1216
|
+
* to its closed-set equivalent and record the original as `legacy_status:`
|
|
1217
|
+
* right after it. Touches only those lines — every other byte (body, other
|
|
1218
|
+
* keys, line endings) is preserved — and never overwrites an existing
|
|
1219
|
+
* `legacy_status`. Refuses (writes nothing) for a path that is not a report
|
|
1220
|
+
* contained in its own phase directory, a report with no frontmatter `status`,
|
|
1221
|
+
* and any status without a mapping.
|
|
1222
|
+
*/
|
|
1223
|
+
function repairLegacyVerificationStatus(filePath) {
|
|
1224
|
+
if (!isReportContained(node_path_1.default.dirname(filePath), filePath)) {
|
|
1225
|
+
return { ok: false, reason: 'the report is not contained in its phase directory' };
|
|
1226
|
+
}
|
|
1227
|
+
let content;
|
|
1228
|
+
try {
|
|
1229
|
+
content = node_fs_1.default.readFileSync(filePath, 'utf-8');
|
|
1230
|
+
}
|
|
1231
|
+
catch (err) {
|
|
1232
|
+
return { ok: false, reason: err instanceof Error ? err.message : String(err) };
|
|
1233
|
+
}
|
|
1234
|
+
// The fence owner (`locateFrontmatterFence`) is the one place that knows where
|
|
1235
|
+
// the frontmatter body starts and ends (BOM, CRLF, lenient closing fence).
|
|
1236
|
+
const fence = (0, frontmatter_fence_cjs_1.locateFrontmatterFence)(content);
|
|
1237
|
+
if (!fence || !fence.closed)
|
|
1238
|
+
return { ok: false, reason: 'the report has no closed frontmatter' };
|
|
1239
|
+
const lines = (0, text_lines_cjs_1.splitLines)(content.slice(fence.openEnd, fence.bodyEnd));
|
|
1240
|
+
// The YAML reader keeps the LAST of duplicate keys, so the line the repair
|
|
1241
|
+
// edits is the last `status:` line — the very value the refusal named. A
|
|
1242
|
+
// trailing comment (`status: pass_with_caveats # x`) is not part of the value.
|
|
1243
|
+
let statusAt = -1;
|
|
1244
|
+
lines.forEach((l, i) => { if (/^status:/.test(l))
|
|
1245
|
+
statusAt = i; });
|
|
1246
|
+
if (statusAt === -1)
|
|
1247
|
+
return { ok: false, reason: 'the report frontmatter has no status' };
|
|
1248
|
+
const raw = lines[statusAt]
|
|
1249
|
+
.replace(/^status:\s*/, '')
|
|
1250
|
+
.replace(/\s+#.*$/, '')
|
|
1251
|
+
.replace(/\s+$/, '')
|
|
1252
|
+
.replace(/^(["'])(.*)\1$/, '$2');
|
|
1253
|
+
const to = legacyStatusRepairTarget(raw);
|
|
1254
|
+
if (to === null)
|
|
1255
|
+
return { ok: false, reason: `${describeRawStatus(raw)} has no known repair` };
|
|
1256
|
+
const legacyStatusKept = lines.some((l) => /^legacy_status:/.test(l));
|
|
1257
|
+
lines[statusAt] = `status: ${to}`;
|
|
1258
|
+
if (!legacyStatusKept)
|
|
1259
|
+
lines.splice(statusAt + 1, 0, `legacy_status: ${raw}`);
|
|
1260
|
+
(0, shell_command_projection_cjs_1.platformWriteSync)(filePath, content.slice(0, fence.openEnd) + (0, text_lines_cjs_1.joinLines)(lines, fence.eol) + content.slice(fence.bodyEnd), { verbatim: true });
|
|
1261
|
+
return { ok: true, from: raw, to, legacyStatusKept };
|
|
1262
|
+
}
|
|
1178
1263
|
/**
|
|
1179
1264
|
* #3518: the shared phase-pinned artifact-selection core BOTH single-pick
|
|
1180
1265
|
* resolvers (`resolveVerificationFile` for `*-VERIFICATION.md`,
|
|
@@ -1499,11 +1584,11 @@ function readVerificationStatus(phaseDir, opts = {}) {
|
|
|
1499
1584
|
isStale = true;
|
|
1500
1585
|
}
|
|
1501
1586
|
else if (storedVersion >= 3) {
|
|
1502
|
-
// #5095 (R1): v3
|
|
1587
|
+
// #5095 (R1): the v3+ digest is computed over the declared set UNIONED
|
|
1503
1588
|
// with the phase's own live artifacts — a plan/summary added after
|
|
1504
1589
|
// fingerprinting already moves the digest itself, so the separate
|
|
1505
1590
|
// live-directory re-scan (`uncoveredCurrentArtifacts`) is redundant
|
|
1506
|
-
// for v3 and is not run.
|
|
1591
|
+
// for v3+ and is not run.
|
|
1507
1592
|
isStale =
|
|
1508
1593
|
computeCoveredDigest(projectRoot, coveredFilesVal, storedVersion, { phaseDir }) !== coveredDigestVal;
|
|
1509
1594
|
if (isStale) {
|
|
@@ -1784,7 +1869,7 @@ function parseFingerprintFileArgs(tokens) {
|
|
|
1784
1869
|
* directly assignable. #5095 (ADR-5057 Phase 2): `raw`
|
|
1785
1870
|
* returning only the digest is safe even though the
|
|
1786
1871
|
* emitted `covered_files` is a SUPERSET of the caller's
|
|
1787
|
-
* declared list — the v3 digest is computed over
|
|
1872
|
+
* declared list — the v3+ digest is computed over
|
|
1788
1873
|
* `canonicalize(declared ∪ phaseArtifactPaths)` on BOTH
|
|
1789
1874
|
* the emit side (here) and the check side
|
|
1790
1875
|
* (`readVerificationStatus`), so a `--raw` caller that
|
|
@@ -2134,6 +2219,8 @@ const verificationModule = {
|
|
|
2134
2219
|
isReportContained,
|
|
2135
2220
|
routeResult,
|
|
2136
2221
|
findVerificationStatusError,
|
|
2222
|
+
legacyStatusRepairTarget,
|
|
2223
|
+
repairLegacyVerificationStatus,
|
|
2137
2224
|
defaultPhaseCleanCommitTimesMs,
|
|
2138
2225
|
resolvePhaseArtifactFile,
|
|
2139
2226
|
resolveVerificationFile,
|
|
@@ -42,7 +42,7 @@ const ioMod = require("./io.cjs");
|
|
|
42
42
|
const { output, error } = ioMod;
|
|
43
43
|
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
44
44
|
const phaseLocatorMod = require("./phase-locator.cjs");
|
|
45
|
-
const { findPhaseInternal } = phaseLocatorMod;
|
|
45
|
+
const { phaseDirectoryOptions, findPhaseInternal } = phaseLocatorMod;
|
|
46
46
|
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
47
47
|
const roadmapParserMod = require("./roadmap-parser.cjs");
|
|
48
48
|
const { stripShippedMilestones } = roadmapParserMod;
|
|
@@ -1282,7 +1282,7 @@ function cmdVerifyPhaseCompleteness(cwd, phase, raw) {
|
|
|
1282
1282
|
if (!phase) {
|
|
1283
1283
|
error('phase required');
|
|
1284
1284
|
}
|
|
1285
|
-
const phaseInfoRaw = findPhaseInternal(cwd, phase);
|
|
1285
|
+
const phaseInfoRaw = findPhaseInternal(cwd, phase, undefined, phaseDirectoryOptions(cwd));
|
|
1286
1286
|
if (!phaseInfoRaw || !phaseInfoRaw['found']) {
|
|
1287
1287
|
// An unresolvable phase is "could not look" (#5170): there is no phase to evaluate.
|
|
1288
1288
|
emitVerbVerdict((0, gate_verdict_cjs_1.gateUnreadable)(false, { error: 'Phase not found', phase }), 'status', raw);
|
|
@@ -1809,6 +1809,8 @@ function repairFixText(slash, action) {
|
|
|
1809
1809
|
return `Run ${slash('health')} --repair to add key`;
|
|
1810
1810
|
case REMEDY_ACTION.BACKFILL_MILESTONES:
|
|
1811
1811
|
return `Run ${slash('health')} --backfill to synthesize missing entries from archive snapshots`;
|
|
1812
|
+
case REMEDY_ACTION.REPAIR_VERIFICATION_STATUS:
|
|
1813
|
+
return `Run ${slash('health')} --repair to rewrite the legacy status (original kept as legacy_status)`;
|
|
1812
1814
|
default:
|
|
1813
1815
|
return '';
|
|
1814
1816
|
}
|
|
@@ -30,7 +30,7 @@ const state_document_cjs_1 = require("./state-document.cjs");
|
|
|
30
30
|
// eslint-disable-next-line @typescript-eslint/no-require-imports -- frontmatter.cjs is an export= CommonJS module
|
|
31
31
|
const frontmatterMod = require("./frontmatter.cjs");
|
|
32
32
|
const { extractFrontmatter, stripFrontmatter } = frontmatterMod;
|
|
33
|
-
const
|
|
33
|
+
const roadmap_progress_cjs_1 = require("./roadmap-progress.cjs");
|
|
34
34
|
// eslint-disable-next-line @typescript-eslint/no-require-imports -- verification.cjs is an export= CommonJS module
|
|
35
35
|
const verificationMod = require("./verification.cjs");
|
|
36
36
|
const { isPhaseComplete, isVerificationStatus, VERIFICATION_STATUS } = verificationMod;
|
|
@@ -41,6 +41,9 @@ const { phaseKeyFromDir, phaseKeyFromProse, parentPhaseKey } = phaseIdMod;
|
|
|
41
41
|
const roadmapParserMod = require("./roadmap-parser.cjs");
|
|
42
42
|
const { getMilestonePhaseFilter, isMilestoneShippedInRoadmap } = roadmapParserMod;
|
|
43
43
|
const workstream_inventory_builder_cjs_1 = require("./workstream-inventory-builder.cjs");
|
|
44
|
+
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
45
|
+
const phaseLocatorMod = require("./phase-locator.cjs");
|
|
46
|
+
const { phaseDirectoryOptions } = phaseLocatorMod;
|
|
44
47
|
// ─── Implementation ───────────────────────────────────────────────────────────
|
|
45
48
|
function workstreamsRoot(cwd) {
|
|
46
49
|
return node_path_1.default.join(planningRoot(cwd), 'workstreams');
|
|
@@ -75,7 +78,7 @@ function countRoadmapPhases(roadmapPath, fallbackCount, cwd, ws, versionOverride
|
|
|
75
78
|
// `null` -> 0 (fallback), `undefined` -> 3. A non-bracket workstream
|
|
76
79
|
// resolves to a value that compiles the same base grammar `null` did, so
|
|
77
80
|
// its count is unchanged (verified against a legacy control).
|
|
78
|
-
const filter = getMilestonePhaseFilter(cwd, versionOverride ?? null, undefined, ws ?? null);
|
|
81
|
+
const filter = getMilestonePhaseFilter(cwd, versionOverride ?? null, undefined, ws ?? null, phaseDirectoryOptions(cwd, undefined, undefined, ws ?? null));
|
|
79
82
|
// A pass-all degrade (phaseCount 0) means the window declared no phases —
|
|
80
83
|
// fall back rather than reporting a confident zero.
|
|
81
84
|
return filter.phaseCount > 0 ? filter.phaseCount : fallbackCount;
|
|
@@ -98,25 +101,22 @@ function countRoadmapPhases(roadmapPath, fallbackCount, cwd, ws, versionOverride
|
|
|
98
101
|
* `phaseKeyFromDir` uses for directories, so a `| 01. … |` row and a `1-slug`
|
|
99
102
|
* directory cannot land in different key spaces (the padding-asymmetry defect).
|
|
100
103
|
*/
|
|
101
|
-
function parseRoadmapProgressRows(
|
|
102
|
-
let content;
|
|
103
|
-
try {
|
|
104
|
-
content = node_fs_1.default.readFileSync(roadmapPath, 'utf-8');
|
|
105
|
-
}
|
|
106
|
-
catch {
|
|
107
|
-
return []; /* no roadmap */
|
|
108
|
-
}
|
|
104
|
+
function parseRoadmapProgressRows(content, directoryContext) {
|
|
109
105
|
// Milestone-ATTRIBUTING shape first. Both shapes carry `Plans Complete`, so
|
|
110
106
|
// probing that column first would pick a flat table appearing earlier in the
|
|
111
107
|
// document over a milestone-grouped one later — every row would come back
|
|
112
108
|
// unattributed and be treated as current-milestone, silently over-including.
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
109
|
+
// #5761: the roadmap-progress owner picks the table (heading-scoped, so a
|
|
110
|
+
// decoy table elsewhere cannot be mistaken for it); this reader only supplies
|
|
111
|
+
// the probe order. A table outside a table-less `## Progress` section has
|
|
112
|
+
// always been read here (#5692: no behavior change), hence `sectionMiss`.
|
|
113
|
+
const { rows: tableRows } = (0, roadmap_progress_cjs_1.locateRoadmapProgress)(content, {
|
|
114
|
+
columns: [['Phase', 'Milestone'], ['Phase', 'Plans Complete']],
|
|
115
|
+
sectionMiss: 'document',
|
|
116
|
+
});
|
|
117
117
|
const rows = [];
|
|
118
|
-
for (const row of
|
|
119
|
-
const key = phaseKeyFromProse(row['Phase']);
|
|
118
|
+
for (const row of tableRows) {
|
|
119
|
+
const key = phaseKeyFromProse(row['Phase'], directoryContext);
|
|
120
120
|
if (key === null)
|
|
121
121
|
continue;
|
|
122
122
|
const cell = (row['Milestone'] ?? '').trim();
|
|
@@ -428,12 +428,18 @@ function inspectWorkstream(cwd, name, options = {}) {
|
|
|
428
428
|
const writeDiagnostic = options.writeDiagnostic ?? ((message) => process.stderr.write(message));
|
|
429
429
|
const p = planningPaths(cwd, name);
|
|
430
430
|
const phaseDirNames = readSubdirectories(p.phases);
|
|
431
|
+
let roadmap = '';
|
|
432
|
+
try {
|
|
433
|
+
roadmap = node_fs_1.default.readFileSync(p.roadmap, 'utf8');
|
|
434
|
+
}
|
|
435
|
+
catch { /* no roadmap */ }
|
|
436
|
+
const directoryContext = phaseDirectoryOptions(cwd, undefined, roadmap, name);
|
|
431
437
|
// #2562: scope progress to the CURRENT milestone. Membership and the
|
|
432
438
|
// denominator are derived in ONE key space (`phaseKeyFromDir` /
|
|
433
439
|
// `phaseKeyFromProse`, both from the phase-id owner module) so the two sides
|
|
434
440
|
// of the rollup cannot disagree.
|
|
435
441
|
const currentVersion = readCurrentMilestoneVersion(p.state, p.roadmap);
|
|
436
|
-
const progressRows = parseRoadmapProgressRows(
|
|
442
|
+
const progressRows = parseRoadmapProgressRows(roadmap, directoryContext);
|
|
437
443
|
// Phase keys the ROADMAP attributes to the current milestone. A row whose
|
|
438
444
|
// Milestone cell is blank or malformed is INCLUDED rather than dropped: a
|
|
439
445
|
// phase we cannot attribute must still be visible to the rollup. Dropping it
|
|
@@ -458,7 +464,7 @@ function inspectWorkstream(cwd, name, options = {}) {
|
|
|
458
464
|
// it is exactly the caller that cannot set `GSD_WORKSTREAM`; spelling `null`
|
|
459
465
|
// pinned every workstream to the legacy grammar and made `headingScoped`
|
|
460
466
|
// unreachable (`phaseCount > 0` never held) on a bracket workstream.
|
|
461
|
-
const headingFilter = getMilestonePhaseFilter(cwd, currentVersion, undefined, name);
|
|
467
|
+
const headingFilter = getMilestonePhaseFilter(cwd, currentVersion, undefined, name, directoryContext);
|
|
462
468
|
const headingScoped = headingFilter.versionScoped && headingFilter.phaseCount > 0;
|
|
463
469
|
// Phase keys the ROADMAP attributes to some OTHER milestone. A row carrying an
|
|
464
470
|
// explicit version that is not the current one is a positive claim by a prior
|
|
@@ -507,7 +513,7 @@ function inspectWorkstream(cwd, name, options = {}) {
|
|
|
507
513
|
const isDirInCurrentMilestone = (dir) => {
|
|
508
514
|
if (!scoped)
|
|
509
515
|
return true;
|
|
510
|
-
const key = phaseKeyFromDir(dir);
|
|
516
|
+
const key = phaseKeyFromDir(dir, undefined, directoryContext);
|
|
511
517
|
if (currentMilestoneKeys.has(key))
|
|
512
518
|
return true;
|
|
513
519
|
const parent = parentPhaseKey(key);
|
|
@@ -563,7 +569,7 @@ function inspectWorkstream(cwd, name, options = {}) {
|
|
|
563
569
|
}
|
|
564
570
|
return {
|
|
565
571
|
directory: dir,
|
|
566
|
-
phaseKey: phaseKeyFromDir(dir),
|
|
572
|
+
phaseKey: phaseKeyFromDir(dir, undefined, directoryContext),
|
|
567
573
|
mtimeMs: phaseDirMtime(phaseDir),
|
|
568
574
|
planCount: counts.planCount,
|
|
569
575
|
summaryCount: counts.summaryCount,
|
|
@@ -176,7 +176,28 @@ function resolveWorktreeContext(cwd, deps = {}) {
|
|
|
176
176
|
reason: 'has_local_planning',
|
|
177
177
|
};
|
|
178
178
|
}
|
|
179
|
-
|
|
179
|
+
const linkage = resolveWorktreeLinkage(cwd, deps);
|
|
180
|
+
if (linkage.reason !== 'linked_worktree')
|
|
181
|
+
return linkage;
|
|
182
|
+
// #4885: from a SUBDIRECTORY of a LINKED worktree the cwd has no .planning of its own, but the
|
|
183
|
+
// worktree's own top-level may. That checkout is the project the caller means; remapping to the
|
|
184
|
+
// main checkout would make `commit` and every planning write land in the wrong repository. A linked
|
|
185
|
+
// worktree with no .planning anywhere still remaps to the main checkout, and the main checkout's own
|
|
186
|
+
// subdirectories are untouched.
|
|
187
|
+
const execGit = deps.execGit || execGitDefault;
|
|
188
|
+
const top = execGit(['rev-parse', '--show-toplevel'], { cwd });
|
|
189
|
+
const topText = String(top.stdout || '').trim();
|
|
190
|
+
if (!top.timedOut && top.exitCode === 0 && topText !== '') {
|
|
191
|
+
const topLevel = node_path_1.default.resolve(cwd, topText);
|
|
192
|
+
if (existsSync(node_path_1.default.join(topLevel, '.planning'))) {
|
|
193
|
+
return {
|
|
194
|
+
effectiveRoot: topLevel,
|
|
195
|
+
mode: 'current_directory',
|
|
196
|
+
reason: 'has_local_planning',
|
|
197
|
+
};
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
return linkage;
|
|
180
201
|
}
|
|
181
202
|
function planWorktreePrune(repoRoot, options = {}, deps = {}) {
|
|
182
203
|
const parsePorcelain = deps.parseWorktreePorcelain || parseWorktreePorcelain;
|