@opengsd/gsd-core 1.7.0-rc.6 → 1.8.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/.opencode/plugins/gsd-core.js +14 -0
- package/README.md +2 -0
- package/agents/gsd-debug-session-manager.md +42 -4
- package/agents/gsd-debugger.md +87 -29
- package/agents/gsd-executor.md +31 -3
- package/agents/gsd-planner.md +29 -36
- package/agents/gsd-security-auditor.md +13 -15
- package/agents/gsd-verifier.md +2 -2
- package/bin/install.js +1157 -84
- package/commands/gsd/ai-integration-phase.md +1 -1
- package/commands/gsd/mempalace-capture.md +31 -1
- package/commands/gsd/new-milestone.md +1 -1
- package/commands/gsd/plan-phase.md +5 -3
- package/commands/gsd/plan-review-convergence.md +3 -2
- package/commands/gsd/surface.md +6 -6
- package/gsd-core/bin/gsd-tools.cjs +1866 -2434
- package/gsd-core/bin/lib/adapter-imperative.cjs +8 -1
- package/gsd-core/bin/lib/agent-command-router.cjs +20 -5
- package/gsd-core/bin/lib/api-coverage.cjs +341 -49
- package/gsd-core/bin/lib/audit.cjs +7 -6
- package/gsd-core/bin/lib/broken-windows.cjs +716 -0
- package/gsd-core/bin/lib/capability-command-router.cjs +733 -0
- package/gsd-core/bin/lib/capability-registry.cjs +157 -88
- package/gsd-core/bin/lib/capability-writer.cjs +6 -1
- package/gsd-core/bin/lib/check-command-router.cjs +129 -26
- package/gsd-core/bin/lib/claude-orchestration-command-router.cjs +115 -27
- package/gsd-core/bin/lib/claude-orchestration.cjs +84 -9
- package/gsd-core/bin/lib/clock.cjs +19 -0
- package/gsd-core/bin/lib/command-aliases.cjs +14 -0
- package/gsd-core/bin/lib/commands.cjs +129 -13
- package/gsd-core/bin/lib/config-loader.cjs +20 -4
- package/gsd-core/bin/lib/config.cjs +81 -18
- package/gsd-core/bin/lib/core-utils.cjs +14 -3
- package/gsd-core/bin/lib/decisions.cjs +32 -8
- package/gsd-core/bin/lib/docs.cjs +6 -0
- package/gsd-core/bin/lib/drift.cjs +4 -4
- package/gsd-core/bin/lib/external-descriptor-trust.cjs +14 -2
- package/gsd-core/bin/lib/frontmatter.cjs +22 -0
- package/gsd-core/bin/lib/gap-checker.cjs +17 -2
- package/gsd-core/bin/lib/gsd2-import.cjs +2 -1
- package/gsd-core/bin/lib/init.cjs +138 -60
- package/gsd-core/bin/lib/install-engine.cjs +301 -25
- package/gsd-core/bin/lib/install-profiles.cjs +239 -1
- package/gsd-core/bin/lib/installer-migration-authoring.cjs +2 -1
- package/gsd-core/bin/lib/installer-migrations/005-opencode-baseline-commands-dir.cjs +146 -0
- package/gsd-core/bin/lib/installer-migrations/006-pi-extension-cjs-to-js.cjs +91 -0
- package/gsd-core/bin/lib/installer-migrations.cjs +45 -6
- package/gsd-core/bin/lib/markdown-sectionizer.cjs +449 -0
- package/gsd-core/bin/lib/markdown-table.cjs +698 -0
- package/gsd-core/bin/lib/milestone.cjs +463 -43
- package/gsd-core/bin/lib/model-catalog.cjs +19 -4
- package/gsd-core/bin/lib/model-resolver.cjs +189 -7
- package/gsd-core/bin/lib/onboard-projection.cjs +11 -8
- package/gsd-core/bin/lib/phase-command-router.cjs +50 -2
- package/gsd-core/bin/lib/phase-id.cjs +26 -4
- package/gsd-core/bin/lib/phase-lifecycle.cjs +62 -36
- package/gsd-core/bin/lib/phase-locator.cjs +23 -2
- package/gsd-core/bin/lib/phase.cjs +636 -72
- package/gsd-core/bin/lib/plan-scan.cjs +73 -2
- package/gsd-core/bin/lib/roadmap-parser.cjs +225 -17
- package/gsd-core/bin/lib/roadmap.cjs +113 -52
- package/gsd-core/bin/lib/runtime-artifact-conversion.cjs +14 -7
- package/gsd-core/bin/lib/runtime-artifact-install-plan.cjs +3 -2
- package/gsd-core/bin/lib/runtime-artifact-layout.cjs +24 -9
- package/gsd-core/bin/lib/runtime-hooks-surface.cjs +41 -17
- package/gsd-core/bin/lib/schema-detect.cjs +2 -1
- package/gsd-core/bin/lib/security.cjs +1 -1
- package/gsd-core/bin/lib/shell-command-projection.cjs +61 -25
- package/gsd-core/bin/lib/smart-entry.cjs +73 -7
- package/gsd-core/bin/lib/state-document.cjs +7 -4
- package/gsd-core/bin/lib/state-transition.cjs +122 -46
- package/gsd-core/bin/lib/state.cjs +456 -137
- package/gsd-core/bin/lib/surface.cjs +53 -11
- package/gsd-core/bin/lib/template.cjs +2 -1
- package/gsd-core/bin/lib/uat.cjs +474 -13
- package/gsd-core/bin/lib/ui-safety-gate.cjs +23 -1
- package/gsd-core/bin/lib/validate.cjs +12 -8
- package/gsd-core/bin/lib/verification.cjs +112 -17
- package/gsd-core/bin/lib/verify.cjs +224 -25
- package/gsd-core/bin/lib/workstream.cjs +3 -2
- package/gsd-core/bin/lib/worktree-safety.cjs +1 -1
- package/gsd-core/bin/lib/write-set.cjs +38 -0
- package/gsd-core/bin/shared/config-schema.manifest.json +5 -2
- package/gsd-core/references/api-coverage.md +37 -7
- package/gsd-core/references/checkpoints.md +13 -1
- package/gsd-core/references/common-bug-patterns.md +13 -0
- package/gsd-core/references/debugger-bug-taxonomy.md +111 -0
- package/gsd-core/references/debugger-fix-acceptance.md +157 -0
- package/gsd-core/references/debugger-philosophy.md +1 -0
- package/gsd-core/references/debugger-prevention.md +98 -0
- package/gsd-core/references/debugger-rca-branching.md +98 -0
- package/gsd-core/references/debugger-repro-hardening.md +130 -0
- package/gsd-core/references/debugger-sbfl.md +110 -0
- package/gsd-core/references/debugger-semantic-recall.md +81 -0
- package/gsd-core/references/execute-phase-quota-recovery.md +55 -0
- package/gsd-core/references/execute-phase-requirement-revert.md +8 -0
- package/gsd-core/references/execute-phase-response-language.md +7 -0
- package/gsd-core/references/planner-antipatterns.md +6 -0
- package/gsd-core/references/planner-mvp-mode.md +12 -13
- package/gsd-core/references/planner-preconditions.md +156 -0
- package/gsd-core/references/planner-reversibility.md +132 -0
- package/gsd-core/references/reviewer-instances.md +9 -7
- package/gsd-core/references/skeleton-template.md +1 -1
- package/gsd-core/references/thinking-models-planning.md +3 -1
- package/gsd-core/templates/DEBUG.md +5 -3
- package/gsd-core/workflows/add-phase.md +2 -0
- package/gsd-core/workflows/add-tests.md +4 -2
- package/gsd-core/workflows/add-todo.md +32 -1
- package/gsd-core/workflows/ai-integration-phase.md +4 -2
- package/gsd-core/workflows/audit-fix.md +2 -2
- package/gsd-core/workflows/check-todos.md +3 -1
- package/gsd-core/workflows/cleanup.md +7 -1
- package/gsd-core/workflows/code-review.md +17 -5
- package/gsd-core/workflows/complete-milestone.md +3 -0
- package/gsd-core/workflows/debug.md +27 -5
- package/gsd-core/workflows/diagnose-issues.md +1 -1
- package/gsd-core/workflows/discovery-phase.md +7 -0
- package/gsd-core/workflows/discuss-phase/templates/context.md +16 -2
- package/gsd-core/workflows/discuss-phase-assumptions.md +3 -0
- package/gsd-core/workflows/do.md +7 -1
- package/gsd-core/workflows/docs-update.md +1 -0
- package/gsd-core/workflows/eval-review.md +3 -0
- package/gsd-core/workflows/execute-phase/steps/post-merge-gate.md +4 -4
- package/gsd-core/workflows/execute-phase/steps/regression-gate.md +2 -2
- package/gsd-core/workflows/execute-phase.md +30 -37
- package/gsd-core/workflows/execute-plan.md +15 -4
- package/gsd-core/workflows/fast.md +8 -22
- package/gsd-core/workflows/graduation.md +3 -0
- package/gsd-core/workflows/health.md +7 -1
- package/gsd-core/workflows/help/modes/full.md +6 -2
- package/gsd-core/workflows/import.md +8 -2
- package/gsd-core/workflows/inbox.md +7 -0
- package/gsd-core/workflows/ingest-docs.md +15 -10
- package/gsd-core/workflows/manager.md +3 -1
- package/gsd-core/workflows/map-codebase.md +4 -4
- package/gsd-core/workflows/mvp-phase.md +3 -0
- package/gsd-core/workflows/new-milestone.md +69 -21
- package/gsd-core/workflows/new-project.md +17 -15
- package/gsd-core/workflows/new-workspace.md +3 -1
- package/gsd-core/workflows/onboard.md +3 -0
- package/gsd-core/workflows/plan-phase.md +14 -5
- package/gsd-core/workflows/plan-review-convergence.md +48 -3
- package/gsd-core/workflows/plant-seed.md +3 -0
- package/gsd-core/workflows/profile-user.md +7 -1
- package/gsd-core/workflows/progress.md +33 -5
- package/gsd-core/workflows/quick.md +21 -7
- package/gsd-core/workflows/remove-workspace.md +3 -0
- package/gsd-core/workflows/review.md +123 -68
- package/gsd-core/workflows/scan.md +1 -1
- package/gsd-core/workflows/secure-phase.md +4 -1
- package/gsd-core/workflows/settings-integrations.md +3 -0
- package/gsd-core/workflows/settings.md +3 -0
- package/gsd-core/workflows/ship.md +58 -5
- package/gsd-core/workflows/sketch.md +3 -0
- package/gsd-core/workflows/smart-entry.md +3 -0
- package/gsd-core/workflows/spec-phase.md +1 -1
- package/gsd-core/workflows/spike.md +7 -1
- package/gsd-core/workflows/transition.md +1 -1
- package/gsd-core/workflows/ui-phase.md +3 -1
- package/gsd-core/workflows/ui-review.md +3 -0
- package/gsd-core/workflows/undo.md +7 -0
- package/gsd-core/workflows/update.md +2 -0
- package/gsd-core/workflows/validate-phase.md +3 -0
- package/gsd-core/workflows/verify-phase.md +2 -2
- package/gsd-core/workflows/verify-work.md +7 -3
- package/hooks/dist/gsd-context-monitor.js +27 -9
- package/hooks/dist/gsd-statusline.js +252 -17
- package/hooks/gsd-context-monitor.js +27 -9
- package/hooks/gsd-statusline.js +252 -17
- package/package.json +8 -4
- package/pi/gsd.cjs +8 -2
- package/scripts/changeset/lint.cjs +1 -0
- package/scripts/changeset/parse.cjs +26 -0
- package/scripts/check-glossary-refs.cjs +220 -0
- package/scripts/ci-rebase-check.cjs +48 -4
- package/scripts/ci-test-scope.cjs +39 -1
- package/scripts/gen-adr-index.cjs +526 -0
- package/scripts/gen-golden-install-parity-zcode.cjs +35 -45
- package/scripts/gen-install-tree-fixtures.cjs +75 -0
- package/scripts/gen-test-timings.cjs +201 -0
- package/scripts/lint-allow-test-rule-refs.allowlist.json +0 -1
- package/scripts/lint-portable-timeout.cjs +140 -0
- package/scripts/lint-table-schema-drift.cjs +157 -0
- package/scripts/lint-test-file-count.allowlist.json +1 -0
- package/scripts/release-tarball-smoke.cjs +18 -11
- package/scripts/run-tests.cjs +420 -58
- package/skills/gsd-ai-integration-phase/SKILL.md +1 -1
- package/skills/gsd-mempalace-capture/SKILL.md +31 -1
- package/skills/gsd-new-milestone/SKILL.md +1 -1
- package/skills/gsd-plan-phase/SKILL.md +5 -3
- package/skills/gsd-plan-review-convergence/SKILL.md +3 -2
- package/skills/gsd-surface/SKILL.md +6 -6
- package/vscode/package.json +1 -1
|
@@ -522,6 +522,27 @@ const FRONTMATTER_SCHEMAS = {
|
|
|
522
522
|
summary: { required: ['phase', 'plan', 'subsystem', 'tags', 'duration', 'completed'] },
|
|
523
523
|
verification: { required: ['phase', 'verified', 'status', 'score'] },
|
|
524
524
|
};
|
|
525
|
+
/**
|
|
526
|
+
* Strip ALL frontmatter blocks from the start of `content`.
|
|
527
|
+
*
|
|
528
|
+
* Handles CRLF line endings and multiple stacked blocks (corruption
|
|
529
|
+
* recovery): greedily strips consecutive `---...---` blocks separated by
|
|
530
|
+
* optional whitespace, so a doubled/tripled frontmatter header (e.g. from a
|
|
531
|
+
* botched merge) is fully removed, not just the first block.
|
|
532
|
+
*
|
|
533
|
+
* Canonical home for this primitive (#2143 audit dedup): previously
|
|
534
|
+
* duplicated byte-identically in both `state.cts` and `state-transition.cts`.
|
|
535
|
+
*/
|
|
536
|
+
function stripFrontmatter(content) {
|
|
537
|
+
let result = content;
|
|
538
|
+
while (true) {
|
|
539
|
+
const stripped = result.replace(/^\s*---\r?\n[\s\S]*?\r?\n---\s*/, '');
|
|
540
|
+
if (stripped === result)
|
|
541
|
+
break;
|
|
542
|
+
result = stripped;
|
|
543
|
+
}
|
|
544
|
+
return result;
|
|
545
|
+
}
|
|
525
546
|
function cmdFrontmatterGet(cwd, filePath, field, raw) {
|
|
526
547
|
if (!filePath) {
|
|
527
548
|
error('file path required');
|
|
@@ -654,6 +675,7 @@ module.exports = {
|
|
|
654
675
|
parseFrontmatter: extractFrontmatter,
|
|
655
676
|
reconstructFrontmatter,
|
|
656
677
|
spliceFrontmatter,
|
|
678
|
+
stripFrontmatter,
|
|
657
679
|
noOpObjectListSetError,
|
|
658
680
|
parseMustHavesBlock,
|
|
659
681
|
FRONTMATTER_SCHEMAS,
|
|
@@ -298,7 +298,16 @@ function runGapAnalysis(cwd, phaseDir, options = {}) {
|
|
|
298
298
|
const mismatchMsg = '## Post-Planning Gap Analysis\n\nextracted 0 of N — possible format mismatch in CONTEXT.md decisions block.\n';
|
|
299
299
|
// If there are also requirement items, include them in the return with the
|
|
300
300
|
// mismatch summary appended, so the caller still sees requirement coverage.
|
|
301
|
-
|
|
301
|
+
// #2334 HIGH 1: gate on `ghostReqIds.length > 0` too — identical defect to
|
|
302
|
+
// the one fixed at #2316-6b (~34 lines below, at the `items.length === 0`
|
|
303
|
+
// early return): a phase whose EVERY cited REQ-ID is unregistered has
|
|
304
|
+
// `items.length === 0` (all its requirement items were filtered out at
|
|
305
|
+
// ~line 297) but still has real ghost rows to report. Without this guard,
|
|
306
|
+
// a single malformed `<decisions>` line in CONTEXT.md made an all-ghost
|
|
307
|
+
// phase's ghost rows silently vanish (this could-not-parse branch fell
|
|
308
|
+
// through to the bare `mismatchMsg`-only return below, dropping ghost
|
|
309
|
+
// rows that the general path further down correctly surfaces).
|
|
310
|
+
if (items.length > 0 || ghostReqIds.length > 0) {
|
|
302
311
|
const rows = sortRows([
|
|
303
312
|
...detectCoverage(items, planText),
|
|
304
313
|
...ghostReqIds.map(id => ({ source: 'REQUIREMENTS.md', item: id, status: 'Missing from REQUIREMENTS.md' })),
|
|
@@ -325,7 +334,13 @@ function runGapAnalysis(cwd, phaseDir, options = {}) {
|
|
|
325
334
|
};
|
|
326
335
|
}
|
|
327
336
|
// #1365: if no items at all, surface a clean no-check message.
|
|
328
|
-
|
|
337
|
+
// #2316-6b: this must NOT fire when `ghostReqIds` is non-empty — a phase
|
|
338
|
+
// whose EVERY cited REQ-ID is unregistered has `items.length === 0` (all
|
|
339
|
+
// its requirement items were filtered out at ~line 297) but still has real
|
|
340
|
+
// ghost rows to report below. Without this guard, an all-orphan phase
|
|
341
|
+
// reported LESS than a partially-orphan one (which falls through to the
|
|
342
|
+
// general path further down and correctly surfaces its ghost rows).
|
|
343
|
+
if (items.length === 0 && ghostReqIds.length === 0) {
|
|
329
344
|
return {
|
|
330
345
|
enabled: true,
|
|
331
346
|
rows: [],
|
|
@@ -26,6 +26,7 @@ const node_fs_1 = __importDefault(require("node:fs"));
|
|
|
26
26
|
const node_path_1 = __importDefault(require("node:path"));
|
|
27
27
|
const shell_command_projection_cjs_1 = require("./shell-command-projection.cjs");
|
|
28
28
|
const runtime_slash_cjs_1 = require("./runtime-slash.cjs");
|
|
29
|
+
const clock_cjs_1 = require("./clock.cjs");
|
|
29
30
|
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
30
31
|
const ioMod = require("./io.cjs");
|
|
31
32
|
const { output } = ioMod;
|
|
@@ -276,7 +277,7 @@ function buildStateMd(phaseMap) {
|
|
|
276
277
|
const status = currentEntry ? 'Ready to plan' : 'All phases complete';
|
|
277
278
|
const filled = Math.round(pct / 10);
|
|
278
279
|
const bar = `[${'█'.repeat(filled)}${'░'.repeat(10 - filled)}]`;
|
|
279
|
-
const today =
|
|
280
|
+
const today = clock_cjs_1.realClock.localToday();
|
|
280
281
|
return [
|
|
281
282
|
'# Project State',
|
|
282
283
|
'',
|
|
@@ -13,6 +13,7 @@ const node_fs_1 = __importDefault(require("node:fs"));
|
|
|
13
13
|
const node_path_1 = __importDefault(require("node:path"));
|
|
14
14
|
const node_os_1 = __importDefault(require("node:os"));
|
|
15
15
|
const shell_command_projection_cjs_1 = require("./shell-command-projection.cjs");
|
|
16
|
+
const clock_cjs_1 = require("./clock.cjs");
|
|
16
17
|
// eslint-disable-next-line @typescript-eslint/no-require-imports -- io.cjs is an export= CommonJS module
|
|
17
18
|
const io = require("./io.cjs");
|
|
18
19
|
// eslint-disable-next-line @typescript-eslint/no-require-imports -- config-loader.cjs is an export= CommonJS module
|
|
@@ -203,7 +204,7 @@ function getInitGitState(cwd) {
|
|
|
203
204
|
}
|
|
204
205
|
resolved = node_path_1.default.resolve(resolved);
|
|
205
206
|
if (process.platform === 'win32') {
|
|
206
|
-
return
|
|
207
|
+
return (0, shell_command_projection_cjs_1.toNativePath)(resolved).toLowerCase();
|
|
207
208
|
}
|
|
208
209
|
return resolved;
|
|
209
210
|
};
|
|
@@ -213,7 +214,7 @@ function getInitGitState(cwd) {
|
|
|
213
214
|
try {
|
|
214
215
|
const prefixResult = (0, shell_command_projection_cjs_1.execGit)(['rev-parse', '--show-prefix'], { cwd, timeout: 5000 });
|
|
215
216
|
if (prefixResult['exitCode'] === 0) {
|
|
216
|
-
const prefix = (typeof prefixResult['stdout'] === 'string' ? prefixResult['stdout'] : '').trim()
|
|
217
|
+
const prefix = (0, shell_command_projection_cjs_1.posixNormalize)((typeof prefixResult['stdout'] === 'string' ? prefixResult['stdout'] : '').trim());
|
|
217
218
|
inNestedSubdir = prefix.length > 0 && prefix !== '.' && prefix !== './';
|
|
218
219
|
resolvedByGitPrefix = true;
|
|
219
220
|
}
|
|
@@ -230,7 +231,7 @@ function getInitGitState(cwd) {
|
|
|
230
231
|
}
|
|
231
232
|
else {
|
|
232
233
|
const rel = node_path_1.default.relative(rootNorm, cwdNorm);
|
|
233
|
-
const relNorm =
|
|
234
|
+
const relNorm = (0, shell_command_projection_cjs_1.toNativePath)(rel);
|
|
234
235
|
inNestedSubdir =
|
|
235
236
|
relNorm !== '' &&
|
|
236
237
|
relNorm !== '.' &&
|
|
@@ -244,7 +245,7 @@ function getInitGitState(cwd) {
|
|
|
244
245
|
}
|
|
245
246
|
}
|
|
246
247
|
if (inNestedSubdir && typeof worktreeRoot === 'string') {
|
|
247
|
-
const toComparableRaw = (p) =>
|
|
248
|
+
const toComparableRaw = (p) => (0, shell_command_projection_cjs_1.posixNormalize)(p).replace(/\/+$/g, '').toLowerCase();
|
|
248
249
|
if (toComparableRaw(worktreeRoot) === toComparableRaw(String(cwd))) {
|
|
249
250
|
inNestedSubdir = false;
|
|
250
251
|
}
|
|
@@ -304,7 +305,11 @@ function cmdInitExecutePhase(cwd, phase, raw, options = {}) {
|
|
|
304
305
|
milestone_branch_template: config.milestone_branch_template,
|
|
305
306
|
verifier_enabled: config.verifier,
|
|
306
307
|
phase_found: !!phaseInfo,
|
|
307
|
-
|
|
308
|
+
// #2376: absolute (anchored on cwd/project_root), not orchestrator-cwd-relative —
|
|
309
|
+
// a spawned subagent's own cwd may differ from the orchestrator's.
|
|
310
|
+
phase_dir: phaseInfo?.['directory']
|
|
311
|
+
? toPosixPath(node_path_1.default.join(cwd, phaseInfo['directory']))
|
|
312
|
+
: null,
|
|
308
313
|
phase_number: phaseInfo?.['phase_number'] || null,
|
|
309
314
|
phase_name: phaseInfo?.['phase_name'] || null,
|
|
310
315
|
phase_slug: phaseInfo?.['phase_slug'] || null,
|
|
@@ -330,9 +335,13 @@ function cmdInitExecutePhase(cwd, phase, raw, options = {}) {
|
|
|
330
335
|
state_exists: node_fs_1.default.existsSync(node_path_1.default.join(planningDir(cwd), 'STATE.md')),
|
|
331
336
|
roadmap_exists: node_fs_1.default.existsSync(node_path_1.default.join(planningDir(cwd), 'ROADMAP.md')),
|
|
332
337
|
config_exists: node_fs_1.default.existsSync(node_path_1.default.join(planningDir(cwd), 'config.json')),
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
338
|
+
// #2376: emit absolute paths — see comment above on phase_dir.
|
|
339
|
+
state_path: toPosixPath(node_path_1.default.join(planningDir(cwd), 'STATE.md')),
|
|
340
|
+
roadmap_path: toPosixPath(node_path_1.default.join(planningDir(cwd), 'ROADMAP.md')),
|
|
341
|
+
config_path: toPosixPath(node_path_1.default.join(planningDir(cwd), 'config.json')),
|
|
342
|
+
// #2376: execute-phase.md's verify_phase_goal step reads this instead of
|
|
343
|
+
// hardcoding '.planning/REQUIREMENTS.md' into the gsd-verifier spawn prompt.
|
|
344
|
+
requirements_path: toPosixPath(node_path_1.default.join(planningDir(cwd), 'REQUIREMENTS.md')),
|
|
336
345
|
};
|
|
337
346
|
if (options['validate']) {
|
|
338
347
|
try {
|
|
@@ -404,7 +413,8 @@ function cmdInitPlanPhase(cwd, phase, raw, options = {}) {
|
|
|
404
413
|
if (slug) {
|
|
405
414
|
const prefix = rawProjectCodePlan ? `${rawProjectCodePlan}-` : '';
|
|
406
415
|
const dirName = `${prefix}${paddedNum}-${slug}`;
|
|
407
|
-
|
|
416
|
+
// #2376: absolute — see comment on phase_dir below.
|
|
417
|
+
expectedPhaseDirPlan = toPosixPath(node_path_1.default.join(planningPaths(cwd).phases, dirName));
|
|
408
418
|
}
|
|
409
419
|
}
|
|
410
420
|
const granularityOverride = options['granularity'];
|
|
@@ -426,7 +436,10 @@ function cmdInitPlanPhase(cwd, phase, raw, options = {}) {
|
|
|
426
436
|
auto_chain_active: !!(config._auto_chain_active),
|
|
427
437
|
mode: config.mode || 'interactive',
|
|
428
438
|
phase_found: !!phaseInfo,
|
|
429
|
-
|
|
439
|
+
// #2376: absolute (anchored on cwd/project_root) — path.join(cwd, phaseDirPlan)
|
|
440
|
+
// handed to a spawned subagent must resolve regardless of that subagent's own cwd.
|
|
441
|
+
// phaseDirPlan itself stays relative — phase_status below still joins it against cwd.
|
|
442
|
+
phase_dir: phaseDirPlan ? toPosixPath(node_path_1.default.join(cwd, phaseDirPlan)) : null,
|
|
430
443
|
expected_phase_dir: expectedPhaseDirPlan,
|
|
431
444
|
phase_number: phaseNumberPlan,
|
|
432
445
|
phase_name: phaseNamePlan,
|
|
@@ -443,9 +456,10 @@ function cmdInitPlanPhase(cwd, phase, raw, options = {}) {
|
|
|
443
456
|
plan_count: phaseInfo?.['plans']?.length || 0,
|
|
444
457
|
planning_exists: node_fs_1.default.existsSync(planningDir(cwd)),
|
|
445
458
|
roadmap_exists: node_fs_1.default.existsSync(node_path_1.default.join(planningDir(cwd), 'ROADMAP.md')),
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
459
|
+
// #2376: absolute — see comment on phase_dir above.
|
|
460
|
+
state_path: toPosixPath(node_path_1.default.join(planningDir(cwd), 'STATE.md')),
|
|
461
|
+
roadmap_path: toPosixPath(node_path_1.default.join(planningDir(cwd), 'ROADMAP.md')),
|
|
462
|
+
requirements_path: toPosixPath(node_path_1.default.join(planningDir(cwd), 'REQUIREMENTS.md')),
|
|
449
463
|
patterns_path: null,
|
|
450
464
|
};
|
|
451
465
|
if (phaseInfo?.['directory']) {
|
|
@@ -454,27 +468,27 @@ function cmdInitPlanPhase(cwd, phase, raw, options = {}) {
|
|
|
454
468
|
const files = node_fs_1.default.readdirSync(phaseDirFull);
|
|
455
469
|
const contextFile = findContextMdIn(phaseDirFull);
|
|
456
470
|
if (contextFile) {
|
|
457
|
-
result['context_path'] = toPosixPath(node_path_1.default.join(
|
|
471
|
+
result['context_path'] = toPosixPath(node_path_1.default.join(phaseDirFull, contextFile));
|
|
458
472
|
}
|
|
459
473
|
const researchFile = files.find((f) => f.endsWith('-RESEARCH.md') || f === 'RESEARCH.md');
|
|
460
474
|
if (researchFile) {
|
|
461
|
-
result['research_path'] = toPosixPath(node_path_1.default.join(
|
|
475
|
+
result['research_path'] = toPosixPath(node_path_1.default.join(phaseDirFull, researchFile));
|
|
462
476
|
}
|
|
463
477
|
const verificationFile = files.find((f) => f.endsWith('-VERIFICATION.md') || f === 'VERIFICATION.md');
|
|
464
478
|
if (verificationFile) {
|
|
465
|
-
result['verification_path'] = toPosixPath(node_path_1.default.join(
|
|
479
|
+
result['verification_path'] = toPosixPath(node_path_1.default.join(phaseDirFull, verificationFile));
|
|
466
480
|
}
|
|
467
481
|
const uatFile = files.find((f) => f.endsWith('-UAT.md') || f === 'UAT.md');
|
|
468
482
|
if (uatFile) {
|
|
469
|
-
result['uat_path'] = toPosixPath(node_path_1.default.join(
|
|
483
|
+
result['uat_path'] = toPosixPath(node_path_1.default.join(phaseDirFull, uatFile));
|
|
470
484
|
}
|
|
471
485
|
const reviewsFile = files.find((f) => f.endsWith('-REVIEWS.md') || f === 'REVIEWS.md');
|
|
472
486
|
if (reviewsFile) {
|
|
473
|
-
result['reviews_path'] = toPosixPath(node_path_1.default.join(
|
|
487
|
+
result['reviews_path'] = toPosixPath(node_path_1.default.join(phaseDirFull, reviewsFile));
|
|
474
488
|
}
|
|
475
489
|
const patternsFile = files.find((f) => f.endsWith('-PATTERNS.md') || f === 'PATTERNS.md');
|
|
476
490
|
if (patternsFile) {
|
|
477
|
-
result['patterns_path'] = toPosixPath(node_path_1.default.join(
|
|
491
|
+
result['patterns_path'] = toPosixPath(node_path_1.default.join(phaseDirFull, patternsFile));
|
|
478
492
|
}
|
|
479
493
|
}
|
|
480
494
|
catch {
|
|
@@ -535,7 +549,14 @@ function cmdInitNewProject(cwd, raw) {
|
|
|
535
549
|
brave_search_available: hasBraveSearch,
|
|
536
550
|
firecrawl_available: hasFirecrawl,
|
|
537
551
|
exa_search_available: hasExaSearch,
|
|
538
|
-
|
|
552
|
+
// #2376: absolute — see comment on phase_dir in cmdInitExecutePhase.
|
|
553
|
+
project_path: toPosixPath(node_path_1.default.join(planningDir(cwd), 'PROJECT.md')),
|
|
554
|
+
// #2376: new-project.md's research-synthesizer/roadmapper spawn prompts
|
|
555
|
+
// read these instead of hardcoding '.planning/...' literals.
|
|
556
|
+
requirements_path: toPosixPath(node_path_1.default.join(planningDir(cwd), 'REQUIREMENTS.md')),
|
|
557
|
+
roadmap_path: toPosixPath(node_path_1.default.join(planningDir(cwd), 'ROADMAP.md')),
|
|
558
|
+
config_path: toPosixPath(node_path_1.default.join(planningDir(cwd), 'config.json')),
|
|
559
|
+
research_dir: toPosixPath(node_path_1.default.join(planningRoot(cwd), 'research')),
|
|
539
560
|
};
|
|
540
561
|
output(withProjectRoot(cwd, result), raw);
|
|
541
562
|
}
|
|
@@ -569,15 +590,22 @@ function cmdInitNewMilestone(cwd, raw) {
|
|
|
569
590
|
latest_completed_milestone: latestCompleted?.version || null,
|
|
570
591
|
latest_completed_milestone_name: latestCompleted?.name || null,
|
|
571
592
|
phase_dir_count: phaseDirCount,
|
|
593
|
+
// #2376: absolute — see comment on phase_dir in cmdInitExecutePhase.
|
|
572
594
|
phase_archive_path: latestCompleted
|
|
573
|
-
? toPosixPath(node_path_1.default.
|
|
595
|
+
? toPosixPath(node_path_1.default.join(planningRoot(cwd), 'milestones', `${latestCompleted.version}-phases`))
|
|
574
596
|
: null,
|
|
575
597
|
project_exists: pathExistsInternal(cwd, '.planning/PROJECT.md'),
|
|
576
598
|
roadmap_exists: node_fs_1.default.existsSync(node_path_1.default.join(planningDir(cwd), 'ROADMAP.md')),
|
|
577
599
|
state_exists: node_fs_1.default.existsSync(node_path_1.default.join(planningDir(cwd), 'STATE.md')),
|
|
578
|
-
project_path: '
|
|
579
|
-
roadmap_path: toPosixPath(node_path_1.default.
|
|
580
|
-
state_path: toPosixPath(node_path_1.default.
|
|
600
|
+
project_path: toPosixPath(node_path_1.default.join(planningDir(cwd), 'PROJECT.md')),
|
|
601
|
+
roadmap_path: toPosixPath(node_path_1.default.join(planningDir(cwd), 'ROADMAP.md')),
|
|
602
|
+
state_path: toPosixPath(node_path_1.default.join(planningDir(cwd), 'STATE.md')),
|
|
603
|
+
// #2376: new-milestone.md's research-synthesizer/roadmapper spawn prompts
|
|
604
|
+
// read these instead of hardcoding '.planning/...' literals.
|
|
605
|
+
requirements_path: toPosixPath(node_path_1.default.join(planningDir(cwd), 'REQUIREMENTS.md')),
|
|
606
|
+
config_path: toPosixPath(node_path_1.default.join(planningDir(cwd), 'config.json')),
|
|
607
|
+
research_dir: toPosixPath(node_path_1.default.join(planningRoot(cwd), 'research')),
|
|
608
|
+
milestones_path: toPosixPath(node_path_1.default.join(planningDir(cwd), 'MILESTONES.md')),
|
|
581
609
|
};
|
|
582
610
|
output(withProjectRoot(cwd, result), raw);
|
|
583
611
|
}
|
|
@@ -613,10 +641,13 @@ function cmdInitQuick(cwd, description, raw) {
|
|
|
613
641
|
quick_id: quickId,
|
|
614
642
|
slug: slug,
|
|
615
643
|
description: description || null,
|
|
616
|
-
date:
|
|
617
|
-
timestamp:
|
|
618
|
-
|
|
619
|
-
|
|
644
|
+
date: clock_cjs_1.realClock.localToday(),
|
|
645
|
+
timestamp: clock_cjs_1.realClock.nowIso(),
|
|
646
|
+
// #2376: absolute — see comment on phase_dir in cmdInitExecutePhase.
|
|
647
|
+
quick_dir: toPosixPath(node_path_1.default.join(planningDir(cwd), 'quick')),
|
|
648
|
+
task_dir: slug
|
|
649
|
+
? toPosixPath(node_path_1.default.join(planningDir(cwd), 'quick', `${quickId}-${slug}`))
|
|
650
|
+
: null,
|
|
620
651
|
roadmap_exists: node_fs_1.default.existsSync(node_path_1.default.join(planningDir(cwd), 'ROADMAP.md')),
|
|
621
652
|
planning_exists: node_fs_1.default.existsSync(planningRoot(cwd)),
|
|
622
653
|
};
|
|
@@ -628,7 +659,18 @@ function cmdInitIngestDocs(cwd, raw) {
|
|
|
628
659
|
project_exists: pathExistsInternal(cwd, '.planning/PROJECT.md'),
|
|
629
660
|
planning_exists: node_fs_1.default.existsSync(planningRoot(cwd)),
|
|
630
661
|
...getInitGitState(cwd),
|
|
631
|
-
|
|
662
|
+
// #2376: absolute — see comment on phase_dir in cmdInitExecutePhase. The
|
|
663
|
+
// classify_parallel/synthesize/route_new_mode spawns in ingest-docs.md
|
|
664
|
+
// (gsd-doc-classifier, gsd-doc-synthesizer, gsd-roadmapper) previously
|
|
665
|
+
// hardcoded bare '.planning/intel/...', '.planning/PROJECT.md', etc.
|
|
666
|
+
// literals into their Agent(prompt=...) blocks; those now interpolate
|
|
667
|
+
// these fields instead.
|
|
668
|
+
project_path: toPosixPath(node_path_1.default.join(planningDir(cwd), 'PROJECT.md')),
|
|
669
|
+
requirements_path: toPosixPath(node_path_1.default.join(planningDir(cwd), 'REQUIREMENTS.md')),
|
|
670
|
+
roadmap_path: toPosixPath(node_path_1.default.join(planningDir(cwd), 'ROADMAP.md')),
|
|
671
|
+
state_path: toPosixPath(node_path_1.default.join(planningDir(cwd), 'STATE.md')),
|
|
672
|
+
intel_dir: toPosixPath(node_path_1.default.join(planningDir(cwd), 'intel')),
|
|
673
|
+
conflicts_path: toPosixPath(node_path_1.default.join(planningDir(cwd), 'INGEST-CONFLICTS.md')),
|
|
632
674
|
commit_docs: config.commit_docs,
|
|
633
675
|
};
|
|
634
676
|
output(withProjectRoot(cwd, result), raw);
|
|
@@ -657,9 +699,10 @@ function cmdInitResume(cwd, raw) {
|
|
|
657
699
|
roadmap_exists: node_fs_1.default.existsSync(node_path_1.default.join(planningDir(cwd), 'ROADMAP.md')),
|
|
658
700
|
project_exists: pathExistsInternal(cwd, '.planning/PROJECT.md'),
|
|
659
701
|
planning_exists: node_fs_1.default.existsSync(planningRoot(cwd)),
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
702
|
+
// #2376: absolute — see comment on phase_dir in cmdInitExecutePhase.
|
|
703
|
+
state_path: toPosixPath(node_path_1.default.join(planningDir(cwd), 'STATE.md')),
|
|
704
|
+
roadmap_path: toPosixPath(node_path_1.default.join(planningDir(cwd), 'ROADMAP.md')),
|
|
705
|
+
project_path: toPosixPath(node_path_1.default.join(planningDir(cwd), 'PROJECT.md')),
|
|
663
706
|
has_interrupted_agent: !!interruptedAgentId,
|
|
664
707
|
interrupted_agent_id: interruptedAgentId,
|
|
665
708
|
commit_docs: config.commit_docs,
|
|
@@ -714,9 +757,15 @@ function cmdInitVerifyWork(cwd, phase, raw) {
|
|
|
714
757
|
checker_model: resolveModelInternal(cwd, 'gsd-plan-checker'),
|
|
715
758
|
commit_docs: config.commit_docs,
|
|
716
759
|
phase_found: !!phaseInfo,
|
|
717
|
-
|
|
760
|
+
// #2376: absolute — see comment on phase_dir in cmdInitExecutePhase. phaseDir
|
|
761
|
+
// itself stays relative — evaluateUatPassed above still joins it against cwd.
|
|
762
|
+
phase_dir: phaseDir ? toPosixPath(node_path_1.default.join(cwd, phaseDir)) : null,
|
|
718
763
|
phase_number: phaseInfo?.['phase_number'] || null,
|
|
719
764
|
phase_name: phaseInfo?.['phase_name'] || null,
|
|
765
|
+
// #2376: verify-work.md's plan_gap_closure step reads these instead of
|
|
766
|
+
// hardcoding '.planning/STATE.md' / '.planning/ROADMAP.md' literals.
|
|
767
|
+
state_path: toPosixPath(node_path_1.default.join(planningDir(cwd), 'STATE.md')),
|
|
768
|
+
roadmap_path: toPosixPath(node_path_1.default.join(planningDir(cwd), 'ROADMAP.md')),
|
|
720
769
|
has_verification: phaseInfo?.['has_verification'] || false,
|
|
721
770
|
phase_completion: {
|
|
722
771
|
...completion,
|
|
@@ -730,6 +779,21 @@ function cmdInitVerifyWork(cwd, phase, raw) {
|
|
|
730
779
|
function cmdInitPhaseOp(cwd, phase, raw) {
|
|
731
780
|
const config = loadConfig(cwd);
|
|
732
781
|
let phaseInfo = guardedFindPhase(cwd, phase, config.project_code);
|
|
782
|
+
// #2237: surface ambiguous phase-directory collisions instead of silently
|
|
783
|
+
// taking the first match when unrelated projects share a .planning/phases/ tree.
|
|
784
|
+
if (phaseInfo?.['ambiguous_matches']) {
|
|
785
|
+
const matches = phaseInfo['ambiguous_matches'];
|
|
786
|
+
const result = {
|
|
787
|
+
phase_found: false,
|
|
788
|
+
phase_dir: null,
|
|
789
|
+
phase_number: null,
|
|
790
|
+
phase_name: null,
|
|
791
|
+
ambiguous_matches: matches,
|
|
792
|
+
warning: `Phase ${phase} is ambiguous: ${matches.length} directories match (${matches.map((m) => `"${m}"`).join(', ')}). Set a distinct project_code in .planning/config.json to scope resolution.`,
|
|
793
|
+
};
|
|
794
|
+
output(withProjectRoot(cwd, result), raw);
|
|
795
|
+
return;
|
|
796
|
+
}
|
|
733
797
|
if (phaseInfo?.['archived']) {
|
|
734
798
|
const roadmapPhase = guardedGetRoadmapPhase(cwd, phase, config.project_code);
|
|
735
799
|
if (roadmapPhase?.['found']) {
|
|
@@ -783,7 +847,8 @@ function cmdInitPhaseOp(cwd, phase, raw) {
|
|
|
783
847
|
if (slug) {
|
|
784
848
|
const prefix = rawProjectCode ? `${rawProjectCode}-` : '';
|
|
785
849
|
const dirName = `${prefix}${paddedNum}-${slug}`;
|
|
786
|
-
|
|
850
|
+
// #2376: absolute — see comment on phase_dir below.
|
|
851
|
+
expectedPhaseDir = toPosixPath(node_path_1.default.join(planningPaths(cwd).phases, dirName));
|
|
787
852
|
}
|
|
788
853
|
}
|
|
789
854
|
const result = {
|
|
@@ -798,7 +863,8 @@ function cmdInitPhaseOp(cwd, phase, raw) {
|
|
|
798
863
|
? (0, secrets_cjs_1.maskIfSecret)('exa_search', config.exa_search)
|
|
799
864
|
: config.exa_search,
|
|
800
865
|
phase_found: !!phaseInfo,
|
|
801
|
-
|
|
866
|
+
// #2376: absolute — see comment on phase_dir in cmdInitExecutePhase.
|
|
867
|
+
phase_dir: phaseDir ? toPosixPath(node_path_1.default.join(cwd, phaseDir)) : null,
|
|
802
868
|
expected_phase_dir: expectedPhaseDir,
|
|
803
869
|
phase_number: phaseNumber,
|
|
804
870
|
phase_name: phaseName,
|
|
@@ -812,9 +878,10 @@ function cmdInitPhaseOp(cwd, phase, raw) {
|
|
|
812
878
|
plan_count: phaseInfo?.['plans']?.length || 0,
|
|
813
879
|
roadmap_exists: node_fs_1.default.existsSync(node_path_1.default.join(planningDir(cwd), 'ROADMAP.md')),
|
|
814
880
|
planning_exists: node_fs_1.default.existsSync(planningDir(cwd)),
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
881
|
+
// #2376: absolute — see comment on phase_dir above.
|
|
882
|
+
state_path: toPosixPath(node_path_1.default.join(planningDir(cwd), 'STATE.md')),
|
|
883
|
+
roadmap_path: toPosixPath(node_path_1.default.join(planningDir(cwd), 'ROADMAP.md')),
|
|
884
|
+
requirements_path: toPosixPath(node_path_1.default.join(planningDir(cwd), 'REQUIREMENTS.md')),
|
|
818
885
|
};
|
|
819
886
|
if (phaseInfo?.['directory']) {
|
|
820
887
|
const phaseDirFull = node_path_1.default.join(cwd, phaseInfo['directory']);
|
|
@@ -822,23 +889,23 @@ function cmdInitPhaseOp(cwd, phase, raw) {
|
|
|
822
889
|
const files = node_fs_1.default.readdirSync(phaseDirFull);
|
|
823
890
|
const contextFile = findContextMdIn(phaseDirFull);
|
|
824
891
|
if (contextFile) {
|
|
825
|
-
result['context_path'] = toPosixPath(node_path_1.default.join(
|
|
892
|
+
result['context_path'] = toPosixPath(node_path_1.default.join(phaseDirFull, contextFile));
|
|
826
893
|
}
|
|
827
894
|
const researchFile = files.find((f) => f.endsWith('-RESEARCH.md') || f === 'RESEARCH.md');
|
|
828
895
|
if (researchFile) {
|
|
829
|
-
result['research_path'] = toPosixPath(node_path_1.default.join(
|
|
896
|
+
result['research_path'] = toPosixPath(node_path_1.default.join(phaseDirFull, researchFile));
|
|
830
897
|
}
|
|
831
898
|
const verificationFile = files.find((f) => f.endsWith('-VERIFICATION.md') || f === 'VERIFICATION.md');
|
|
832
899
|
if (verificationFile) {
|
|
833
|
-
result['verification_path'] = toPosixPath(node_path_1.default.join(
|
|
900
|
+
result['verification_path'] = toPosixPath(node_path_1.default.join(phaseDirFull, verificationFile));
|
|
834
901
|
}
|
|
835
902
|
const uatFile = files.find((f) => f.endsWith('-UAT.md') || f === 'UAT.md');
|
|
836
903
|
if (uatFile) {
|
|
837
|
-
result['uat_path'] = toPosixPath(node_path_1.default.join(
|
|
904
|
+
result['uat_path'] = toPosixPath(node_path_1.default.join(phaseDirFull, uatFile));
|
|
838
905
|
}
|
|
839
906
|
const reviewsFile = files.find((f) => f.endsWith('-REVIEWS.md') || f === 'REVIEWS.md');
|
|
840
907
|
if (reviewsFile) {
|
|
841
|
-
result['reviews_path'] = toPosixPath(node_path_1.default.join(
|
|
908
|
+
result['reviews_path'] = toPosixPath(node_path_1.default.join(phaseDirFull, reviewsFile));
|
|
842
909
|
}
|
|
843
910
|
}
|
|
844
911
|
catch {
|
|
@@ -849,7 +916,6 @@ function cmdInitPhaseOp(cwd, phase, raw) {
|
|
|
849
916
|
}
|
|
850
917
|
function cmdInitTodos(cwd, area, raw) {
|
|
851
918
|
const config = loadConfig(cwd);
|
|
852
|
-
const now = new Date();
|
|
853
919
|
const pendingDir = node_path_1.default.join(planningDir(cwd), 'todos', 'pending');
|
|
854
920
|
let count = 0;
|
|
855
921
|
const todos = [];
|
|
@@ -863,6 +929,9 @@ function cmdInitTodos(cwd, area, raw) {
|
|
|
863
929
|
const createdMatch = content.match(/^created:\s*(.+)$/m);
|
|
864
930
|
const titleMatch = content.match(/^title:\s*(.+)$/m);
|
|
865
931
|
const areaMatch = content.match(/^area:\s*(.+)$/m);
|
|
932
|
+
// #2337: kept in parity with cmdListTodos — surface severity when
|
|
933
|
+
// present, omit the key entirely for todos with no severity line.
|
|
934
|
+
const severityMatch = content.match(/^severity:\s*(.+)$/m);
|
|
866
935
|
const todoArea = areaMatch ? areaMatch[1].trim() : 'general';
|
|
867
936
|
if (area && todoArea !== area)
|
|
868
937
|
continue;
|
|
@@ -872,7 +941,9 @@ function cmdInitTodos(cwd, area, raw) {
|
|
|
872
941
|
created: createdMatch ? createdMatch[1].trim() : 'unknown',
|
|
873
942
|
title: titleMatch ? titleMatch[1].trim() : 'Untitled',
|
|
874
943
|
area: todoArea,
|
|
875
|
-
|
|
944
|
+
// #2376: absolute — see comment on phase_dir in cmdInitExecutePhase.
|
|
945
|
+
path: toPosixPath(node_path_1.default.join(planningDir(cwd), 'todos', 'pending', file)),
|
|
946
|
+
...(severityMatch ? { severity: severityMatch[1].trim() } : {}),
|
|
876
947
|
});
|
|
877
948
|
}
|
|
878
949
|
catch {
|
|
@@ -885,13 +956,14 @@ function cmdInitTodos(cwd, area, raw) {
|
|
|
885
956
|
}
|
|
886
957
|
const result = {
|
|
887
958
|
commit_docs: config.commit_docs,
|
|
888
|
-
date:
|
|
889
|
-
timestamp:
|
|
959
|
+
date: clock_cjs_1.realClock.localToday(),
|
|
960
|
+
timestamp: clock_cjs_1.realClock.nowIso(),
|
|
890
961
|
todo_count: count,
|
|
891
962
|
todos,
|
|
892
963
|
area_filter: area || null,
|
|
893
|
-
|
|
894
|
-
|
|
964
|
+
// #2376: absolute — see comment on phase_dir in cmdInitExecutePhase.
|
|
965
|
+
pending_dir: toPosixPath(node_path_1.default.join(planningDir(cwd), 'todos', 'pending')),
|
|
966
|
+
completed_dir: toPosixPath(node_path_1.default.join(planningDir(cwd), 'todos', 'completed')),
|
|
895
967
|
planning_exists: node_fs_1.default.existsSync(planningDir(cwd)),
|
|
896
968
|
todos_dir_exists: node_fs_1.default.existsSync(node_path_1.default.join(planningDir(cwd), 'todos')),
|
|
897
969
|
pending_dir_exists: node_fs_1.default.existsSync(node_path_1.default.join(planningDir(cwd), 'todos', 'pending')),
|
|
@@ -1007,7 +1079,6 @@ function cmdInitMilestoneOp(cwd, raw) {
|
|
|
1007
1079
|
}
|
|
1008
1080
|
function cmdInitMapCodebase(cwd, raw) {
|
|
1009
1081
|
const config = loadConfig(cwd);
|
|
1010
|
-
const now = new Date();
|
|
1011
1082
|
const codebaseDir = node_path_1.default.join(planningRoot(cwd), 'codebase');
|
|
1012
1083
|
let existingMaps = [];
|
|
1013
1084
|
try {
|
|
@@ -1022,9 +1093,10 @@ function cmdInitMapCodebase(cwd, raw) {
|
|
|
1022
1093
|
search_gitignored: config.search_gitignored,
|
|
1023
1094
|
parallelization: config.parallelization,
|
|
1024
1095
|
subagent_timeout: config.subagent_timeout,
|
|
1025
|
-
date:
|
|
1026
|
-
timestamp:
|
|
1027
|
-
|
|
1096
|
+
date: clock_cjs_1.realClock.localToday(),
|
|
1097
|
+
timestamp: clock_cjs_1.realClock.nowIso(),
|
|
1098
|
+
// #2376: absolute — see comment on phase_dir in cmdInitExecutePhase.
|
|
1099
|
+
codebase_dir: toPosixPath(node_path_1.default.join(planningRoot(cwd), 'codebase')),
|
|
1028
1100
|
existing_maps: existingMaps,
|
|
1029
1101
|
has_maps: existingMaps.length > 0,
|
|
1030
1102
|
planning_exists: pathExistsInternal(cwd, '.planning'),
|
|
@@ -1425,7 +1497,10 @@ function cmdInitProgress(cwd, raw) {
|
|
|
1425
1497
|
const phaseInfo = {
|
|
1426
1498
|
number: phaseNumber,
|
|
1427
1499
|
name: phaseName,
|
|
1428
|
-
|
|
1500
|
+
// #2376: absolute — see comment on phase_dir in cmdInitExecutePhase.
|
|
1501
|
+
// phaseDirRel itself stays relative — buildPhaseCompletionProjection
|
|
1502
|
+
// above still joins it against cwd.
|
|
1503
|
+
directory: toPosixPath(node_path_1.default.join(cwd, phaseDirRel)),
|
|
1429
1504
|
status,
|
|
1430
1505
|
plan_count: plans.length,
|
|
1431
1506
|
summary_count: summaries.length,
|
|
@@ -1493,10 +1568,11 @@ function cmdInitProgress(cwd, raw) {
|
|
|
1493
1568
|
project_exists: pathExistsInternal(cwd, '.planning/PROJECT.md'),
|
|
1494
1569
|
roadmap_exists: node_fs_1.default.existsSync(node_path_1.default.join(planningDir(cwd), 'ROADMAP.md')),
|
|
1495
1570
|
state_exists: node_fs_1.default.existsSync(node_path_1.default.join(planningDir(cwd), 'STATE.md')),
|
|
1496
|
-
|
|
1497
|
-
|
|
1498
|
-
|
|
1499
|
-
|
|
1571
|
+
// #2376: absolute — see comment on phase_dir in cmdInitExecutePhase.
|
|
1572
|
+
state_path: toPosixPath(node_path_1.default.join(planningDir(cwd), 'STATE.md')),
|
|
1573
|
+
roadmap_path: toPosixPath(node_path_1.default.join(planningDir(cwd), 'ROADMAP.md')),
|
|
1574
|
+
project_path: toPosixPath(node_path_1.default.join(planningDir(cwd), 'PROJECT.md')),
|
|
1575
|
+
config_path: toPosixPath(node_path_1.default.join(planningDir(cwd), 'config.json')),
|
|
1500
1576
|
};
|
|
1501
1577
|
output(withProjectRoot(cwd, result), raw);
|
|
1502
1578
|
}
|
|
@@ -1654,7 +1730,9 @@ function cmdInitRemoveWorkspace(cwd, name, raw) {
|
|
|
1654
1730
|
dirty_repos: dirtyRepos,
|
|
1655
1731
|
has_dirty_repos: dirtyRepos.length > 0,
|
|
1656
1732
|
};
|
|
1657
|
-
|
|
1733
|
+
// #2402: sibling init commands route through withProjectRoot so response_language
|
|
1734
|
+
// (and project_root/agents_installed) reach the workflow; this one didn't.
|
|
1735
|
+
output(withProjectRoot(cwd, result), raw);
|
|
1658
1736
|
}
|
|
1659
1737
|
function buildAgentSkillsBlock(config, agentType, projectRoot, diagnostics) {
|
|
1660
1738
|
const warn = (message) => {
|
|
@@ -1763,7 +1841,7 @@ function buildAgentSkillsBlock(config, agentType, projectRoot, diagnostics) {
|
|
|
1763
1841
|
if (entry.kind === 'directive') {
|
|
1764
1842
|
return `- Load the \`${entry.name}\` skill via the Skill tool before proceeding (plugin-provided).`;
|
|
1765
1843
|
}
|
|
1766
|
-
return `- @${String(entry.ref)
|
|
1844
|
+
return `- @${(0, shell_command_projection_cjs_1.posixNormalize)(String(entry.ref))}`;
|
|
1767
1845
|
}).join('\n');
|
|
1768
1846
|
return `<agent_skills>\nRead these user-configured skills:\n${lines}\n</agent_skills>`;
|
|
1769
1847
|
}
|