From 7b3bf9be3fae4badba68bfa22c48603f852f001e Mon Sep 17 00:00:00 2001 From: Cursor Agent Date: Fri, 3 Jul 2026 15:30:48 +0000 Subject: [PATCH] fix: align new-project map gate and guard onboarding summary overwrite init new-project now uses the same seven-file codebase map completeness check as init onboard, so partial .planning/codebase/ directories no longer skip the brownfield mapping offer after onboarding warns about an incomplete map. The onboard workflow now branches on onboarding_summary_exists and asks for confirmation before regenerating SUMMARY.md on repeat runs. --- gsd-core/workflows/onboard.md | 27 +++++++++++++++++++++++++++ src/init.cts | 10 ++++++---- tests/init.test.cjs | 3 +++ 3 files changed, 36 insertions(+), 4 deletions(-) diff --git a/gsd-core/workflows/onboard.md b/gsd-core/workflows/onboard.md index 112b942e1..8520d5524 100644 --- a/gsd-core/workflows/onboard.md +++ b/gsd-core/workflows/onboard.md @@ -177,6 +177,33 @@ true, continue. Create `.planning/onboarding/SUMMARY.md` only after PROJECT.md exists. If it already exists, update it only after confirmation; do not overwrite silently. +If `onboarding_summary_exists` is true: + +- If `TEXT_MODE=true`, print: + +```text +Onboarding summary already exists at .planning/onboarding/SUMMARY.md. + +1. Update summary — regenerate from current artifact status (Recommended) +2. Keep existing summary — skip writing + +Enter number: +``` + +Stop and wait for the user's reply. + +- Otherwise use AskUserQuestion: + - header: "Onboarding Summary" + - question: "Onboarding summary already exists. Update it from current artifact status?" + - options: + - "Update summary" — Regenerate `.planning/onboarding/SUMMARY.md` (Recommended) + - "Keep existing summary" — Skip writing + +If the user chooses to keep the existing summary, skip to Step 7 without writing. + +If `onboarding_summary_exists` is false or the user confirms an update, write the summary +using the template below. + Summary contents: ```markdown diff --git a/src/init.cts b/src/init.cts index a82bae89d..b22c29d79 100644 --- a/src/init.cts +++ b/src/init.cts @@ -747,6 +747,9 @@ function cmdInitNewProject(cwd: string, raw: boolean): void { const hasCode = hasCodeFilesInternal(cwd); const hasPackageFile = hasPackageFileInternal(cwd); + const isBrownfield = hasCode || hasPackageFile; + const codebaseMapFiles = listCodebaseMapFiles(cwd); + const hasCodebaseMap = codebaseMapFiles.length === REQUIRED_CODEBASE_MAP_FILES.length; const result: Record = { researcher_model: resolveModelInternal(cwd, 'gsd-project-researcher'), @@ -756,14 +759,13 @@ function cmdInitNewProject(cwd: string, raw: boolean): void { commit_docs: config.commit_docs, project_exists: pathExistsInternal(cwd, '.planning/PROJECT.md'), - has_codebase_map: pathExistsInternal(cwd, '.planning/codebase'), + has_codebase_map: hasCodebaseMap, planning_exists: pathExistsInternal(cwd, '.planning'), has_existing_code: hasCode, has_package_file: hasPackageFile, - is_brownfield: hasCode || hasPackageFile, - needs_codebase_map: - (hasCode || hasPackageFile) && !pathExistsInternal(cwd, '.planning/codebase'), + is_brownfield: isBrownfield, + needs_codebase_map: isBrownfield && !hasCodebaseMap, ...getInitGitState(cwd), diff --git a/tests/init.test.cjs b/tests/init.test.cjs index 964ce48f1..2ede0d0e8 100644 --- a/tests/init.test.cjs +++ b/tests/init.test.cjs @@ -1599,6 +1599,9 @@ describe('cmdInitNewProject', () => { test('brownfield with codebase map does not need map', () => { fs.writeFileSync(path.join(tmpDir, 'package.json'), '{"name":"test"}'); fs.mkdirSync(path.join(tmpDir, '.planning', 'codebase'), { recursive: true }); + for (const name of ['STACK', 'ARCHITECTURE', 'STRUCTURE', 'CONVENTIONS', 'TESTING', 'INTEGRATIONS', 'CONCERNS']) { + fs.writeFileSync(path.join(tmpDir, '.planning', 'codebase', `${name}.md`), `# ${name}\n`); + } const result = runGsdTools('init new-project', tmpDir); assert.ok(result.success, `Command failed: ${result.error}`);