@opengsd/gsd-core 1.9.0 → 1.10.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 -3
- package/.opencode/plugins/gsd-core.js +8 -1
- package/agents/gsd-code-fixer.md +131 -34
- package/agents/gsd-debugger.md +12 -246
- package/agents/gsd-executor.md +7 -5
- package/agents/gsd-integration-checker.md +3 -0
- package/agents/gsd-plan-checker.md +9 -0
- package/agents/gsd-planner.md +5 -8
- package/agents/gsd-roadmapper.md +21 -3
- package/agents/gsd-verifier.md +14 -70
- package/bin/install.js +503 -341
- package/commands/gsd/mempalace-capture.md +1 -1
- package/commands/gsd/new-milestone.md +1 -1
- package/commands/gsd/plan-phase.md +1 -1
- package/gsd-core/bin/gsd-tools.cjs +607 -63
- package/gsd-core/bin/lib/active-workstream-store.cjs +25 -0
- package/gsd-core/bin/lib/agent-install-check.cjs +38 -6
- package/gsd-core/bin/lib/api-coverage.cjs +120 -0
- package/gsd-core/bin/lib/audit.cjs +89 -1
- package/gsd-core/bin/lib/broken-windows.cjs +36 -6
- package/gsd-core/bin/lib/capability-registry.cjs +96 -110
- package/gsd-core/bin/lib/capability-validator.cjs +12 -2
- package/gsd-core/bin/lib/check-command-router.cjs +43 -1
- package/gsd-core/bin/lib/command-aliases.cjs +72 -0
- package/gsd-core/bin/lib/commands.cjs +26 -25
- package/gsd-core/bin/lib/commonjs-marker.cjs +136 -0
- package/gsd-core/bin/lib/config-loader.cjs +1 -0
- package/gsd-core/bin/lib/config.cjs +12 -1
- package/gsd-core/bin/lib/context-composer.cjs +278 -0
- package/gsd-core/bin/lib/context-predicates.cjs +506 -0
- package/gsd-core/bin/lib/core-utils.cjs +91 -12
- package/gsd-core/bin/lib/docs.cjs +3 -2
- package/gsd-core/bin/lib/external-job.cjs +19 -4
- package/gsd-core/bin/lib/frontmatter.cjs +84 -12
- package/gsd-core/bin/lib/gate-predicate-evaluator.cjs +57 -6
- package/gsd-core/bin/lib/git-base-branch.cjs +58 -15
- package/gsd-core/bin/lib/graphify.cjs +142 -27
- package/gsd-core/bin/lib/gsd2-import.cjs +27 -4
- package/gsd-core/bin/lib/host-integration.cjs +13 -1
- package/gsd-core/bin/lib/init-command-router.cjs +83 -8
- package/gsd-core/bin/lib/init.cjs +1021 -57
- package/gsd-core/bin/lib/install-engine.cjs +64 -10
- package/gsd-core/bin/lib/install-profiles.cjs +27 -1
- package/gsd-core/bin/lib/installer-migration-authoring.cjs +3 -1
- package/gsd-core/bin/lib/installer-migration-report.cjs +4 -0
- package/gsd-core/bin/lib/installer-migrations/007-retire-config-root-commonjs-marker.cjs +149 -0
- package/gsd-core/bin/lib/installer-migrations/008-cursor-retire-commands-surface.cjs +55 -0
- package/gsd-core/bin/lib/installer-migrations/009-pi-retire-reserved-hooks-dir.cjs +199 -0
- package/gsd-core/bin/lib/installer-migrations.cjs +87 -1
- package/gsd-core/bin/lib/io.cjs +28 -3
- package/gsd-core/bin/lib/markdown-sectionizer.cjs +6 -0
- package/gsd-core/bin/lib/mcp-catalog.cjs +518 -0
- package/gsd-core/bin/lib/mcp-server.cjs +135 -3
- package/gsd-core/bin/lib/milestone.cjs +106 -51
- package/gsd-core/bin/lib/phase-id.cjs +63 -0
- package/gsd-core/bin/lib/phase-locator.cjs +138 -45
- package/gsd-core/bin/lib/phase.cjs +260 -25
- package/gsd-core/bin/lib/plan-dependency-graph.cjs +232 -0
- package/gsd-core/bin/lib/planning-workspace.cjs +4 -0
- package/gsd-core/bin/lib/project-root.cjs +48 -0
- package/gsd-core/bin/lib/prompt-budget.cjs +128 -165
- package/gsd-core/bin/lib/retired-artifact-cleanup.cjs +80 -0
- package/gsd-core/bin/lib/review-lane-descriptor.cjs +99 -0
- package/gsd-core/bin/lib/review-lane-runner.cjs +30 -6
- package/gsd-core/bin/lib/roadmap-command-router.cjs +42 -9
- package/gsd-core/bin/lib/roadmap-parser.cjs +100 -18
- package/gsd-core/bin/lib/roadmap.cjs +37 -7
- package/gsd-core/bin/lib/runtime-artifact-conversion.cjs +195 -62
- package/gsd-core/bin/lib/runtime-artifact-layout.cjs +15 -3
- package/gsd-core/bin/lib/runtime-homes.cjs +154 -41
- package/gsd-core/bin/lib/runtime-hooks-surface.cjs +105 -41
- package/gsd-core/bin/lib/section-manifest.cjs +209 -0
- package/gsd-core/bin/lib/shell-command-projection.cjs +113 -27
- package/gsd-core/bin/lib/smart-entry.cjs +12 -0
- package/gsd-core/bin/lib/state-transition.cjs +73 -8
- package/gsd-core/bin/lib/state.cjs +151 -62
- package/gsd-core/bin/lib/surface.cjs +12 -1
- package/gsd-core/bin/lib/uat-predicate.cjs +11 -1
- package/gsd-core/bin/lib/uat.cjs +320 -21
- package/gsd-core/bin/lib/unusable-input.cjs +9 -0
- package/gsd-core/bin/lib/verification.cjs +29 -12
- package/gsd-core/bin/lib/verify.cjs +29 -5
- package/gsd-core/bin/lib/workflow-fragments.cjs +557 -0
- package/gsd-core/bin/lib/workstream-inventory-builder.cjs +181 -18
- package/gsd-core/bin/lib/workstream-inventory.cjs +519 -27
- package/gsd-core/bin/lib/workstream.cjs +6 -0
- package/gsd-core/bin/lib/worktree-base-ref.cjs +50 -6
- package/gsd-core/bin/lib/worktree-safety.cjs +276 -118
- package/gsd-core/bin/shared/config-schema.manifest.json +2 -0
- package/gsd-core/references/artifact-types.md +10 -3
- package/gsd-core/references/autonomous-ui-design-contract.md +42 -0
- package/gsd-core/references/debugger-techniques.md +255 -0
- package/gsd-core/references/research-documentation-lookup.md +5 -3
- package/gsd-core/references/specless-probe-fallback.md +7 -6
- package/gsd-core/references/verifier-wiring-patterns.md +100 -0
- package/gsd-core/references/worktree-branch-check.md +2 -2
- package/gsd-core/templates/summary-complex.md +2 -0
- package/gsd-core/templates/summary-minimal.md +2 -0
- package/gsd-core/templates/summary-standard.md +2 -0
- package/gsd-core/templates/summary.md +2 -0
- package/gsd-core/workflows/audit-milestone.md +3 -0
- package/gsd-core/workflows/autonomous/steps/converge-banner.md +1 -0
- package/gsd-core/workflows/autonomous/steps/converge-dispatch-bg.md +11 -0
- package/gsd-core/workflows/autonomous/steps/converge-dispatch-inline.md +7 -0
- package/gsd-core/workflows/autonomous/steps/converge-fail-fast.md +21 -0
- package/gsd-core/workflows/autonomous/steps/converge-loop.md +7 -0
- package/gsd-core/workflows/autonomous.md +32 -69
- package/gsd-core/workflows/code-review/steps/dispatch-fix.md +39 -0
- package/gsd-core/workflows/code-review/steps/structural-pre-pass.md +83 -0
- package/gsd-core/workflows/code-review.md +42 -145
- package/gsd-core/workflows/complete-milestone/steps/git-tag.md +29 -0
- package/gsd-core/workflows/complete-milestone.md +23 -81
- package/gsd-core/workflows/debug.md +9 -12
- package/gsd-core/workflows/diagnose-issues.md +22 -0
- package/gsd-core/workflows/discovery-phase.md +4 -4
- package/gsd-core/workflows/discuss-phase-assumptions/steps/auto-advance-dispatch.md +15 -0
- package/gsd-core/workflows/discuss-phase-assumptions.md +5 -16
- package/gsd-core/workflows/docs-update/steps/dispatch-monorepo-packages.md +51 -0
- package/gsd-core/workflows/docs-update.md +8 -51
- package/gsd-core/workflows/execute-phase/steps/executor-isolation-dispatch.md +34 -2
- package/gsd-core/workflows/execute-phase/steps/gap-closure-artifacts.md +50 -0
- package/gsd-core/workflows/execute-phase/steps/partial-wave.md +31 -0
- package/gsd-core/workflows/execute-phase/steps/per-plan-worktree-gate.md +19 -0
- package/gsd-core/workflows/execute-phase/steps/regression-gate-run.md +42 -0
- package/gsd-core/workflows/execute-phase/steps/regression-gate.md +43 -37
- package/gsd-core/workflows/execute-phase.md +65 -137
- package/gsd-core/workflows/execute-plan.md +1 -1
- package/gsd-core/workflows/help/modes/full.md +6 -1
- package/gsd-core/workflows/ingest-docs.md +2 -1
- package/gsd-core/workflows/new-milestone/steps/project-md-milestone-write.md +16 -0
- package/gsd-core/workflows/new-milestone/steps/reset-phase-safety.md +19 -0
- package/gsd-core/workflows/new-milestone.md +21 -38
- package/gsd-core/workflows/new-project/steps/auto-mode-config.md +176 -0
- package/gsd-core/workflows/new-project/steps/auto-mode-detection.md +32 -0
- package/gsd-core/workflows/new-project/steps/codebase-map-offer.md +18 -0
- package/gsd-core/workflows/new-project.md +13 -226
- package/gsd-core/workflows/plan-phase/steps/adr-ingest-express-path.md +15 -0
- package/gsd-core/workflows/plan-phase/steps/chunked-planning-mode.md +110 -0
- package/gsd-core/workflows/plan-phase/steps/prd-express-gate.md +8 -0
- package/gsd-core/workflows/plan-phase/steps/research-only-early-exit.md +17 -0
- package/gsd-core/workflows/plan-phase/steps/research-only-modifiers.md +16 -0
- package/gsd-core/workflows/plan-phase/steps/reviews-prerequisite.md +17 -0
- package/gsd-core/workflows/plan-phase/steps/stall-detection-helpers.md +149 -0
- package/gsd-core/workflows/plan-phase.md +49 -193
- package/gsd-core/workflows/progress/steps/forensic-audit.md +125 -0
- package/gsd-core/workflows/progress/steps/mvp-display.md +18 -0
- package/gsd-core/workflows/progress.md +11 -153
- package/gsd-core/workflows/quick/steps/discussion-phase.md +124 -0
- package/gsd-core/workflows/quick/steps/plan-checker-loop.md +111 -0
- package/gsd-core/workflows/quick/steps/quick-verification.md +46 -0
- package/gsd-core/workflows/quick/steps/research-phase.md +72 -0
- package/gsd-core/workflows/quick/steps/worktree-pre-dispatch-commit.md +37 -0
- package/gsd-core/workflows/quick.md +20 -390
- package/gsd-core/workflows/resume-project.md +3 -0
- package/gsd-core/workflows/review/steps/reviewer-instances-note-1.md +4 -0
- package/gsd-core/workflows/review/steps/reviewer-instances-note-2.md +3 -0
- package/gsd-core/workflows/review.md +15 -8
- package/gsd-core/workflows/section-manifest.json +219 -0
- package/gsd-core/workflows/sketch.md +1 -1
- package/gsd-core/workflows/spec-phase.md +17 -14
- package/gsd-core/workflows/spike-wrap-up.md +20 -5
- package/gsd-core/workflows/spike.md +50 -16
- package/gsd-core/workflows/sync-skills.md +49 -11
- package/gsd-core/workflows/transition/steps/workstream-collision-check.md +17 -0
- package/gsd-core/workflows/transition.md +8 -21
- package/gsd-core/workflows/ui-phase.md +8 -7
- package/gsd-core/workflows/update/steps/channel-banner.md +7 -0
- package/gsd-core/workflows/update.md +18 -7
- package/gsd-core/workflows/verify-phase.md +4 -7
- package/gsd-core/workflows/verify-work/steps/automated-ui-verification.md +36 -0
- package/gsd-core/workflows/verify-work/steps/mvp-uat-framing.md +21 -0
- package/gsd-core/workflows/verify-work.md +8 -58
- package/hooks/dist/gsd-agent-isolation-guard.js +428 -0
- package/hooks/dist/gsd-check-update-worker.js +14 -5
- package/hooks/dist/gsd-cursor-subagent-start.js +532 -26
- package/hooks/dist/gsd-read-injection-scanner.js +7 -0
- package/hooks/dist/gsd-statusline.js +72 -6
- package/hooks/dist/gsd-worktree-path-guard.js +2 -1
- package/hooks/dist/gsd-write-guard.js +359 -0
- package/hooks/dist/lib/isolation-sentinel.js +268 -0
- package/hooks/dist/managed-hooks-registry.cjs +2 -0
- package/hooks/gsd-agent-isolation-guard.js +428 -0
- package/hooks/gsd-check-update-worker.js +14 -5
- package/hooks/gsd-cursor-subagent-start.js +532 -26
- package/hooks/gsd-read-injection-scanner.js +7 -0
- package/hooks/gsd-statusline.js +72 -6
- package/hooks/gsd-worktree-path-guard.js +2 -1
- package/hooks/gsd-write-guard.js +359 -0
- package/hooks/hooks.json +12 -0
- package/hooks/lib/isolation-sentinel.js +268 -0
- package/hooks/managed-hooks-registry.cjs +2 -0
- package/package.json +14 -5
- package/pi/gsd.cjs +57 -12
- package/scripts/build-hooks.js +9 -0
- package/scripts/changeset/lint.cjs +9 -2
- package/scripts/changeset/serialize.cjs +5 -1
- package/scripts/gen-capability-matrix.cjs +1 -1
- package/scripts/gen-context-index.cjs +448 -0
- package/scripts/gen-inventory-manifest.cjs +101 -1
- package/scripts/gen-prompt-budget-parity-corpus.cjs +645 -0
- package/scripts/gen-registry.cjs +39 -15
- package/scripts/gen-section-manifest.cjs +638 -0
- package/scripts/generate-package-identity.cjs +4 -2
- package/scripts/lint-allow-test-rule-refs.allowlist.json +17 -31
- package/scripts/lint-compiled-artifact-sync.cjs +6 -1
- package/scripts/lint-docs-command-form.cjs +195 -0
- package/scripts/lint-docs-required.cjs +9 -1
- package/scripts/lint-emitted-drift-ack.cjs +215 -20
- package/scripts/lint-example-parser-parity.cjs +395 -0
- package/scripts/lint-test-file-count.allowlist.json +27 -1
- package/scripts/mutation-matrix.cjs +13 -0
- package/scripts/prompt-injection-scan.sh +27 -6
- package/scripts/registry-schema.cjs +323 -94
- package/scripts/run-tests.cjs +3 -2
- package/scripts/validate-registry.cjs +10 -6
- package/skills/gsd-autonomous/SKILL.md +1 -1
- package/skills/gsd-execute-phase/SKILL.md +1 -1
- package/skills/gsd-mempalace-capture/SKILL.md +1 -1
- package/skills/gsd-new-milestone/SKILL.md +1 -1
- package/skills/gsd-plan-phase/SKILL.md +2 -2
- package/vscode/package.json +1 -1
- package/scripts/gen-emitted-baseline.cjs +0 -145
|
@@ -30,7 +30,67 @@ const { readSubdirectories, getPhaseFileStats, extractCanonicalPlanId, toPosixPa
|
|
|
30
30
|
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
31
31
|
const planningWorkspace = require("./planning-workspace.cjs");
|
|
32
32
|
const { planningDir } = planningWorkspace;
|
|
33
|
+
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
34
|
+
const frontmatterModule = require("./frontmatter.cjs");
|
|
35
|
+
const { extractFrontmatter } = frontmatterModule;
|
|
36
|
+
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
37
|
+
const planDependencyGraphModule = require("./plan-dependency-graph.cjs");
|
|
38
|
+
const { computeHaltPropagation, buildSummaryFileIndex, isSummaryFileHalted } = planDependencyGraphModule;
|
|
39
|
+
/**
|
|
40
|
+
* #2830: parse a plan file's `depends_on` frontmatter. Returns [] — never
|
|
41
|
+
* throws — on a missing/unreadable/malformed plan or absent field, matching
|
|
42
|
+
* this primitive's existing fail-safe posture (a plan directory this
|
|
43
|
+
* primitive can otherwise read must never throw here).
|
|
44
|
+
*/
|
|
45
|
+
function parsePlanDependsOn(phaseDir, planFile) {
|
|
46
|
+
try {
|
|
47
|
+
const planPath = node_path_1.default.join(phaseDir, planFile);
|
|
48
|
+
const content = node_fs_1.default.readFileSync(planPath, 'utf-8');
|
|
49
|
+
const fm = extractFrontmatter(content, planPath);
|
|
50
|
+
const fmDeps = fm['depends_on'];
|
|
51
|
+
if (Array.isArray(fmDeps))
|
|
52
|
+
return fmDeps.map(String);
|
|
53
|
+
if (typeof fmDeps === 'string' && fmDeps.trim() !== '')
|
|
54
|
+
return [fmDeps];
|
|
55
|
+
return [];
|
|
56
|
+
}
|
|
57
|
+
catch {
|
|
58
|
+
return [];
|
|
59
|
+
}
|
|
60
|
+
}
|
|
33
61
|
// ─── Phase search helpers ─────────────────────────────────────────────────────
|
|
62
|
+
/**
|
|
63
|
+
* #2855: single source of truth for resolving and enumerating a project's
|
|
64
|
+
* (or, when a workstream is active, that workstream's OWN) archived-milestone
|
|
65
|
+
* directories — `<planningDir(cwd)>/milestones/vX.Y-phases/`. Both
|
|
66
|
+
* `findPhaseInternal`'s archive fallback and `getArchivedPhaseDirs` used to
|
|
67
|
+
* carry independent copies of this resolve-then-enumerate logic, which is
|
|
68
|
+
* exactly the shape that let the original #2855 bug (hardcoded root path)
|
|
69
|
+
* exist in one copy and not the other. Sharing this seam means a future
|
|
70
|
+
* change to how the archive tree is located only needs to happen once.
|
|
71
|
+
* Most-recent-milestone-first order (reverse-sorted directory names).
|
|
72
|
+
* Never throws: an absent/unreadable milestones/ dir yields [].
|
|
73
|
+
*/
|
|
74
|
+
function listArchiveVersionDirs(cwd) {
|
|
75
|
+
const milestonesDir = node_path_1.default.join(planningDir(cwd), 'milestones');
|
|
76
|
+
if (!node_fs_1.default.existsSync(milestonesDir))
|
|
77
|
+
return [];
|
|
78
|
+
try {
|
|
79
|
+
const milestoneEntries = node_fs_1.default.readdirSync(milestonesDir, { withFileTypes: true });
|
|
80
|
+
return milestoneEntries
|
|
81
|
+
.filter(e => e.isDirectory() && /^v[\d.]+-phases$/.test(e.name))
|
|
82
|
+
.map(e => e.name)
|
|
83
|
+
.sort()
|
|
84
|
+
.reverse()
|
|
85
|
+
.map(archiveName => ({
|
|
86
|
+
version: archiveName.match(/^(v[\d.]+)-phases$/)[1],
|
|
87
|
+
archivePath: node_path_1.default.join(milestonesDir, archiveName),
|
|
88
|
+
}));
|
|
89
|
+
}
|
|
90
|
+
catch {
|
|
91
|
+
return [];
|
|
92
|
+
}
|
|
93
|
+
}
|
|
34
94
|
function searchPhaseInDir(baseDir, relBase, normalized) {
|
|
35
95
|
try {
|
|
36
96
|
const dirs = readSubdirectories(baseDir, true);
|
|
@@ -55,6 +115,9 @@ function searchPhaseInDir(baseDir, relBase, normalized) {
|
|
|
55
115
|
has_verification: false,
|
|
56
116
|
has_reviews: false,
|
|
57
117
|
ambiguous_matches: matches,
|
|
118
|
+
halted_plans: [],
|
|
119
|
+
blocked_by: {},
|
|
120
|
+
runnable_plans: [],
|
|
58
121
|
};
|
|
59
122
|
}
|
|
60
123
|
const match = matches[0];
|
|
@@ -76,6 +139,50 @@ function searchPhaseInDir(baseDir, relBase, normalized) {
|
|
|
76
139
|
const canonical = extractCanonicalPlanId(p);
|
|
77
140
|
return !completedPlanIds.has(planId) && !completedPlanIds.has(canonical);
|
|
78
141
|
});
|
|
142
|
+
// #2830: reverse lookup from a completed plan's id (exact or canonical) to
|
|
143
|
+
// its actual summary filename. Shared builder (also used by phase.cts's
|
|
144
|
+
// cmdPhasePlanIndex) so the two can never disagree about which summary
|
|
145
|
+
// belongs to which plan.
|
|
146
|
+
const summaryFileByPlanId = buildSummaryFileIndex(summaries, extractCanonicalPlanId);
|
|
147
|
+
// #2830: this primitive previously never parsed depends_on at all — see
|
|
148
|
+
// src/plan-dependency-graph.cts's file header. Build the same
|
|
149
|
+
// PlanHaltNode[] shape phase.cts's cmdPhasePlanIndex builds (id resolution
|
|
150
|
+
// mirrors its planMap/canonicalToId pattern) and hand it to the ONE
|
|
151
|
+
// shared halt-propagation traversal so this reader and the wave-grouping
|
|
152
|
+
// reader can never diverge on the halt rule again.
|
|
153
|
+
const planIds = plans.map(p => p.replace('-PLAN.md', '').replace('PLAN.md', ''));
|
|
154
|
+
const planIdByLower = new Map(planIds.map(id => [id.toLowerCase(), id]));
|
|
155
|
+
const canonicalToPlanId = new Map(plans.map((p, i) => [extractCanonicalPlanId(p).toLowerCase(), planIds[i]]));
|
|
156
|
+
const haltNodes = plans.map((p, i) => {
|
|
157
|
+
const planId = planIds[i];
|
|
158
|
+
const canonical = extractCanonicalPlanId(p);
|
|
159
|
+
const summaryFile = summaryFileByPlanId.get(planId) ?? summaryFileByPlanId.get(canonical);
|
|
160
|
+
const halted = summaryFile !== undefined && isSummaryFileHalted(node_path_1.default.join(phaseDir, summaryFile));
|
|
161
|
+
const resolvedDependsOn = parsePlanDependsOn(phaseDir, p)
|
|
162
|
+
.map((dep) => {
|
|
163
|
+
const lower = dep.toLowerCase();
|
|
164
|
+
return planIdByLower.get(lower) ?? canonicalToPlanId.get(lower) ?? null;
|
|
165
|
+
})
|
|
166
|
+
.filter((id) => id !== null);
|
|
167
|
+
return { id: planId, resolvedDependsOn, halted };
|
|
168
|
+
});
|
|
169
|
+
const { blockedBy } = computeHaltPropagation(haltNodes);
|
|
170
|
+
const haltedPlans = plans.filter((_, i) => haltNodes[i].halted);
|
|
171
|
+
const incompletePlanSet = new Set(incompletePlans);
|
|
172
|
+
const blockedByFiles = {};
|
|
173
|
+
const runnablePlans = [];
|
|
174
|
+
for (let i = 0; i < plans.length; i++) {
|
|
175
|
+
const p = plans[i];
|
|
176
|
+
if (!incompletePlanSet.has(p))
|
|
177
|
+
continue;
|
|
178
|
+
const causes = blockedBy.get(planIds[i]) ?? [];
|
|
179
|
+
if (causes.length > 0) {
|
|
180
|
+
blockedByFiles[p] = causes;
|
|
181
|
+
}
|
|
182
|
+
else {
|
|
183
|
+
runnablePlans.push(p);
|
|
184
|
+
}
|
|
185
|
+
}
|
|
79
186
|
return {
|
|
80
187
|
found: true,
|
|
81
188
|
directory: toPosixPath(node_path_1.default.join(relBase, match)),
|
|
@@ -89,6 +196,9 @@ function searchPhaseInDir(baseDir, relBase, normalized) {
|
|
|
89
196
|
has_context: hasContext,
|
|
90
197
|
has_verification: hasVerification,
|
|
91
198
|
has_reviews: hasReviews,
|
|
199
|
+
halted_plans: haltedPlans,
|
|
200
|
+
blocked_by: blockedByFiles,
|
|
201
|
+
runnable_plans: runnablePlans,
|
|
92
202
|
};
|
|
93
203
|
}
|
|
94
204
|
catch {
|
|
@@ -104,59 +214,42 @@ function findPhaseInternal(cwd, phase) {
|
|
|
104
214
|
const current = searchPhaseInDir(phasesDir, relPhasesDir, normalized);
|
|
105
215
|
if (current)
|
|
106
216
|
return current;
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
const result = searchPhaseInDir(archivePath, relBase, normalized);
|
|
123
|
-
if (result) {
|
|
124
|
-
result.archived = version;
|
|
125
|
-
return result;
|
|
126
|
-
}
|
|
217
|
+
// #2855: scope the archived-milestone fallback to the SAME workstream as the
|
|
218
|
+
// active-phase search above (planningDir(cwd) resolves GSD_WORKSTREAM/GSD_PROJECT
|
|
219
|
+
// the identical way both places), not the hardcoded project-root tree. Archived
|
|
220
|
+
// phases genuinely live under a workstream's own `.planning/workstreams/<ws>/
|
|
221
|
+
// milestones/` — that is where archivePhaseDirectories (milestone.cts) writes
|
|
222
|
+
// them via the same planningDir(cwd) resolution. Hardcoding root here let a
|
|
223
|
+
// pending workstream phase resolve to an unrelated workstream's (or a flat-mode
|
|
224
|
+
// project's) archived phase that merely shares a phase number. Shared with
|
|
225
|
+
// getArchivedPhaseDirs via listArchiveVersionDirs (see its doc comment).
|
|
226
|
+
for (const { version, archivePath } of listArchiveVersionDirs(cwd)) {
|
|
227
|
+
const relBase = toPosixPath(node_path_1.default.relative(cwd, archivePath));
|
|
228
|
+
const result = searchPhaseInDir(archivePath, relBase, normalized);
|
|
229
|
+
if (result) {
|
|
230
|
+
result.archived = version;
|
|
231
|
+
return result;
|
|
127
232
|
}
|
|
128
233
|
}
|
|
129
|
-
catch { /* intentionally empty */ }
|
|
130
234
|
return null;
|
|
131
235
|
}
|
|
132
236
|
function getArchivedPhaseDirs(cwd) {
|
|
133
|
-
|
|
237
|
+
// #2855: same workstream-scoped resolution as findPhaseInternal above, via
|
|
238
|
+
// the shared listArchiveVersionDirs helper. `phase.list --include-archived`
|
|
239
|
+
// (the primary non-init consumer) must not leak a different workstream's
|
|
240
|
+
// archive either.
|
|
134
241
|
const results = [];
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
for (const archiveName of phaseDirs) {
|
|
145
|
-
const versionMatch = archiveName.match(/^(v[\d.]+)-phases$/);
|
|
146
|
-
const version = versionMatch[1];
|
|
147
|
-
const archivePath = node_path_1.default.join(milestonesDir, archiveName);
|
|
148
|
-
const dirs = readSubdirectories(archivePath, true);
|
|
149
|
-
for (const dir of dirs) {
|
|
150
|
-
results.push({
|
|
151
|
-
name: dir,
|
|
152
|
-
milestone: version,
|
|
153
|
-
basePath: node_path_1.default.join('.planning', 'milestones', archiveName),
|
|
154
|
-
fullPath: node_path_1.default.join(archivePath, dir),
|
|
155
|
-
});
|
|
156
|
-
}
|
|
242
|
+
for (const { version, archivePath } of listArchiveVersionDirs(cwd)) {
|
|
243
|
+
const dirs = readSubdirectories(archivePath, true);
|
|
244
|
+
for (const dir of dirs) {
|
|
245
|
+
results.push({
|
|
246
|
+
name: dir,
|
|
247
|
+
milestone: version,
|
|
248
|
+
basePath: toPosixPath(node_path_1.default.relative(cwd, archivePath)),
|
|
249
|
+
fullPath: node_path_1.default.join(archivePath, dir),
|
|
250
|
+
});
|
|
157
251
|
}
|
|
158
252
|
}
|
|
159
|
-
catch { /* intentionally empty */ }
|
|
160
253
|
return results;
|
|
161
254
|
}
|
|
162
255
|
module.exports = {
|