From bee9d6f7ec6d6e877633f44789b740af208a2f7d Mon Sep 17 00:00:00 2001 From: Cursor Agent Date: Fri, 3 Jul 2026 22:35:55 +0000 Subject: [PATCH] fix(onboard): align PROJECT.md path resolution with workstream-aware planning buildOnboardProjection now resolves PROJECT.md from both the shared .planning root and the active planningDir scope, matching how REQUIREMENTS.md, ROADMAP.md, and STATE.md are resolved. This prevents false partial-planning or new-project routing when planning artifacts live under a workstream or GSD_PROJECT scope. --- src/onboard-projection.cts | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/src/onboard-projection.cts b/src/onboard-projection.cts index 68e144004..c88c1c345 100644 --- a/src/onboard-projection.cts +++ b/src/onboard-projection.cts @@ -247,6 +247,7 @@ function nextAction(params: { projectExists: boolean; mapReadiness: MapReadiness; onboardingSummaryExists: boolean; + onboardingSummaryPath: string; hasPlanningArtifacts: boolean; missingPlanningFiles: string[]; handoffCommands: OnboardHandoffCommands; @@ -302,7 +303,7 @@ function nextAction(params: { if (!params.onboardingSummaryExists) { return { kind: 'write-summary', - summary_path: '.planning/onboarding/SUMMARY.md', + summary_path: params.onboardingSummaryPath, reason: 'Onboarding summary is missing.', }; } @@ -344,11 +345,15 @@ function buildOnboardProjection(cwd: string, options: BuildOnboardProjectionOpti const needsCodebaseMap = isBrownfield && !hasCodebaseMap; const needsFastCodebaseMap = isBrownfield && !hasFastCodebaseMap; const needsOnboardCodebaseMap = options.fast ? needsFastCodebaseMap : needsCodebaseMap; - const projectExists = pathExistsInternal(cwd, '.planning/PROJECT.md'); + const projectRootPath = path.join(planningRoot(cwd), 'PROJECT.md'); + const projectScopedPath = path.join(planningDir(cwd), 'PROJECT.md'); + const projectExists = + fs.existsSync(projectRootPath) || fs.existsSync(projectScopedPath); const requirementsExists = fs.existsSync(path.join(planningDir(cwd), 'REQUIREMENTS.md')); const roadmapExists = fs.existsSync(path.join(planningDir(cwd), 'ROADMAP.md')); const stateExists = fs.existsSync(path.join(planningDir(cwd), 'STATE.md')); - const onboardingSummaryExists = pathExistsInternal(cwd, '.planning/onboarding/SUMMARY.md'); + const onboardingSummaryPath = path.join(planningRoot(cwd), 'onboarding', 'SUMMARY.md'); + const onboardingSummaryExists = fs.existsSync(onboardingSummaryPath); const hasPlanningArtifacts = projectExists || requirementsExists || roadmapExists || stateExists; const missingPlanningFiles = planningMissing( projectExists, @@ -383,6 +388,7 @@ function buildOnboardProjection(cwd: string, options: BuildOnboardProjectionOpti projectExists, mapReadiness: mapReadinessValue, onboardingSummaryExists, + onboardingSummaryPath: toPosixPath(path.relative(cwd, onboardingSummaryPath)), hasPlanningArtifacts, missingPlanningFiles, handoffCommands, @@ -404,9 +410,12 @@ function buildOnboardProjection(cwd: string, options: BuildOnboardProjectionOpti doc_candidates: docCandidates, onboarding_summary_exists: onboardingSummaryExists, - onboarding_summary_path: '.planning/onboarding/SUMMARY.md', + onboarding_summary_path: toPosixPath(path.relative(cwd, onboardingSummaryPath)), - project_path: '.planning/PROJECT.md', + project_path: toPosixPath(path.relative( + cwd, + fs.existsSync(projectRootPath) ? projectRootPath : projectScopedPath, + )), requirements_path: toPosixPath( path.relative(cwd, path.join(planningDir(cwd), 'REQUIREMENTS.md')), ),