From 896c2740d36117d6396040d983dd0768526667b8 Mon Sep 17 00:00:00 2001 From: Jeremy McSpadden Date: Fri, 3 Jul 2026 09:28:58 -0500 Subject: [PATCH 01/48] feat(#1990): add onboard command for brownfield setup --- .changeset/steady-mice-frolic.md | 5 + commands/gsd/onboard.md | 46 +++++ docs/COMMANDS.md | 19 ++ docs/INVENTORY.md | 2 + gsd-core/workflows/help/modes/brief.md | 3 +- gsd-core/workflows/help/modes/default.md | 3 +- gsd-core/workflows/help/modes/full.md | 10 + gsd-core/workflows/help/modes/topic.md | 2 +- gsd-core/workflows/onboard.md | 246 +++++++++++++++++++++++ skills/gsd-onboard/SKILL.md | 46 +++++ src/clusters.cts | 1 + src/command-aliases.cts | 8 + src/init-command-router.cts | 2 + src/init.cts | 216 ++++++++++++++------ src/install-profiles.cts | 2 + tests/onboard-command.test.cjs | 158 +++++++++++++++ 16 files changed, 704 insertions(+), 65 deletions(-) create mode 100644 .changeset/steady-mice-frolic.md create mode 100644 commands/gsd/onboard.md create mode 100644 gsd-core/workflows/onboard.md create mode 100644 skills/gsd-onboard/SKILL.md create mode 100644 tests/onboard-command.test.cjs diff --git a/.changeset/steady-mice-frolic.md b/.changeset/steady-mice-frolic.md new file mode 100644 index 000000000..cf3a8ba59 --- /dev/null +++ b/.changeset/steady-mice-frolic.md @@ -0,0 +1,5 @@ +--- +type: Added +pr: 1991 +--- +**`/gsd:onboard` guides brownfield setup** — existing repos now have a top-level onboarding command that routes through codebase mapping, docs ingest, project initialization, and an onboarding summary without silently overwriting planning files. diff --git a/commands/gsd/onboard.md b/commands/gsd/onboard.md new file mode 100644 index 000000000..ae2517b1c --- /dev/null +++ b/commands/gsd/onboard.md @@ -0,0 +1,46 @@ +--- +name: gsd:onboard +description: Guide existing codebase onboarding through mapping, doc ingest, and planning setup +argument-hint: "[--fast] [--text]" +allowed-tools: + - Read + - Bash + - Write + - Glob + - Grep + - Agent + - AskUserQuestion +requires: [config, new-project, map-codebase, ingest-docs] +--- + +**Copilot (VS Code):** Use `vscode_askquestions` wherever this workflow calls `AskUserQuestion`. They are equivalent — `vscode_askquestions` is the VS Code Copilot implementation of the same interactive question API. + + + +Guide brownfield onboarding for an existing codebase by routing through the existing GSD primitives in the safe order: codebase map → docs ingest → project initialization → onboarding summary. + +**Creates or confirms:** +- `.planning/codebase/` — evidence-backed codebase map from `/gsd:map-codebase` +- `.planning/PROJECT.md`, `REQUIREMENTS.md`, `ROADMAP.md`, `STATE.md` — project setup from `/gsd:new-project` or `/gsd:ingest-docs` +- `.planning/onboarding/SUMMARY.md` — lightweight index of what was learned and the next command + +**Non-goals:** This command does not execute phases, ship work, or overwrite existing planning artifacts without an explicit gate. + + + +@~/.claude/gsd-core/workflows/onboard.md +@~/.claude/gsd-core/references/ui-brand.md +@~/.claude/gsd-core/references/gate-prompts.md + + + +Arguments: $ARGUMENTS + +Flags: +- `--fast` — prefer `/gsd:map-codebase --fast` for the mapping handoff. +- `--text` — use plain-text numbered lists instead of TUI menus. + + + +Execute the onboard workflow end-to-end. Preserve all safety gates, text-mode fallbacks, idempotency checks, and top-level handoff rules for nested interactive commands. + diff --git a/docs/COMMANDS.md b/docs/COMMANDS.md index e8f968d1b..5e25aeffd 100644 --- a/docs/COMMANDS.md +++ b/docs/COMMANDS.md @@ -58,6 +58,25 @@ Initialize a new project with deep context gathering. --- +### `/gsd-onboard` + +Guide an existing codebase through first-time GSD onboarding. The command checks repo state, routes you through codebase mapping, optional docs ingest, project initialization, and creates an onboarding summary once planning exists. + +| Flag | Description | +|------|-------------| +| `--fast` | Prefer the lightweight `/gsd-map-codebase --fast` mapping handoff | +| `--text` | Use numbered plain-text gates instead of TUI menus | + +**Prerequisites:** Existing repo or planning docs. For empty greenfield projects, use `/gsd-new-project`. +**Produces:** `.planning/codebase/` via map-codebase, `.planning/` via new-project or ingest-docs, and `.planning/onboarding/SUMMARY.md` after project setup. + +```bash +/gsd-onboard # Guided brownfield onboarding +/gsd-onboard --fast # Use lightweight codebase mapping first +``` + +--- + ### `/gsd-workspace` Manage GSD workspaces — create, list, or remove isolated workspace environments with repo copies and independent `.planning/` directories. diff --git a/docs/INVENTORY.md b/docs/INVENTORY.md index aa41acbdf..a05d6e304 100644 --- a/docs/INVENTORY.md +++ b/docs/INVENTORY.md @@ -79,6 +79,7 @@ These six routers are descriptor-only entries that the model picks first; the bo | Command | Role | Source | |---------|------|--------| | `/gsd-new-project` | Initialize a new project with deep context gathering and PROJECT.md. | [commands/gsd/new-project.md](../commands/gsd/new-project.md) | +| `/gsd-onboard` | Guide existing codebase onboarding through mapping, docs ingest, project setup, and onboarding summary. | [commands/gsd/onboard.md](../commands/gsd/onboard.md) | | `/gsd-workspace` | Manage GSD workspaces — create (`--new`), list (`--list`), or remove (`--remove`) isolated workspace environments. | [commands/gsd/workspace.md](../commands/gsd/workspace.md) | | `/gsd-discuss-phase` | Gather phase context through adaptive questioning before planning. | [commands/gsd/discuss-phase.md](../commands/gsd/discuss-phase.md) | | `/gsd-mvp-phase` | Plan a phase as a vertical MVP slice — user story, SPIDR splitting, then plan-phase. | [commands/gsd/mvp-phase.md](../commands/gsd/mvp-phase.md) | @@ -223,6 +224,7 @@ Full roster at `gsd-core/workflows/*.md`. Workflows are thin orchestrators that | `milestone-summary.md` | Milestone summary synthesis — onboarding and review artifact from milestone artifacts. | `/gsd-milestone-summary` | | `new-milestone.md` | Start a new milestone cycle — load project context, gather goals, update PROJECT.md/STATE.md. | `/gsd-new-milestone` | | `new-project.md` | Unified new-project flow — questioning, research (optional), requirements, roadmap. | `/gsd-new-project` | +| `onboard.md` | Brownfield onboarding orchestration — map codebase, ingest docs, initialize planning, summarize next step. | `/gsd-onboard` | | `new-workspace.md` | Create an isolated workspace with repo worktrees/clones and an independent `.planning/`. | `/gsd-workspace --new` | | `next.md` | Detect current project state and automatically advance to the next logical step. | `/gsd-progress --next` | | `node-repair.md` | Autonomous repair operator for failed task verification; invoked by `execute-plan`. | `execute-plan.md` (recovery) | diff --git a/gsd-core/workflows/help/modes/brief.md b/gsd-core/workflows/help/modes/brief.md index 359c32f1a..46a1cd41f 100644 --- a/gsd-core/workflows/help/modes/brief.md +++ b/gsd-core/workflows/help/modes/brief.md @@ -7,7 +7,8 @@ One-liner refresher for returning users. Output ONLY the `` content b ```text /gsd:new-project Initialize a project (greenfield) -/gsd:map-codebase Map an existing codebase (brownfield) +/gsd:onboard Onboard an existing codebase (brownfield) +/gsd:map-codebase Refresh/map codebase intelligence /gsd:plan-phase Create a phase plan /gsd:execute-phase Execute a phase /gsd:progress Where am I, what's next diff --git a/gsd-core/workflows/help/modes/default.md b/gsd-core/workflows/help/modes/default.md index 866f1d7dd..86274d63b 100644 --- a/gsd-core/workflows/help/modes/default.md +++ b/gsd-core/workflows/help/modes/default.md @@ -11,11 +11,12 @@ Plan-driven development for solo agentic work with Claude Code. GSD Core turns a ```text /gsd:new-project # Greenfield: questioning → research → requirements → roadmap +/gsd:onboard # Existing codebase: map → ingest docs → initialize planning /gsd:plan-phase 1 # Create a detailed plan for phase 1 /gsd:execute-phase 1 # Execute all plans in the phase ``` -Existing codebase? Run `/gsd:map-codebase` first to ground GSD in your code. +Existing codebase? Run `/gsd:onboard` to map the repo, ingest existing docs, and initialize planning safely. ## Common commands diff --git a/gsd-core/workflows/help/modes/full.md b/gsd-core/workflows/help/modes/full.md index a6686bbae..d571e66ca 100644 --- a/gsd-core/workflows/help/modes/full.md +++ b/gsd-core/workflows/help/modes/full.md @@ -62,6 +62,16 @@ Creates all `.planning/` artifacts: Usage: `/gsd:new-project` +**`/gsd:onboard [--fast] [--text]`** +Guide first-time onboarding for an existing codebase. + +- Detects brownfield code, existing planning docs, and partial `.planning/` state +- Routes through `/gsd:map-codebase`, `/gsd:ingest-docs`, and `/gsd:new-project` in the safe order +- Creates `.planning/onboarding/SUMMARY.md` after project setup +- Idempotent: confirms existing artifacts and does not overwrite planning silently + +Usage: `/gsd:onboard` + **`/gsd:map-codebase [--fast] [--focus ] [--query ]`** Map an existing codebase for brownfield projects. diff --git a/gsd-core/workflows/help/modes/topic.md b/gsd-core/workflows/help/modes/topic.md index d89229607..89b380263 100644 --- a/gsd-core/workflows/help/modes/topic.md +++ b/gsd-core/workflows/help/modes/topic.md @@ -9,7 +9,7 @@ Emit a section from the full reference for the topic in `$ARGUMENTS`. Read `work |---|---| | `next`, `smart-entry` | `### Smart Entry` | | `workflow`, `core`, `core-workflow` | `## Core Workflow` (entire section through end of `### Quick Mode`) | -| `init`, `new-project` | `### Project Initialization` | +| `init`, `new-project`, `onboard`, `onboarding`, `brownfield` | `### Project Initialization` | | `map`, `map-codebase` | The `/gsd:map-codebase` block under `### Project Initialization` | | `discuss`, `discuss-phase` | The `/gsd:discuss-phase` block under `### Phase Planning` | | `plan`, `planning`, `plan-phase` | `### Phase Planning` | diff --git a/gsd-core/workflows/onboard.md b/gsd-core/workflows/onboard.md new file mode 100644 index 000000000..851a7f642 --- /dev/null +++ b/gsd-core/workflows/onboard.md @@ -0,0 +1,246 @@ + +Guide existing-codebase onboarding by sequencing the already-owned GSD primitives: +`/gsd:map-codebase`, `/gsd:ingest-docs`, and `/gsd:new-project`. The workflow is +idempotent: it confirms existing artifacts, refuses to overwrite planning data silently, +and stops with the exact next top-level command whenever a nested interactive workflow +would be unsafe. + + + +Read all files referenced by the invoking prompt's execution_context before starting. + + + + +## 1. Initialize + +Display banner: + +``` +━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + GSD ► ONBOARDING +━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ +``` + +Parse `$ARGUMENTS`: +- `--fast` sets `MAP_COMMAND` to `/gsd:map-codebase --fast`; otherwise `/gsd:map-codebase`. +- `--text` sets `TEXT_MODE=true`. + +Run the init projection: + +```bash +_GSD_SHIM_NAME="gsd-tools.cjs"; _GSD_RUNTIME_ROOT="${RUNTIME_DIR:-$(git rev-parse --show-toplevel 2>/dev/null || pwd)}"; GSD_TOOLS="${_GSD_RUNTIME_ROOT}/gsd-core/bin/${_GSD_SHIM_NAME}"; if [ -f "$GSD_TOOLS" ]; then gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${_GSD_RUNTIME_ROOT}/.claude/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${_GSD_RUNTIME_ROOT}/.claude/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${_GSD_RUNTIME_ROOT}/.codex/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${_GSD_RUNTIME_ROOT}/.codex/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif command -v gsd-tools >/dev/null 2>&1; then GSD_TOOLS="$(command -v gsd-tools)"; gsd_run() { "$GSD_TOOLS" "$@"; }; elif [ -f "$HOME/.claude/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="$HOME/.claude/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${CODEX_HOME:-$HOME/.codex}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${CODEX_HOME:-$HOME/.codex}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; else echo "ERROR: gsd-tools.cjs not found. Run: npx -y @opengsd/gsd-core@latest --local" >&2; exit 1; fi +INIT=$(gsd_run init onboard) +if [[ "$INIT" == @file:* ]]; then INIT=$(cat "${INIT#@file:}"); fi +``` + +Parse JSON fields: `planning_exists`, `project_exists`, `roadmap_exists`, `state_exists`, +`has_existing_code`, `has_package_file`, `is_brownfield`, `has_codebase_map`, +`missing_codebase_map_files`, `has_docs_candidates`, `doc_candidate_count`, +`onboarding_summary_exists`, `text_mode`, `agents_installed`, `missing_agents`, +`has_git`, `git_worktree_root`, `in_nested_subdir`. + +Set `TEXT_MODE=true` if `--text` is present OR `text_mode` from INIT is true. + +## 2. Git and Existing Planning Safety + +If `has_git` is true and `in_nested_subdir` is true, warn that onboarding artifacts will +belong to the outer worktree at `git_worktree_root`. Do not run `git init` here. + +If `planning_exists` is true, do not overwrite PROJECT/ROADMAP/STATE. Onboarding is +idempotent and must only confirm or summarize existing files unless the user explicitly +runs the lower-level refresh commands. + +## 3. Codebase Mapping Gate + +If `is_brownfield` is true and `has_codebase_map` is false: + +- If `TEXT_MODE=true`, print: + +```text +Existing code was detected, but the complete .planning/codebase/ map is missing. +Missing map files: {missing_codebase_map_files} + +1. Map codebase first — run {MAP_COMMAND} to understand the repo before project setup (Recommended) +2. Skip mapping — continue with weaker onboarding context + +Enter number: +``` + +Stop and wait for the user's reply. + +- Otherwise use AskUserQuestion: + - header: "Codebase" + - question: "Existing code was detected, but the complete .planning/codebase/ map is missing. Map it first?" + - options: + - "Map codebase first" — Run `{MAP_COMMAND}` to understand the repo before project setup (Recommended) + - "Skip mapping" — Continue with weaker onboarding context + +If the user chooses mapping, do not nest the interactive map-codebase workflow. Print: + +```text +Run this top-level command first, then rerun /gsd:onboard: + +{MAP_COMMAND} +``` + +Exit. + +If the user skips mapping, continue with a warning. + +If `is_brownfield` is false and `planning_exists` is false, print: + +```text +No existing code was detected. For a greenfield project, run: + +/gsd:new-project +``` + +Exit. + +## 4. Existing Docs Gate + +If `has_docs_candidates` is true and `planning_exists` is false: + +- If `TEXT_MODE=true`, print: + +```text +Detected {doc_candidate_count} possible ADR/PRD/SPEC/RFC document(s). + +1. Ingest docs first — run /gsd:ingest-docs to bootstrap planning from existing docs (Recommended) +2. Skip docs ingest — continue to /gsd:new-project + +Enter number: +``` + +Stop and wait for the user's reply. + +- Otherwise use AskUserQuestion: + - header: "Docs" + - question: "Detected {doc_candidate_count} possible ADR/PRD/SPEC/RFC document(s). Ingest them first?" + - options: + - "Ingest docs first" — Run `/gsd:ingest-docs` to bootstrap planning from existing docs (Recommended) + - "Skip docs ingest" — Continue to `/gsd:new-project` + +If the user chooses ingest, do not nest the interactive ingest-docs workflow. Print: + +```text +Run this top-level command first, then rerun /gsd:onboard: + +/gsd:ingest-docs +``` + +Exit. + +## 5. Project Initialization Gate + +If `project_exists` is false: + +Print: + +```text +Codebase context is ready for project initialization. + +Run this top-level command, then rerun /gsd:onboard: + +/gsd:new-project +``` + +Exit. + +If `project_exists` is true, continue. If `roadmap_exists` or `state_exists` is false, +warn that `.planning/` is partial and route to `/gsd:ingest-docs --mode merge` or +`/gsd:new-project` rather than overwriting files in-place. + +## 6. Write Onboarding Summary + +Create `.planning/onboarding/SUMMARY.md` only after PROJECT.md exists. If it already +exists, update it only after confirmation; do not overwrite silently. + +Summary contents: + +```markdown +# Onboarding Summary + +**Generated:** {YYYY-MM-DD} +**Status:** Ready for GSD workflow + +## Confirmed Artifacts + +- Project: .planning/PROJECT.md +- Roadmap: .planning/ROADMAP.md +- State: .planning/STATE.md +- Codebase map: .planning/codebase/ + +## Codebase Map + +- STACK.md +- ARCHITECTURE.md +- STRUCTURE.md +- CONVENTIONS.md +- TESTING.md +- INTEGRATIONS.md +- CONCERNS.md + +## Existing Docs + +Detected planning docs: {doc_candidate_count} + +## Recommended Next Step + +/gsd:discuss-phase 1 +``` + +Commit the summary if `commit_docs` is true: + +```bash +gsd_run query commit "docs: create onboarding summary" --files .planning/onboarding/SUMMARY.md +``` + +## 7. Final Status + +Print: + +``` +━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + GSD ► ONBOARDING COMPLETE ✓ +━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + +Created / confirmed: +- .planning/codebase/ +- .planning/PROJECT.md +- .planning/REQUIREMENTS.md +- .planning/ROADMAP.md +- .planning/STATE.md +- .planning/onboarding/SUMMARY.md + +─────────────────────────────────────────────────────────────── + +## ▶ Next Up + +**Discuss Phase 1** — capture implementation decisions before planning. + +`/gsd:discuss-phase 1` + +─────────────────────────────────────────────────────────────── + +**Also available:** +- `/gsd:map-codebase` — refresh the codebase map after significant changes +- `/gsd:ingest-docs --mode merge` — merge new ADR/PRD/SPEC docs into planning +- `/gsd:progress` — inspect current workflow state + +─────────────────────────────────────────────────────────────── +``` + + + + +- [ ] Existing codebase detected before project initialization +- [ ] Missing codebase map routes to `/gsd:map-codebase` or `/gsd:map-codebase --fast` +- [ ] Existing planning docs route to `/gsd:ingest-docs` +- [ ] Missing project setup routes to `/gsd:new-project` +- [ ] Existing `.planning/` files are not overwritten silently +- [ ] Text mode stops and waits at numbered-list gates +- [ ] `.planning/onboarding/SUMMARY.md` is created only after PROJECT.md exists +- [ ] User sees next command + diff --git a/skills/gsd-onboard/SKILL.md b/skills/gsd-onboard/SKILL.md new file mode 100644 index 000000000..3625c3ef1 --- /dev/null +++ b/skills/gsd-onboard/SKILL.md @@ -0,0 +1,46 @@ +--- +name: gsd-onboard +description: "Guide existing codebase onboarding through mapping, doc ingest, and planning setup" +argument-hint: "[--fast] [--text]" +allowed-tools: + - Read + - Bash + - Write + - Glob + - Grep + - Agent + - AskUserQuestion +--- + + +**Copilot (VS Code):** Use `vscode_askquestions` wherever this workflow calls `AskUserQuestion`. They are equivalent — `vscode_askquestions` is the VS Code Copilot implementation of the same interactive question API. + + + +Guide brownfield onboarding for an existing codebase by routing through the existing GSD primitives in the safe order: codebase map → docs ingest → project initialization → onboarding summary. + +**Creates or confirms:** +- `.planning/codebase/` — evidence-backed codebase map from `/gsd-map-codebase` +- `.planning/PROJECT.md`, `REQUIREMENTS.md`, `ROADMAP.md`, `STATE.md` — project setup from `/gsd-new-project` or `/gsd-ingest-docs` +- `.planning/onboarding/SUMMARY.md` — lightweight index of what was learned and the next command + +**Non-goals:** This command does not execute phases, ship work, or overwrite existing planning artifacts without an explicit gate. + + + +@~/.claude/gsd-core/workflows/onboard.md +@~/.claude/gsd-core/references/ui-brand.md +@~/.claude/gsd-core/references/gate-prompts.md + + + +Arguments: $ARGUMENTS + +Flags: +- `--fast` — prefer `/gsd-map-codebase --fast` for the mapping handoff. +- `--text` — use plain-text numbered lists instead of TUI menus. + + + +Execute the onboard workflow end-to-end. Preserve all safety gates, text-mode fallbacks, idempotency checks, and top-level handoff rules for nested interactive commands. + diff --git a/src/clusters.cts b/src/clusters.cts index 2ea92abfd..7ba2ff05b 100644 --- a/src/clusters.cts +++ b/src/clusters.cts @@ -33,6 +33,7 @@ export const CLUSTERS: ClusterMap = Object.freeze({ core_loop: Object.freeze([ 'next', 'new-project', + 'onboard', 'discuss-phase', 'plan-phase', 'execute-phase', diff --git a/src/command-aliases.cts b/src/command-aliases.cts index 9df935e33..19c2a36be 100644 --- a/src/command-aliases.cts +++ b/src/command-aliases.cts @@ -296,6 +296,14 @@ export const INIT_COMMAND_ALIASES: CommandAlias[] = [ "subcommand": "new-milestone", "mutation": false }, + { + "canonical": "init.onboard", + "aliases": [ + "init onboard" + ], + "subcommand": "onboard", + "mutation": false + }, { "canonical": "init.quick", "aliases": [ diff --git a/src/init-command-router.cts b/src/init-command-router.cts index 317ce0059..29b84ea59 100644 --- a/src/init-command-router.cts +++ b/src/init-command-router.cts @@ -28,6 +28,7 @@ interface InitModule { cmdInitPlanPhase(cwd: string, phase: string | undefined, raw: boolean, opts: Record): void; cmdInitNewProject(cwd: string, raw: boolean): void; cmdInitNewMilestone(cwd: string, raw: boolean): void; + cmdInitOnboard(cwd: string, raw: boolean): void; cmdInitQuick(cwd: string, name: string, raw: boolean): void; cmdInitIngestDocs(cwd: string, raw: boolean): void; cmdInitResume(cwd: string, raw: boolean): void; @@ -71,6 +72,7 @@ function routeInitCommand({ init, args, cwd, raw, error }: RouteInitCommandOptio }, 'new-project': () => init.cmdInitNewProject(cwd, raw), 'new-milestone': () => init.cmdInitNewMilestone(cwd, raw), + onboard: () => init.cmdInitOnboard(cwd, raw), quick: () => init.cmdInitQuick(cwd, args.slice(2).join(' '), raw), 'ingest-docs': () => init.cmdInitIngestDocs(cwd, raw), resume: () => init.cmdInitResume(cwd, raw), diff --git a/src/init.cts b/src/init.cts index 1b9de1cb0..a533d65fd 100644 --- a/src/init.cts +++ b/src/init.cts @@ -86,6 +86,106 @@ void stripShippedMilestones; // Accept all bold/colon variants of the Requirements header (#2769) const REQUIREMENTS_HEADER_RE = /^\*\*Requirements:?\*\*[^\S\n]*:?[^\S\n]*([^\n]*)$/m; +const CODE_EXTENSIONS = new Set([ + '.ts', '.tsx', '.js', '.jsx', '.mjs', '.cjs', '.py', '.go', '.rs', '.swift', '.java', + '.kt', '.kts', '.c', '.cpp', '.cc', '.h', '.hpp', '.cs', '.rb', '.php', '.dart', + '.m', '.mm', '.scala', '.groovy', '.lua', '.r', '.R', '.zig', '.ex', '.exs', '.clj', +]); + +const CODE_SCAN_SKIP_DIRS = new Set([ + 'node_modules', '.git', '.planning', '.claude', '.codex', '__pycache__', 'target', + 'dist', 'build', '.next', '.nuxt', '.svelte-kit', 'coverage', 'vendor', '.venv', 'venv', +]); + +const PACKAGE_FILES = [ + 'package.json', 'requirements.txt', 'pyproject.toml', 'Cargo.toml', 'go.mod', + 'Package.swift', 'build.gradle', 'build.gradle.kts', 'pom.xml', 'Gemfile', + 'composer.json', 'pubspec.yaml', 'CMakeLists.txt', 'Makefile', 'build.zig', + 'mix.exs', 'project.clj', +]; + +const REQUIRED_CODEBASE_MAP_FILES = [ + 'STACK.md', 'ARCHITECTURE.md', 'STRUCTURE.md', 'CONVENTIONS.md', 'TESTING.md', + 'INTEGRATIONS.md', 'CONCERNS.md', +]; + +function hasCodeFilesInternal(dir: string, depth = 0): boolean { + if (depth > 3) return false; + let entries: fs.Dirent[]; + try { + entries = fs.readdirSync(dir, { withFileTypes: true }); + } catch { + return false; + } + + for (const entry of entries) { + if (entry.isFile() && CODE_EXTENSIONS.has(path.extname(entry.name))) return true; + if (entry.isDirectory() && !CODE_SCAN_SKIP_DIRS.has(entry.name)) { + if (hasCodeFilesInternal(path.join(dir, entry.name), depth + 1)) return true; + } + } + + return false; +} + +function hasPackageFileInternal(cwd: string): boolean { + return PACKAGE_FILES.some((file) => pathExistsInternal(cwd, file)); +} + +function listPlanningDocCandidates(cwd: string): string[] { + const roots = ['docs', 'adr', 'adrs', 'prd', 'prds', 'spec', 'specs', 'rfcs']; + const candidates = new Set(); + + const visit = (dir: string, relDir: string, depth: number): void => { + if (depth > 3) return; + let entries: fs.Dirent[]; + try { + entries = fs.readdirSync(dir, { withFileTypes: true }); + } catch { + return; + } + + for (const entry of entries) { + const rel = relDir ? `${relDir}/${entry.name}` : entry.name; + if (entry.isDirectory()) { + if (!CODE_SCAN_SKIP_DIRS.has(entry.name)) { + visit(path.join(dir, entry.name), rel, depth + 1); + } + continue; + } + + if (!entry.isFile() || !entry.name.toLowerCase().endsWith('.md')) continue; + const upperName = entry.name.toUpperCase(); + const relLower = rel.toLowerCase(); + if ( + /(^|[-_ ])(ADR|PRD|SPEC|RFC)([-_ ]|\.)/i.test(entry.name) || + /^\d{4}[-_].+\.md$/i.test(entry.name) || + relLower.includes('/adr') || + relLower.includes('/prd') || + relLower.includes('/spec') || + upperName === 'REQUIREMENTS.md' + ) { + candidates.add(toPosixPath(rel)); + } + } + }; + + for (const root of roots) { + const full = path.join(cwd, root); + if (fs.existsSync(full)) visit(full, root, 0); + } + + return [...candidates].sort(); +} + +function listCodebaseMapFiles(cwd: string): string[] { + const codebaseDir = path.join(planningRoot(cwd), 'codebase'); + if (!fs.existsSync(codebaseDir)) return []; + return REQUIRED_CODEBASE_MAP_FILES.filter((file) => + fs.existsSync(path.join(codebaseDir, file)), + ); +} + function listPhaseSummaryFiles(phaseDir: string): string[] { return (scanPhasePlans(phaseDir) as unknown as Record)['summaryFiles']; } @@ -625,68 +725,8 @@ function cmdInitNewProject(cwd: string, raw: boolean): void { const exaKeyFile = path.join(homedir, '.gsd', 'exa_api_key'); const hasExaSearch = !!(process.env['EXA_API_KEY'] || fs.existsSync(exaKeyFile)); - let hasCode = false; - let hasPackageFile = false; - try { - const codeExtensions = new Set([ - '.ts', '.js', '.py', '.go', '.rs', '.swift', '.java', - '.kt', '.kts', - '.c', '.cpp', '.h', - '.cs', - '.rb', - '.php', - '.dart', - '.m', '.mm', - '.scala', - '.groovy', - '.lua', - '.r', '.R', - '.zig', - '.ex', '.exs', - '.clj', - ]); - const skipDirs = new Set([ - 'node_modules', '.git', '.planning', '.claude', '.codex', - '__pycache__', 'target', 'dist', 'build', - ]); - function findCodeFiles(dir: string, depth: number): boolean { - if (depth > 3) return false; - let entries: fs.Dirent[]; - try { - entries = fs.readdirSync(dir, { withFileTypes: true }); - } catch { - return false; - } - for (const entry of entries) { - if (entry.isFile() && codeExtensions.has(path.extname(entry.name))) return true; - if (entry.isDirectory() && !skipDirs.has(entry.name)) { - if (findCodeFiles(path.join(dir, entry.name), depth + 1)) return true; - } - } - return false; - } - hasCode = findCodeFiles(cwd, 0); - } catch { - /* intentionally empty — best-effort detection */ - } - - hasPackageFile = - pathExistsInternal(cwd, 'package.json') || - pathExistsInternal(cwd, 'requirements.txt') || - pathExistsInternal(cwd, 'Cargo.toml') || - pathExistsInternal(cwd, 'go.mod') || - pathExistsInternal(cwd, 'Package.swift') || - pathExistsInternal(cwd, 'build.gradle') || - pathExistsInternal(cwd, 'build.gradle.kts') || - pathExistsInternal(cwd, 'pom.xml') || - pathExistsInternal(cwd, 'Gemfile') || - pathExistsInternal(cwd, 'composer.json') || - pathExistsInternal(cwd, 'pubspec.yaml') || - pathExistsInternal(cwd, 'CMakeLists.txt') || - pathExistsInternal(cwd, 'Makefile') || - pathExistsInternal(cwd, 'build.zig') || - pathExistsInternal(cwd, 'mix.exs') || - pathExistsInternal(cwd, 'project.clj'); + const hasCode = hasCodeFilesInternal(cwd); + const hasPackageFile = hasPackageFileInternal(cwd); const result: Record = { researcher_model: resolveModelInternal(cwd, 'gsd-project-researcher'), @@ -840,6 +880,57 @@ function cmdInitIngestDocs(cwd: string, raw: boolean): void { output(withProjectRoot(cwd, result), raw); } +function cmdInitOnboard(cwd: string, raw: boolean): void { + const config = loadConfig(cwd); + const codebaseMapFiles = listCodebaseMapFiles(cwd); + const missingCodebaseMapFiles = REQUIRED_CODEBASE_MAP_FILES.filter( + (file) => !codebaseMapFiles.includes(file), + ); + const docCandidates = listPlanningDocCandidates(cwd); + const hasCode = hasCodeFilesInternal(cwd); + const hasPackageFile = hasPackageFileInternal(cwd); + const isBrownfield = hasCode || hasPackageFile; + const hasCodebaseMap = codebaseMapFiles.length === REQUIRED_CODEBASE_MAP_FILES.length; + + const result: Record = { + commit_docs: config.commit_docs, + text_mode: + !!config.text_mode || !!((config.workflow ?? {}) as Record)['text_mode'], + + project_exists: pathExistsInternal(cwd, '.planning/PROJECT.md'), + planning_exists: fs.existsSync(planningRoot(cwd)), + roadmap_exists: fs.existsSync(path.join(planningDir(cwd), 'ROADMAP.md')), + state_exists: fs.existsSync(path.join(planningDir(cwd), 'STATE.md')), + config_exists: fs.existsSync(path.join(planningDir(cwd), 'config.json')), + + has_existing_code: hasCode, + has_package_file: hasPackageFile, + is_brownfield: isBrownfield, + needs_codebase_map: isBrownfield && !hasCodebaseMap, + has_codebase_map: hasCodebaseMap, + codebase_dir_exists: fs.existsSync(path.join(planningRoot(cwd), 'codebase')), + codebase_map_files_present: codebaseMapFiles, + missing_codebase_map_files: missingCodebaseMapFiles, + + has_docs_candidates: docCandidates.length > 0, + doc_candidate_count: docCandidates.length, + doc_candidates: docCandidates, + + onboarding_summary_exists: pathExistsInternal(cwd, '.planning/onboarding/SUMMARY.md'), + onboarding_summary_path: '.planning/onboarding/SUMMARY.md', + + project_path: '.planning/PROJECT.md', + roadmap_path: toPosixPath(path.relative(cwd, path.join(planningDir(cwd), 'ROADMAP.md'))), + state_path: toPosixPath(path.relative(cwd, path.join(planningDir(cwd), 'STATE.md'))), + codebase_dir: toPosixPath(path.relative(cwd, path.join(planningRoot(cwd), 'codebase'))), + onboarding_dir: toPosixPath(path.relative(cwd, path.join(planningRoot(cwd), 'onboarding'))), + + ...getInitGitState(cwd), + }; + + output(withProjectRoot(cwd, result), raw); +} + function cmdInitResume(cwd: string, raw: boolean): void { const config = loadConfig(cwd); @@ -2606,6 +2697,7 @@ export = { cmdInitNewMilestone, cmdInitQuick, cmdInitIngestDocs, + cmdInitOnboard, cmdInitResume, cmdInitVerifyWork, cmdInitPhaseOp, diff --git a/src/install-profiles.cts b/src/install-profiles.cts index 90674c367..5db870050 100644 --- a/src/install-profiles.cts +++ b/src/install-profiles.cts @@ -40,6 +40,7 @@ const { const PROFILES = Object.freeze({ core: Object.freeze([ 'new-project', + 'onboard', 'discuss-phase', 'plan-phase', 'execute-phase', @@ -51,6 +52,7 @@ const PROFILES = Object.freeze({ standard: Object.freeze([ // Core loop 'new-project', + 'onboard', 'discuss-phase', 'plan-phase', 'execute-phase', diff --git a/tests/onboard-command.test.cjs b/tests/onboard-command.test.cjs new file mode 100644 index 000000000..a7903fe90 --- /dev/null +++ b/tests/onboard-command.test.cjs @@ -0,0 +1,158 @@ +// allow-test-rule: source-text-is-the-product +// Command/workflow markdown is deployed runtime product; source-text assertions +// below verify the installed command contract. CLI assertions exercise real +// gsd-tools behavior through the public command boundary. + +const { describe, test, beforeEach, afterEach } = require('node:test'); +const assert = require('node:assert/strict'); +const fs = require('fs'); +const path = require('path'); +const { runGsdTools, cleanup } = require('./helpers.cjs'); +const { createFixture } = require('./fixtures/index.cjs'); + +const ROOT = path.join(__dirname, '..'); +const CMD_PATH = path.join(ROOT, 'commands', 'gsd', 'onboard.md'); +const WF_PATH = path.join(ROOT, 'gsd-core', 'workflows', 'onboard.md'); + +describe('init onboard public CLI projection', () => { + let tmpDir; + + beforeEach(() => { + tmpDir = createFixture({ planning: false, projectDoc: false }); + }); + + afterEach(() => { + cleanup(tmpDir); + }); + + test('reports brownfield code, docs, and missing planning state', () => { + fs.mkdirSync(path.join(tmpDir, 'src'), { recursive: true }); + fs.writeFileSync(path.join(tmpDir, 'src', 'server.ts'), 'export const server = true;\n'); + fs.mkdirSync(path.join(tmpDir, 'docs', 'adr'), { recursive: true }); + fs.writeFileSync(path.join(tmpDir, 'docs', 'adr', '0001-runtime.md'), '# ADR: Runtime\n'); + + const result = runGsdTools('init onboard --raw', tmpDir, { HOME: tmpDir }); + assert.ok(result.success, `init onboard should succeed: ${result.error}`); + + const parsed = JSON.parse(result.output); + assert.strictEqual(parsed.planning_exists, false); + assert.strictEqual(parsed.project_exists, false); + assert.strictEqual(parsed.has_existing_code, true); + assert.strictEqual(parsed.has_codebase_map, false); + assert.strictEqual(parsed.has_docs_candidates, true); + assert.strictEqual(parsed.doc_candidate_count, 1); + assert.deepStrictEqual(parsed.codebase_map_files_present, []); + assert.ok(parsed.doc_candidates.includes('docs/adr/0001-runtime.md')); + for (const file of ['STACK.md', 'ARCHITECTURE.md', 'STRUCTURE.md', 'CONVENTIONS.md', 'TESTING.md', 'INTEGRATIONS.md', 'CONCERNS.md']) { + assert.ok(parsed.missing_codebase_map_files.includes(file), `missing map files should include ${file}`); + } + assert.strictEqual(parsed.onboarding_summary_exists, false); + assert.strictEqual(parsed.text_mode, false); + }); + + test('reports complete codebase map and onboarding summary in existing planning', () => { + 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`); + } + fs.mkdirSync(path.join(tmpDir, '.planning', 'onboarding'), { recursive: true }); + fs.writeFileSync(path.join(tmpDir, '.planning', 'onboarding', 'SUMMARY.md'), '# Onboarding Summary\n'); + fs.writeFileSync(path.join(tmpDir, '.planning', 'PROJECT.md'), '# Project\n'); + fs.writeFileSync(path.join(tmpDir, '.planning', 'ROADMAP.md'), '# Roadmap\n'); + fs.writeFileSync(path.join(tmpDir, '.planning', 'STATE.md'), '# State\n'); + fs.writeFileSync(path.join(tmpDir, '.planning', 'config.json'), JSON.stringify({ workflow: { text_mode: true } })); + + const trackedFiles = [ + path.join(tmpDir, '.planning', 'PROJECT.md'), + path.join(tmpDir, '.planning', 'ROADMAP.md'), + path.join(tmpDir, '.planning', 'STATE.md'), + path.join(tmpDir, '.planning', 'onboarding', 'SUMMARY.md'), + ]; + const before = new Map(trackedFiles.map(file => [file, fs.readFileSync(file, 'utf8')])); + + const result = runGsdTools('init onboard --raw', tmpDir, { HOME: tmpDir }); + assert.ok(result.success, `init onboard should succeed: ${result.error}`); + + for (const file of trackedFiles) { + assert.strictEqual(fs.readFileSync(file, 'utf8'), before.get(file), `${path.basename(file)} must not be mutated by init onboard`); + } + + const parsed = JSON.parse(result.output); + assert.strictEqual(parsed.planning_exists, true); + assert.strictEqual(parsed.project_exists, true); + assert.strictEqual(parsed.roadmap_exists, true); + assert.strictEqual(parsed.state_exists, true); + assert.strictEqual(parsed.has_codebase_map, true); + assert.deepStrictEqual(parsed.missing_codebase_map_files, []); + assert.strictEqual(parsed.onboarding_summary_exists, true); + assert.strictEqual(parsed.onboarding_summary_path, '.planning/onboarding/SUMMARY.md'); + assert.strictEqual(parsed.text_mode, true); + }); + + test('ignores generated and vendor directories when detecting existing code', () => { + fs.mkdirSync(path.join(tmpDir, 'node_modules', 'pkg'), { recursive: true }); + fs.writeFileSync(path.join(tmpDir, 'node_modules', 'pkg', 'index.ts'), 'export const ignored = true;\n'); + fs.mkdirSync(path.join(tmpDir, 'dist'), { recursive: true }); + fs.writeFileSync(path.join(tmpDir, 'dist', 'bundle.js'), 'console.log("ignored");\n'); + + const result = runGsdTools('init onboard --raw', tmpDir, { HOME: tmpDir }); + assert.ok(result.success, `init onboard should succeed: ${result.error}`); + + const parsed = JSON.parse(result.output); + assert.strictEqual(parsed.has_existing_code, false); + assert.strictEqual(parsed.has_package_file, false); + assert.strictEqual(parsed.is_brownfield, false); + assert.strictEqual(parsed.needs_codebase_map, false); + }); + + test('treats package manifests as brownfield even without source files', () => { + fs.writeFileSync(path.join(tmpDir, 'package.json'), '{"name":"fixture"}\n'); + + const result = runGsdTools('init onboard --raw', tmpDir, { HOME: tmpDir }); + assert.ok(result.success, `init onboard should succeed: ${result.error}`); + + const parsed = JSON.parse(result.output); + assert.strictEqual(parsed.has_existing_code, false); + assert.strictEqual(parsed.has_package_file, true); + assert.strictEqual(parsed.is_brownfield, true); + assert.strictEqual(parsed.needs_codebase_map, true); + }); + + test('dotted query init.onboard matches direct init onboard', () => { + fs.writeFileSync(path.join(tmpDir, 'package.json'), '{"name":"fixture"}\n'); + + const direct = runGsdTools(['init', 'onboard', '--raw'], tmpDir, { HOME: tmpDir }); + const query = runGsdTools(['query', 'init.onboard', '--raw'], tmpDir, { HOME: tmpDir }); + assert.equal(direct.success, true, direct.error || direct.output); + assert.equal(query.success, true, query.error || query.output); + assert.deepStrictEqual(JSON.parse(query.output), JSON.parse(direct.output)); + }); + +}); + +describe('/gsd:onboard command contract', () => { + test('command file declares the onboard command and loads its workflow', () => { + const content = fs.readFileSync(CMD_PATH, 'utf8'); + assert.match(content, /^name:\s*gsd:onboard$/m); + assert.match(content, /^description:\s*.*(?:existing codebase|brownfield|onboard).*$/mi); + assert.match(content, /^\s*- AskUserQuestion$/m); + assert.match(content, /^\s*- Agent$/m); + assert.ok(content.includes('@~/.claude/gsd-core/workflows/onboard.md')); + assert.ok(content.includes('@~/.claude/gsd-core/references/ui-brand.md')); + assert.ok(content.includes('@~/.claude/gsd-core/references/gate-prompts.md')); + }); + + test('workflow routes through existing primitives and protects existing planning', () => { + const content = fs.readFileSync(WF_PATH, 'utf8'); + + assert.ok(content.includes('init onboard'), 'workflow must use init onboard projection'); + assert.ok(content.includes('map-codebase'), 'workflow must route to map-codebase'); + assert.ok(content.includes('ingest-docs'), 'workflow must route to ingest-docs'); + assert.ok(content.includes('new-project'), 'workflow must route to new-project'); + assert.ok(content.includes('.planning/onboarding/SUMMARY.md'), 'workflow must create onboarding summary'); + assert.match(content, /overwrite|idempotent|do not overwrite/i, 'workflow must protect existing planning'); + assert.ok(content.includes('--text'), 'workflow must document text-mode fallback'); + assert.ok(!content.includes('execute-phase'), 'onboarding must not execute implementation phases'); + assert.ok(!content.includes('gsd:ship'), 'onboarding must not ship work'); + }); +}); From e0196d53697d3e536366e44bb012b84177fc51a0 Mon Sep 17 00:00:00 2001 From: Jeremy McSpadden Date: Fri, 3 Jul 2026 09:38:22 -0500 Subject: [PATCH 02/48] no-mistakes(review): Fix onboarding artifact status --- gsd-core/workflows/onboard.md | 43 +++++++++++++++++++++++++++-------- 1 file changed, 33 insertions(+), 10 deletions(-) diff --git a/gsd-core/workflows/onboard.md b/gsd-core/workflows/onboard.md index 851a7f642..9fef9229f 100644 --- a/gsd-core/workflows/onboard.md +++ b/gsd-core/workflows/onboard.md @@ -36,9 +36,9 @@ if [[ "$INIT" == @file:* ]]; then INIT=$(cat "${INIT#@file:}"); fi Parse JSON fields: `planning_exists`, `project_exists`, `roadmap_exists`, `state_exists`, `has_existing_code`, `has_package_file`, `is_brownfield`, `has_codebase_map`, -`missing_codebase_map_files`, `has_docs_candidates`, `doc_candidate_count`, -`onboarding_summary_exists`, `text_mode`, `agents_installed`, `missing_agents`, -`has_git`, `git_worktree_root`, `in_nested_subdir`. +`codebase_map_files_present`, `missing_codebase_map_files`, `has_docs_candidates`, +`doc_candidate_count`, `onboarding_summary_exists`, `text_mode`, `agents_installed`, +`missing_agents`, `has_git`, `git_worktree_root`, `in_nested_subdir`. Set `TEXT_MODE=true` if `--text` is present OR `text_mode` from INIT is true. @@ -148,9 +148,25 @@ Run this top-level command, then rerun /gsd:onboard: Exit. -If `project_exists` is true, continue. If `roadmap_exists` or `state_exists` is false, -warn that `.planning/` is partial and route to `/gsd:ingest-docs --mode merge` or -`/gsd:new-project` rather than overwriting files in-place. +If `project_exists` is true and either `roadmap_exists` or `state_exists` is false, print: + +```text +Existing PROJECT.md was found, but planning is incomplete. + +Planning file status: +- ROADMAP.md: {roadmap_exists ? "present" : "missing"} +- STATE.md: {state_exists ? "present" : "missing"} + +Run one of these top-level commands, then rerun /gsd:onboard: + +/gsd:ingest-docs --mode merge +/gsd:new-project +``` + +Exit. Do not write `.planning/onboarding/SUMMARY.md` and do not print the onboarding +complete status for partial planning. + +If `project_exists`, `roadmap_exists`, and `state_exists` are all true, continue. ## 6. Write Onboarding Summary @@ -165,15 +181,17 @@ Summary contents: **Generated:** {YYYY-MM-DD} **Status:** Ready for GSD workflow -## Confirmed Artifacts +## Artifact Status - Project: .planning/PROJECT.md - Roadmap: .planning/ROADMAP.md - State: .planning/STATE.md -- Codebase map: .planning/codebase/ +- Codebase map: {has_codebase_map ? ".planning/codebase/ (complete)" : ".planning/codebase/ (incomplete or skipped)"} ## Codebase Map +{if has_codebase_map} +Confirmed files: - STACK.md - ARCHITECTURE.md - STRUCTURE.md @@ -181,6 +199,11 @@ Summary contents: - TESTING.md - INTEGRATIONS.md - CONCERNS.md +{else} +Present files: {codebase_map_files_present} +Missing files: {missing_codebase_map_files} +Context strength: weaker because codebase mapping was skipped or is incomplete. +{endif} ## Existing Docs @@ -206,8 +229,8 @@ Print: GSD ► ONBOARDING COMPLETE ✓ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ -Created / confirmed: -- .planning/codebase/ +Created / confirmed / status: +- .planning/codebase/ {has_codebase_map ? "(complete)" : "(incomplete or skipped; missing: {missing_codebase_map_files})"} - .planning/PROJECT.md - .planning/REQUIREMENTS.md - .planning/ROADMAP.md From 6b0b5f1b2c416ffca29133b625b3a44661eb3fa7 Mon Sep 17 00:00:00 2001 From: Jeremy McSpadden Date: Fri, 3 Jul 2026 09:45:08 -0500 Subject: [PATCH 03/48] no-mistakes(review): Fix onboard planning detection --- gsd-core/workflows/onboard.md | 15 +++++++++----- src/init.cts | 13 +++++++++--- tests/onboard-command.test.cjs | 36 ++++++++++++++++++++++++++++++++++ 3 files changed, 56 insertions(+), 8 deletions(-) diff --git a/gsd-core/workflows/onboard.md b/gsd-core/workflows/onboard.md index 9fef9229f..f2702a8aa 100644 --- a/gsd-core/workflows/onboard.md +++ b/gsd-core/workflows/onboard.md @@ -34,8 +34,9 @@ INIT=$(gsd_run init onboard) if [[ "$INIT" == @file:* ]]; then INIT=$(cat "${INIT#@file:}"); fi ``` -Parse JSON fields: `planning_exists`, `project_exists`, `roadmap_exists`, `state_exists`, -`has_existing_code`, `has_package_file`, `is_brownfield`, `has_codebase_map`, +Parse JSON fields: `planning_exists`, `project_exists`, `requirements_exists`, +`roadmap_exists`, `state_exists`, `has_existing_code`, `has_package_file`, +`is_brownfield`, `has_codebase_map`, `codebase_map_files_present`, `missing_codebase_map_files`, `has_docs_candidates`, `doc_candidate_count`, `onboarding_summary_exists`, `text_mode`, `agents_installed`, `missing_agents`, `has_git`, `git_worktree_root`, `in_nested_subdir`. @@ -148,12 +149,14 @@ Run this top-level command, then rerun /gsd:onboard: Exit. -If `project_exists` is true and either `roadmap_exists` or `state_exists` is false, print: +If `project_exists` is true and either `requirements_exists`, `roadmap_exists`, or +`state_exists` is false, print: ```text Existing PROJECT.md was found, but planning is incomplete. Planning file status: +- REQUIREMENTS.md: {requirements_exists ? "present" : "missing"} - ROADMAP.md: {roadmap_exists ? "present" : "missing"} - STATE.md: {state_exists ? "present" : "missing"} @@ -166,7 +169,8 @@ Run one of these top-level commands, then rerun /gsd:onboard: Exit. Do not write `.planning/onboarding/SUMMARY.md` and do not print the onboarding complete status for partial planning. -If `project_exists`, `roadmap_exists`, and `state_exists` are all true, continue. +If `project_exists`, `requirements_exists`, `roadmap_exists`, and `state_exists` are all +true, continue. ## 6. Write Onboarding Summary @@ -184,6 +188,7 @@ Summary contents: ## Artifact Status - Project: .planning/PROJECT.md +- Requirements: .planning/REQUIREMENTS.md - Roadmap: .planning/ROADMAP.md - State: .planning/STATE.md - Codebase map: {has_codebase_map ? ".planning/codebase/ (complete)" : ".planning/codebase/ (incomplete or skipped)"} @@ -232,7 +237,7 @@ Print: Created / confirmed / status: - .planning/codebase/ {has_codebase_map ? "(complete)" : "(incomplete or skipped; missing: {missing_codebase_map_files})"} - .planning/PROJECT.md -- .planning/REQUIREMENTS.md +- .planning/REQUIREMENTS.md {requirements_exists ? "(present)" : "(missing; onboarding incomplete)"} - .planning/ROADMAP.md - .planning/STATE.md - .planning/onboarding/SUMMARY.md diff --git a/src/init.cts b/src/init.cts index a533d65fd..c4bb421a8 100644 --- a/src/init.cts +++ b/src/init.cts @@ -109,6 +109,10 @@ const REQUIRED_CODEBASE_MAP_FILES = [ 'INTEGRATIONS.md', 'CONCERNS.md', ]; +const PLANNING_DOC_SEGMENTS = new Set([ + 'adr', 'adrs', 'prd', 'prds', 'spec', 'specs', 'rfc', 'rfcs', +]); + function hasCodeFilesInternal(dir: string, depth = 0): boolean { if (depth > 3) return false; let entries: fs.Dirent[]; @@ -157,12 +161,11 @@ function listPlanningDocCandidates(cwd: string): string[] { if (!entry.isFile() || !entry.name.toLowerCase().endsWith('.md')) continue; const upperName = entry.name.toUpperCase(); const relLower = rel.toLowerCase(); + const pathSegments = relLower.split('/'); if ( /(^|[-_ ])(ADR|PRD|SPEC|RFC)([-_ ]|\.)/i.test(entry.name) || /^\d{4}[-_].+\.md$/i.test(entry.name) || - relLower.includes('/adr') || - relLower.includes('/prd') || - relLower.includes('/spec') || + pathSegments.some((segment) => PLANNING_DOC_SEGMENTS.has(segment)) || upperName === 'REQUIREMENTS.md' ) { candidates.add(toPosixPath(rel)); @@ -899,6 +902,7 @@ function cmdInitOnboard(cwd: string, raw: boolean): void { project_exists: pathExistsInternal(cwd, '.planning/PROJECT.md'), planning_exists: fs.existsSync(planningRoot(cwd)), + requirements_exists: fs.existsSync(path.join(planningDir(cwd), 'REQUIREMENTS.md')), roadmap_exists: fs.existsSync(path.join(planningDir(cwd), 'ROADMAP.md')), state_exists: fs.existsSync(path.join(planningDir(cwd), 'STATE.md')), config_exists: fs.existsSync(path.join(planningDir(cwd), 'config.json')), @@ -920,6 +924,9 @@ function cmdInitOnboard(cwd: string, raw: boolean): void { onboarding_summary_path: '.planning/onboarding/SUMMARY.md', project_path: '.planning/PROJECT.md', + requirements_path: toPosixPath( + path.relative(cwd, path.join(planningDir(cwd), 'REQUIREMENTS.md')), + ), roadmap_path: toPosixPath(path.relative(cwd, path.join(planningDir(cwd), 'ROADMAP.md'))), state_path: toPosixPath(path.relative(cwd, path.join(planningDir(cwd), 'STATE.md'))), codebase_dir: toPosixPath(path.relative(cwd, path.join(planningRoot(cwd), 'codebase'))), diff --git a/tests/onboard-command.test.cjs b/tests/onboard-command.test.cjs index a7903fe90..deb69cf82 100644 --- a/tests/onboard-command.test.cjs +++ b/tests/onboard-command.test.cjs @@ -50,6 +50,21 @@ describe('init onboard public CLI projection', () => { assert.strictEqual(parsed.text_mode, false); }); + test('detects planning docs in top-level ADR and PRD folders', () => { + fs.mkdirSync(path.join(tmpDir, 'prd'), { recursive: true }); + fs.writeFileSync(path.join(tmpDir, 'prd', 'product.md'), '# Product Requirements\n'); + fs.mkdirSync(path.join(tmpDir, 'adr'), { recursive: true }); + fs.writeFileSync(path.join(tmpDir, 'adr', 'decision.md'), '# Architecture Decision\n'); + + const result = runGsdTools('init onboard --raw', tmpDir, { HOME: tmpDir }); + assert.ok(result.success, `init onboard should succeed: ${result.error}`); + + const parsed = JSON.parse(result.output); + assert.strictEqual(parsed.has_docs_candidates, true); + assert.strictEqual(parsed.doc_candidate_count, 2); + assert.deepStrictEqual(parsed.doc_candidates, ['adr/decision.md', 'prd/product.md']); + }); + test('reports complete codebase map and onboarding summary in existing planning', () => { fs.mkdirSync(path.join(tmpDir, '.planning', 'codebase'), { recursive: true }); for (const name of ['STACK', 'ARCHITECTURE', 'STRUCTURE', 'CONVENTIONS', 'TESTING', 'INTEGRATIONS', 'CONCERNS']) { @@ -58,6 +73,7 @@ describe('init onboard public CLI projection', () => { fs.mkdirSync(path.join(tmpDir, '.planning', 'onboarding'), { recursive: true }); fs.writeFileSync(path.join(tmpDir, '.planning', 'onboarding', 'SUMMARY.md'), '# Onboarding Summary\n'); fs.writeFileSync(path.join(tmpDir, '.planning', 'PROJECT.md'), '# Project\n'); + fs.writeFileSync(path.join(tmpDir, '.planning', 'REQUIREMENTS.md'), '# Requirements\n'); fs.writeFileSync(path.join(tmpDir, '.planning', 'ROADMAP.md'), '# Roadmap\n'); fs.writeFileSync(path.join(tmpDir, '.planning', 'STATE.md'), '# State\n'); fs.writeFileSync(path.join(tmpDir, '.planning', 'config.json'), JSON.stringify({ workflow: { text_mode: true } })); @@ -80,6 +96,7 @@ describe('init onboard public CLI projection', () => { const parsed = JSON.parse(result.output); assert.strictEqual(parsed.planning_exists, true); assert.strictEqual(parsed.project_exists, true); + assert.strictEqual(parsed.requirements_exists, true); assert.strictEqual(parsed.roadmap_exists, true); assert.strictEqual(parsed.state_exists, true); assert.strictEqual(parsed.has_codebase_map, true); @@ -89,6 +106,22 @@ describe('init onboard public CLI projection', () => { assert.strictEqual(parsed.text_mode, true); }); + test('reports missing requirements in otherwise existing planning', () => { + fs.mkdirSync(path.join(tmpDir, '.planning'), { recursive: true }); + fs.writeFileSync(path.join(tmpDir, '.planning', 'PROJECT.md'), '# Project\n'); + fs.writeFileSync(path.join(tmpDir, '.planning', 'ROADMAP.md'), '# Roadmap\n'); + fs.writeFileSync(path.join(tmpDir, '.planning', 'STATE.md'), '# State\n'); + + const result = runGsdTools('init onboard --raw', tmpDir, { HOME: tmpDir }); + assert.ok(result.success, `init onboard should succeed: ${result.error}`); + + const parsed = JSON.parse(result.output); + assert.strictEqual(parsed.project_exists, true); + assert.strictEqual(parsed.requirements_exists, false); + assert.strictEqual(parsed.roadmap_exists, true); + assert.strictEqual(parsed.state_exists, true); + }); + test('ignores generated and vendor directories when detecting existing code', () => { fs.mkdirSync(path.join(tmpDir, 'node_modules', 'pkg'), { recursive: true }); fs.writeFileSync(path.join(tmpDir, 'node_modules', 'pkg', 'index.ts'), 'export const ignored = true;\n'); @@ -151,6 +184,9 @@ describe('/gsd:onboard command contract', () => { assert.ok(content.includes('new-project'), 'workflow must route to new-project'); assert.ok(content.includes('.planning/onboarding/SUMMARY.md'), 'workflow must create onboarding summary'); assert.match(content, /overwrite|idempotent|do not overwrite/i, 'workflow must protect existing planning'); + assert.ok(content.includes('requirements_exists'), 'workflow must parse requirements existence'); + assert.match(content, /REQUIREMENTS\.md: \{requirements_exists \? "present" : "missing"\}/, 'workflow must report missing requirements in partial planning'); + assert.match(content, /If `project_exists` is true and .*`requirements_exists`.* is false/s, 'workflow must gate partial planning on missing requirements'); assert.ok(content.includes('--text'), 'workflow must document text-mode fallback'); assert.ok(!content.includes('execute-phase'), 'onboarding must not execute implementation phases'); assert.ok(!content.includes('gsd:ship'), 'onboarding must not ship work'); From f29f981486b37a905d7eba5ade7484aad9c31b29 Mon Sep 17 00:00:00 2001 From: Jeremy McSpadden Date: Fri, 3 Jul 2026 09:50:33 -0500 Subject: [PATCH 04/48] no-mistakes(review): Fix onboarding docs gate detection --- gsd-core/workflows/onboard.md | 2 +- src/init.cts | 2 +- tests/onboard-command.test.cjs | 17 ++++++++++++++--- 3 files changed, 16 insertions(+), 5 deletions(-) diff --git a/gsd-core/workflows/onboard.md b/gsd-core/workflows/onboard.md index f2702a8aa..2c8bfd135 100644 --- a/gsd-core/workflows/onboard.md +++ b/gsd-core/workflows/onboard.md @@ -101,7 +101,7 @@ Exit. ## 4. Existing Docs Gate -If `has_docs_candidates` is true and `planning_exists` is false: +If `has_docs_candidates` is true and `project_exists` is false: - If `TEXT_MODE=true`, print: diff --git a/src/init.cts b/src/init.cts index c4bb421a8..472de1ab7 100644 --- a/src/init.cts +++ b/src/init.cts @@ -137,7 +137,7 @@ function hasPackageFileInternal(cwd: string): boolean { } function listPlanningDocCandidates(cwd: string): string[] { - const roots = ['docs', 'adr', 'adrs', 'prd', 'prds', 'spec', 'specs', 'rfcs']; + const roots = ['docs', 'adr', 'adrs', 'prd', 'prds', 'spec', 'specs', 'rfc', 'rfcs']; const candidates = new Set(); const visit = (dir: string, relDir: string, depth: number): void => { diff --git a/tests/onboard-command.test.cjs b/tests/onboard-command.test.cjs index deb69cf82..aac86784d 100644 --- a/tests/onboard-command.test.cjs +++ b/tests/onboard-command.test.cjs @@ -50,19 +50,25 @@ describe('init onboard public CLI projection', () => { assert.strictEqual(parsed.text_mode, false); }); - test('detects planning docs in top-level ADR and PRD folders', () => { + test('detects planning docs in top-level ADR, PRD, and RFC folders', () => { fs.mkdirSync(path.join(tmpDir, 'prd'), { recursive: true }); fs.writeFileSync(path.join(tmpDir, 'prd', 'product.md'), '# Product Requirements\n'); fs.mkdirSync(path.join(tmpDir, 'adr'), { recursive: true }); fs.writeFileSync(path.join(tmpDir, 'adr', 'decision.md'), '# Architecture Decision\n'); + fs.mkdirSync(path.join(tmpDir, 'rfc'), { recursive: true }); + fs.writeFileSync(path.join(tmpDir, 'rfc', 'proposal.md'), '# Request for Comments\n'); const result = runGsdTools('init onboard --raw', tmpDir, { HOME: tmpDir }); assert.ok(result.success, `init onboard should succeed: ${result.error}`); const parsed = JSON.parse(result.output); assert.strictEqual(parsed.has_docs_candidates, true); - assert.strictEqual(parsed.doc_candidate_count, 2); - assert.deepStrictEqual(parsed.doc_candidates, ['adr/decision.md', 'prd/product.md']); + assert.strictEqual(parsed.doc_candidate_count, 3); + assert.deepStrictEqual(parsed.doc_candidates, [ + 'adr/decision.md', + 'prd/product.md', + 'rfc/proposal.md', + ]); }); test('reports complete codebase map and onboarding summary in existing planning', () => { @@ -181,6 +187,11 @@ describe('/gsd:onboard command contract', () => { assert.ok(content.includes('init onboard'), 'workflow must use init onboard projection'); assert.ok(content.includes('map-codebase'), 'workflow must route to map-codebase'); assert.ok(content.includes('ingest-docs'), 'workflow must route to ingest-docs'); + assert.match( + content, + /If `has_docs_candidates` is true and `project_exists` is false:/, + 'workflow must offer docs ingest before project setup even when codebase mapping already created .planning', + ); assert.ok(content.includes('new-project'), 'workflow must route to new-project'); assert.ok(content.includes('.planning/onboarding/SUMMARY.md'), 'workflow must create onboarding summary'); assert.match(content, /overwrite|idempotent|do not overwrite/i, 'workflow must protect existing planning'); From 66ff521c71fba736490a21e3d439d28d1fded049 Mon Sep 17 00:00:00 2001 From: Jeremy McSpadden Date: Fri, 3 Jul 2026 09:59:19 -0500 Subject: [PATCH 05/48] no-mistakes(review): Fix onboard runtime and doc detection --- gsd-core/workflows/onboard.md | 4 ++-- src/init.cts | 41 ++++++++++++++++++++++++---------- tests/onboard-command.test.cjs | 37 ++++++++++++++++++++++++++++++ 3 files changed, 68 insertions(+), 14 deletions(-) diff --git a/gsd-core/workflows/onboard.md b/gsd-core/workflows/onboard.md index 2c8bfd135..80fac011c 100644 --- a/gsd-core/workflows/onboard.md +++ b/gsd-core/workflows/onboard.md @@ -29,7 +29,7 @@ Parse `$ARGUMENTS`: Run the init projection: ```bash -_GSD_SHIM_NAME="gsd-tools.cjs"; _GSD_RUNTIME_ROOT="${RUNTIME_DIR:-$(git rev-parse --show-toplevel 2>/dev/null || pwd)}"; GSD_TOOLS="${_GSD_RUNTIME_ROOT}/gsd-core/bin/${_GSD_SHIM_NAME}"; if [ -f "$GSD_TOOLS" ]; then gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${_GSD_RUNTIME_ROOT}/.claude/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${_GSD_RUNTIME_ROOT}/.claude/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${_GSD_RUNTIME_ROOT}/.codex/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${_GSD_RUNTIME_ROOT}/.codex/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif command -v gsd-tools >/dev/null 2>&1; then GSD_TOOLS="$(command -v gsd-tools)"; gsd_run() { "$GSD_TOOLS" "$@"; }; elif [ -f "$HOME/.claude/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="$HOME/.claude/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${CODEX_HOME:-$HOME/.codex}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${CODEX_HOME:-$HOME/.codex}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; else echo "ERROR: gsd-tools.cjs not found. Run: npx -y @opengsd/gsd-core@latest --local" >&2; exit 1; fi +_GSD_SHIM_NAME="gsd-tools.cjs"; _GSD_RUNTIME_ROOT="${RUNTIME_DIR:-$(git rev-parse --show-toplevel 2>/dev/null || pwd)}"; GSD_TOOLS="${_GSD_RUNTIME_ROOT}/gsd-core/bin/${_GSD_SHIM_NAME}"; if [ -f "$GSD_TOOLS" ]; then gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${_GSD_RUNTIME_ROOT}/.claude/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${_GSD_RUNTIME_ROOT}/.claude/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${_GSD_RUNTIME_ROOT}/.codex/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${_GSD_RUNTIME_ROOT}/.codex/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif command -v gsd-tools >/dev/null 2>&1; then GSD_TOOLS="$(command -v gsd-tools)"; gsd_run() { "$GSD_TOOLS" "$@"; }; elif [ -f "$HOME/.claude/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="$HOME/.claude/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${HERMES_HOME:-$HOME/.hermes}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${HERMES_HOME:-$HOME/.hermes}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${CURSOR_CONFIG_DIR:-$HOME/.cursor}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${CURSOR_CONFIG_DIR:-$HOME/.cursor}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${CODEX_HOME:-$HOME/.codex}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${CODEX_HOME:-$HOME/.codex}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${GEMINI_CONFIG_DIR:-$HOME/.gemini}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${GEMINI_CONFIG_DIR:-$HOME/.gemini}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${COPILOT_CONFIG_DIR:-$HOME/.copilot}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${COPILOT_CONFIG_DIR:-$HOME/.copilot}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${WINDSURF_CONFIG_DIR:-$HOME/.codeium/windsurf}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${WINDSURF_CONFIG_DIR:-$HOME/.codeium/windsurf}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${AUGMENT_CONFIG_DIR:-$HOME/.augment}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${AUGMENT_CONFIG_DIR:-$HOME/.augment}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${TRAE_CONFIG_DIR:-$HOME/.trae}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${TRAE_CONFIG_DIR:-$HOME/.trae}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${QWEN_CONFIG_DIR:-$HOME/.qwen}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${QWEN_CONFIG_DIR:-$HOME/.qwen}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${CODEBUDDY_CONFIG_DIR:-$HOME/.codebuddy}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${CODEBUDDY_CONFIG_DIR:-$HOME/.codebuddy}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${CLINE_CONFIG_DIR:-$HOME/.cline}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${CLINE_CONFIG_DIR:-$HOME/.cline}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${GROK_AGENTS_HOME:-$HOME/.agents}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${GROK_AGENTS_HOME:-$HOME/.agents}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${ANTIGRAVITY_CONFIG_DIR:-$HOME/.gemini/antigravity}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${ANTIGRAVITY_CONFIG_DIR:-$HOME/.gemini/antigravity}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${OPENCODE_CONFIG_DIR:-${XDG_CONFIG_HOME:-$HOME/.config}/opencode}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${OPENCODE_CONFIG_DIR:-${XDG_CONFIG_HOME:-$HOME/.config}/opencode}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${KILO_CONFIG_DIR:-${XDG_CONFIG_HOME:-$HOME/.config}/kilo}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${KILO_CONFIG_DIR:-${XDG_CONFIG_HOME:-$HOME/.config}/kilo}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; else echo "ERROR: gsd-tools.cjs not found at $GSD_TOOLS and gsd-tools is not on PATH. Run: npx -y @opengsd/gsd-core@latest --claude --local" >&2; exit 1; fi; if [ -n "${CLAUDE_ENV_FILE:-}" ] && [ -n "${GSD_TOOLS:-}" ]; then printf "export PATH='%s':\"\$PATH\"\n" "${GSD_TOOLS%/*}" >> "$CLAUDE_ENV_FILE" 2>/dev/null || true; fi INIT=$(gsd_run init onboard) if [[ "$INIT" == @file:* ]]; then INIT=$(cat "${INIT#@file:}"); fi ``` @@ -38,7 +38,7 @@ Parse JSON fields: `planning_exists`, `project_exists`, `requirements_exists`, `roadmap_exists`, `state_exists`, `has_existing_code`, `has_package_file`, `is_brownfield`, `has_codebase_map`, `codebase_map_files_present`, `missing_codebase_map_files`, `has_docs_candidates`, -`doc_candidate_count`, `onboarding_summary_exists`, `text_mode`, `agents_installed`, +`doc_candidate_count`, `onboarding_summary_exists`, `text_mode`, `commit_docs`, `agents_installed`, `missing_agents`, `has_git`, `git_worktree_root`, `in_nested_subdir`. Set `TEXT_MODE=true` if `--text` is present OR `text_mode` from INIT is true. diff --git a/src/init.cts b/src/init.cts index 472de1ab7..a82bae89d 100644 --- a/src/init.cts +++ b/src/init.cts @@ -140,6 +140,24 @@ function listPlanningDocCandidates(cwd: string): string[] { const roots = ['docs', 'adr', 'adrs', 'prd', 'prds', 'spec', 'specs', 'rfc', 'rfcs']; const candidates = new Set(); + const isPlanningDocCandidate = (rel: string, name: string): boolean => { + const upperName = name.toUpperCase(); + const relLower = rel.toLowerCase(); + const pathSegments = relLower.split('/'); + return ( + /(^|[-_ ])(ADR|PRD|SPEC|RFC)([-_ ]|\.)/i.test(name) || + /^\d{4}[-_].+\.md$/i.test(name) || + pathSegments.some((segment) => PLANNING_DOC_SEGMENTS.has(segment)) || + upperName === 'REQUIREMENTS.MD' + ); + }; + + const addCandidate = (rel: string, name: string): void => { + if (name.toLowerCase().endsWith('.md') && isPlanningDocCandidate(rel, name)) { + candidates.add(toPosixPath(rel)); + } + }; + const visit = (dir: string, relDir: string, depth: number): void => { if (depth > 3) return; let entries: fs.Dirent[]; @@ -158,21 +176,20 @@ function listPlanningDocCandidates(cwd: string): string[] { continue; } - if (!entry.isFile() || !entry.name.toLowerCase().endsWith('.md')) continue; - const upperName = entry.name.toUpperCase(); - const relLower = rel.toLowerCase(); - const pathSegments = relLower.split('/'); - if ( - /(^|[-_ ])(ADR|PRD|SPEC|RFC)([-_ ]|\.)/i.test(entry.name) || - /^\d{4}[-_].+\.md$/i.test(entry.name) || - pathSegments.some((segment) => PLANNING_DOC_SEGMENTS.has(segment)) || - upperName === 'REQUIREMENTS.md' - ) { - candidates.add(toPosixPath(rel)); - } + if (entry.isFile()) addCandidate(rel, entry.name); } }; + let rootEntries: fs.Dirent[] = []; + try { + rootEntries = fs.readdirSync(cwd, { withFileTypes: true }); + } catch { + rootEntries = []; + } + for (const entry of rootEntries) { + if (entry.isFile()) addCandidate(entry.name, entry.name); + } + for (const root of roots) { const full = path.join(cwd, root); if (fs.existsSync(full)) visit(full, root, 0); diff --git a/tests/onboard-command.test.cjs b/tests/onboard-command.test.cjs index aac86784d..ccaa85c84 100644 --- a/tests/onboard-command.test.cjs +++ b/tests/onboard-command.test.cjs @@ -71,6 +71,32 @@ describe('init onboard public CLI projection', () => { ]); }); + test('detects root-level planning docs without broad repo scan', () => { + fs.writeFileSync(path.join(tmpDir, 'PRD.md'), '# Product Requirements\n'); + fs.writeFileSync(path.join(tmpDir, 'SPEC.md'), '# Specification\n'); + fs.writeFileSync(path.join(tmpDir, 'RFC.md'), '# Request for Comments\n'); + fs.writeFileSync(path.join(tmpDir, 'ADR.md'), '# Architecture Decision\n'); + fs.writeFileSync(path.join(tmpDir, 'REQUIREMENTS.md'), '# Requirements\n'); + fs.writeFileSync(path.join(tmpDir, '0001-decision.md'), '# Decision\n'); + fs.mkdirSync(path.join(tmpDir, 'src'), { recursive: true }); + fs.writeFileSync(path.join(tmpDir, 'src', 'PRD.md'), '# Nested Product Requirements\n'); + + const result = runGsdTools('init onboard --raw', tmpDir, { HOME: tmpDir }); + assert.ok(result.success, `init onboard should succeed: ${result.error}`); + + const parsed = JSON.parse(result.output); + assert.strictEqual(parsed.has_docs_candidates, true); + assert.strictEqual(parsed.doc_candidate_count, 6); + assert.deepStrictEqual(parsed.doc_candidates, [ + '0001-decision.md', + 'ADR.md', + 'PRD.md', + 'REQUIREMENTS.md', + 'RFC.md', + 'SPEC.md', + ]); + }); + test('reports complete codebase map and onboarding summary in existing planning', () => { fs.mkdirSync(path.join(tmpDir, '.planning', 'codebase'), { recursive: true }); for (const name of ['STACK', 'ARCHITECTURE', 'STRUCTURE', 'CONVENTIONS', 'TESTING', 'INTEGRATIONS', 'CONCERNS']) { @@ -185,6 +211,17 @@ describe('/gsd:onboard command contract', () => { const content = fs.readFileSync(WF_PATH, 'utf8'); assert.ok(content.includes('init onboard'), 'workflow must use init onboard projection'); + for (const runtimeHome of [ + 'HERMES_HOME', + 'CURSOR_CONFIG_DIR', + 'CODEX_HOME', + 'GEMINI_CONFIG_DIR', + 'WINDSURF_CONFIG_DIR', + 'OPENCODE_CONFIG_DIR', + ]) { + assert.ok(content.includes(runtimeHome), `workflow resolver must include ${runtimeHome}`); + } + assert.match(content, /Parse JSON fields:.*`commit_docs`/s, 'workflow must parse commit_docs before using it'); assert.ok(content.includes('map-codebase'), 'workflow must route to map-codebase'); assert.ok(content.includes('ingest-docs'), 'workflow must route to ingest-docs'); assert.match( From b006b1a23eb1d4c4dcaa526f4192cf37cf06f57e Mon Sep 17 00:00:00 2001 From: Jeremy McSpadden Date: Fri, 3 Jul 2026 10:05:50 -0500 Subject: [PATCH 06/48] no-mistakes(review): Fix doc-only onboarding route --- gsd-core/workflows/onboard.md | 2 +- tests/onboard-command.test.cjs | 5 +++++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/gsd-core/workflows/onboard.md b/gsd-core/workflows/onboard.md index 80fac011c..112b942e1 100644 --- a/gsd-core/workflows/onboard.md +++ b/gsd-core/workflows/onboard.md @@ -89,7 +89,7 @@ Exit. If the user skips mapping, continue with a warning. -If `is_brownfield` is false and `planning_exists` is false, print: +If `is_brownfield` is false and `planning_exists` is false and `has_docs_candidates` is false, print: ```text No existing code was detected. For a greenfield project, run: diff --git a/tests/onboard-command.test.cjs b/tests/onboard-command.test.cjs index ccaa85c84..9a7b55395 100644 --- a/tests/onboard-command.test.cjs +++ b/tests/onboard-command.test.cjs @@ -229,6 +229,11 @@ describe('/gsd:onboard command contract', () => { /If `has_docs_candidates` is true and `project_exists` is false:/, 'workflow must offer docs ingest before project setup even when codebase mapping already created .planning', ); + assert.match( + content, + /If `is_brownfield` is false and `planning_exists` is false and `has_docs_candidates` is false, print:/, + 'workflow must not send doc-only repos to new-project before the docs ingest gate', + ); assert.ok(content.includes('new-project'), 'workflow must route to new-project'); assert.ok(content.includes('.planning/onboarding/SUMMARY.md'), 'workflow must create onboarding summary'); assert.match(content, /overwrite|idempotent|do not overwrite/i, 'workflow must protect existing planning'); From a3cca0704da2e307aa71aedc5fadd797a23e57cc Mon Sep 17 00:00:00 2001 From: Jeremy McSpadden Date: Fri, 3 Jul 2026 10:23:01 -0500 Subject: [PATCH 07/48] no-mistakes(document): Sync onboard documentation --- README.md | 7 +-- commands/gsd/map-codebase.md | 6 +-- docs/CLI-TOOLS.md | 3 +- docs/COMMANDS.md | 2 +- docs/FEATURES.md | 24 ++++++++++- docs/USER-GUIDE.md | 11 +++-- docs/ja-JP/COMMANDS.md | 19 ++++++++ docs/ja-JP/FEATURES.md | 16 ++++++- docs/ja-JP/INVENTORY.md | 2 + docs/ja-JP/USER-GUIDE.md | 7 +-- .../onboarding-an-existing-codebase.md | 7 +-- docs/ko-KR/COMMANDS.md | 19 ++++++++ docs/ko-KR/FEATURES.md | 16 ++++++- docs/ko-KR/INVENTORY.md | 2 + docs/ko-KR/USER-GUIDE.md | 7 +-- .../onboarding-an-existing-codebase.md | 5 ++- docs/pt-BR/COMMANDS.md | 19 ++++++++ docs/pt-BR/FEATURES.md | 2 +- docs/pt-BR/INVENTORY.md | 2 + docs/pt-BR/USER-GUIDE.md | 7 +-- .../onboarding-an-existing-codebase.md | 5 ++- docs/reference/planning-artifacts.md | 18 ++++++-- .../onboarding-an-existing-codebase.md | 43 ++++++++++++++++--- docs/zh-CN/COMMANDS.md | 19 ++++++++ docs/zh-CN/FEATURES.md | 16 ++++++- docs/zh-CN/INVENTORY.md | 2 + docs/zh-CN/USER-GUIDE.md | 7 +-- .../onboarding-an-existing-codebase.md | 7 +-- gsd-core/templates/project.md | 2 +- gsd-core/workflows/do.md | 7 +-- gsd-core/workflows/help/modes/full.md | 2 +- skills/gsd-map-codebase/SKILL.md | 6 +-- skills/gsd-surface/SKILL.md | 2 +- 33 files changed, 260 insertions(+), 59 deletions(-) diff --git a/README.md b/README.md index d18deabc7..9f5f08857 100644 --- a/README.md +++ b/README.md @@ -47,13 +47,14 @@ The installer prompts for your runtime (Claude Code, OpenCode, Antigravity CLI, On another runtime or without Node.js? See [Install on your runtime](docs/how-to/install-on-your-runtime.md). -Once installed, start your first project: +Once installed, start a new project or onboard an existing repo: ```bash -/gsd-new-project +/gsd-new-project # greenfield project +/gsd-onboard # existing codebase ``` -New here? Follow [Your first project](docs/tutorials/your-first-project.md) for a guided walkthrough from install to first shipped phase. +New here? Follow [Your first project](docs/tutorials/your-first-project.md) for a guided walkthrough from install to first shipped phase, or [Onboarding an existing codebase](docs/tutorials/onboarding-an-existing-codebase.md) for brownfield setup. --- diff --git a/commands/gsd/map-codebase.md b/commands/gsd/map-codebase.md index b48db59a5..0d0a0f2f8 100644 --- a/commands/gsd/map-codebase.md +++ b/commands/gsd/map-codebase.md @@ -42,7 +42,7 @@ Parse the first token of $ARGUMENTS: Check for .planning/STATE.md - loads context if project already initialized **This command can run:** -- Before /gsd:new-project (brownfield codebases) - creates codebase map first +- Via /gsd:onboard for first-time brownfield setup - creates codebase map first - After /gsd:new-project (greenfield codebases) - updates codebase map as code evolves - Anytime to refresh codebase understanding @@ -51,7 +51,7 @@ Check for .planning/STATE.md - loads context if project already initialized **Use map-codebase for:** - Brownfield projects before initialization (understand existing code first) - Refreshing codebase map after significant changes -- Onboarding to an unfamiliar codebase +- Refreshing or deepening an onboarded codebase map - Before major refactoring (understand current state) - When STATE.md references outdated codebase info @@ -71,7 +71,7 @@ Check for .planning/STATE.md - loads context if project already initialized 4. Wait for agents to complete, collect confirmations (NOT document contents) 5. Verify all 7 documents exist with line counts 6. Commit codebase map -7. Offer next steps (typically: /gsd:new-project or /gsd:plan-phase) +7. Offer next steps (typically: /gsd:onboard, /gsd:new-project, or /gsd:plan-phase) diff --git a/docs/CLI-TOOLS.md b/docs/CLI-TOOLS.md index 392656603..9381be660 100644 --- a/docs/CLI-TOOLS.md +++ b/docs/CLI-TOOLS.md @@ -421,13 +421,14 @@ node gsd-tools.cjs scaffold phase-dir --phase N --name "phase name" ## Init Commands (Compound Context Loading) -Load all context needed for a specific workflow in one call. Returns JSON with project info, config, state, and workflow-specific data. +Load all context needed for a specific workflow in one call. Returns JSON with project info, config, state, and workflow-specific data. `init onboard` reports brownfield signals, planning-doc candidates, codebase-map completeness, partial planning state, and onboarding summary status for `/gsd-onboard`. ```bash node gsd-tools.cjs init execute-phase node gsd-tools.cjs init plan-phase node gsd-tools.cjs init new-project node gsd-tools.cjs init new-milestone +node gsd-tools.cjs init onboard node gsd-tools.cjs init quick node gsd-tools.cjs init resume node gsd-tools.cjs init verify-work diff --git a/docs/COMMANDS.md b/docs/COMMANDS.md index 5e25aeffd..e8d2b9095 100644 --- a/docs/COMMANDS.md +++ b/docs/COMMANDS.md @@ -1202,7 +1202,7 @@ gsd capability remove my-cap --scope project # Turn the installed overl ### `/gsd-map-codebase` -Analyze existing codebase with parallel mapper agents. Use `--fast` for a quick single-agent scan, or `--query` to search existing intel. +Analyze existing codebase with parallel mapper agents. Use `--fast` for a quick single-agent scan, or `--query` to search existing intel. First-time brownfield setup should usually start with `/gsd-onboard`, which hands off to this command when a map is missing. | Argument | Required | Description | |----------|----------|-------------| diff --git a/docs/FEATURES.md b/docs/FEATURES.md index 0019ee7dd..8f1b647dd 100644 --- a/docs/FEATURES.md +++ b/docs/FEATURES.md @@ -38,6 +38,7 @@ - [Model Profiles](#26-model-profiles) - [Brownfield Features](#brownfield-features) - [Codebase Mapping](#27-codebase-mapping) + - [Existing Codebase Onboarding](#27b-existing-codebase-onboarding) - [Utility Features](#utility-features) - [Debug System](#28-debug-system) - [Todo Management](#29-todo-management) @@ -789,7 +790,7 @@ **Command:** `/gsd-map-codebase [area]` -**Purpose:** Analyze an existing codebase before starting a new project, so GSD understands what exists. +**Purpose:** Analyze an existing codebase before starting a new project or as the mapping handoff from `/gsd-onboard`, so GSD understands what exists. **Requirements:** - REQ-MAP-01: System MUST spawn parallel mapper agents for each analysis area @@ -817,6 +818,27 @@ only the subtrees the phase actually changed. Each produced document carries `last_mapped_commit` in its YAML frontmatter so drift can be measured against the mapping point, not HEAD. +### 27b. Existing Codebase Onboarding + +**Command:** `/gsd-onboard [--fast] [--text]` + +**Purpose:** Guide first-time setup for an existing repository by checking brownfield state, routing through codebase mapping and docs ingest, then handing off to project initialization without silently overwriting planning artifacts. + +**Requirements:** +- REQ-ONBOARD-01: System MUST detect existing code, package manifests, planning documents, partial `.planning/` state, and complete or missing codebase-map files. +- REQ-ONBOARD-02: System MUST hand off to `/gsd-map-codebase` or `/gsd-map-codebase --fast` when brownfield code lacks a complete `.planning/codebase/` map. +- REQ-ONBOARD-03: System MUST offer `/gsd-ingest-docs` before `/gsd-new-project` when ADR/PRD/SPEC/RFC candidates exist and no project exists. +- REQ-ONBOARD-04: System MUST refuse to report onboarding complete until `PROJECT.md`, `REQUIREMENTS.md`, `ROADMAP.md`, and `STATE.md` all exist. +- REQ-ONBOARD-05: System MUST create or confirm `.planning/onboarding/SUMMARY.md` only after project setup exists. +- REQ-ONBOARD-06: System MUST support `--text` for numbered plain-text gates on runtimes without interactive menus. + +**Produces:** +| Artifact | Description | +|----------|-------------| +| `.planning/codebase/` | Codebase map produced by the `/gsd-map-codebase` handoff | +| `.planning/PROJECT.md`, `REQUIREMENTS.md`, `ROADMAP.md`, `STATE.md` | Planning setup produced by `/gsd-new-project` or `/gsd-ingest-docs` | +| `.planning/onboarding/SUMMARY.md` | Onboarding status, artifact index, and next-command summary | + ### 27a. Post-Execute Codebase Drift Detection **Introduced by:** #2003 diff --git a/docs/USER-GUIDE.md b/docs/USER-GUIDE.md index e06c10d4d..aaaee31af 100644 --- a/docs/USER-GUIDE.md +++ b/docs/USER-GUIDE.md @@ -79,7 +79,7 @@ The core GSD loop is: **discuss → plan → execute → verify → ship**, repe See [Your first project](tutorials/your-first-project.md). -For onboarding an existing codebase before starting a new milestone, see [Onboarding an existing codebase](tutorials/onboarding-an-existing-codebase.md). +For onboarding an existing codebase before starting a new milestone, run `/gsd-onboard` or see [Onboarding an existing codebase](tutorials/onboarding-an-existing-codebase.md). **Relevant flags at a glance:** @@ -536,11 +536,13 @@ claude --dangerously-skip-permissions ### Existing Codebase ```bash -/gsd-map-codebase # Analyse what exists (parallel agents) -/gsd-new-project # Questions focus on what you're ADDING +/gsd-onboard # Safely map, ingest docs, and initialize planning +# Follow the printed top-level handoff commands, then rerun /gsd-onboard # (normal phase workflow from here) ``` +`/gsd-onboard` routes through `/gsd-map-codebase`, `/gsd-ingest-docs`, and `/gsd-new-project` without nesting interactive workflows or overwriting existing planning files silently. + **Post-execute drift detection (#2003).** After every `/gsd-execute-phase`, GSD checks whether the phase introduced enough structural change to make `.planning/codebase/STRUCTURE.md` stale. Flip the behavior with: ```bash @@ -986,7 +988,8 @@ To disable parallel execution entirely: `/gsd-settings` → set `parallelization themes/ default.css # Shared CSS variables for all sketches MANIFEST.md # Index of all sketches with winners - codebase/ # Brownfield codebase mapping (from /gsd-map-codebase) + codebase/ # Brownfield codebase mapping (from /gsd-map-codebase or /gsd-onboard) + onboarding/ # Brownfield onboarding summary (from /gsd-onboard) phases/ XX-phase-name/ XX-YY-PLAN.md # Atomic execution plans diff --git a/docs/ja-JP/COMMANDS.md b/docs/ja-JP/COMMANDS.md index d63034e51..c3c9ca0a5 100644 --- a/docs/ja-JP/COMMANDS.md +++ b/docs/ja-JP/COMMANDS.md @@ -51,6 +51,25 @@ v1.40 では、最初のステージエントリーポイントとして6つの --- +### `/gsd-onboard` + +既存コードベースの初回 GSD オンボーディングを案内します。リポジトリ状態を確認し、コードベースマッピング、任意のドキュメント取り込み、プロジェクト初期化へ安全にハンドオフし、計画が揃った後にオンボーディング summary を作成します。 + +| フラグ | 説明 | +|------|-------------| +| `--fast` | 軽量な `/gsd-map-codebase --fast` マッピングハンドオフを優先 | +| `--text` | TUI メニューではなく番号付きプレーンテキストのゲートを使用 | + +**前提条件:** 既存リポジトリまたは計画ドキュメント。空のグリーンフィールドプロジェクトには `/gsd-new-project` を使用します。 +**生成物:** map-codebase による `.planning/codebase/`、new-project または ingest-docs による `.planning/`、セットアップ後の `.planning/onboarding/SUMMARY.md`。 + +```bash +/gsd-onboard # ガイド付き brownfield オンボーディング +/gsd-onboard --fast # 先に軽量コードベースマッピングを使用 +``` + +--- + ### `/gsd-workspace` GSD ワークスペースを管理 — リポジトリコピーと独立した `.planning/` ディレクトリを持つ隔離されたワークスペース環境を作成、一覧表示、または削除します。 diff --git a/docs/ja-JP/FEATURES.md b/docs/ja-JP/FEATURES.md index 6f91953c6..6e1bb6742 100644 --- a/docs/ja-JP/FEATURES.md +++ b/docs/ja-JP/FEATURES.md @@ -38,6 +38,7 @@ - [モデルプロファイル](#26-モデルプロファイル) - [ブラウンフィールド機能](#ブラウンフィールド機能) - [コードベースマッピング](#27-コードベースマッピング) + - [既存コードベースオンボーディング](#27b-既存コードベースオンボーディング) - [ユーティリティ機能](#ユーティリティ機能) - [デバッグシステム](#28-デバッグシステム) - [Todo 管理](#29-todo-管理) @@ -781,7 +782,7 @@ **コマンド:** `/gsd-map-codebase [area]` -**目的:** 新しいプロジェクトを開始する前に既存のコードベースを分析し、GSD が既存の構成を理解できるようにします。 +**目的:** 新しいプロジェクトを開始する前、または `/gsd-onboard` からのマッピングハンドオフとして既存のコードベースを分析し、GSD が既存の構成を理解できるようにします。 **要件:** - REQ-MAP-01: システムは各分析領域に対して並列マッパーエージェントを起動しなければならない @@ -805,6 +806,19 @@ `--paths ` スコープヒントを受け付けます。指定した場合、ツリー全体をスキャンする代わりに、リストされたリポジトリ相対プレフィックスに探索を制限します。 これはフェーズが実際に変更したサブツリーのみを更新するために、実行後コードベースドリフトゲートが使用するパスウェイです。各生成ドキュメントはその YAML フロントマターに `last_mapped_commit` を持ち、ドリフトを HEAD ではなくマッピング時点と照らし合わせて計測できます。 +### 27b. 既存コードベースオンボーディング + +**コマンド:** `/gsd-onboard [--fast] [--text]` + +**目的:** 既存リポジトリの初回セットアップを案内し、brownfield 状態を確認してコードベースマッピング、docs 取り込み、プロジェクト初期化へ安全にハンドオフします。 + +**要件:** +- REQ-ONBOARD-01: 既存コード、package manifest、計画ドキュメント、部分的な `.planning/`、コードベースマップの不足を検出する。 +- REQ-ONBOARD-02: 完全な `.planning/codebase/` がない brownfield では `/gsd-map-codebase` または `/gsd-map-codebase --fast` へハンドオフする。 +- REQ-ONBOARD-03: ADR/PRD/SPEC/RFC 候補があり project がない場合、`/gsd-new-project` の前に `/gsd-ingest-docs` を提示する。 +- REQ-ONBOARD-04: `PROJECT.md`、`REQUIREMENTS.md`、`ROADMAP.md`、`STATE.md` が揃うまで完了扱いにしない。 +- REQ-ONBOARD-05: project setup 後にのみ `.planning/onboarding/SUMMARY.md` を作成または確認する。 + ### 27a. 実行後コードベースドリフト検出 **導入:** #2003 diff --git a/docs/ja-JP/INVENTORY.md b/docs/ja-JP/INVENTORY.md index a1d5a6a70..506e18442 100644 --- a/docs/ja-JP/INVENTORY.md +++ b/docs/ja-JP/INVENTORY.md @@ -78,6 +78,7 @@ | コマンド | 役割 | ソース | |----------|------|--------| | `/gsd-new-project` | 深いコンテキスト収集と PROJECT.md で新しいプロジェクトを初期化。 | [commands/gsd/new-project.md](../../commands/gsd/new-project.md) | +| `/gsd-onboard` | 既存コードベースをマッピング、ドキュメント取り込み、プロジェクト設定、onboarding summary へ案内。 | [commands/gsd/onboard.md](../../commands/gsd/onboard.md) | | `/gsd-workspace` | GSD ワークスペースを管理 — 独立したワークスペース環境を作成(`--new`)、一覧表示(`--list`)、削除(`--remove`)。 | [commands/gsd/workspace.md](../../commands/gsd/workspace.md) | | `/gsd-discuss-phase` | 計画前にアダプティブな質問でフェーズコンテキストを収集。 | [commands/gsd/discuss-phase.md](../../commands/gsd/discuss-phase.md) | | `/gsd-mvp-phase` | フェーズを垂直 MVP スライスとして計画 — ユーザーストーリー、SPIDR 分割、その後 plan-phase。 | [commands/gsd/mvp-phase.md](../../commands/gsd/mvp-phase.md) | @@ -218,6 +219,7 @@ | `milestone-summary.md` | マイルストーンサマリー合成 — マイルストーンアーティファクトからオンボーディングとレビューアーティファクトを作成。 | `/gsd-milestone-summary` | | `new-milestone.md` | 新しいマイルストーンサイクルを開始 — プロジェクトコンテキストを読み込み、目標を収集して PROJECT.md/STATE.md を更新。 | `/gsd-new-milestone` | | `new-project.md` | 統合新プロジェクトフロー — 質問、調査(任意)、要件、ロードマップ。 | `/gsd-new-project` | +| `onboard.md` | Brownfield onboarding orchestration — コードベースをマップし、docs を取り込み、planning を初期化し、次のステップを要約。 | `/gsd-onboard` | | `new-workspace.md` | リポジトリのワークツリー/クローンと独立した `.planning/` を持つ独立したワークスペースを作成。 | `/gsd-workspace --new` | | `next.md` | 現在のプロジェクト状態を検出して次の論理的なステップに自動的に進む。 | `/gsd-progress --next` | | `node-repair.md` | タスク検証が失敗した場合の自律修復オペレーター。`execute-plan` から呼び出し。 | `execute-plan.md` (recovery) | diff --git a/docs/ja-JP/USER-GUIDE.md b/docs/ja-JP/USER-GUIDE.md index 264953822..15c4ee089 100644 --- a/docs/ja-JP/USER-GUIDE.md +++ b/docs/ja-JP/USER-GUIDE.md @@ -474,8 +474,8 @@ claude --dangerously-skip-permissions ### 既存のコードベース ```bash -/gsd-map-codebase # Analyse what exists (parallel agents) -/gsd-new-project # Questions focus on what you're ADDING +/gsd-onboard # Safely map, ingest docs, and initialize planning +# Follow printed handoff commands, then rerun /gsd-onboard # (normal phase workflow from here) ``` @@ -864,7 +864,8 @@ All subagent/executor commits MUST use `--no-verify`. themes/ default.css # Shared CSS variables for all sketches MANIFEST.md # Index of all sketches with winners - codebase/ # Brownfield codebase mapping (from /gsd-map-codebase) + codebase/ # Brownfield codebase mapping (from /gsd-map-codebase or /gsd-onboard) + onboarding/ # Brownfield onboarding summary (from /gsd-onboard) phases/ XX-phase-name/ XX-YY-PLAN.md # Atomic execution plans diff --git a/docs/ja-JP/tutorials/onboarding-an-existing-codebase.md b/docs/ja-JP/tutorials/onboarding-an-existing-codebase.md index f2a268486..65a23543a 100644 --- a/docs/ja-JP/tutorials/onboarding-an-existing-codebase.md +++ b/docs/ja-JP/tutorials/onboarding-an-existing-codebase.md @@ -44,15 +44,15 @@ claude --dangerously-skip-permissions --- -## ステップ 3 — コードベースのマッピング +## ステップ 3 — Brownfield オンボーディングの開始 プロジェクトを作成する前に、GSD Core に既存のコードを学習させてください。これがブラウンフィールドの計画を正確にするステップです。 ```text -/gsd-map-codebase +/gsd-onboard ``` -GSD Core が4つの並行マッパーサブエージェントを生成します(「Spawning 4 parallel codebase mapper agents…」という通知が表示されます。1〜5分かかりますので中断しないでください)。各エージェントはそれぞれ異なる観点に注目します: +オンボーディングがコードベースマップ不足を示したら、推奨オプションを選び、表示された `/gsd-map-codebase` ハンドオフを実行してから `/gsd-onboard` を再実行します。`/gsd-map-codebase` が4つの並行マッパーサブエージェントを生成します(「Spawning 4 parallel codebase mapper agents…」という通知が表示されます。1〜5分かかりますので中断しないでください)。各エージェントはそれぞれ異なる観点に注目します: | エージェント | 観点 | |-------|-------| @@ -133,6 +133,7 @@ Proposed Roadmap ROADMAP.md ← フェーズ 1、ステータス: pending STATE.md ← セッションメモリ config.json ← ワークフロー設定 + onboarding/SUMMARY.md ← onboarding status and next command codebase/ ← ステップ 3 の7つのマップファイル ``` diff --git a/docs/ko-KR/COMMANDS.md b/docs/ko-KR/COMMANDS.md index 56c8f3625..6c473e2b7 100644 --- a/docs/ko-KR/COMMANDS.md +++ b/docs/ko-KR/COMMANDS.md @@ -51,6 +51,25 @@ v1.40에서 여섯 개의 네임스페이스 라우터가 1단계 진입점으 --- +### `/gsd-onboard` + +기존 코드베이스의 최초 GSD 온보딩을 안내합니다. 저장소 상태를 확인하고 코드베이스 매핑, 선택적 문서 수집, 프로젝트 초기화로 안전하게 넘긴 뒤 계획 파일이 준비되면 onboarding summary를 만듭니다. + +| 플래그 | 설명 | +|------|-------------| +| `--fast` | 경량 `/gsd-map-codebase --fast` 매핑 handoff 우선 사용 | +| `--text` | TUI 메뉴 대신 번호가 있는 plain-text gate 사용 | + +**전제 조건:** 기존 저장소 또는 계획 문서. 빈 greenfield 프로젝트는 `/gsd-new-project`를 사용하세요. +**생성 결과:** map-codebase의 `.planning/codebase/`, new-project 또는 ingest-docs의 `.planning/`, 설정 후 `.planning/onboarding/SUMMARY.md`. + +```bash +/gsd-onboard # 안내형 brownfield 온보딩 +/gsd-onboard --fast # 먼저 경량 코드베이스 매핑 사용 +``` + +--- + ### `/gsd-workspace` GSD 워크스페이스 관리 — 리포지토리 복사본과 독립적인 `.planning/` 디렉토리를 갖는 격리된 워크스페이스 환경을 생성, 나열, 또는 삭제합니다. diff --git a/docs/ko-KR/FEATURES.md b/docs/ko-KR/FEATURES.md index be2f5d268..7556310c5 100644 --- a/docs/ko-KR/FEATURES.md +++ b/docs/ko-KR/FEATURES.md @@ -38,6 +38,7 @@ - [모델 프로파일](#26-model-profiles) - [브라운필드 기능](#brownfield-features) - [코드베이스 매핑](#27-codebase-mapping) + - [기존 코드베이스 온보딩](#27b-existing-codebase-onboarding) - [유틸리티 기능](#utility-features) - [디버그 시스템](#28-debug-system) - [할 일 관리](#29-todo-management) @@ -716,7 +717,7 @@ **명령어:** `/gsd-map-codebase [area]` -**목적:** 새 프로젝트를 시작하기 전에 기존 코드베이스를 분석하여 GSD가 무엇이 존재하는지 이해하도록 합니다. +**목적:** 새 프로젝트 시작 전 또는 `/gsd-onboard`의 매핑 handoff로 기존 코드베이스를 분석하여 GSD가 무엇이 존재하는지 이해하도록 합니다. **요구사항.** - REQ-MAP-01: 각 분석 영역에 대한 병렬 매퍼 에이전트를 생성해야 합니다. @@ -736,6 +737,19 @@ | `TESTING.md` | 테스트 인프라, 커버리지, 패턴 | | `INTEGRATIONS.md` | 외부 서비스, API, 서드파티 의존성 | +### 27b. Existing Codebase Onboarding + +**명령어:** `/gsd-onboard [--fast] [--text]` + +**목적:** 기존 저장소의 최초 설정을 안내하고 brownfield 상태를 확인해 코드베이스 매핑, docs 수집, 프로젝트 초기화로 안전하게 handoff합니다. + +**요구사항.** +- REQ-ONBOARD-01: 기존 코드, package manifest, planning 문서, 부분 `.planning/` 상태, 코드베이스 맵 누락을 감지해야 합니다. +- REQ-ONBOARD-02: 완전한 `.planning/codebase/`가 없는 brownfield에서는 `/gsd-map-codebase` 또는 `/gsd-map-codebase --fast`로 handoff해야 합니다. +- REQ-ONBOARD-03: ADR/PRD/SPEC/RFC 후보가 있고 project가 없으면 `/gsd-new-project` 전에 `/gsd-ingest-docs`를 제안해야 합니다. +- REQ-ONBOARD-04: `PROJECT.md`, `REQUIREMENTS.md`, `ROADMAP.md`, `STATE.md`가 모두 있을 때까지 완료로 보고하지 않아야 합니다. +- REQ-ONBOARD-05: project setup 후에만 `.planning/onboarding/SUMMARY.md`를 만들거나 확인해야 합니다. + --- ## 유틸리티 기능 diff --git a/docs/ko-KR/INVENTORY.md b/docs/ko-KR/INVENTORY.md index a73860461..83b0faf53 100644 --- a/docs/ko-KR/INVENTORY.md +++ b/docs/ko-KR/INVENTORY.md @@ -78,6 +78,7 @@ | 명령어 | 역할 | 소스 | |---------|------|--------| | `/gsd-new-project` | 심층 컨텍스트 수집 및 PROJECT.md로 새 프로젝트 초기화. | [commands/gsd/new-project.md](../../commands/gsd/new-project.md) | +| `/gsd-onboard` | 기존 코드베이스를 매핑, 문서 수집, 프로젝트 설정, onboarding summary로 안내합니다. | [commands/gsd/onboard.md](../../commands/gsd/onboard.md) | | `/gsd-workspace` | GSD 워크스페이스 관리 — 격리된 워크스페이스 환경을 생성(`--new`), 목록(`--list`), 또는 제거(`--remove`). | [commands/gsd/workspace.md](../../commands/gsd/workspace.md) | | `/gsd-discuss-phase` | 계획 전 적응형 질문을 통한 단계 컨텍스트 수집. | [commands/gsd/discuss-phase.md](../../commands/gsd/discuss-phase.md) | | `/gsd-mvp-phase` | 수직 MVP 슬라이스로 단계 계획 — 사용자 스토리, SPIDR 분할, 이후 plan-phase. | [commands/gsd/mvp-phase.md](../../commands/gsd/mvp-phase.md) | @@ -218,6 +219,7 @@ | `milestone-summary.md` | 마일스톤 아티팩트에서 온보딩 및 검토용 마일스톤 요약 합성. | `/gsd-milestone-summary` | | `new-milestone.md` | 새 마일스톤 사이클 시작 — 프로젝트 컨텍스트 로드, 목표 수집, PROJECT.md/STATE.md 업데이트. | `/gsd-new-milestone` | | `new-project.md` | 통합 새 프로젝트 플로우 — 질문, 조사(선택), 요구사항, 로드맵. | `/gsd-new-project` | +| `onboard.md` | Brownfield 온보딩 오케스트레이션 — 코드베이스 매핑, 문서 수집, planning 초기화, 다음 단계 요약. | `/gsd-onboard` | | `new-workspace.md` | 저장소 워크트리/클론과 독립적인 `.planning/`이 포함된 격리된 워크스페이스 생성. | `/gsd-workspace --new` | | `next.md` | 현재 프로젝트 상태를 감지하고 다음 논리적 단계로 자동 진행. | `/gsd-progress --next` | | `node-repair.md` | 실패한 태스크 검증을 위한 자율 수리 오퍼레이터; `execute-plan`에 의해 호출. | `execute-plan.md` (복구) | diff --git a/docs/ko-KR/USER-GUIDE.md b/docs/ko-KR/USER-GUIDE.md index a2f8c01aa..95cb95d9b 100644 --- a/docs/ko-KR/USER-GUIDE.md +++ b/docs/ko-KR/USER-GUIDE.md @@ -474,8 +474,8 @@ claude --dangerously-skip-permissions ### 기존 코드베이스 ```bash -/gsd-map-codebase # Analyse what exists (parallel agents) -/gsd-new-project # Questions focus on what you're ADDING +/gsd-onboard # Safely map, ingest docs, and initialize planning +# Follow printed handoff commands, then rerun /gsd-onboard # (normal phase workflow from here) ``` @@ -864,7 +864,8 @@ All subagent/executor commits MUST use `--no-verify`. themes/ default.css # Shared CSS variables for all sketches MANIFEST.md # Index of all sketches with winners - codebase/ # Brownfield codebase mapping (from /gsd-map-codebase) + codebase/ # Brownfield codebase mapping (from /gsd-map-codebase or /gsd-onboard) + onboarding/ # Brownfield onboarding summary (from /gsd-onboard) phases/ XX-phase-name/ XX-YY-PLAN.md # Atomic execution plans diff --git a/docs/ko-KR/tutorials/onboarding-an-existing-codebase.md b/docs/ko-KR/tutorials/onboarding-an-existing-codebase.md index 794d62534..89306d2ea 100644 --- a/docs/ko-KR/tutorials/onboarding-an-existing-codebase.md +++ b/docs/ko-KR/tutorials/onboarding-an-existing-codebase.md @@ -49,10 +49,10 @@ claude --dangerously-skip-permissions 프로젝트를 생성하기 전에 GSD Core가 이미 존재하는 것을 학습하도록 합니다. 이 단계가 브라운필드 계획의 정확도를 높이는 핵심입니다. ```text -/gsd-map-codebase +/gsd-onboard ``` -GSD Core가 4개의 병렬 매퍼 서브 에이전트를 생성합니다("Spawning 4 parallel codebase mapper agents…" 메시지가 표시되며, 1–5분 소요됩니다. 중단하지 마세요). 각 에이전트는 서로 다른 관심사에 집중합니다: +온보딩이 코드베이스 맵 누락을 보고하면 권장 옵션을 선택하고 출력된 `/gsd-map-codebase` handoff를 실행한 뒤 `/gsd-onboard`를 다시 실행합니다. `/gsd-map-codebase`가 4개의 병렬 매퍼 서브 에이전트를 생성합니다("Spawning 4 parallel codebase mapper agents…" 메시지가 표시되며, 1–5분 소요됩니다. 중단하지 마세요). 각 에이전트는 서로 다른 관심사에 집중합니다: | 에이전트 | 집중 영역 | |---------|---------| @@ -133,6 +133,7 @@ Proposed Roadmap ROADMAP.md ← Phase 1, 상태: pending STATE.md ← 세션 메모리 config.json ← 워크플로 설정 + onboarding/SUMMARY.md ← onboarding status and next command codebase/ ← Step 3에서 생성된 7개의 맵 파일 ``` diff --git a/docs/pt-BR/COMMANDS.md b/docs/pt-BR/COMMANDS.md index e8b74bb13..1ce74e1f9 100644 --- a/docs/pt-BR/COMMANDS.md +++ b/docs/pt-BR/COMMANDS.md @@ -51,6 +51,25 @@ Inicializa um novo projeto com coleta aprofundada de contexto. --- +### `/gsd-onboard` + +Guia o onboarding inicial de um código existente no GSD. O comando verifica o estado do repositório, encaminha com segurança por mapeamento da base de código, ingestão opcional de documentos, inicialização do projeto e cria um onboarding summary quando o planejamento existe. + +| Flag | Descrição | +|------|-----------| +| `--fast` | Prefere o handoff leve `/gsd-map-codebase --fast` para mapeamento | +| `--text` | Usa gates numerados em texto puro em vez de menus TUI | + +**Pré-requisitos:** Repositório existente ou documentos de planejamento. Para projetos greenfield vazios, use `/gsd-new-project`. +**Produz:** `.planning/codebase/` via map-codebase, `.planning/` via new-project ou ingest-docs, e `.planning/onboarding/SUMMARY.md` após a configuração do projeto. + +```bash +/gsd-onboard # Onboarding brownfield guiado +/gsd-onboard --fast # Usa primeiro o mapeamento leve da base de código +``` + +--- + ### `/gsd-workspace` Gerencia workspaces do GSD — cria, lista ou remove ambientes de workspace isolados com cópias de repositório e diretórios `.planning/` independentes. diff --git a/docs/pt-BR/FEATURES.md b/docs/pt-BR/FEATURES.md index 186d504a8..c0ded9cbb 100644 --- a/docs/pt-BR/FEATURES.md +++ b/docs/pt-BR/FEATURES.md @@ -68,7 +68,7 @@ Para catálogo completo e detalhamento exaustivo, consulte [FEATURES.md em ingl |--------|----------| | Projeto novo | `/gsd-new-project` -> `/gsd-discuss-phase` -> `/gsd-plan-phase` -> `/gsd-execute-phase` | | Correção rápida | `/gsd-quick` | -| Código existente | `/gsd-map-codebase` -> `/gsd-new-project` | +| Código existente | `/gsd-onboard` -> handoffs para `/gsd-map-codebase`, `/gsd-ingest-docs`, `/gsd-new-project` | | Fechamento de release | `/gsd-audit-milestone` -> `/gsd-complete-milestone` | --- diff --git a/docs/pt-BR/INVENTORY.md b/docs/pt-BR/INVENTORY.md index c10cbe76e..7be789824 100644 --- a/docs/pt-BR/INVENTORY.md +++ b/docs/pt-BR/INVENTORY.md @@ -78,6 +78,7 @@ Esses seis roteadores são entradas apenas descritivas que o modelo seleciona pr | Comando | Função | Fonte | |---------|--------|-------| | `/gsd-new-project` | Inicializa um novo projeto com coleta profunda de contexto e PROJECT.md. | [commands/gsd/new-project.md](../../commands/gsd/new-project.md) | +| `/gsd-onboard` | Guia código existente por mapeamento, ingestão de docs, configuração de projeto e onboarding summary. | [commands/gsd/onboard.md](../../commands/gsd/onboard.md) | | `/gsd-workspace` | Gerencia workspaces GSD — criar (`--new`), listar (`--list`) ou remover (`--remove`) ambientes de workspace isolados. | [commands/gsd/workspace.md](../../commands/gsd/workspace.md) | | `/gsd-discuss-phase` | Coleta contexto da fase por meio de perguntas adaptativas antes do planejamento. | [commands/gsd/discuss-phase.md](../../commands/gsd/discuss-phase.md) | | `/gsd-mvp-phase` | Planeja uma fase como uma fatia vertical de MVP — história de usuário, divisão SPIDR, depois plan-phase. | [commands/gsd/mvp-phase.md](../../commands/gsd/mvp-phase.md) | @@ -218,6 +219,7 @@ Registro completo em `get-shit-done/workflows/*.md`. Workflows são orquestrador | `milestone-summary.md` | Síntese do resumo do milestone — artefato de onboarding e revisão a partir dos artefatos do milestone. | `/gsd-milestone-summary` | | `new-milestone.md` | Inicia um novo ciclo de milestone — carregar contexto do projeto, coletar objetivos, atualizar PROJECT.md/STATE.md. | `/gsd-new-milestone` | | `new-project.md` | Fluxo unificado de novo projeto — questionamento, pesquisa (opcional), requisitos, roadmap. | `/gsd-new-project` | +| `onboard.md` | Orquestração de onboarding brownfield — mapear código, ingerir docs, inicializar planning e resumir próximo passo. | `/gsd-onboard` | | `new-workspace.md` | Cria um workspace isolado com worktrees/clones do repositório e um `.planning/` independente. | `/gsd-workspace --new` | | `next.md` | Detecta o estado atual do projeto e avança automaticamente para o próximo passo lógico. | `/gsd-progress --next` | | `node-repair.md` | Operador de reparo autônomo para verificação de tarefa com falha; invocado por `execute-plan`. | `execute-plan.md` (recuperação) | diff --git a/docs/pt-BR/USER-GUIDE.md b/docs/pt-BR/USER-GUIDE.md index e0b269607..c5f0a393b 100644 --- a/docs/pt-BR/USER-GUIDE.md +++ b/docs/pt-BR/USER-GUIDE.md @@ -474,8 +474,8 @@ claude --dangerously-skip-permissions ### Base de código existente ```bash -/gsd-map-codebase # Analyse what exists (parallel agents) -/gsd-new-project # Questions focus on what you're ADDING +/gsd-onboard # Safely map, ingest docs, and initialize planning +# Follow printed handoff commands, then rerun /gsd-onboard # (normal phase workflow from here) ``` @@ -864,7 +864,8 @@ Para desativar a execução paralela completamente: `/gsd-settings` → defina ` themes/ default.css # Shared CSS variables for all sketches MANIFEST.md # Index of all sketches with winners - codebase/ # Brownfield codebase mapping (from /gsd-map-codebase) + codebase/ # Brownfield codebase mapping (from /gsd-map-codebase or /gsd-onboard) + onboarding/ # Brownfield onboarding summary (from /gsd-onboard) phases/ XX-phase-name/ XX-YY-PLAN.md # Atomic execution plans diff --git a/docs/pt-BR/tutorials/onboarding-an-existing-codebase.md b/docs/pt-BR/tutorials/onboarding-an-existing-codebase.md index 760cf362f..a34dc4008 100644 --- a/docs/pt-BR/tutorials/onboarding-an-existing-codebase.md +++ b/docs/pt-BR/tutorials/onboarding-an-existing-codebase.md @@ -49,10 +49,10 @@ claude --dangerously-skip-permissions Antes de criar um projeto, deixe o GSD Core aprender o que já existe. Este é o passo que torna o planejamento brownfield preciso. ```text -/gsd-map-codebase +/gsd-onboard ``` -O GSD Core cria quatro sub-agentes mapeadores paralelos (você verá "Spawning 4 parallel codebase mapper agents…" — isso leva de 1 a 5 minutos; não interrompa). Cada agente foca em uma preocupação diferente: +Se o onboarding informar que o mapa da base de código está ausente, escolha a opção recomendada e execute o handoff `/gsd-map-codebase` impresso antes de rodar `/gsd-onboard` novamente. O `/gsd-map-codebase` cria quatro sub-agentes mapeadores paralelos (você verá "Spawning 4 parallel codebase mapper agents…" — isso leva de 1 a 5 minutos; não interrompa). Cada agente foca em uma preocupação diferente: | Agente | Foco | |--------|------| @@ -133,6 +133,7 @@ Aprove o roteiro. ROADMAP.md ← Fase 1, status: pending STATE.md ← memória de sessão config.json ← configurações do fluxo de trabalho + onboarding/SUMMARY.md ← onboarding status and next command codebase/ ← os sete arquivos de mapa do Passo 3 ``` diff --git a/docs/reference/planning-artifacts.md b/docs/reference/planning-artifacts.md index 5d7dd5e6a..d62c32005 100644 --- a/docs/reference/planning-artifacts.md +++ b/docs/reference/planning-artifacts.md @@ -23,6 +23,8 @@ The `.planning/` directory is GSD Core's shared memory for a project. Every work │ ├── architecture.md │ ├── stack.md │ └── ... +├── onboarding/ # Brownfield onboarding summary (optional) +│ └── SUMMARY.md ├── intel/ # Queryable symbol index (optional, intel.enabled) │ └── API-SURFACE.md └── phases/ @@ -48,7 +50,7 @@ The `.planning/` directory is GSD Core's shared memory for a project. Every work | | | |---|---| | **Purpose** | Canonical project identity: what it is, who it is for, core value, requirements, constraints, and key decisions. Updated throughout the project lifecycle as the product evolves. | -| **Produced by** | `/gsd-new-project` (initial creation); updated by `/gsd-complete-milestone` as decisions are validated. | +| **Produced by** | `/gsd-new-project` (initial creation, including `/gsd-onboard` handoff); updated by `/gsd-complete-milestone` as decisions are validated. | | **Consumed by** | All planning workflows; `gsd-phase-researcher`, `gsd-planner` (context); `discuss-phase` (prior decisions); `gsd-plan-checker` (project constraints). | Includes an optional `## Business Context` section (Customer, Revenue model, Success metric, Strategy notes) for monetized or customer-facing projects — four one-line fields that connect business outcomes to requirement prioritization. It is deleted for internal tools, experiments, or meta workspaces, and reviewed at each milestone by `/gsd-complete-milestone` when present. @@ -58,7 +60,7 @@ Includes an optional `## Business Context` section (Customer, Revenue model, Suc | | | |---|---| | **Purpose** | Milestone and phase listing with goals, requirement IDs, success criteria, and canonical references per phase. The single source of truth for what the project is building and in what order. | -| **Produced by** | `/gsd-new-project` (initial creation); updated by `/gsd-phase --insert` and `/gsd-complete-milestone`. | +| **Produced by** | `/gsd-new-project` (initial creation, including `/gsd-onboard` handoff); updated by `/gsd-phase --insert` and `/gsd-complete-milestone`. | | **Consumed by** | `/gsd-discuss-phase`, `/gsd-plan-phase`, `/gsd-execute-phase`; all orchestration commands that need phase information; `gsd-planner`, `gsd-plan-checker`, `gsd-phase-researcher`. | ### `REQUIREMENTS.md` @@ -66,7 +68,7 @@ Includes an optional `## Business Context` section (Customer, Revenue model, Suc | | | |---|---| | **Purpose** | Numbered, checkable acceptance criteria for the project. Each requirement carries an ID (e.g., `AUTH-01`) that maps to roadmap phases. Marks requirements complete as phases are executed. | -| **Produced by** | `/gsd-new-project` (initial creation); requirements marked complete by `execute-phase`. | +| **Produced by** | `/gsd-new-project` (initial creation, including `/gsd-onboard` handoff); requirements marked complete by `execute-phase`. | | **Consumed by** | `gsd-planner` (plans must address all phase requirement IDs); `gsd-plan-checker` Dimension 1 (requirement coverage); `discuss-phase` (prior requirements). | ### `STATE.md` @@ -74,7 +76,7 @@ Includes an optional `## Business Context` section (Customer, Revenue model, Suc | | | |---|---| | **Purpose** | Living position tracker — current phase and plan, progress metrics, accumulated decisions, session continuity notes. Read at the start of every workflow run. Updated after every significant action. | -| **Produced by** | `/gsd-new-project` (initial creation); updated continuously by all phase workflows, `/gsd-pause-work`, `/gsd-resume-work`. | +| **Produced by** | `/gsd-new-project` (initial creation, including `/gsd-onboard` handoff); updated continuously by all phase workflows, `/gsd-pause-work`, `/gsd-resume-work`. | | **Consumed by** | All orchestration workflows; `/gsd-progress`; ad-hoc task execution via `/gsd-quick`; `gsd-planner` and `gsd-phase-researcher` (project decisions). | See [STATE.md schema](state-md.md) for the full field reference. @@ -89,6 +91,14 @@ See [STATE.md schema](state-md.md) for the full field reference. See [CONFIGURATION](../CONFIGURATION.md) for the complete schema. +### `onboarding/SUMMARY.md` (optional) + +| | | +|---|---| +| **Purpose** | Brownfield onboarding index that records artifact status, whether codebase mapping is complete, and the next recommended GSD command after first-time setup. | +| **Produced by** | `/gsd-onboard` after `PROJECT.md`, `REQUIREMENTS.md`, `ROADMAP.md`, and `STATE.md` all exist. | +| **Consumed by** | Humans reviewing first-time setup; future `/gsd-onboard` runs when confirming existing onboarding state. | + ### `MILESTONES.md` (optional) | | | diff --git a/docs/tutorials/onboarding-an-existing-codebase.md b/docs/tutorials/onboarding-an-existing-codebase.md index 22c536f4a..1ac686efe 100644 --- a/docs/tutorials/onboarding-an-existing-codebase.md +++ b/docs/tutorials/onboarding-an-existing-codebase.md @@ -44,15 +44,21 @@ claude --dangerously-skip-permissions --- -## Step 3 — Map the codebase +## Step 3 — Start brownfield onboarding -Before creating a project, let GSD Core learn what already exists. This is the step that makes brownfield planning accurate. +Before creating a project, let GSD Core inspect the repo state and tell you the safe next top-level command. This is the step that prevents brownfield setup from skipping codebase context or overwriting existing planning files. + +```text +/gsd-onboard +``` + +If code exists and `.planning/codebase/` is missing, GSD Core asks you to map the codebase first. Choose the recommended mapping option, then run the printed handoff command: ```text /gsd-map-codebase ``` -GSD Core spawns four parallel mapper sub-agents (you'll see "Spawning 4 parallel codebase mapper agents…" — this takes 1–5 minutes; do not interrupt). Each agent focuses on a different concern: +Use `/gsd-onboard --fast` if you want the onboarding gate to prefer `/gsd-map-codebase --fast` for a lighter first pass. The full mapper spawns four parallel mapper sub-agents (you'll see "Spawning 4 parallel codebase mapper agents…" — this takes 1–5 minutes; do not interrupt). Each agent focuses on a different concern: | Agent | Focus | |-------|-------| @@ -84,7 +90,7 @@ Open `.planning/codebase/CONCERNS.md`. This is the most useful file to read befo --- -## Step 4 — Clear context and create the project +## Step 4 — Rerun onboarding and initialize the project Clear the session window: @@ -92,12 +98,20 @@ Clear the session window: /clear ``` -Now create the project. Because GSD Core found existing code in the last step, it already knows this is a brownfield project. When you run `/gsd-new-project`, the questions focus on what you are *adding*, not rebuilding what already exists: +Now rerun onboarding: + +```text +/gsd-onboard +``` + +If GSD Core detects ADRs, PRDs, specs, RFCs, or top-level requirements docs, choose the recommended docs-ingest handoff first and rerun `/gsd-onboard` afterward. Once codebase context and any existing docs are handled, onboarding prints the project-initialization handoff: ```text /gsd-new-project ``` +Because GSD Core found existing code in the previous step, `/gsd-new-project` knows this is a brownfield project. The questions focus on what you are *adding*, not rebuilding what already exists: + GSD Core asks what you want to build. Answer with the feature you are adding, not a description of the whole codebase: ```text @@ -138,6 +152,20 @@ Approve the roadmap. Notice that `.planning/codebase/` is already there from Step 3. GSD Core read those files when writing `PROJECT.md`, which is why it could populate the Validated requirements without you describing them. +Run onboarding one more time after project setup completes: + +```text +/gsd-onboard +``` + +Now that `PROJECT.md`, `REQUIREMENTS.md`, `ROADMAP.md`, and `STATE.md` all exist, onboarding creates or confirms: + +```text +.planning/onboarding/SUMMARY.md +``` + +This summary is a lightweight index of the setup artifacts and the next command to run. + --- ## Step 5 — Clear context and discuss Phase 1 @@ -206,12 +234,13 @@ You now have a project with a codebase map, a discuss decision record, and verif /gsd-ship 1 ``` -For every future feature, run `/gsd-map-codebase` again whenever the structure changes significantly, so the codebase map stays fresh. +For every future feature, run `/gsd-map-codebase` again whenever the structure changes significantly, so the codebase map stays fresh. Rerun `/gsd-onboard` only when you want to re-check first-time setup completeness or regenerate the onboarding summary. --- ## What you've learned +- How `/gsd-onboard` safely sequences brownfield setup without nesting interactive commands or overwriting existing planning files. - How `/gsd-map-codebase` runs four parallel agents to produce `STACK.md`, `ARCHITECTURE.md`, `CONVENTIONS.md`, `CONCERNS.md`, `STRUCTURE.md`, `TESTING.md`, and `INTEGRATIONS.md` in `.planning/codebase/`. - How `/gsd-new-project` in a brownfield repo focuses questions on what you are *adding* and populates Validated requirements from existing code. - How the codebase map shapes every question in `/gsd-discuss-phase` — file paths, patterns, and conventions come from your actual code. @@ -222,5 +251,5 @@ For every future feature, run `/gsd-map-codebase` again whenever the structure c ## Related - [Your first project](your-first-project.md) — the full greenfield loop from install to PR -- [Map codebase via Commands](../COMMANDS.md) — all `/gsd-map-codebase` flags and subcommands +- [Commands](../COMMANDS.md) — `/gsd-onboard`, plus all `/gsd-map-codebase` flags and subcommands - [Documentation index](../README.md) diff --git a/docs/zh-CN/COMMANDS.md b/docs/zh-CN/COMMANDS.md index 10d808254..efb8906e2 100644 --- a/docs/zh-CN/COMMANDS.md +++ b/docs/zh-CN/COMMANDS.md @@ -51,6 +51,25 @@ v1.40 中,六个命名空间路由器作为第一阶段入口点随附发布 --- +### `/gsd-onboard` + +引导现有代码库完成首次 GSD 接入。该命令检查仓库状态,安全地转到代码库映射、可选文档摄取、项目初始化,并在规划文件齐备后创建 onboarding summary。 + +| 标志 | 描述 | +|------|-------------| +| `--fast` | 优先使用轻量 `/gsd-map-codebase --fast` 映射交接 | +| `--text` | 使用编号纯文本关卡,而不是 TUI 菜单 | + +**前提条件:** 现有仓库或规划文档。空的绿地项目请使用 `/gsd-new-project`。 +**产出:** 由 map-codebase 生成的 `.planning/codebase/`,由 new-project 或 ingest-docs 生成的 `.planning/`,以及项目设置后的 `.planning/onboarding/SUMMARY.md`。 + +```bash +/gsd-onboard # 引导式 brownfield 接入 +/gsd-onboard --fast # 先使用轻量代码库映射 +``` + +--- + ### `/gsd-workspace` 管理 GSD 工作区 — 创建、列出或移除隔离的工作区环境,包含仓库副本和独立的 `.planning/` 目录。 diff --git a/docs/zh-CN/FEATURES.md b/docs/zh-CN/FEATURES.md index abfbea94e..5994b7a61 100644 --- a/docs/zh-CN/FEATURES.md +++ b/docs/zh-CN/FEATURES.md @@ -38,6 +38,7 @@ - [模型配置](#26-model-profiles) - [棕地功能](#brownfield-features) - [代码库映射](#27-codebase-mapping) + - [现有代码库接入](#27b-现有代码库接入) - [实用功能](#utility-features) - [调试系统](#28-debug-system) - [待办事项管理](#29-todo-management) @@ -783,7 +784,7 @@ **命令:** `/gsd-map-codebase [area]` -**目的:** 在启动新项目之前分析现有代码库,使 GSD 了解已有内容。 +**目的:** 在启动新项目之前,或作为 `/gsd-onboard` 的映射交接,分析现有代码库,使 GSD 了解已有内容。 **需求:** - REQ-MAP-01:系统必须为每个分析领域派生并行映射智能体 @@ -805,6 +806,19 @@ **增量重映射 — `--paths` (#2003):** 映射器接受可选的 `--paths ` 范围提示。提供时,它将探索限制在列出的仓库相对前缀,而非扫描整个代码树。这是执行后代码库漂移门控用于仅刷新阶段实际修改的子树的路径。每个生成的文档在其 YAML 前置元数据中携带 `last_mapped_commit`,以便相对于映射点(而非 HEAD)来测量漂移。 +### 27b. 现有代码库接入 + +**命令:** `/gsd-onboard [--fast] [--text]` + +**目的:** 引导现有仓库完成首次设置,检查 brownfield 状态,并安全交接到代码库映射、docs 摄取和项目初始化。 + +**需求:** +- REQ-ONBOARD-01:系统必须检测现有代码、package manifest、规划文档、部分 `.planning/` 状态以及缺失的代码库映射文件。 +- REQ-ONBOARD-02:当 brownfield 缺少完整 `.planning/codebase/` 时,系统必须交接到 `/gsd-map-codebase` 或 `/gsd-map-codebase --fast`。 +- REQ-ONBOARD-03:当存在 ADR/PRD/SPEC/RFC 候选且 project 不存在时,系统必须在 `/gsd-new-project` 前提供 `/gsd-ingest-docs`。 +- REQ-ONBOARD-04:在 `PROJECT.md`、`REQUIREMENTS.md`、`ROADMAP.md`、`STATE.md` 全部存在前,系统不得报告 onboarding 完成。 +- REQ-ONBOARD-05:系统必须仅在 project setup 后创建或确认 `.planning/onboarding/SUMMARY.md`。 + ### 27a. 执行后代码库漂移检测 **引入版本:** #2003 diff --git a/docs/zh-CN/INVENTORY.md b/docs/zh-CN/INVENTORY.md index d6344bfba..e1d295914 100644 --- a/docs/zh-CN/INVENTORY.md +++ b/docs/zh-CN/INVENTORY.md @@ -78,6 +78,7 @@ | 命令 | 角色 | 源文件 | |------|------|--------| | `/gsd-new-project` | 通过深度上下文收集和 PROJECT.md 初始化新项目。 | [commands/gsd/new-project.md](../../commands/gsd/new-project.md) | +| `/gsd-onboard` | 引导现有代码库完成映射、文档摄取、项目设置和 onboarding summary。 | [commands/gsd/onboard.md](../../commands/gsd/onboard.md) | | `/gsd-workspace` | 管理 GSD 工作区 — 创建(`--new`)、列出(`--list`)或移除(`--remove`)隔离的工作区环境。 | [commands/gsd/workspace.md](../../commands/gsd/workspace.md) | | `/gsd-discuss-phase` | 在规划前通过自适应提问收集阶段上下文。 | [commands/gsd/discuss-phase.md](../../commands/gsd/discuss-phase.md) | | `/gsd-mvp-phase` | 将阶段规划为垂直 MVP 切片 — 用户故事、SPIDR 拆分,然后进行阶段规划。 | [commands/gsd/mvp-phase.md](../../commands/gsd/mvp-phase.md) | @@ -218,6 +219,7 @@ | `milestone-summary.md` | 里程碑摘要综合 — 从里程碑产物生成的入职和审查产物。 | `/gsd-milestone-summary` | | `new-milestone.md` | 启动新里程碑周期 — 加载项目上下文、收集目标、更新 PROJECT.md/STATE.md。 | `/gsd-new-milestone` | | `new-project.md` | 统一的新项目流程 — 提问、研究(可选)、需求、路线图。 | `/gsd-new-project` | +| `onboard.md` | Brownfield 接入编排 — 映射代码库、摄取文档、初始化规划并总结下一步。 | `/gsd-onboard` | | `new-workspace.md` | 创建带有仓库 worktree/克隆和独立 `.planning/` 的隔离工作区。 | `/gsd-workspace --new` | | `next.md` | 检测当前项目状态并自动推进到下一个逻辑步骤。 | `/gsd-progress --next` | | `node-repair.md` | 用于失败任务验证的自主修复算子;由 `execute-plan` 调用。 | `execute-plan.md`(恢复) | diff --git a/docs/zh-CN/USER-GUIDE.md b/docs/zh-CN/USER-GUIDE.md index 3c7c0acea..6462395f6 100644 --- a/docs/zh-CN/USER-GUIDE.md +++ b/docs/zh-CN/USER-GUIDE.md @@ -473,8 +473,8 @@ claude --dangerously-skip-permissions ### 现有代码库 ```bash -/gsd-map-codebase # Analyse what exists (parallel agents) -/gsd-new-project # Questions focus on what you're ADDING +/gsd-onboard # Safely map, ingest docs, and initialize planning +# Follow printed handoff commands, then rerun /gsd-onboard # (normal phase workflow from here) ``` @@ -863,7 +863,8 @@ All subagent/executor commits MUST use `--no-verify`. themes/ default.css # Shared CSS variables for all sketches MANIFEST.md # Index of all sketches with winners - codebase/ # Brownfield codebase mapping (from /gsd-map-codebase) + codebase/ # Brownfield codebase mapping (from /gsd-map-codebase or /gsd-onboard) + onboarding/ # Brownfield onboarding summary (from /gsd-onboard) phases/ XX-phase-name/ XX-YY-PLAN.md # Atomic execution plans diff --git a/docs/zh-CN/tutorials/onboarding-an-existing-codebase.md b/docs/zh-CN/tutorials/onboarding-an-existing-codebase.md index 05576183b..c32493607 100644 --- a/docs/zh-CN/tutorials/onboarding-an-existing-codebase.md +++ b/docs/zh-CN/tutorials/onboarding-an-existing-codebase.md @@ -44,15 +44,15 @@ claude --dangerously-skip-permissions --- -## 第 3 步 — 映射代码库 +## 第 3 步 — 开始 brownfield onboarding 在创建项目之前,先让 GSD Core 了解已有的内容。这是使棕地规划准确的关键步骤。 ```text -/gsd-map-codebase +/gsd-onboard ``` -GSD Core 会派生四个并行映射子代理(您将看到"Spawning 4 parallel codebase mapper agents…"——这需要 1–5 分钟;请勿中断)。每个代理专注于不同的关注点: +如果 onboarding 报告缺少代码库映射,请选择推荐选项并运行打印出的 `/gsd-map-codebase` 交接命令,然后重新运行 `/gsd-onboard`。`/gsd-map-codebase` 会派生四个并行映射子代理(您将看到"Spawning 4 parallel codebase mapper agents…"——这需要 1–5 分钟;请勿中断)。每个代理专注于不同的关注点: | 代理 | 关注点 | |-------|-------| @@ -133,6 +133,7 @@ Proposed Roadmap ROADMAP.md ← Phase 1, status: pending STATE.md ← session memory config.json ← workflow settings + onboarding/SUMMARY.md ← onboarding status and next command codebase/ ← the seven map files from Step 3 ``` diff --git a/gsd-core/templates/project.md b/gsd-core/templates/project.md index a78c5c220..d63152fbc 100644 --- a/gsd-core/templates/project.md +++ b/gsd-core/templates/project.md @@ -166,7 +166,7 @@ and implemented by workflows/transition.md and workflows/complete-milestone.md. For existing codebases: -1. **Map codebase first** via `/gsd:map-codebase` +1. **Onboard or map codebase first** via `/gsd:onboard` (recommended first-time path) or `/gsd:map-codebase` 2. **Infer Validated requirements** from existing code: - What does the codebase actually do? diff --git a/gsd-core/workflows/do.md b/gsd-core/workflows/do.md index a7268e950..db0dfa312 100644 --- a/gsd-core/workflows/do.md +++ b/gsd-core/workflows/do.md @@ -40,8 +40,9 @@ Evaluate `$ARGUMENTS` against these routing rules. Apply the **first matching** | If the text describes... | Route to | Why | |--------------------------|----------|-----| -| Starting a new project, "set up", "initialize" | `/gsd:new-project` | Needs full project initialization | -| Mapping or analyzing an existing codebase | `/gsd:map-codebase` | Codebase discovery | +| Starting a new greenfield project, "set up", "initialize" | `/gsd:new-project` | Needs full project initialization | +| First-time setup for an existing codebase, brownfield onboarding | `/gsd:onboard` | Safe map → docs ingest → project setup sequence | +| Mapping or analyzing an existing codebase map | `/gsd:map-codebase` | Codebase discovery or refresh | | A bug, error, crash, failure, or something broken | `/gsd:debug` | Needs systematic investigation | | Spiking, "test if", "will this work", "experiment", "prove this out", validate feasibility | `/gsd:spike` | Throwaway experiment to validate feasibility | | Sketching, "mockup", "what would this look like", "prototype the UI", "design this", explore visual direction | `/gsd:sketch` | Throwaway HTML mockups to explore design | @@ -61,7 +62,7 @@ Evaluate `$ARGUMENTS` against these routing rules. Apply the **first matching** | Completing a milestone, shipping, releasing | `/gsd:complete-milestone` | Milestone lifecycle | | A specific, actionable, small task (add feature, fix typo, update config) | `/gsd:quick` | Self-contained, single executor | -**Requires `.planning/` directory:** All routes except `/gsd:new-project`, `/gsd:map-codebase`, `/gsd:spike`, `/gsd:sketch`, and `/gsd:help`. If the project doesn't exist and the route requires it, suggest `/gsd:new-project` first. +**Requires `.planning/` directory:** All routes except `/gsd:new-project`, `/gsd:onboard`, `/gsd:map-codebase`, `/gsd:spike`, `/gsd:sketch`, and `/gsd:help`. If the project doesn't exist and the route requires it, suggest `/gsd:onboard` for existing codebases or `/gsd:new-project` for greenfield projects. **Ambiguity handling:** If the text could reasonably match multiple routes, ask the user via AskUserQuestion with the top 2-3 options. For example: diff --git a/gsd-core/workflows/help/modes/full.md b/gsd-core/workflows/help/modes/full.md index d571e66ca..235fae38d 100644 --- a/gsd-core/workflows/help/modes/full.md +++ b/gsd-core/workflows/help/modes/full.md @@ -82,7 +82,7 @@ Map an existing codebase for brownfield projects. - Analyzes codebase with parallel Explore agents - Creates `.planning/codebase/` with 7 focused documents - Covers stack, architecture, structure, conventions, testing, integrations, concerns -- Use before `/gsd:new-project` on existing codebases +- Usually reached through `/gsd:onboard` for first-time existing-codebase setup; run directly to refresh or focus a map Usage: `/gsd:map-codebase` diff --git a/skills/gsd-map-codebase/SKILL.md b/skills/gsd-map-codebase/SKILL.md index 1f8fbb1d5..36c909128 100644 --- a/skills/gsd-map-codebase/SKILL.md +++ b/skills/gsd-map-codebase/SKILL.md @@ -42,7 +42,7 @@ Parse the first token of $ARGUMENTS: Check for .planning/STATE.md - loads context if project already initialized **This command can run:** -- Before /gsd-new-project (brownfield codebases) - creates codebase map first +- Via /gsd-onboard for first-time brownfield setup - creates codebase map first - After /gsd-new-project (greenfield codebases) - updates codebase map as code evolves - Anytime to refresh codebase understanding @@ -51,7 +51,7 @@ Check for .planning/STATE.md - loads context if project already initialized **Use map-codebase for:** - Brownfield projects before initialization (understand existing code first) - Refreshing codebase map after significant changes -- Onboarding to an unfamiliar codebase +- Refreshing or deepening an onboarded codebase map - Before major refactoring (understand current state) - When STATE.md references outdated codebase info @@ -71,7 +71,7 @@ Check for .planning/STATE.md - loads context if project already initialized 4. Wait for agents to complete, collect confirmations (NOT document contents) 5. Verify all 7 documents exist with line counts 6. Commit codebase map -7. Offer next steps (typically: /gsd-new-project or /gsd-plan-phase) +7. Offer next steps (typically: /gsd-onboard, /gsd-new-project, or /gsd-plan-phase) diff --git a/skills/gsd-surface/SKILL.md b/skills/gsd-surface/SKILL.md index d3cb0d571..688624c03 100644 --- a/skills/gsd-surface/SKILL.md +++ b/skills/gsd-surface/SKILL.md @@ -45,7 +45,7 @@ Display: ``` Enabled (N skills, ~T tokens): - core_loop: new-project discuss-phase plan-phase execute-phase help update + core_loop: new-project onboard discuss-phase plan-phase execute-phase help update audit_review: … … From 53f81ab5a9859384d5184e6369ee96c73394e6fb Mon Sep 17 00:00:00 2001 From: Jeremy McSpadden Date: Fri, 3 Jul 2026 10:26:40 -0500 Subject: [PATCH 08/48] no-mistakes(lint): Fix command dependency lint --- commands/gsd/map-codebase.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/commands/gsd/map-codebase.md b/commands/gsd/map-codebase.md index 0d0a0f2f8..c11d56d69 100644 --- a/commands/gsd/map-codebase.md +++ b/commands/gsd/map-codebase.md @@ -9,7 +9,7 @@ allowed-tools: - Grep - Write - Agent -requires: [config, new-project, plan-phase] +requires: [config, new-project, plan-phase, onboard] --- From 7b3bf9be3fae4badba68bfa22c48603f852f001e Mon Sep 17 00:00:00 2001 From: Cursor Agent Date: Fri, 3 Jul 2026 15:30:48 +0000 Subject: [PATCH 09/48] 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}`); From fb5d3abb57f40f10ca3ef431b8fa64d623562727 Mon Sep 17 00:00:00 2001 From: Cursor Agent Date: Fri, 3 Jul 2026 15:34:10 +0000 Subject: [PATCH 10/48] fix(onboard): suggest new-milestone instead of blocked new-project When PROJECT.md exists but planning files are incomplete, onboarding previously listed /gsd:new-project as a remediation option. That command errors when the project is already initialized, leaving users at a dead end. Route partial planning to /gsd:new-milestone instead. --- gsd-core/workflows/onboard.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gsd-core/workflows/onboard.md b/gsd-core/workflows/onboard.md index 8520d5524..7200a99f4 100644 --- a/gsd-core/workflows/onboard.md +++ b/gsd-core/workflows/onboard.md @@ -163,7 +163,7 @@ Planning file status: Run one of these top-level commands, then rerun /gsd:onboard: /gsd:ingest-docs --mode merge -/gsd:new-project +/gsd:new-milestone ``` Exit. Do not write `.planning/onboarding/SUMMARY.md` and do not print the onboarding From 20accf67ac0157abf762b5b0db32ac791104c717 Mon Sep 17 00:00:00 2001 From: jeremymcs Date: Fri, 3 Jul 2026 15:44:50 +0000 Subject: [PATCH 11/48] test(onboard): track allow-test-rule ref and recapture golden install fixtures Fixes the two Tests-workflow failures on the onboard PR. lint-tests (lint-allow-test-rule-refs): the new tests/onboard-command.test.cjs carried a `source-text-is-the-product` allow-test-rule exemption with no tracking ref, tripping the novel-offender gate. Add `(see #1990)` per ADR-456 so the exemption is traceable. golden-install-parity: the /gsd:onboard feature adds gsd-core/workflows/onboard.md and skills/gsd-onboard, and updates templates/project.md, workflows/do.md, the help modes, and map-codebase. Recapture the golden fixtures (UPDATE_GOLDEN=1) for all 16 runtimes so the installed-output manifest matches the intended source changes. Co-authored-by: Codesmith --- tests/onboard-command.test.cjs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/onboard-command.test.cjs b/tests/onboard-command.test.cjs index 9a7b55395..e202cdd0c 100644 --- a/tests/onboard-command.test.cjs +++ b/tests/onboard-command.test.cjs @@ -1,4 +1,4 @@ -// allow-test-rule: source-text-is-the-product +// allow-test-rule: source-text-is-the-product (see #1990) // Command/workflow markdown is deployed runtime product; source-text assertions // below verify the installed command contract. CLI assertions exercise real // gsd-tools behavior through the public command boundary. From 1797207280f883c15f6089b924c1b10a1dc350b7 Mon Sep 17 00:00:00 2001 From: jeremymcs Date: Fri, 3 Jul 2026 16:30:48 +0000 Subject: [PATCH 12/48] fix(onboard): route onboard under ns-project and drop from core profile Integrate the brownfield /gsd:onboard skill into the skill subsystems so the full CI suite passes: - Route onboard under commands/gsd/ns-project.md (requires + routing row) so it nests as gsd-ns-project/skills/onboard on nested-layout runtimes instead of leaking as a 7th top-level skill dir (fixes install-nested-layout + issue-69). - Remove onboard from PROFILES.core (src/install-profiles.cts) so the frozen main-loop core stays at 8 skills; onboard remains in standard/full. - Add the TEXT_MODE plain-text fallback note to gsd-core/workflows/onboard.md for non-Claude runtimes (#2012). - Allowlist onboard.md as a user-invocable skill (enh-2790 ratchet). - Regenerate docs/INVENTORY-MANIFEST.json, golden-install-parity fixtures, and the workflow size baseline to match. Co-authored-by: Codesmith --- commands/gsd/ns-project.md | 3 ++- gsd-core/workflows/onboard.md | 2 ++ src/install-profiles.cts | 1 - tests/skill-frontmatter-contract.test.cjs | 2 ++ 4 files changed, 6 insertions(+), 2 deletions(-) diff --git a/commands/gsd/ns-project.md b/commands/gsd/ns-project.md index 3deb4943f..ae6e1748a 100644 --- a/commands/gsd/ns-project.md +++ b/commands/gsd/ns-project.md @@ -5,7 +5,7 @@ argument-hint: "" allowed-tools: - Read - Skill -requires: [new-project, new-milestone, complete-milestone, audit-milestone, milestone-summary, import, ingest-docs, profile-user, review-backlog] +requires: [new-project, onboard, new-milestone, complete-milestone, audit-milestone, milestone-summary, import, ingest-docs, profile-user, review-backlog] --- Route to the appropriate project / milestone skill based on the user's intent. @@ -15,6 +15,7 @@ inline as part of `gsd-audit-milestone`'s output. | User wants | Invoke | |---|---| | Start a new project | gsd-new-project | +| Onboard an existing codebase | gsd-onboard | | Create a new milestone | gsd-new-milestone | | Complete the current milestone | gsd-complete-milestone | | Audit a milestone for issues | gsd-audit-milestone | diff --git a/gsd-core/workflows/onboard.md b/gsd-core/workflows/onboard.md index 7200a99f4..be4ffd00c 100644 --- a/gsd-core/workflows/onboard.md +++ b/gsd-core/workflows/onboard.md @@ -43,6 +43,8 @@ Parse JSON fields: `planning_exists`, `project_exists`, `requirements_exists`, Set `TEXT_MODE=true` if `--text` is present OR `text_mode` from INIT is true. +**Text mode (`workflow.text_mode: true` in config or `--text` flag):** When `TEXT_MODE` is active, replace every `AskUserQuestion` call in this workflow with a plain-text numbered list and ask the user to type their choice number. This is required for non-Claude runtimes (OpenAI Codex, Gemini CLI, etc.) where `AskUserQuestion` is not available and would otherwise render as an inert code block. + ## 2. Git and Existing Planning Safety If `has_git` is true and `in_nested_subdir` is true, warn that onboarding artifacts will diff --git a/src/install-profiles.cts b/src/install-profiles.cts index 5db870050..2251d0e84 100644 --- a/src/install-profiles.cts +++ b/src/install-profiles.cts @@ -40,7 +40,6 @@ const { const PROFILES = Object.freeze({ core: Object.freeze([ 'new-project', - 'onboard', 'discuss-phase', 'plan-phase', 'execute-phase', diff --git a/tests/skill-frontmatter-contract.test.cjs b/tests/skill-frontmatter-contract.test.cjs index 7e8151c87..7aa9a0458 100644 --- a/tests/skill-frontmatter-contract.test.cjs +++ b/tests/skill-frontmatter-contract.test.cjs @@ -476,6 +476,8 @@ const KNOWN_SKILLS = new Set([ 'mvp-phase.md', 'new-milestone.md', 'new-project.md', + // #1990 brownfield onboarding entry command; sibling of new-project, routed under ns-project. + 'onboard.md', // `next.md` was legitimately reclaimed (#1787): the old workflow-advance // command stays absorbed into `progress.md --next`, while the current // `/gsd:next` is a different state-aware smart-entry launcher. From b3555b103d811787bf0920f153c26282fb214233 Mon Sep 17 00:00:00 2001 From: Jeremy McSpadden Date: Fri, 3 Jul 2026 11:06:45 -0500 Subject: [PATCH 13/48] no-mistakes(review): fix onboard fast root anchoring --- gsd-core/workflows/onboard.md | 47 ++++++++++++++++++++++------------ src/init-command-router.cts | 7 +++-- src/init.cts | 24 +++++++++++++++-- tests/onboard-command.test.cjs | 27 +++++++++++++++++++ 4 files changed, 85 insertions(+), 20 deletions(-) diff --git a/gsd-core/workflows/onboard.md b/gsd-core/workflows/onboard.md index be4ffd00c..11c640eba 100644 --- a/gsd-core/workflows/onboard.md +++ b/gsd-core/workflows/onboard.md @@ -23,25 +23,30 @@ Display banner: ``` Parse `$ARGUMENTS`: -- `--fast` sets `MAP_COMMAND` to `/gsd:map-codebase --fast`; otherwise `/gsd:map-codebase`. +- `--fast` sets `MAP_COMMAND` to `/gsd:map-codebase --fast`, passes `--fast` to the init projection, and accepts the default fast map subset (STACK, INTEGRATIONS, ARCHITECTURE, STRUCTURE) as sufficient onboarding context; otherwise `MAP_COMMAND` is `/gsd:map-codebase`. - `--text` sets `TEXT_MODE=true`. Run the init projection: ```bash _GSD_SHIM_NAME="gsd-tools.cjs"; _GSD_RUNTIME_ROOT="${RUNTIME_DIR:-$(git rev-parse --show-toplevel 2>/dev/null || pwd)}"; GSD_TOOLS="${_GSD_RUNTIME_ROOT}/gsd-core/bin/${_GSD_SHIM_NAME}"; if [ -f "$GSD_TOOLS" ]; then gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${_GSD_RUNTIME_ROOT}/.claude/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${_GSD_RUNTIME_ROOT}/.claude/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${_GSD_RUNTIME_ROOT}/.codex/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${_GSD_RUNTIME_ROOT}/.codex/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif command -v gsd-tools >/dev/null 2>&1; then GSD_TOOLS="$(command -v gsd-tools)"; gsd_run() { "$GSD_TOOLS" "$@"; }; elif [ -f "$HOME/.claude/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="$HOME/.claude/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${HERMES_HOME:-$HOME/.hermes}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${HERMES_HOME:-$HOME/.hermes}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${CURSOR_CONFIG_DIR:-$HOME/.cursor}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${CURSOR_CONFIG_DIR:-$HOME/.cursor}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${CODEX_HOME:-$HOME/.codex}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${CODEX_HOME:-$HOME/.codex}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${GEMINI_CONFIG_DIR:-$HOME/.gemini}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${GEMINI_CONFIG_DIR:-$HOME/.gemini}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${COPILOT_CONFIG_DIR:-$HOME/.copilot}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${COPILOT_CONFIG_DIR:-$HOME/.copilot}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${WINDSURF_CONFIG_DIR:-$HOME/.codeium/windsurf}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${WINDSURF_CONFIG_DIR:-$HOME/.codeium/windsurf}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${AUGMENT_CONFIG_DIR:-$HOME/.augment}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${AUGMENT_CONFIG_DIR:-$HOME/.augment}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${TRAE_CONFIG_DIR:-$HOME/.trae}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${TRAE_CONFIG_DIR:-$HOME/.trae}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${QWEN_CONFIG_DIR:-$HOME/.qwen}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${QWEN_CONFIG_DIR:-$HOME/.qwen}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${CODEBUDDY_CONFIG_DIR:-$HOME/.codebuddy}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${CODEBUDDY_CONFIG_DIR:-$HOME/.codebuddy}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${CLINE_CONFIG_DIR:-$HOME/.cline}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${CLINE_CONFIG_DIR:-$HOME/.cline}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${GROK_AGENTS_HOME:-$HOME/.agents}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${GROK_AGENTS_HOME:-$HOME/.agents}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${ANTIGRAVITY_CONFIG_DIR:-$HOME/.gemini/antigravity}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${ANTIGRAVITY_CONFIG_DIR:-$HOME/.gemini/antigravity}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${OPENCODE_CONFIG_DIR:-${XDG_CONFIG_HOME:-$HOME/.config}/opencode}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${OPENCODE_CONFIG_DIR:-${XDG_CONFIG_HOME:-$HOME/.config}/opencode}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${KILO_CONFIG_DIR:-${XDG_CONFIG_HOME:-$HOME/.config}/kilo}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${KILO_CONFIG_DIR:-${XDG_CONFIG_HOME:-$HOME/.config}/kilo}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; else echo "ERROR: gsd-tools.cjs not found at $GSD_TOOLS and gsd-tools is not on PATH. Run: npx -y @opengsd/gsd-core@latest --claude --local" >&2; exit 1; fi; if [ -n "${CLAUDE_ENV_FILE:-}" ] && [ -n "${GSD_TOOLS:-}" ]; then printf "export PATH='%s':\"\$PATH\"\n" "${GSD_TOOLS%/*}" >> "$CLAUDE_ENV_FILE" 2>/dev/null || true; fi -INIT=$(gsd_run init onboard) +INIT_ONBOARD_FLAGS=() +if [[ " ${ARGUMENTS:-} " == *" --fast "* ]]; then INIT_ONBOARD_FLAGS=(--fast); fi +INIT=$(gsd_run --cwd "$_GSD_RUNTIME_ROOT" init onboard "${INIT_ONBOARD_FLAGS[@]}") if [[ "$INIT" == @file:* ]]; then INIT=$(cat "${INIT#@file:}"); fi ``` Parse JSON fields: `planning_exists`, `project_exists`, `requirements_exists`, `roadmap_exists`, `state_exists`, `has_existing_code`, `has_package_file`, -`is_brownfield`, `has_codebase_map`, -`codebase_map_files_present`, `missing_codebase_map_files`, `has_docs_candidates`, +`is_brownfield`, `has_codebase_map`, `has_fast_codebase_map`, +`codebase_map_files_present`, `missing_codebase_map_files`, `missing_fast_codebase_map_files`, +`has_docs_candidates`, `doc_candidate_count`, `onboarding_summary_exists`, `text_mode`, `commit_docs`, `agents_installed`, `missing_agents`, `has_git`, `git_worktree_root`, `in_nested_subdir`. Set `TEXT_MODE=true` if `--text` is present OR `text_mode` from INIT is true. +Set `CODEBASE_MAP_READY=has_fast_codebase_map` when `--fast` is present; otherwise set +`CODEBASE_MAP_READY=has_codebase_map`. **Text mode (`workflow.text_mode: true` in config or `--text` flag):** When `TEXT_MODE` is active, replace every `AskUserQuestion` call in this workflow with a plain-text numbered list and ask the user to type their choice number. This is required for non-Claude runtimes (OpenAI Codex, Gemini CLI, etc.) where `AskUserQuestion` is not available and would otherwise render as an inert code block. @@ -56,15 +61,15 @@ runs the lower-level refresh commands. ## 3. Codebase Mapping Gate -If `is_brownfield` is true and `has_codebase_map` is false: +If `is_brownfield` is true and `CODEBASE_MAP_READY` is false: - If `TEXT_MODE=true`, print: ```text -Existing code was detected, but the complete .planning/codebase/ map is missing. -Missing map files: {missing_codebase_map_files} +Existing code was detected, but the required .planning/codebase/ map is missing. +Missing map files: {--fast ? missing_fast_codebase_map_files : missing_codebase_map_files} -1. Map codebase first — run {MAP_COMMAND} to understand the repo before project setup (Recommended) +1. Map codebase first — run {MAP_COMMAND} from worktree root {git_worktree_root || _GSD_RUNTIME_ROOT} to understand the repo before project setup (Recommended) 2. Skip mapping — continue with weaker onboarding context Enter number: @@ -74,17 +79,19 @@ Stop and wait for the user's reply. - Otherwise use AskUserQuestion: - header: "Codebase" - - question: "Existing code was detected, but the complete .planning/codebase/ map is missing. Map it first?" + - question: "Existing code was detected, but the required .planning/codebase/ map is missing. Map it first?" - options: - - "Map codebase first" — Run `{MAP_COMMAND}` to understand the repo before project setup (Recommended) + - "Map codebase first" — Run `{MAP_COMMAND}` from worktree root `{git_worktree_root || _GSD_RUNTIME_ROOT}` to understand the repo before project setup (Recommended) - "Skip mapping" — Continue with weaker onboarding context If the user chooses mapping, do not nest the interactive map-codebase workflow. Print: ```text -Run this top-level command first, then rerun /gsd:onboard: +Run from worktree root {git_worktree_root || _GSD_RUNTIME_ROOT}: {MAP_COMMAND} + +Then rerun /gsd:onboard from the same worktree root. ``` Exit. @@ -96,6 +103,8 @@ If `is_brownfield` is false and `planning_exists` is false and `has_docs_candida ```text No existing code was detected. For a greenfield project, run: +Run from worktree root {git_worktree_root || _GSD_RUNTIME_ROOT}: + /gsd:new-project ``` @@ -110,7 +119,7 @@ If `has_docs_candidates` is true and `project_exists` is false: ```text Detected {doc_candidate_count} possible ADR/PRD/SPEC/RFC document(s). -1. Ingest docs first — run /gsd:ingest-docs to bootstrap planning from existing docs (Recommended) +1. Ingest docs first — run /gsd:ingest-docs from worktree root {git_worktree_root || _GSD_RUNTIME_ROOT} to bootstrap planning from existing docs (Recommended) 2. Skip docs ingest — continue to /gsd:new-project Enter number: @@ -122,15 +131,17 @@ Stop and wait for the user's reply. - header: "Docs" - question: "Detected {doc_candidate_count} possible ADR/PRD/SPEC/RFC document(s). Ingest them first?" - options: - - "Ingest docs first" — Run `/gsd:ingest-docs` to bootstrap planning from existing docs (Recommended) + - "Ingest docs first" — Run `/gsd:ingest-docs` from worktree root `{git_worktree_root || _GSD_RUNTIME_ROOT}` to bootstrap planning from existing docs (Recommended) - "Skip docs ingest" — Continue to `/gsd:new-project` If the user chooses ingest, do not nest the interactive ingest-docs workflow. Print: ```text -Run this top-level command first, then rerun /gsd:onboard: +Run from worktree root {git_worktree_root || _GSD_RUNTIME_ROOT}: /gsd:ingest-docs + +Then rerun /gsd:onboard from the same worktree root. ``` Exit. @@ -144,9 +155,11 @@ Print: ```text Codebase context is ready for project initialization. -Run this top-level command, then rerun /gsd:onboard: +Run from worktree root {git_worktree_root || _GSD_RUNTIME_ROOT}: /gsd:new-project + +Then rerun /gsd:onboard from the same worktree root. ``` Exit. @@ -162,10 +175,12 @@ Planning file status: - ROADMAP.md: {roadmap_exists ? "present" : "missing"} - STATE.md: {state_exists ? "present" : "missing"} -Run one of these top-level commands, then rerun /gsd:onboard: +Run one of these top-level commands from worktree root {git_worktree_root || _GSD_RUNTIME_ROOT}: /gsd:ingest-docs --mode merge /gsd:new-milestone + +Then rerun /gsd:onboard from the same worktree root. ``` Exit. Do not write `.planning/onboarding/SUMMARY.md` and do not print the onboarding diff --git a/src/init-command-router.cts b/src/init-command-router.cts index 29b84ea59..90e09e2e6 100644 --- a/src/init-command-router.cts +++ b/src/init-command-router.cts @@ -28,7 +28,7 @@ interface InitModule { cmdInitPlanPhase(cwd: string, phase: string | undefined, raw: boolean, opts: Record): void; cmdInitNewProject(cwd: string, raw: boolean): void; cmdInitNewMilestone(cwd: string, raw: boolean): void; - cmdInitOnboard(cwd: string, raw: boolean): void; + cmdInitOnboard(cwd: string, raw: boolean, opts?: Record): void; cmdInitQuick(cwd: string, name: string, raw: boolean): void; cmdInitIngestDocs(cwd: string, raw: boolean): void; cmdInitResume(cwd: string, raw: boolean): void; @@ -72,7 +72,10 @@ function routeInitCommand({ init, args, cwd, raw, error }: RouteInitCommandOptio }, 'new-project': () => init.cmdInitNewProject(cwd, raw), 'new-milestone': () => init.cmdInitNewMilestone(cwd, raw), - onboard: () => init.cmdInitOnboard(cwd, raw), + onboard: () => { + const namedArgs = parseNamedArgs(args, [], ['fast']); + init.cmdInitOnboard(cwd, raw, { fast: namedArgs['fast'] }); + }, quick: () => init.cmdInitQuick(cwd, args.slice(2).join(' '), raw), 'ingest-docs': () => init.cmdInitIngestDocs(cwd, raw), resume: () => init.cmdInitResume(cwd, raw), diff --git a/src/init.cts b/src/init.cts index b22c29d79..853e186cf 100644 --- a/src/init.cts +++ b/src/init.cts @@ -109,6 +109,10 @@ const REQUIRED_CODEBASE_MAP_FILES = [ 'INTEGRATIONS.md', 'CONCERNS.md', ]; +const FAST_CODEBASE_MAP_FILES = [ + 'STACK.md', 'INTEGRATIONS.md', 'ARCHITECTURE.md', 'STRUCTURE.md', +]; + const PLANNING_DOC_SEGMENTS = new Set([ 'adr', 'adrs', 'prd', 'prds', 'spec', 'specs', 'rfc', 'rfcs', ]); @@ -902,17 +906,29 @@ function cmdInitIngestDocs(cwd: string, raw: boolean): void { output(withProjectRoot(cwd, result), raw); } -function cmdInitOnboard(cwd: string, raw: boolean): void { +function cmdInitOnboard( + cwd: string, + raw: boolean, + options: Record = {}, +): void { const config = loadConfig(cwd); const codebaseMapFiles = listCodebaseMapFiles(cwd); const missingCodebaseMapFiles = REQUIRED_CODEBASE_MAP_FILES.filter( (file) => !codebaseMapFiles.includes(file), ); + const missingFastCodebaseMapFiles = FAST_CODEBASE_MAP_FILES.filter( + (file) => !codebaseMapFiles.includes(file), + ); const docCandidates = listPlanningDocCandidates(cwd); const hasCode = hasCodeFilesInternal(cwd); const hasPackageFile = hasPackageFileInternal(cwd); const isBrownfield = hasCode || hasPackageFile; const hasCodebaseMap = codebaseMapFiles.length === REQUIRED_CODEBASE_MAP_FILES.length; + const fastMode = options['fast'] === true; + const hasFastCodebaseMap = missingFastCodebaseMapFiles.length === 0; + const needsCodebaseMap = isBrownfield && ( + fastMode ? !hasFastCodebaseMap : !hasCodebaseMap + ); const result: Record = { commit_docs: config.commit_docs, @@ -929,11 +945,15 @@ function cmdInitOnboard(cwd: string, raw: boolean): void { has_existing_code: hasCode, has_package_file: hasPackageFile, is_brownfield: isBrownfield, - needs_codebase_map: isBrownfield && !hasCodebaseMap, + fast_mode: fastMode, + needs_codebase_map: needsCodebaseMap, has_codebase_map: hasCodebaseMap, + has_fast_codebase_map: hasFastCodebaseMap, codebase_dir_exists: fs.existsSync(path.join(planningRoot(cwd), 'codebase')), + fast_codebase_map_files_required: FAST_CODEBASE_MAP_FILES, codebase_map_files_present: codebaseMapFiles, missing_codebase_map_files: missingCodebaseMapFiles, + missing_fast_codebase_map_files: missingFastCodebaseMapFiles, has_docs_candidates: docCandidates.length > 0, doc_candidate_count: docCandidates.length, diff --git a/tests/onboard-command.test.cjs b/tests/onboard-command.test.cjs index e202cdd0c..cf1f6ddca 100644 --- a/tests/onboard-command.test.cjs +++ b/tests/onboard-command.test.cjs @@ -138,6 +138,29 @@ describe('init onboard public CLI projection', () => { assert.strictEqual(parsed.text_mode, true); }); + test('reports fast codebase map readiness for the default fast subset', () => { + fs.mkdirSync(path.join(tmpDir, '.planning', 'codebase'), { recursive: true }); + for (const name of ['STACK', 'INTEGRATIONS', 'ARCHITECTURE', 'STRUCTURE']) { + fs.writeFileSync(path.join(tmpDir, '.planning', 'codebase', `${name}.md`), `# ${name}\n`); + } + fs.writeFileSync(path.join(tmpDir, 'package.json'), '{"name":"fixture"}\n'); + + const result = runGsdTools(['init', 'onboard', '--fast', '--raw'], tmpDir, { HOME: tmpDir }); + assert.ok(result.success, `init onboard should succeed: ${result.error}`); + + const parsed = JSON.parse(result.output); + assert.strictEqual(parsed.has_codebase_map, false); + assert.strictEqual(parsed.has_fast_codebase_map, true); + assert.strictEqual(parsed.needs_codebase_map, false); + assert.deepStrictEqual(parsed.fast_codebase_map_files_required, [ + 'STACK.md', + 'INTEGRATIONS.md', + 'ARCHITECTURE.md', + 'STRUCTURE.md', + ]); + assert.deepStrictEqual(parsed.missing_fast_codebase_map_files, []); + }); + test('reports missing requirements in otherwise existing planning', () => { fs.mkdirSync(path.join(tmpDir, '.planning'), { recursive: true }); fs.writeFileSync(path.join(tmpDir, '.planning', 'PROJECT.md'), '# Project\n'); @@ -211,6 +234,10 @@ describe('/gsd:onboard command contract', () => { const content = fs.readFileSync(WF_PATH, 'utf8'); assert.ok(content.includes('init onboard'), 'workflow must use init onboard projection'); + assert.match(content, /gsd_run --cwd "\$_GSD_RUNTIME_ROOT" init onboard/, 'workflow must anchor init onboard at runtime root'); + assert.ok(content.includes('has_fast_codebase_map'), 'workflow must parse fast map readiness'); + assert.match(content, /CODEBASE_MAP_READY=.*has_fast_codebase_map/s, 'workflow must treat the fast subset as acceptable in fast mode'); + assert.ok(content.includes('Run from worktree root'), 'workflow handoffs must be anchored at the worktree root'); for (const runtimeHome of [ 'HERMES_HOME', 'CURSOR_CONFIG_DIR', From 6f2c2c2fd65b29a6223abceb561516637fbf7fc2 Mon Sep 17 00:00:00 2001 From: Jeremy McSpadden Date: Fri, 3 Jul 2026 11:12:50 -0500 Subject: [PATCH 14/48] no-mistakes(review): Anchor onboard summary writes --- gsd-core/workflows/onboard.md | 10 +++++++--- tests/onboard-command.test.cjs | 15 +++++++++++++++ 2 files changed, 22 insertions(+), 3 deletions(-) diff --git a/gsd-core/workflows/onboard.md b/gsd-core/workflows/onboard.md index 11c640eba..ec912c894 100644 --- a/gsd-core/workflows/onboard.md +++ b/gsd-core/workflows/onboard.md @@ -191,8 +191,12 @@ true, continue. ## 6. Write Onboarding Summary -Create `.planning/onboarding/SUMMARY.md` only after PROJECT.md exists. If it already -exists, update it only after confirmation; do not overwrite silently. +Resolve `ONBOARDING_ROOT={git_worktree_root || _GSD_RUNTIME_ROOT}` before this step. +Use `ONBOARDING_ROOT` for every filesystem write and commit in this step so nested-cwd +invocations do not create `subdir/.planning` artifacts. + +Create `{ONBOARDING_ROOT}/.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: @@ -266,7 +270,7 @@ Detected planning docs: {doc_candidate_count} Commit the summary if `commit_docs` is true: ```bash -gsd_run query commit "docs: create onboarding summary" --files .planning/onboarding/SUMMARY.md +gsd_run --cwd "$ONBOARDING_ROOT" query commit "docs: create onboarding summary" --files .planning/onboarding/SUMMARY.md ``` ## 7. Final Status diff --git a/tests/onboard-command.test.cjs b/tests/onboard-command.test.cjs index cf1f6ddca..270a0ee67 100644 --- a/tests/onboard-command.test.cjs +++ b/tests/onboard-command.test.cjs @@ -263,6 +263,21 @@ describe('/gsd:onboard command contract', () => { ); assert.ok(content.includes('new-project'), 'workflow must route to new-project'); assert.ok(content.includes('.planning/onboarding/SUMMARY.md'), 'workflow must create onboarding summary'); + assert.match( + content, + /ONBOARDING_ROOT=\{git_worktree_root \|\| _GSD_RUNTIME_ROOT\}/, + 'workflow must resolve a single root for summary writes', + ); + assert.match( + content, + /Create `\{ONBOARDING_ROOT\}\/\.planning\/onboarding\/SUMMARY\.md`/, + 'workflow must anchor summary writes at onboarding root', + ); + assert.match( + content, + /gsd_run --cwd "\$ONBOARDING_ROOT" query commit "docs: create onboarding summary" --files \.planning\/onboarding\/SUMMARY\.md/, + 'workflow must commit the root-relative summary path from onboarding root', + ); assert.match(content, /overwrite|idempotent|do not overwrite/i, 'workflow must protect existing planning'); assert.ok(content.includes('requirements_exists'), 'workflow must parse requirements existence'); assert.match(content, /REQUIREMENTS\.md: \{requirements_exists \? "present" : "missing"\}/, 'workflow must report missing requirements in partial planning'); From 3e0dbf6cf4880577450bbea9c1b1c63025b12832 Mon Sep 17 00:00:00 2001 From: Jeremy McSpadden Date: Fri, 3 Jul 2026 11:31:29 -0500 Subject: [PATCH 15/48] no-mistakes(review): Label fast onboard partial maps --- gsd-core/workflows/onboard.md | 28 ++++++++++++++++++++++++---- tests/onboard-command.test.cjs | 10 ++++++++++ 2 files changed, 34 insertions(+), 4 deletions(-) diff --git a/gsd-core/workflows/onboard.md b/gsd-core/workflows/onboard.md index ec912c894..69e4d6c27 100644 --- a/gsd-core/workflows/onboard.md +++ b/gsd-core/workflows/onboard.md @@ -38,14 +38,15 @@ if [[ "$INIT" == @file:* ]]; then INIT=$(cat "${INIT#@file:}"); fi Parse JSON fields: `planning_exists`, `project_exists`, `requirements_exists`, `roadmap_exists`, `state_exists`, `has_existing_code`, `has_package_file`, -`is_brownfield`, `has_codebase_map`, `has_fast_codebase_map`, +`is_brownfield`, `fast_mode`, `has_codebase_map`, `has_fast_codebase_map`, `codebase_map_files_present`, `missing_codebase_map_files`, `missing_fast_codebase_map_files`, `has_docs_candidates`, `doc_candidate_count`, `onboarding_summary_exists`, `text_mode`, `commit_docs`, `agents_installed`, `missing_agents`, `has_git`, `git_worktree_root`, `in_nested_subdir`. +Set `FAST_MODE=fast_mode` from INIT. Set `TEXT_MODE=true` if `--text` is present OR `text_mode` from INIT is true. -Set `CODEBASE_MAP_READY=has_fast_codebase_map` when `--fast` is present; otherwise set +Set `CODEBASE_MAP_READY=has_fast_codebase_map` when `FAST_MODE` is true; otherwise set `CODEBASE_MAP_READY=has_codebase_map`. **Text mode (`workflow.text_mode: true` in config or `--text` flag):** When `TEXT_MODE` is active, replace every `AskUserQuestion` call in this workflow with a plain-text numbered list and ask the user to type their choice number. This is required for non-Claude runtimes (OpenAI Codex, Gemini CLI, etc.) where `AskUserQuestion` is not available and would otherwise render as an inert code block. @@ -225,6 +226,18 @@ 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. +Before rendering summary and final status, derive map status values: + +- If `has_codebase_map` is true: + - `CODEBASE_MAP_SUMMARY_STATUS=.planning/codebase/ (complete)` + - `CODEBASE_MAP_FINAL_STATUS=(complete)` +- Else if `fast_mode && has_fast_codebase_map` is true: + - `CODEBASE_MAP_SUMMARY_STATUS=.planning/codebase/ (fast/partial-but-accepted codebase map)` + - `CODEBASE_MAP_FINAL_STATUS=(fast/partial-but-accepted; required fast files present)` +- Else: + - `CODEBASE_MAP_SUMMARY_STATUS=.planning/codebase/ (incomplete or skipped)` + - `CODEBASE_MAP_FINAL_STATUS=(incomplete or skipped; missing: {missing_codebase_map_files})` + Summary contents: ```markdown @@ -239,7 +252,7 @@ Summary contents: - Requirements: .planning/REQUIREMENTS.md - Roadmap: .planning/ROADMAP.md - State: .planning/STATE.md -- Codebase map: {has_codebase_map ? ".planning/codebase/ (complete)" : ".planning/codebase/ (incomplete or skipped)"} +- Codebase map: {CODEBASE_MAP_SUMMARY_STATUS} ## Codebase Map @@ -252,6 +265,13 @@ Confirmed files: - TESTING.md - INTEGRATIONS.md - CONCERNS.md +{else if fast_mode && has_fast_codebase_map} +Accepted fast map files: +- STACK.md +- INTEGRATIONS.md +- ARCHITECTURE.md +- STRUCTURE.md +Context strength: fast/partial-but-accepted codebase map; not all seven map files are present. {else} Present files: {codebase_map_files_present} Missing files: {missing_codebase_map_files} @@ -283,7 +303,7 @@ Print: ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ Created / confirmed / status: -- .planning/codebase/ {has_codebase_map ? "(complete)" : "(incomplete or skipped; missing: {missing_codebase_map_files})"} +- .planning/codebase/ {CODEBASE_MAP_FINAL_STATUS} - .planning/PROJECT.md - .planning/REQUIREMENTS.md {requirements_exists ? "(present)" : "(missing; onboarding incomplete)"} - .planning/ROADMAP.md diff --git a/tests/onboard-command.test.cjs b/tests/onboard-command.test.cjs index 270a0ee67..d75df86ad 100644 --- a/tests/onboard-command.test.cjs +++ b/tests/onboard-command.test.cjs @@ -278,6 +278,16 @@ describe('/gsd:onboard command contract', () => { /gsd_run --cwd "\$ONBOARDING_ROOT" query commit "docs: create onboarding summary" --files \.planning\/onboarding\/SUMMARY\.md/, 'workflow must commit the root-relative summary path from onboarding root', ); + assert.match( + content, + /CODEBASE_MAP_SUMMARY_STATUS=\.planning\/codebase\/ \(fast\/partial-but-accepted codebase map\)/, + 'workflow summary must label fast accepted maps without implying a complete map', + ); + assert.match( + content, + /CODEBASE_MAP_FINAL_STATUS=\(fast\/partial-but-accepted; required fast files present\)/, + 'final status must distinguish complete maps from accepted fast maps', + ); assert.match(content, /overwrite|idempotent|do not overwrite/i, 'workflow must protect existing planning'); assert.ok(content.includes('requirements_exists'), 'workflow must parse requirements existence'); assert.match(content, /REQUIREMENTS\.md: \{requirements_exists \? "present" : "missing"\}/, 'workflow must report missing requirements in partial planning'); From 41015129e1d78b0b02dbb26b28a518ef71752723 Mon Sep 17 00:00:00 2001 From: Jeremy McSpadden Date: Fri, 3 Jul 2026 11:39:09 -0500 Subject: [PATCH 16/48] no-mistakes(review): Derive onboard map status before summary prompt --- gsd-core/workflows/onboard.md | 24 ++++++++++++------------ tests/onboard-command.test.cjs | 8 ++++++++ 2 files changed, 20 insertions(+), 12 deletions(-) diff --git a/gsd-core/workflows/onboard.md b/gsd-core/workflows/onboard.md index 69e4d6c27..ee3016dd4 100644 --- a/gsd-core/workflows/onboard.md +++ b/gsd-core/workflows/onboard.md @@ -199,6 +199,18 @@ invocations do not create `subdir/.planning` artifacts. Create `{ONBOARDING_ROOT}/.planning/onboarding/SUMMARY.md` only after PROJECT.md exists. If it already exists, update it only after confirmation; do not overwrite silently. +Before summary keep/update choices, derive map status values safely: + +- If `has_codebase_map` is true: + - `CODEBASE_MAP_SUMMARY_STATUS=.planning/codebase/ (complete)` + - `CODEBASE_MAP_FINAL_STATUS=(complete)` +- Else if `fast_mode && has_fast_codebase_map` is true: + - `CODEBASE_MAP_SUMMARY_STATUS=.planning/codebase/ (fast/partial-but-accepted codebase map)` + - `CODEBASE_MAP_FINAL_STATUS=(fast/partial-but-accepted; required fast files present)` +- Else: + - `CODEBASE_MAP_SUMMARY_STATUS=.planning/codebase/ (incomplete or skipped)` + - `CODEBASE_MAP_FINAL_STATUS=(incomplete or skipped; missing: {missing_codebase_map_files})` + If `onboarding_summary_exists` is true: - If `TEXT_MODE=true`, print: @@ -226,18 +238,6 @@ 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. -Before rendering summary and final status, derive map status values: - -- If `has_codebase_map` is true: - - `CODEBASE_MAP_SUMMARY_STATUS=.planning/codebase/ (complete)` - - `CODEBASE_MAP_FINAL_STATUS=(complete)` -- Else if `fast_mode && has_fast_codebase_map` is true: - - `CODEBASE_MAP_SUMMARY_STATUS=.planning/codebase/ (fast/partial-but-accepted codebase map)` - - `CODEBASE_MAP_FINAL_STATUS=(fast/partial-but-accepted; required fast files present)` -- Else: - - `CODEBASE_MAP_SUMMARY_STATUS=.planning/codebase/ (incomplete or skipped)` - - `CODEBASE_MAP_FINAL_STATUS=(incomplete or skipped; missing: {missing_codebase_map_files})` - Summary contents: ```markdown diff --git a/tests/onboard-command.test.cjs b/tests/onboard-command.test.cjs index d75df86ad..afd6ec81e 100644 --- a/tests/onboard-command.test.cjs +++ b/tests/onboard-command.test.cjs @@ -288,6 +288,14 @@ describe('/gsd:onboard command contract', () => { /CODEBASE_MAP_FINAL_STATUS=\(fast\/partial-but-accepted; required fast files present\)/, 'final status must distinguish complete maps from accepted fast maps', ); + const deriveMapStatusIndex = content.indexOf('Before summary keep/update choices, derive map status values safely:'); + const keepExistingSummaryIndex = content.indexOf('If `onboarding_summary_exists` is true:'); + assert.ok(deriveMapStatusIndex >= 0, 'workflow must derive map status values'); + assert.ok(keepExistingSummaryIndex >= 0, 'workflow must define the existing-summary branch'); + assert.ok( + deriveMapStatusIndex < keepExistingSummaryIndex, + 'workflow must derive final map status before a keep-existing-summary path can skip to final status', + ); assert.match(content, /overwrite|idempotent|do not overwrite/i, 'workflow must protect existing planning'); assert.ok(content.includes('requirements_exists'), 'workflow must parse requirements existence'); assert.match(content, /REQUIREMENTS\.md: \{requirements_exists \? "present" : "missing"\}/, 'workflow must report missing requirements in partial planning'); From 1c992bf57d6a376eb379f9be7566345f573cc542 Mon Sep 17 00:00:00 2001 From: Jeremy McSpadden Date: Fri, 3 Jul 2026 11:44:48 -0500 Subject: [PATCH 17/48] no-mistakes(review): Stop fast onboard dead-end --- gsd-core/workflows/onboard.md | 16 ++++++++++++++++ tests/onboard-command.test.cjs | 10 ++++++++++ 2 files changed, 26 insertions(+) diff --git a/gsd-core/workflows/onboard.md b/gsd-core/workflows/onboard.md index ee3016dd4..f8b501ee3 100644 --- a/gsd-core/workflows/onboard.md +++ b/gsd-core/workflows/onboard.md @@ -149,6 +149,22 @@ Exit. ## 5. Project Initialization Gate +If `project_exists` is false and `fast_mode && has_fast_codebase_map && !has_codebase_map` is true: + +Print: + +```text +Fast codebase context is accepted for onboarding, but /gsd:new-project still requires the complete codebase map. + +Run from worktree root {git_worktree_root || _GSD_RUNTIME_ROOT}: + +/gsd:map-codebase + +Then rerun /gsd:onboard from the same worktree root. +``` + +Exit. + If `project_exists` is false: Print: diff --git a/tests/onboard-command.test.cjs b/tests/onboard-command.test.cjs index afd6ec81e..0de2a27be 100644 --- a/tests/onboard-command.test.cjs +++ b/tests/onboard-command.test.cjs @@ -288,6 +288,16 @@ describe('/gsd:onboard command contract', () => { /CODEBASE_MAP_FINAL_STATUS=\(fast\/partial-but-accepted; required fast files present\)/, 'final status must distinguish complete maps from accepted fast maps', ); + assert.match( + content, + /If `project_exists` is false and `fast_mode && has_fast_codebase_map && !has_codebase_map` is true:/, + 'workflow must not hand fast-partial maps directly to new-project', + ); + assert.match( + content, + /Fast codebase context is accepted for onboarding, but \/gsd:new-project still requires the complete codebase map\./, + 'workflow must explain why fast-partial onboarding stops before new-project', + ); const deriveMapStatusIndex = content.indexOf('Before summary keep/update choices, derive map status values safely:'); const keepExistingSummaryIndex = content.indexOf('If `onboarding_summary_exists` is true:'); assert.ok(deriveMapStatusIndex >= 0, 'workflow must derive map status values'); From ddd855887394539c23ce0e0ab922a0ccfc3938a2 Mon Sep 17 00:00:00 2001 From: Jeremy McSpadden Date: Fri, 3 Jul 2026 12:02:02 -0500 Subject: [PATCH 18/48] no-mistakes(document): Sync onboarding documentation gaps --- docs/ARCHITECTURE.md | 3 ++- docs/how-to/install-on-your-runtime.md | 5 +++-- docs/ja-JP/ARCHITECTURE.md | 3 ++- docs/ja-JP/how-to/install-on-your-runtime.md | 5 +++-- docs/ja-JP/reference/planning-artifacts.md | 18 ++++++++++++++---- .../onboarding-an-existing-codebase.md | 13 +++++++++---- docs/ko-KR/ARCHITECTURE.md | 3 ++- docs/ko-KR/how-to/install-on-your-runtime.md | 5 +++-- docs/ko-KR/reference/planning-artifacts.md | 18 ++++++++++++++---- .../onboarding-an-existing-codebase.md | 13 ++++++++----- docs/pt-BR/ARCHITECTURE.md | 3 ++- docs/pt-BR/how-to/install-on-your-runtime.md | 5 +++-- docs/pt-BR/reference/planning-artifacts.md | 18 ++++++++++++++---- .../onboarding-an-existing-codebase.md | 15 ++++++++++----- docs/zh-CN/ARCHITECTURE.md | 3 ++- docs/zh-CN/how-to/install-on-your-runtime.md | 5 +++-- docs/zh-CN/reference/planning-artifacts.md | 18 ++++++++++++++---- .../onboarding-an-existing-codebase.md | 15 ++++++++++----- 18 files changed, 118 insertions(+), 50 deletions(-) diff --git a/docs/ARCHITECTURE.md b/docs/ARCHITECTURE.md index 07e25df3a..760409bcd 100644 --- a/docs/ARCHITECTURE.md +++ b/docs/ARCHITECTURE.md @@ -620,7 +620,8 @@ Equivalent paths for other runtimes: │ ├── FEATURES.md │ ├── ARCHITECTURE.md │ └── PITFALLS.md -├── codebase/ # Brownfield mapping (from /gsd-map-codebase) +├── codebase/ # Brownfield mapping (from /gsd-map-codebase or /gsd-onboard) +├── onboarding/ # Brownfield onboarding summary (from /gsd-onboard) │ ├── STACK.md # YAML frontmatter carries `last_mapped_commit` │ ├── ARCHITECTURE.md # for the post-execute drift gate (#2003) │ ├── CONVENTIONS.md diff --git a/docs/how-to/install-on-your-runtime.md b/docs/how-to/install-on-your-runtime.md index d24c1203f..258290f07 100644 --- a/docs/how-to/install-on-your-runtime.md +++ b/docs/how-to/install-on-your-runtime.md @@ -447,10 +447,11 @@ npx @opengsd/gsd-core@latest --opencode --global ## After install -Restart your runtime to pick up new commands and agents. Then start your first project: +Restart your runtime to pick up new commands and agents. Then start a new project or onboard an existing repo: ```bash -/gsd-new-project +/gsd-new-project # greenfield project +/gsd-onboard # existing codebase ``` If the command is not found after restart, verify the install directory matches the runtime's expected config path. The prerelease-editions section above covers the most common mismatch. diff --git a/docs/ja-JP/ARCHITECTURE.md b/docs/ja-JP/ARCHITECTURE.md index 18cfae29f..b35afae2a 100644 --- a/docs/ja-JP/ARCHITECTURE.md +++ b/docs/ja-JP/ARCHITECTURE.md @@ -474,7 +474,8 @@ UI-SPEC.md (per phase) ─────────────────── │ ├── FEATURES.md │ ├── ARCHITECTURE.md │ └── PITFALLS.md -├── codebase/ # ブラウンフィールドマッピング(/gsd-map-codebase から) +├── codebase/ # ブラウンフィールドマッピング(/gsd-map-codebase または /gsd-onboard から) +├── onboarding/ # ブラウンフィールドオンボーディング概要(/gsd-onboard から) │ ├── STACK.md │ ├── ARCHITECTURE.md │ ├── CONVENTIONS.md diff --git a/docs/ja-JP/how-to/install-on-your-runtime.md b/docs/ja-JP/how-to/install-on-your-runtime.md index 1c1900736..bcd26fc82 100644 --- a/docs/ja-JP/how-to/install-on-your-runtime.md +++ b/docs/ja-JP/how-to/install-on-your-runtime.md @@ -273,10 +273,11 @@ npx @opengsd/gsd-core@latest --opencode --global ## インストール後の作業 -新しいコマンドとエージェントを反映するためにランタイムを再起動してください。その後、最初のプロジェクトを開始します。 +新しいコマンドとエージェントを反映するためにランタイムを再起動してください。その後、新規プロジェクトを開始するか既存リポジトリをオンボーディングします。 ```bash -/gsd-new-project +/gsd-new-project # グリーンフィールドプロジェクト +/gsd-onboard # 既存コードベース ``` 再起動後もコマンドが見つからない場合は、インストールディレクトリがランタイムの期待する設定パスと一致しているか確認してください。最もよくある不一致については上記のプレリリースエディションのセクションを参照してください。 diff --git a/docs/ja-JP/reference/planning-artifacts.md b/docs/ja-JP/reference/planning-artifacts.md index 1f51165ca..f231de028 100644 --- a/docs/ja-JP/reference/planning-artifacts.md +++ b/docs/ja-JP/reference/planning-artifacts.md @@ -23,6 +23,8 @@ │ ├── architecture.md │ ├── stack.md │ └── ... +├── onboarding/ # ブラウンフィールドオンボーディング概要(オプション) +│ └── SUMMARY.md ├── intel/ # クエリ可能なシンボルインデックス(オプション、intel.enabled) │ └── API-SURFACE.md └── phases/ @@ -48,7 +50,7 @@ | | | |---|---| | **用途** | プロジェクトの正規アイデンティティ: 概要、対象ユーザー、コアバリュー、要件、制約、主要な意思決定。プロダクトの進化に伴いプロジェクトライフサイクル全体を通じて更新されます。 | -| **生成元** | `/gsd-new-project`(初回作成); 意思決定が検証されると `/gsd-complete-milestone` によって更新されます。 | +| **生成元** | `/gsd-new-project`(初回作成、`/gsd-onboard` のハンドオフを含む); 意思決定が検証されると `/gsd-complete-milestone` によって更新されます。 | | **参照先** | すべてのプランニングワークフロー; `gsd-phase-researcher`、`gsd-planner`(コンテキスト); `discuss-phase`(過去の意思決定); `gsd-plan-checker`(プロジェクト制約)。 | ### `ROADMAP.md` @@ -56,7 +58,7 @@ | | | |---|---| | **用途** | マイルストーンおよびフェーズ一覧。ゴール、要件 ID、成功基準、フェーズごとの正規リファレンスを含みます。プロジェクトが何をどの順序で構築するかに関する唯一の信頼できる情報源です。 | -| **生成元** | `/gsd-new-project`(初回作成); `/gsd-phase --insert` および `/gsd-complete-milestone` によって更新されます。 | +| **生成元** | `/gsd-new-project`(初回作成、`/gsd-onboard` のハンドオフを含む); `/gsd-phase --insert` および `/gsd-complete-milestone` によって更新されます。 | | **参照先** | `/gsd-discuss-phase`、`/gsd-plan-phase`、`/gsd-execute-phase`; フェーズ情報を必要とするすべてのオーケストレーションコマンド; `gsd-planner`、`gsd-plan-checker`、`gsd-phase-researcher`。 | ### `REQUIREMENTS.md` @@ -64,7 +66,7 @@ | | | |---|---| | **用途** | 番号付きのチェック可能な受け入れ基準。各要件はロードマップフェーズにマッピングされる ID(例: `AUTH-01`)を持ちます。フェーズが実行されると要件を完了済みとしてマークします。 | -| **生成元** | `/gsd-new-project`(初回作成); `execute-phase` によって要件が完了済みとしてマークされます。 | +| **生成元** | `/gsd-new-project`(初回作成、`/gsd-onboard` のハンドオフを含む); `execute-phase` によって要件が完了済みとしてマークされます。 | | **参照先** | `gsd-planner`(プランはすべてのフェーズ要件 ID に対処しなければならない); `gsd-plan-checker` ディメンション1(要件カバレッジ); `discuss-phase`(過去の要件)。 | ### `STATE.md` @@ -72,7 +74,7 @@ | | | |---|---| | **用途** | 現在地を追跡するリビングドキュメント — 現在のフェーズとプラン、進捗指標、蓄積された意思決定、セッション継続性ノート。すべてのワークフロー実行の開始時に読み込まれます。重要なアクションのたびに更新されます。 | -| **生成元** | `/gsd-new-project`(初回作成); すべてのフェーズワークフロー、`/gsd-pause-work`、`/gsd-resume-work` によって継続的に更新されます。 | +| **生成元** | `/gsd-new-project`(初回作成、`/gsd-onboard` のハンドオフを含む); すべてのフェーズワークフロー、`/gsd-pause-work`、`/gsd-resume-work` によって継続的に更新されます。 | | **参照先** | すべてのオーケストレーションワークフロー; `/gsd-progress`; `/gsd-quick` 経由のアドホックタスク実行; `gsd-planner` および `gsd-phase-researcher`(プロジェクトの意思決定)。 | 完全なフィールドリファレンスは [STATE.md スキーマ](state-md.md) を参照してください。 @@ -87,6 +89,14 @@ 完全なスキーマは [CONFIGURATION](../../CONFIGURATION.md) を参照してください。 +### `onboarding/SUMMARY.md`(オプション) + +| | | +|---|---| +| **用途** | ブラウンフィールドオンボーディングの索引。アーティファクト状態、コードベースマッピングの完了状況、初回セットアップ後に推奨される次の GSD コマンドを記録します。 | +| **生成元** | `PROJECT.md`、`REQUIREMENTS.md`、`ROADMAP.md`、`STATE.md` がすべて存在した後の `/gsd-onboard`。 | +| **参照先** | 初回セットアップを確認する人間、および既存オンボーディング状態を確認する今後の `/gsd-onboard` 実行。 | + ### `MILESTONES.md`(オプション) | | | diff --git a/docs/ja-JP/tutorials/onboarding-an-existing-codebase.md b/docs/ja-JP/tutorials/onboarding-an-existing-codebase.md index 65a23543a..a877ff94b 100644 --- a/docs/ja-JP/tutorials/onboarding-an-existing-codebase.md +++ b/docs/ja-JP/tutorials/onboarding-an-existing-codebase.md @@ -46,7 +46,7 @@ claude --dangerously-skip-permissions ## ステップ 3 — Brownfield オンボーディングの開始 -プロジェクトを作成する前に、GSD Core に既存のコードを学習させてください。これがブラウンフィールドの計画を正確にするステップです。 +プロジェクトを作成する前に、GSD Core にリポジトリ状態を確認させ、安全な次のトップレベルコマンドを表示させます。これにより、コードベースコンテキストの取りこぼしや既存 planning ファイルの上書きを防げます。 ```text /gsd-onboard @@ -84,7 +84,7 @@ Created .planning/codebase/: --- -## ステップ 4 — コンテキストをクリアしてプロジェクトを作成 +## ステップ 4 — オンボーディングを再実行してプロジェクトを初期化する セッションウィンドウをクリアします: @@ -92,12 +92,14 @@ Created .planning/codebase/: /clear ``` -プロジェクトを作成します。前のステップで GSD Core が既存のコードを見つけているため、これがブラウンフィールドプロジェクトであることをすでに把握しています。`/gsd-new-project` を実行すると、既存のものを再説明するのではなく、*追加する*内容に焦点を当てた質問がされます: +`/gsd-onboard` をもう一度実行します。GSD Core が ADR、PRD、spec、RFC、またはルートレベルの要件ドキュメントを検出した場合は、先に推奨される `/gsd-ingest-docs` ハンドオフを実行し、その後 `/gsd-onboard` を再実行してください。コンテキストが整うと、オンボーディングはプロジェクト初期化のハンドオフを表示します: ```text /gsd-new-project ``` +前のステップで GSD Core が既存のコードを見つけているため、`/gsd-new-project` はこれがブラウンフィールドプロジェクトだと分かっています。質問は既存のものを再説明するのではなく、*追加する*内容に焦点を当てます: + GSD Core が何を作りたいかを尋ねます。コードベース全体の説明ではなく、追加する機能で答えてください: ```text @@ -124,6 +126,8 @@ Proposed Roadmap ロードマップを承認してください。 +プロジェクト設定が完了したら、もう一度 `/gsd-onboard` を実行します。`PROJECT.md`、`REQUIREMENTS.md`、`ROADMAP.md`、`STATE.md` がすべて存在するため、オンボーディングは `.planning/onboarding/SUMMARY.md` を作成または確認します。 + **`.planning/` に作成されるファイル:** ```text @@ -133,7 +137,7 @@ Proposed Roadmap ROADMAP.md ← フェーズ 1、ステータス: pending STATE.md ← セッションメモリ config.json ← ワークフロー設定 - onboarding/SUMMARY.md ← onboarding status and next command + onboarding/SUMMARY.md ← オンボーディング状態と次のコマンド codebase/ ← ステップ 3 の7つのマップファイル ``` @@ -213,6 +217,7 @@ GSD Core があなたの `CONVENTIONS.md` と `ARCHITECTURE.md` を読み込ん ## 学んだこと +- `/gsd-onboard` が対話型コマンドをネストしたり既存 planning ファイルを上書きしたりせずに、ブラウンフィールド設定を安全に順序付ける仕組み。 - `/gsd-map-codebase` が4つの並行エージェントを実行して `.planning/codebase/` に `STACK.md`、`ARCHITECTURE.md`、`CONVENTIONS.md`、`CONCERNS.md`、`STRUCTURE.md`、`TESTING.md`、`INTEGRATIONS.md` を生成する仕組み。 - ブラウンフィールドリポジトリで `/gsd-new-project` を実行すると、*追加する*内容に焦点を当てた質問がされ、既存コードから Validated 要件が自動入力される仕組み。 - コードベースマップが `/gsd-discuss-phase` のすべての質問を形成する方法 — ファイルパス、パターン、規約が実際のコードから導出される。 diff --git a/docs/ko-KR/ARCHITECTURE.md b/docs/ko-KR/ARCHITECTURE.md index 3c8481647..2e737c75c 100644 --- a/docs/ko-KR/ARCHITECTURE.md +++ b/docs/ko-KR/ARCHITECTURE.md @@ -512,7 +512,8 @@ UI-SPEC.md (단계별) ─────────────────── │ ├── FEATURES.md │ ├── ARCHITECTURE.md │ └── PITFALLS.md -├── codebase/ # 브라운필드 매핑 (/gsd-map-codebase에서) +├── codebase/ # 브라운필드 매핑 (/gsd-map-codebase 또는 /gsd-onboard에서) +├── onboarding/ # 브라운필드 온보딩 요약 (/gsd-onboard에서) │ ├── STACK.md # YAML 전문에 `last_mapped_commit` 포함 │ ├── ARCHITECTURE.md # 실행 후 드리프트 게이트를 위한 (#2003) │ ├── CONVENTIONS.md diff --git a/docs/ko-KR/how-to/install-on-your-runtime.md b/docs/ko-KR/how-to/install-on-your-runtime.md index 1a296068f..435e48c81 100644 --- a/docs/ko-KR/how-to/install-on-your-runtime.md +++ b/docs/ko-KR/how-to/install-on-your-runtime.md @@ -273,10 +273,11 @@ npx @opengsd/gsd-core@latest --opencode --global ## 설치 후 -새 명령과 에이전트를 적용하려면 런타임을 재시작하세요. 그런 다음 첫 번째 프로젝트를 시작합니다: +새 명령과 에이전트를 적용하려면 런타임을 재시작하세요. 그런 다음 새 프로젝트를 시작하거나 기존 저장소를 온보딩합니다: ```bash -/gsd-new-project +/gsd-new-project # 그린필드 프로젝트 +/gsd-onboard # 기존 코드베이스 ``` 재시작 후 명령을 찾을 수 없다면 설치 디렉터리가 런타임이 기대하는 설정 경로와 일치하는지 확인하세요. 위의 프리릴리스 에디션 섹션에서 가장 흔한 불일치 사례를 다룹니다. diff --git a/docs/ko-KR/reference/planning-artifacts.md b/docs/ko-KR/reference/planning-artifacts.md index 0447a9392..04c163b7a 100644 --- a/docs/ko-KR/reference/planning-artifacts.md +++ b/docs/ko-KR/reference/planning-artifacts.md @@ -23,6 +23,8 @@ │ ├── architecture.md │ ├── stack.md │ └── ... +├── onboarding/ # 브라운필드 온보딩 요약 (선택) +│ └── SUMMARY.md ├── intel/ # 쿼리 가능한 심볼 인덱스 (선택, intel.enabled) │ └── API-SURFACE.md └── phases/ @@ -48,7 +50,7 @@ | | | |---|---| | **목적** | 표준 프로젝트 아이덴티티: 무엇인지, 누구를 위한 것인지, 핵심 가치, 요구사항, 제약 사항, 주요 결정. 제품이 발전함에 따라 프로젝트 생명주기 전반에 걸쳐 업데이트됩니다. | -| **생성자** | `/gsd-new-project` (최초 생성); 결정이 검증됨에 따라 `/gsd-complete-milestone`에 의해 업데이트됩니다. | +| **생성자** | `/gsd-new-project` (최초 생성, `/gsd-onboard` handoff 포함); 결정이 검증됨에 따라 `/gsd-complete-milestone`에 의해 업데이트됩니다. | | **소비자** | 모든 플래닝 워크플로; `gsd-phase-researcher`, `gsd-planner` (컨텍스트); `discuss-phase` (이전 결정); `gsd-plan-checker` (프로젝트 제약 사항). | ### `ROADMAP.md` @@ -56,7 +58,7 @@ | | | |---|---| | **목적** | 목표, 요구사항 ID, 성공 기준, 페이즈별 표준 참조가 있는 마일스톤 및 페이즈 목록. 프로젝트가 무엇을 빌드하고 어떤 순서로 하는지에 대한 단일 진실의 원천. | -| **생성자** | `/gsd-new-project` (최초 생성); `/gsd-phase --insert`와 `/gsd-complete-milestone`에 의해 업데이트됩니다. | +| **생성자** | `/gsd-new-project` (최초 생성, `/gsd-onboard` handoff 포함); `/gsd-phase --insert`와 `/gsd-complete-milestone`에 의해 업데이트됩니다. | | **소비자** | `/gsd-discuss-phase`, `/gsd-plan-phase`, `/gsd-execute-phase`; 페이즈 정보가 필요한 모든 오케스트레이션 명령; `gsd-planner`, `gsd-plan-checker`, `gsd-phase-researcher`. | ### `REQUIREMENTS.md` @@ -64,7 +66,7 @@ | | | |---|---| | **목적** | 프로젝트의 번호가 매겨진 체크 가능한 인수 기준. 각 요구사항은 로드맵 페이즈에 매핑되는 ID(예: `AUTH-01`)를 가집니다. 페이즈가 실행됨에 따라 요구사항을 완료로 표시합니다. | -| **생성자** | `/gsd-new-project` (최초 생성); `execute-phase`에 의해 요구사항이 완료로 표시됩니다. | +| **생성자** | `/gsd-new-project` (최초 생성, `/gsd-onboard` handoff 포함); `execute-phase`에 의해 요구사항이 완료로 표시됩니다. | | **소비자** | `gsd-planner` (플랜은 모든 페이즈 요구사항 ID를 처리해야 함); `gsd-plan-checker` Dimension 1 (요구사항 커버리지); `discuss-phase` (이전 요구사항). | ### `STATE.md` @@ -72,7 +74,7 @@ | | | |---|---| | **목적** | 살아있는 위치 추적기 — 현재 페이즈와 플랜, 진행 지표, 누적된 결정, 세션 연속성 노트. 모든 워크플로 실행 시작 시 읽힙니다. 중요한 작업 이후 업데이트됩니다. | -| **생성자** | `/gsd-new-project` (최초 생성); 모든 페이즈 워크플로, `/gsd-pause-work`, `/gsd-resume-work`에 의해 지속적으로 업데이트됩니다. | +| **생성자** | `/gsd-new-project` (최초 생성, `/gsd-onboard` handoff 포함); 모든 페이즈 워크플로, `/gsd-pause-work`, `/gsd-resume-work`에 의해 지속적으로 업데이트됩니다. | | **소비자** | 모든 오케스트레이션 워크플로; `/gsd-progress`; `/gsd-quick`을 통한 임시 태스크 실행; `gsd-planner` 및 `gsd-phase-researcher` (프로젝트 결정). | 전체 필드 참조는 [STATE.md 스키마](state-md.md)를 참조하세요. @@ -87,6 +89,14 @@ 전체 스키마는 [CONFIGURATION](../../CONFIGURATION.md)을 참조하세요. +### `onboarding/SUMMARY.md` (선택) + +| | | +|---|---| +| **목적** | 브라운필드 온보딩 인덱스. 아티팩트 상태, 코드베이스 매핑 완료 여부, 초기 설정 후 권장되는 다음 GSD 명령을 기록합니다. | +| **생성자** | `PROJECT.md`, `REQUIREMENTS.md`, `ROADMAP.md`, `STATE.md`가 모두 존재한 뒤 `/gsd-onboard`. | +| **소비자** | 초기 설정을 검토하는 사람; 기존 온보딩 상태를 확인하는 향후 `/gsd-onboard` 실행. | + ### `MILESTONES.md` (선택) | | | diff --git a/docs/ko-KR/tutorials/onboarding-an-existing-codebase.md b/docs/ko-KR/tutorials/onboarding-an-existing-codebase.md index 89306d2ea..c1a058550 100644 --- a/docs/ko-KR/tutorials/onboarding-an-existing-codebase.md +++ b/docs/ko-KR/tutorials/onboarding-an-existing-codebase.md @@ -44,9 +44,9 @@ claude --dangerously-skip-permissions --- -## Step 3 — 코드베이스 매핑 +## Step 3 — 브라운필드 온보딩 시작 -프로젝트를 생성하기 전에 GSD Core가 이미 존재하는 것을 학습하도록 합니다. 이 단계가 브라운필드 계획의 정확도를 높이는 핵심입니다. +프로젝트를 생성하기 전에 GSD Core가 저장소 상태를 검사하고 안전한 다음 top-level 명령을 알려주게 하세요. 이 단계는 코드베이스 컨텍스트를 건너뛰거나 기존 planning 파일을 덮어쓰는 일을 방지합니다. ```text /gsd-onboard @@ -84,7 +84,7 @@ Created .planning/codebase/: --- -## Step 4 — 컨텍스트 초기화 후 프로젝트 생성 +## Step 4 — 온보딩 재실행 및 프로젝트 초기화 세션 창을 초기화합니다: @@ -92,7 +92,7 @@ Created .planning/codebase/: /clear ``` -이제 프로젝트를 생성합니다. GSD Core가 이전 단계에서 기존 코드를 발견했으므로, 이미 이것이 브라운필드 프로젝트임을 알고 있습니다. `/gsd-new-project`를 실행하면 기존의 것을 재구성하는 것이 아니라 *추가하는* 것에 집중한 질문을 합니다: +이제 `/gsd-onboard`를 다시 실행합니다. GSD Core가 ADR, PRD, spec, RFC 또는 루트 요구사항 문서를 감지하면 먼저 권장되는 `/gsd-ingest-docs` handoff를 실행하고 이후 `/gsd-onboard`를 다시 실행하세요. 컨텍스트가 준비되면 온보딩이 프로젝트 초기화 handoff를 출력합니다: ```text /gsd-new-project @@ -124,6 +124,8 @@ Proposed Roadmap 로드맵을 승인합니다. +프로젝트 설정이 끝난 뒤 `/gsd-onboard`를 한 번 더 실행합니다. 이제 `PROJECT.md`, `REQUIREMENTS.md`, `ROADMAP.md`, `STATE.md`가 모두 있으므로 온보딩은 `.planning/onboarding/SUMMARY.md`를 생성하거나 확인합니다. + **`.planning/`에 생성되는 파일:** ```text @@ -133,7 +135,7 @@ Proposed Roadmap ROADMAP.md ← Phase 1, 상태: pending STATE.md ← 세션 메모리 config.json ← 워크플로 설정 - onboarding/SUMMARY.md ← onboarding status and next command + onboarding/SUMMARY.md ← 온보딩 상태와 다음 명령 codebase/ ← Step 3에서 생성된 7개의 맵 파일 ``` @@ -213,6 +215,7 @@ GSD Core가 `CONVENTIONS.md`와 `ARCHITECTURE.md`를 읽었으므로, 질문들 ## 배운 내용 +- `/gsd-onboard`가 인터랙티브 명령을 중첩하거나 기존 planning 파일을 덮어쓰지 않고 브라운필드 설정을 안전하게 순서화하는 방법. - `/gsd-map-codebase`가 4개의 병렬 에이전트를 실행하여 `.planning/codebase/`에 `STACK.md`, `ARCHITECTURE.md`, `CONVENTIONS.md`, `CONCERNS.md`, `STRUCTURE.md`, `TESTING.md`, `INTEGRATIONS.md`를 생성하는 방법. - 브라운필드 저장소에서 `/gsd-new-project`가 *추가하는* 것에 집중한 질문을 하고 기존 코드에서 Validated 요구사항을 채우는 방법. - 코드베이스 맵이 `/gsd-discuss-phase`의 모든 질문을 형성하는 방법 — 파일 경로, 패턴, 컨벤션이 실제 코드에서 옵니다. diff --git a/docs/pt-BR/ARCHITECTURE.md b/docs/pt-BR/ARCHITECTURE.md index 4b2f1cf3f..14ff90570 100644 --- a/docs/pt-BR/ARCHITECTURE.md +++ b/docs/pt-BR/ARCHITECTURE.md @@ -527,7 +527,8 @@ Caminhos equivalentes para outros runtimes: │ ├── FEATURES.md │ ├── ARCHITECTURE.md │ └── PITFALLS.md -├── codebase/ # Mapeamento de brownfield (do /gsd-map-codebase) +├── codebase/ # Mapeamento de brownfield (do /gsd-map-codebase ou /gsd-onboard) +├── onboarding/ # Resumo de onboarding brownfield (do /gsd-onboard) │ ├── STACK.md # Frontmatter YAML carrega `last_mapped_commit` │ ├── ARCHITECTURE.md # para o portão de desvio pós-execução (#2003) │ ├── CONVENTIONS.md diff --git a/docs/pt-BR/how-to/install-on-your-runtime.md b/docs/pt-BR/how-to/install-on-your-runtime.md index ba0d31ea1..3b70bc4e8 100644 --- a/docs/pt-BR/how-to/install-on-your-runtime.md +++ b/docs/pt-BR/how-to/install-on-your-runtime.md @@ -273,10 +273,11 @@ npx @opengsd/gsd-core@latest --opencode --global ## Após a instalação -Reinicie seu ambiente para carregar os novos comandos e agentes. Em seguida, inicie seu primeiro projeto: +Reinicie seu ambiente para carregar os novos comandos e agentes. Em seguida, inicie um projeto novo ou faça onboarding de um repositório existente: ```bash -/gsd-new-project +/gsd-new-project # projeto greenfield +/gsd-onboard # base de código existente ``` Se o comando não for encontrado após o reinício, verifique se o diretório de instalação corresponde ao caminho de configuração esperado pelo ambiente. A seção de edições de pré-lançamento acima cobre a incompatibilidade mais comum. diff --git a/docs/pt-BR/reference/planning-artifacts.md b/docs/pt-BR/reference/planning-artifacts.md index 7d6859acc..5ddb9ecfa 100644 --- a/docs/pt-BR/reference/planning-artifacts.md +++ b/docs/pt-BR/reference/planning-artifacts.md @@ -23,6 +23,8 @@ O diretório `.planning/` é a memória compartilhada do GSD Core para um projet │ ├── architecture.md │ ├── stack.md │ └── ... +├── onboarding/ # Resumo de onboarding brownfield (opcional) +│ └── SUMMARY.md ├── intel/ # Índice de símbolos consultável (opcional, intel.enabled) │ └── API-SURFACE.md └── phases/ @@ -48,7 +50,7 @@ O diretório `.planning/` é a memória compartilhada do GSD Core para um projet | | | |---|---| | **Finalidade** | Identidade canônica do projeto: o que é, para quem é, valor central, requisitos, restrições e decisões-chave. Atualizado ao longo do ciclo de vida do projeto conforme o produto evolui. | -| **Produzido por** | `/gsd-new-project` (criação inicial); atualizado por `/gsd-complete-milestone` à medida que as decisões são validadas. | +| **Produzido por** | `/gsd-new-project` (criação inicial, incluindo handoff do `/gsd-onboard`); atualizado por `/gsd-complete-milestone` à medida que as decisões são validadas. | | **Consumido por** | Todos os fluxos de trabalho de planejamento; `gsd-phase-researcher`, `gsd-planner` (contexto); `discuss-phase` (decisões anteriores); `gsd-plan-checker` (restrições do projeto). | ### `ROADMAP.md` @@ -56,7 +58,7 @@ O diretório `.planning/` é a memória compartilhada do GSD Core para um projet | | | |---|---| | **Finalidade** | Listagem de marcos e fases com objetivos, IDs de requisitos, critérios de sucesso e referências canônicas por fase. A fonte única de verdade sobre o que o projeto está construindo e em que ordem. | -| **Produzido por** | `/gsd-new-project` (criação inicial); atualizado por `/gsd-phase --insert` e `/gsd-complete-milestone`. | +| **Produzido por** | `/gsd-new-project` (criação inicial, incluindo handoff do `/gsd-onboard`); atualizado por `/gsd-phase --insert` e `/gsd-complete-milestone`. | | **Consumido por** | `/gsd-discuss-phase`, `/gsd-plan-phase`, `/gsd-execute-phase`; todos os comandos de orquestração que precisam de informações de fase; `gsd-planner`, `gsd-plan-checker`, `gsd-phase-researcher`. | ### `REQUIREMENTS.md` @@ -64,7 +66,7 @@ O diretório `.planning/` é a memória compartilhada do GSD Core para um projet | | | |---|---| | **Finalidade** | Critérios de aceitação numerados e verificáveis para o projeto. Cada requisito possui um ID (ex.: `AUTH-01`) que mapeia para as fases do roadmap. Marca os requisitos como concluídos conforme as fases são executadas. | -| **Produzido por** | `/gsd-new-project` (criação inicial); requisitos marcados como concluídos por `execute-phase`. | +| **Produzido por** | `/gsd-new-project` (criação inicial, incluindo handoff do `/gsd-onboard`); requisitos marcados como concluídos por `execute-phase`. | | **Consumido por** | `gsd-planner` (os planos devem contemplar todos os IDs de requisitos da fase); `gsd-plan-checker` Dimensão 1 (cobertura de requisitos); `discuss-phase` (requisitos anteriores). | ### `STATE.md` @@ -72,7 +74,7 @@ O diretório `.planning/` é a memória compartilhada do GSD Core para um projet | | | |---|---| | **Finalidade** | Rastreador de posição em andamento — fase e plano atuais, métricas de progresso, decisões acumuladas, notas de continuidade de sessão. Lido no início de toda execução de fluxo de trabalho. Atualizado após cada ação significativa. | -| **Produzido por** | `/gsd-new-project` (criação inicial); atualizado continuamente por todos os fluxos de fase, `/gsd-pause-work`, `/gsd-resume-work`. | +| **Produzido por** | `/gsd-new-project` (criação inicial, incluindo handoff do `/gsd-onboard`); atualizado continuamente por todos os fluxos de fase, `/gsd-pause-work`, `/gsd-resume-work`. | | **Consumido por** | Todos os fluxos de orquestração; `/gsd-progress`; execução de tarefas avulsas via `/gsd-quick`; `gsd-planner` e `gsd-phase-researcher` (decisões do projeto). | Consulte o [esquema de STATE.md](state-md.md) para a referência completa de campos. @@ -87,6 +89,14 @@ Consulte o [esquema de STATE.md](state-md.md) para a referência completa de cam Consulte [CONFIGURATION](../CONFIGURATION.md) para o esquema completo. +### `onboarding/SUMMARY.md` (opcional) + +| | | +|---|---| +| **Finalidade** | Índice de onboarding brownfield que registra status dos artefatos, se o mapeamento do código-base está completo e o próximo comando GSD recomendado após a configuração inicial. | +| **Produzido por** | `/gsd-onboard` depois que `PROJECT.md`, `REQUIREMENTS.md`, `ROADMAP.md` e `STATE.md` existem. | +| **Consumido por** | Humanos revisando a configuração inicial; futuras execuções de `/gsd-onboard` ao confirmar o estado de onboarding existente. | + ### `MILESTONES.md` (opcional) | | | diff --git a/docs/pt-BR/tutorials/onboarding-an-existing-codebase.md b/docs/pt-BR/tutorials/onboarding-an-existing-codebase.md index a34dc4008..26584a9db 100644 --- a/docs/pt-BR/tutorials/onboarding-an-existing-codebase.md +++ b/docs/pt-BR/tutorials/onboarding-an-existing-codebase.md @@ -44,9 +44,9 @@ claude --dangerously-skip-permissions --- -## Passo 3 — Mapear a base de código +## Passo 3 — Iniciar o onboarding brownfield -Antes de criar um projeto, deixe o GSD Core aprender o que já existe. Este é o passo que torna o planejamento brownfield preciso. +Antes de criar um projeto, deixe o GSD Core inspecionar o estado do repositório e indicar o próximo comando de nível superior seguro. Este passo evita pular contexto de código ou sobrescrever arquivos de planning existentes. ```text /gsd-onboard @@ -84,7 +84,7 @@ Abra `.planning/codebase/CONCERNS.md`. Este é o arquivo mais útil para ler ant --- -## Passo 4 — Limpar o contexto e criar o projeto +## Passo 4 — Reexecutar o onboarding e inicializar o projeto Limpe a janela de sessão: @@ -92,12 +92,14 @@ Limpe a janela de sessão: /clear ``` -Agora crie o projeto. Como o GSD Core encontrou código existente no passo anterior, já sabe que se trata de um projeto brownfield. Quando você executa `/gsd-new-project`, as perguntas focam no que você está *adicionando*, e não em reconstruir o que já existe: +Agora execute `/gsd-onboard` novamente. Se o GSD Core detectar ADRs, PRDs, specs, RFCs ou requisitos de nível raiz, aceite o handoff recomendado para `/gsd-ingest-docs` primeiro e depois rode `/gsd-onboard` de novo. Quando o contexto estiver pronto, o onboarding imprimirá o handoff de inicialização: ```text /gsd-new-project ``` +Como o GSD Core encontrou código existente no passo anterior, `/gsd-new-project` sabe que é um projeto brownfield. As perguntas focam no que você está *adicionando*, não em reconstruir o que já existe: + O GSD Core pergunta o que você quer construir. Responda com o recurso que está adicionando, e não com uma descrição de toda a base de código: ```text @@ -124,6 +126,8 @@ Proposed Roadmap Aprove o roteiro. +Execute `/gsd-onboard` mais uma vez depois que a configuração do projeto terminar. Agora que `PROJECT.md`, `REQUIREMENTS.md`, `ROADMAP.md` e `STATE.md` existem, o onboarding cria ou confirma `.planning/onboarding/SUMMARY.md`. + **O que é criado em `.planning/`:** ```text @@ -133,7 +137,7 @@ Aprove o roteiro. ROADMAP.md ← Fase 1, status: pending STATE.md ← memória de sessão config.json ← configurações do fluxo de trabalho - onboarding/SUMMARY.md ← onboarding status and next command + onboarding/SUMMARY.md ← status do onboarding e próximo comando codebase/ ← os sete arquivos de mapa do Passo 3 ``` @@ -213,6 +217,7 @@ Para cada recurso futuro, execute `/gsd-map-codebase` novamente sempre que a est ## O que você aprendeu +- Como `/gsd-onboard` sequencia com segurança o setup brownfield sem aninhar comandos interativos ou sobrescrever planning existente. - Como `/gsd-map-codebase` executa quatro agentes paralelos para produzir `STACK.md`, `ARCHITECTURE.md`, `CONVENTIONS.md`, `CONCERNS.md`, `STRUCTURE.md`, `TESTING.md` e `INTEGRATIONS.md` em `.planning/codebase/`. - Como `/gsd-new-project` em um repositório brownfield concentra as perguntas no que você está *adicionando* e preenche os requisitos Validated a partir do código existente. - Como o mapa da base de código orienta cada pergunta em `/gsd-discuss-phase` — caminhos de arquivos, padrões e convenções vêm do seu código real. diff --git a/docs/zh-CN/ARCHITECTURE.md b/docs/zh-CN/ARCHITECTURE.md index 5a92e72bb..6395b3733 100644 --- a/docs/zh-CN/ARCHITECTURE.md +++ b/docs/zh-CN/ARCHITECTURE.md @@ -512,7 +512,8 @@ UI-SPEC.md (per phase) ─────────────────── │ ├── FEATURES.md │ ├── ARCHITECTURE.md │ └── PITFALLS.md -├── codebase/ # Brownfield mapping (from /gsd-map-codebase) +├── codebase/ # Brownfield mapping (from /gsd-map-codebase or /gsd-onboard) +├── onboarding/ # Brownfield onboarding summary (from /gsd-onboard) │ ├── STACK.md # YAML frontmatter carries `last_mapped_commit` │ ├── ARCHITECTURE.md # for the post-execute drift gate (#2003) │ ├── CONVENTIONS.md diff --git a/docs/zh-CN/how-to/install-on-your-runtime.md b/docs/zh-CN/how-to/install-on-your-runtime.md index 63a97cce3..7bf6f97fb 100644 --- a/docs/zh-CN/how-to/install-on-your-runtime.md +++ b/docs/zh-CN/how-to/install-on-your-runtime.md @@ -273,10 +273,11 @@ npx @opengsd/gsd-core@latest --opencode --global ## 安装后 -重启您的运行时以加载新命令和代理。然后启动您的第一个项目: +重启您的运行时以加载新命令和代理。然后启动新项目或接入现有仓库: ```bash -/gsd-new-project +/gsd-new-project # 新建项目 +/gsd-onboard # 现有代码库 ``` 如果重启后找不到该命令,请确认安装目录与运行时预期的配置路径匹配。上方的预发布版章节介绍了最常见的路径不匹配情况。 diff --git a/docs/zh-CN/reference/planning-artifacts.md b/docs/zh-CN/reference/planning-artifacts.md index 7039e8cd5..73c513916 100644 --- a/docs/zh-CN/reference/planning-artifacts.md +++ b/docs/zh-CN/reference/planning-artifacts.md @@ -23,6 +23,8 @@ │ ├── architecture.md │ ├── stack.md │ └── ... +├── onboarding/ # Brownfield onboarding 摘要(可选) +│ └── SUMMARY.md ├── intel/ # 可查询的符号索引(可选,intel.enabled) │ └── API-SURFACE.md └── phases/ @@ -48,7 +50,7 @@ | | | |---|---| | **用途** | 规范的项目标识:项目内容、目标用户、核心价值、需求、约束和关键决策。随项目演进持续更新。 | -| **生成者** | `/gsd-new-project`(初始创建);由 `/gsd-complete-milestone` 在决策验证后更新。 | +| **生成者** | `/gsd-new-project`(初始创建,包含 `/gsd-onboard` 交接);由 `/gsd-complete-milestone` 在决策验证后更新。 | | **消费者** | 所有规划工作流;`gsd-phase-researcher`、`gsd-planner`(上下文);`discuss-phase`(历史决策);`gsd-plan-checker`(项目约束)。 | ### `ROADMAP.md` @@ -56,7 +58,7 @@ | | | |---|---| | **用途** | 里程碑与阶段列表,含目标、需求 ID、成功标准以及每个阶段的规范参考。是项目构建内容和顺序的唯一可信来源。 | -| **生成者** | `/gsd-new-project`(初始创建);由 `/gsd-phase --insert` 和 `/gsd-complete-milestone` 更新。 | +| **生成者** | `/gsd-new-project`(初始创建,包含 `/gsd-onboard` 交接);由 `/gsd-phase --insert` 和 `/gsd-complete-milestone` 更新。 | | **消费者** | `/gsd-discuss-phase`、`/gsd-plan-phase`、`/gsd-execute-phase`;所有需要阶段信息的编排命令;`gsd-planner`、`gsd-plan-checker`、`gsd-phase-researcher`。 | ### `REQUIREMENTS.md` @@ -64,7 +66,7 @@ | | | |---|---| | **用途** | 编号化、可勾选的项目验收标准。每条需求带有 ID(如 `AUTH-01`),映射到路线图阶段。随着阶段执行,逐步标记需求为已完成。 | -| **生成者** | `/gsd-new-project`(初始创建);需求由 `execute-phase` 标记为已完成。 | +| **生成者** | `/gsd-new-project`(初始创建,包含 `/gsd-onboard` 交接);需求由 `execute-phase` 标记为已完成。 | | **消费者** | `gsd-planner`(计划必须覆盖所有阶段需求 ID);`gsd-plan-checker` 维度 1(需求覆盖);`discuss-phase`(历史需求)。 | ### `STATE.md` @@ -72,7 +74,7 @@ | | | |---|---| | **用途** | 实时进度跟踪器——当前阶段与计划、进度指标、积累的决策、会话连续性说明。每次工作流运行时首先读取,每次重要操作后更新。 | -| **生成者** | `/gsd-new-project`(初始创建);由所有阶段工作流、`/gsd-pause-work`、`/gsd-resume-work` 持续更新。 | +| **生成者** | `/gsd-new-project`(初始创建,包含 `/gsd-onboard` 交接);由所有阶段工作流、`/gsd-pause-work`、`/gsd-resume-work` 持续更新。 | | **消费者** | 所有编排工作流;`/gsd-progress`;通过 `/gsd-quick` 执行的临时任务;`gsd-planner` 和 `gsd-phase-researcher`(项目决策)。 | 完整字段参考请参见 [STATE.md 模式](state-md.md)。 @@ -87,6 +89,14 @@ 完整模式请参见 [CONFIGURATION](../CONFIGURATION.md)。 +### `onboarding/SUMMARY.md`(可选) + +| | | +|---|---| +| **用途** | Brownfield onboarding 索引,记录产物状态、代码库映射是否完整,以及初次设置后的下一个推荐 GSD 命令。 | +| **生成者** | `/gsd-onboard`,在 `PROJECT.md`、`REQUIREMENTS.md`、`ROADMAP.md` 和 `STATE.md` 全部存在后生成。 | +| **消费者** | 审查初次设置的人;以后确认现有 onboarding 状态的 `/gsd-onboard` 运行。 | + ### `MILESTONES.md`(可选) | | | diff --git a/docs/zh-CN/tutorials/onboarding-an-existing-codebase.md b/docs/zh-CN/tutorials/onboarding-an-existing-codebase.md index c32493607..5f3513fc6 100644 --- a/docs/zh-CN/tutorials/onboarding-an-existing-codebase.md +++ b/docs/zh-CN/tutorials/onboarding-an-existing-codebase.md @@ -46,7 +46,7 @@ claude --dangerously-skip-permissions ## 第 3 步 — 开始 brownfield onboarding -在创建项目之前,先让 GSD Core 了解已有的内容。这是使棕地规划准确的关键步骤。 +在创建项目之前,让 GSD Core 检查仓库状态并告诉您安全的下一个顶层命令。这一步可避免跳过代码库上下文或覆盖现有 planning 文件。 ```text /gsd-onboard @@ -84,7 +84,7 @@ Created .planning/codebase/: --- -## 第 4 步 — 清除上下文并创建项目 +## 第 4 步 — 重新运行 onboarding 并初始化项目 清除会话窗口: @@ -92,12 +92,14 @@ Created .planning/codebase/: /clear ``` -现在创建项目。由于 GSD Core 在上一步中发现了现有代码,它已经知道这是一个棕地项目。当您运行 `/gsd-new-project` 时,问题将聚焦于您所*新增*的内容,而非重新描述已有的内容: +现在再次运行 `/gsd-onboard`。如果 GSD Core 检测到 ADR、PRD、spec、RFC 或根级需求文档,请先接受推荐的 `/gsd-ingest-docs` 交接,然后再运行 `/gsd-onboard`。上下文准备好后,onboarding 会打印项目初始化交接命令: ```text /gsd-new-project ``` +由于 GSD Core 在上一步中发现了现有代码,`/gsd-new-project` 知道这是一个棕地项目。问题将聚焦于您所*新增*的内容,而非重新描述已有的内容: + GSD Core 会询问您想构建什么。请用您正在添加的功能来回答,而不是描述整个代码库: ```text @@ -124,6 +126,8 @@ Proposed Roadmap 批准路线图。 +项目设置完成后,再运行一次 `/gsd-onboard`。现在 `PROJECT.md`、`REQUIREMENTS.md`、`ROADMAP.md` 和 `STATE.md` 都已存在,onboarding 会创建或确认 `.planning/onboarding/SUMMARY.md`。 + **在 `.planning/` 中创建的内容:** ```text @@ -133,8 +137,8 @@ Proposed Roadmap ROADMAP.md ← Phase 1, status: pending STATE.md ← session memory config.json ← workflow settings - onboarding/SUMMARY.md ← onboarding status and next command - codebase/ ← the seven map files from Step 3 + onboarding/SUMMARY.md ← onboarding 状态和下一个命令 + codebase/ ← 第 3 步生成的七个映射文件 ``` 注意 `.planning/codebase/` 已经从第 3 步存在。GSD Core 在编写 `PROJECT.md` 时读取了这些文件,这就是为什么它无需您描述即可填充已验证的需求。 @@ -213,6 +217,7 @@ Proposed Roadmap ## 您学到了什么 +- `/gsd-onboard` 如何安全编排 brownfield 设置,不嵌套交互式命令,也不覆盖现有 planning 文件。 - `/gsd-map-codebase` 如何运行四个并行代理,在 `.planning/codebase/` 中生成 `STACK.md`、`ARCHITECTURE.md`、`CONVENTIONS.md`、`CONCERNS.md`、`STRUCTURE.md`、`TESTING.md` 和 `INTEGRATIONS.md`。 - 在棕地仓库中运行 `/gsd-new-project` 如何将问题聚焦于您所*新增*的内容,并从现有代码中填充已验证的需求。 - 代码库映射如何塑造 `/gsd-discuss-phase` 中的每个问题——文件路径、模式和规范均来自您的实际代码。 From afc3309b61618a2eacfab1958b070e645cb35f1b Mon Sep 17 00:00:00 2001 From: Jeremy McSpadden Date: Fri, 3 Jul 2026 12:23:12 -0500 Subject: [PATCH 19/48] no-mistakes(review): Forward onboard fast init flag --- gsd-core/workflows/onboard.md | 8 +++++--- tests/onboard-command.test.cjs | 14 ++++++++++++++ 2 files changed, 19 insertions(+), 3 deletions(-) diff --git a/gsd-core/workflows/onboard.md b/gsd-core/workflows/onboard.md index f8b501ee3..6dc5a1f97 100644 --- a/gsd-core/workflows/onboard.md +++ b/gsd-core/workflows/onboard.md @@ -30,9 +30,11 @@ Run the init projection: ```bash _GSD_SHIM_NAME="gsd-tools.cjs"; _GSD_RUNTIME_ROOT="${RUNTIME_DIR:-$(git rev-parse --show-toplevel 2>/dev/null || pwd)}"; GSD_TOOLS="${_GSD_RUNTIME_ROOT}/gsd-core/bin/${_GSD_SHIM_NAME}"; if [ -f "$GSD_TOOLS" ]; then gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${_GSD_RUNTIME_ROOT}/.claude/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${_GSD_RUNTIME_ROOT}/.claude/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${_GSD_RUNTIME_ROOT}/.codex/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${_GSD_RUNTIME_ROOT}/.codex/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif command -v gsd-tools >/dev/null 2>&1; then GSD_TOOLS="$(command -v gsd-tools)"; gsd_run() { "$GSD_TOOLS" "$@"; }; elif [ -f "$HOME/.claude/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="$HOME/.claude/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${HERMES_HOME:-$HOME/.hermes}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${HERMES_HOME:-$HOME/.hermes}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${CURSOR_CONFIG_DIR:-$HOME/.cursor}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${CURSOR_CONFIG_DIR:-$HOME/.cursor}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${CODEX_HOME:-$HOME/.codex}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${CODEX_HOME:-$HOME/.codex}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${GEMINI_CONFIG_DIR:-$HOME/.gemini}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${GEMINI_CONFIG_DIR:-$HOME/.gemini}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${COPILOT_CONFIG_DIR:-$HOME/.copilot}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${COPILOT_CONFIG_DIR:-$HOME/.copilot}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${WINDSURF_CONFIG_DIR:-$HOME/.codeium/windsurf}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${WINDSURF_CONFIG_DIR:-$HOME/.codeium/windsurf}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${AUGMENT_CONFIG_DIR:-$HOME/.augment}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${AUGMENT_CONFIG_DIR:-$HOME/.augment}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${TRAE_CONFIG_DIR:-$HOME/.trae}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${TRAE_CONFIG_DIR:-$HOME/.trae}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${QWEN_CONFIG_DIR:-$HOME/.qwen}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${QWEN_CONFIG_DIR:-$HOME/.qwen}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${CODEBUDDY_CONFIG_DIR:-$HOME/.codebuddy}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${CODEBUDDY_CONFIG_DIR:-$HOME/.codebuddy}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${CLINE_CONFIG_DIR:-$HOME/.cline}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${CLINE_CONFIG_DIR:-$HOME/.cline}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${GROK_AGENTS_HOME:-$HOME/.agents}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${GROK_AGENTS_HOME:-$HOME/.agents}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${ANTIGRAVITY_CONFIG_DIR:-$HOME/.gemini/antigravity}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${ANTIGRAVITY_CONFIG_DIR:-$HOME/.gemini/antigravity}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${OPENCODE_CONFIG_DIR:-${XDG_CONFIG_HOME:-$HOME/.config}/opencode}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${OPENCODE_CONFIG_DIR:-${XDG_CONFIG_HOME:-$HOME/.config}/opencode}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${KILO_CONFIG_DIR:-${XDG_CONFIG_HOME:-$HOME/.config}/kilo}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${KILO_CONFIG_DIR:-${XDG_CONFIG_HOME:-$HOME/.config}/kilo}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; else echo "ERROR: gsd-tools.cjs not found at $GSD_TOOLS and gsd-tools is not on PATH. Run: npx -y @opengsd/gsd-core@latest --claude --local" >&2; exit 1; fi; if [ -n "${CLAUDE_ENV_FILE:-}" ] && [ -n "${GSD_TOOLS:-}" ]; then printf "export PATH='%s':\"\$PATH\"\n" "${GSD_TOOLS%/*}" >> "$CLAUDE_ENV_FILE" 2>/dev/null || true; fi -INIT_ONBOARD_FLAGS=() -if [[ " ${ARGUMENTS:-} " == *" --fast "* ]]; then INIT_ONBOARD_FLAGS=(--fast); fi -INIT=$(gsd_run --cwd "$_GSD_RUNTIME_ROOT" init onboard "${INIT_ONBOARD_FLAGS[@]}") +``` + +Run init from parsed prompt args, not shell `$ARGUMENTS`: `--fast` => `INIT=$(gsd_run --cwd "$_GSD_RUNTIME_ROOT" init onboard --fast)`; default omits `--fast`. + +```bash if [[ "$INIT" == @file:* ]]; then INIT=$(cat "${INIT#@file:}"); fi ``` diff --git a/tests/onboard-command.test.cjs b/tests/onboard-command.test.cjs index 0de2a27be..2201b3730 100644 --- a/tests/onboard-command.test.cjs +++ b/tests/onboard-command.test.cjs @@ -235,6 +235,20 @@ describe('/gsd:onboard command contract', () => { assert.ok(content.includes('init onboard'), 'workflow must use init onboard projection'); assert.match(content, /gsd_run --cwd "\$_GSD_RUNTIME_ROOT" init onboard/, 'workflow must anchor init onboard at runtime root'); + assert.ok( + !content.includes('ARGUMENTS:-'), + 'workflow must not depend on an unexported shell ARGUMENTS variable', + ); + assert.match( + content, + /Run init from parsed prompt args, not shell `\$ARGUMENTS`/, + 'workflow must forward fast mode from parsed prompt arguments into init onboard', + ); + assert.match( + content, + /gsd_run --cwd "\$_GSD_RUNTIME_ROOT" init onboard --fast/, + 'workflow must provide a literal fast init command', + ); assert.ok(content.includes('has_fast_codebase_map'), 'workflow must parse fast map readiness'); assert.match(content, /CODEBASE_MAP_READY=.*has_fast_codebase_map/s, 'workflow must treat the fast subset as acceptable in fast mode'); assert.ok(content.includes('Run from worktree root'), 'workflow handoffs must be anchored at the worktree root'); From e3f2070a42f23fa6fb995f081f79bdaa03061289 Mon Sep 17 00:00:00 2001 From: Jeremy McSpadden Date: Fri, 3 Jul 2026 12:35:49 -0500 Subject: [PATCH 20/48] no-mistakes(document): Sync onboard docs --- docs/CLI-TOOLS.md | 4 ++-- docs/how-to/install-minimal-and-add-skills.md | 2 +- docs/ja-JP/CLI-TOOLS.md | 3 ++- docs/ko-KR/CLI-TOOLS.md | 3 ++- docs/pt-BR/CLI-TOOLS.md | 3 ++- docs/zh-CN/CLI-TOOLS.md | 3 ++- 6 files changed, 11 insertions(+), 7 deletions(-) diff --git a/docs/CLI-TOOLS.md b/docs/CLI-TOOLS.md index 9381be660..e0454074a 100644 --- a/docs/CLI-TOOLS.md +++ b/docs/CLI-TOOLS.md @@ -421,14 +421,14 @@ node gsd-tools.cjs scaffold phase-dir --phase N --name "phase name" ## Init Commands (Compound Context Loading) -Load all context needed for a specific workflow in one call. Returns JSON with project info, config, state, and workflow-specific data. `init onboard` reports brownfield signals, planning-doc candidates, codebase-map completeness, partial planning state, and onboarding summary status for `/gsd-onboard`. +Load all context needed for a specific workflow in one call. Returns JSON with project info, config, state, and workflow-specific data. `init onboard [--fast]` reports brownfield signals, planning-doc candidates, codebase-map completeness, fast-map readiness, partial planning state, and onboarding summary status for `/gsd-onboard`. ```bash node gsd-tools.cjs init execute-phase node gsd-tools.cjs init plan-phase node gsd-tools.cjs init new-project node gsd-tools.cjs init new-milestone -node gsd-tools.cjs init onboard +node gsd-tools.cjs init onboard [--fast] node gsd-tools.cjs init quick node gsd-tools.cjs init resume node gsd-tools.cjs init verify-work diff --git a/docs/how-to/install-minimal-and-add-skills.md b/docs/how-to/install-minimal-and-add-skills.md index e30537af7..53a6f772d 100644 --- a/docs/how-to/install-minimal-and-add-skills.md +++ b/docs/how-to/install-minimal-and-add-skills.md @@ -45,7 +45,7 @@ If `core` is too small, pick a wider profile instead. Pass it with `--profile= node gsd-tools.cjs init plan-phase node gsd-tools.cjs init new-project node gsd-tools.cjs init new-milestone +node gsd-tools.cjs init onboard [--fast] node gsd-tools.cjs init quick node gsd-tools.cjs init resume node gsd-tools.cjs init verify-work diff --git a/docs/ko-KR/CLI-TOOLS.md b/docs/ko-KR/CLI-TOOLS.md index 80496bf35..3f375c3ec 100644 --- a/docs/ko-KR/CLI-TOOLS.md +++ b/docs/ko-KR/CLI-TOOLS.md @@ -288,13 +288,14 @@ node gsd-tools.cjs scaffold phase-dir --phase N --name "phase name" ## Init 명령 (복합 컨텍스트 로딩) -하나의 호출로 특정 워크플로우에 필요한 모든 컨텍스트를 로드합니다. 프로젝트 정보, 설정, 상태, 워크플로우별 데이터가 포함된 JSON을 반환합니다. +하나의 호출로 특정 워크플로우에 필요한 모든 컨텍스트를 로드합니다. 프로젝트 정보, 설정, 상태, 워크플로우별 데이터가 포함된 JSON을 반환합니다. `init onboard [--fast]`는 `/gsd-onboard`를 위해 brownfield 신호, 계획 문서 후보, 코드베이스 맵 완성도, fast 맵 준비 상태, 부분 planning 상태, 온보딩 요약 상태를 반환합니다. ```bash node gsd-tools.cjs init execute-phase node gsd-tools.cjs init plan-phase node gsd-tools.cjs init new-project node gsd-tools.cjs init new-milestone +node gsd-tools.cjs init onboard [--fast] node gsd-tools.cjs init quick node gsd-tools.cjs init resume node gsd-tools.cjs init verify-work diff --git a/docs/pt-BR/CLI-TOOLS.md b/docs/pt-BR/CLI-TOOLS.md index 24441e6bd..2094b6bb0 100644 --- a/docs/pt-BR/CLI-TOOLS.md +++ b/docs/pt-BR/CLI-TOOLS.md @@ -290,13 +290,14 @@ node gsd-tools.cjs scaffold phase-dir --phase N --name "phase name" ## Comandos Init (Carregamento de Contexto Composto) -Carrega todo o contexto necessário para um fluxo de trabalho específico em uma única chamada. Retorna JSON com informações do projeto, configuração, estado e dados específicos do fluxo de trabalho. +Carrega todo o contexto necessário para um fluxo de trabalho específico em uma única chamada. Retorna JSON com informações do projeto, configuração, estado e dados específicos do fluxo de trabalho. `init onboard [--fast]` retorna, para `/gsd-onboard`, sinais de brownfield, candidatos a docs de planning, completude do mapa de código, prontidão do mapa fast, estado parcial de planning e status do resumo de onboarding. ```bash node gsd-tools.cjs init execute-phase node gsd-tools.cjs init plan-phase node gsd-tools.cjs init new-project node gsd-tools.cjs init new-milestone +node gsd-tools.cjs init onboard [--fast] node gsd-tools.cjs init quick node gsd-tools.cjs init resume node gsd-tools.cjs init verify-work diff --git a/docs/zh-CN/CLI-TOOLS.md b/docs/zh-CN/CLI-TOOLS.md index ff86c98e9..70cb595a6 100644 --- a/docs/zh-CN/CLI-TOOLS.md +++ b/docs/zh-CN/CLI-TOOLS.md @@ -288,13 +288,14 @@ node gsd-tools.cjs scaffold phase-dir --phase N --name "phase name" ## Init 命令(复合上下文加载) -通过单次调用加载特定工作流所需的所有上下文。返回包含项目信息、配置、状态和工作流专属数据的 JSON。 +通过单次调用加载特定工作流所需的所有上下文。返回包含项目信息、配置、状态和工作流专属数据的 JSON。`init onboard [--fast]` 会为 `/gsd-onboard` 返回 brownfield 信号、planning 文档候选、代码库映射完整性、fast 映射就绪状态、部分 planning 状态和 onboarding summary 状态。 ```bash node gsd-tools.cjs init execute-phase node gsd-tools.cjs init plan-phase node gsd-tools.cjs init new-project node gsd-tools.cjs init new-milestone +node gsd-tools.cjs init onboard [--fast] node gsd-tools.cjs init quick node gsd-tools.cjs init resume node gsd-tools.cjs init verify-work From a5298c1fc069c26b50368d8303ac88f463f669c7 Mon Sep 17 00:00:00 2001 From: Jeremy McSpadden Date: Fri, 3 Jul 2026 14:11:42 -0500 Subject: [PATCH 21/48] refactor: project onboard routing in init --- .gitignore | 1 + eslint.config.mjs | 1 + gsd-core/references/gsd-run-resolver.md | 8 + gsd-core/workflows/onboard.md | 355 +++++++--------------- src/init.cts | 199 +----------- src/onboard-projection.cts | 383 ++++++++++++++++++++++++ tests/onboard-command.test.cjs | 186 ++++++------ 7 files changed, 613 insertions(+), 520 deletions(-) create mode 100644 gsd-core/references/gsd-run-resolver.md create mode 100644 src/onboard-projection.cts diff --git a/.gitignore b/.gitignore index 9562ecd17..c44176af8 100644 --- a/.gitignore +++ b/.gitignore @@ -192,6 +192,7 @@ build/ /gsd-core/bin/lib/eval.cjs /gsd-core/bin/lib/eval-command-router.cjs /gsd-core/bin/lib/init-command-router.cjs +/gsd-core/bin/lib/onboard-projection.cjs /gsd-core/bin/lib/agent-command-router.cjs /gsd-core/bin/lib/agent-install-check.cjs /gsd-core/bin/lib/task-command-router.cjs diff --git a/eslint.config.mjs b/eslint.config.mjs index 580c90822..a000dd984 100644 --- a/eslint.config.mjs +++ b/eslint.config.mjs @@ -162,6 +162,7 @@ export default tseslint.config( 'gsd-core/bin/lib/eval.cjs', 'gsd-core/bin/lib/eval-command-router.cjs', 'gsd-core/bin/lib/init-command-router.cjs', + 'gsd-core/bin/lib/onboard-projection.cjs', 'gsd-core/bin/lib/agent-command-router.cjs', 'gsd-core/bin/lib/agent-install-check.cjs', 'gsd-core/bin/lib/task-command-router.cjs', diff --git a/gsd-core/references/gsd-run-resolver.md b/gsd-core/references/gsd-run-resolver.md new file mode 100644 index 000000000..dd584b755 --- /dev/null +++ b/gsd-core/references/gsd-run-resolver.md @@ -0,0 +1,8 @@ +# Standard `gsd_run` Resolver + +Use this bootstrap block when a workflow must call `gsd-tools` from the active worktree/runtime. +Keep this resolver centralized; workflows should reference this file instead of copying the shell probe. + +```bash +_GSD_SHIM_NAME="gsd-tools.cjs"; _GSD_RUNTIME_ROOT="${RUNTIME_DIR:-$(git rev-parse --show-toplevel 2>/dev/null || pwd)}"; GSD_TOOLS="${_GSD_RUNTIME_ROOT}/gsd-core/bin/${_GSD_SHIM_NAME}"; if [ -f "$GSD_TOOLS" ]; then gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${_GSD_RUNTIME_ROOT}/.claude/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${_GSD_RUNTIME_ROOT}/.claude/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${_GSD_RUNTIME_ROOT}/.codex/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${_GSD_RUNTIME_ROOT}/.codex/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif command -v gsd-tools >/dev/null 2>&1; then GSD_TOOLS="$(command -v gsd-tools)"; gsd_run() { "$GSD_TOOLS" "$@"; }; elif [ -f "$HOME/.claude/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="$HOME/.claude/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${HERMES_HOME:-$HOME/.hermes}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${HERMES_HOME:-$HOME/.hermes}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${CURSOR_CONFIG_DIR:-$HOME/.cursor}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${CURSOR_CONFIG_DIR:-$HOME/.cursor}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${CODEX_HOME:-$HOME/.codex}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${CODEX_HOME:-$HOME/.codex}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${GEMINI_CONFIG_DIR:-$HOME/.gemini}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${GEMINI_CONFIG_DIR:-$HOME/.gemini}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${COPILOT_CONFIG_DIR:-$HOME/.copilot}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${COPILOT_CONFIG_DIR:-$HOME/.copilot}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${WINDSURF_CONFIG_DIR:-$HOME/.codeium/windsurf}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${WINDSURF_CONFIG_DIR:-$HOME/.codeium/windsurf}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${AUGMENT_CONFIG_DIR:-$HOME/.augment}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${AUGMENT_CONFIG_DIR:-$HOME/.augment}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${TRAE_CONFIG_DIR:-$HOME/.trae}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${TRAE_CONFIG_DIR:-$HOME/.trae}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${QWEN_CONFIG_DIR:-$HOME/.qwen}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${QWEN_CONFIG_DIR:-$HOME/.qwen}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${CODEBUDDY_CONFIG_DIR:-$HOME/.codebuddy}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${CODEBUDDY_CONFIG_DIR:-$HOME/.codebuddy}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${CLINE_CONFIG_DIR:-$HOME/.cline}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${CLINE_CONFIG_DIR:-$HOME/.cline}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${GROK_AGENTS_HOME:-$HOME/.agents}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${GROK_AGENTS_HOME:-$HOME/.agents}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${ANTIGRAVITY_CONFIG_DIR:-$HOME/.gemini/antigravity}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${ANTIGRAVITY_CONFIG_DIR:-$HOME/.gemini/antigravity}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${OPENCODE_CONFIG_DIR:-${XDG_CONFIG_HOME:-$HOME/.config}/opencode}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${OPENCODE_CONFIG_DIR:-${XDG_CONFIG_HOME:-$HOME/.config}/opencode}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${KILO_CONFIG_DIR:-${XDG_CONFIG_HOME:-$HOME/.config}/kilo}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${KILO_CONFIG_DIR:-${XDG_CONFIG_HOME:-$HOME/.config}/kilo}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; else echo "ERROR: gsd-tools.cjs not found at $GSD_TOOLS and gsd-tools is not on PATH. Run: npx -y @opengsd/gsd-core@latest --claude --local" >&2; exit 1; fi; if [ -n "${CLAUDE_ENV_FILE:-}" ] && [ -n "${GSD_TOOLS:-}" ]; then printf "export PATH='%s':\"\$PATH\"\n" "${GSD_TOOLS%/*}" >> "$CLAUDE_ENV_FILE" 2>/dev/null || true; fi +``` diff --git a/gsd-core/workflows/onboard.md b/gsd-core/workflows/onboard.md index 6dc5a1f97..d955e3048 100644 --- a/gsd-core/workflows/onboard.md +++ b/gsd-core/workflows/onboard.md @@ -1,360 +1,219 @@ - -Guide existing-codebase onboarding by sequencing the already-owned GSD primitives: -`/gsd:map-codebase`, `/gsd:ingest-docs`, and `/gsd:new-project`. The workflow is -idempotent: it confirms existing artifacts, refuses to overwrite planning data silently, -and stops with the exact next top-level command whenever a nested interactive workflow -would be unsafe. - +# /gsd:onboard Workflow - -Read all files referenced by the invoking prompt's execution_context before starting. - +One-command onboarding for an existing or unknown repo. This workflow is a thin +renderer around `init onboard`; deterministic routing lives in the CLI projection. - +@~/.claude/gsd-core/references/gsd-run-resolver.md -## 1. Initialize - -Display banner: - -``` -━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - GSD ► ONBOARDING -━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ -``` +## 1. Render the Onboarding Projection Parse `$ARGUMENTS`: -- `--fast` sets `MAP_COMMAND` to `/gsd:map-codebase --fast`, passes `--fast` to the init projection, and accepts the default fast map subset (STACK, INTEGRATIONS, ARCHITECTURE, STRUCTURE) as sufficient onboarding context; otherwise `MAP_COMMAND` is `/gsd:map-codebase`. -- `--text` sets `TEXT_MODE=true`. +- `--fast` passes `--fast` to `init onboard`. Fast mode accepts the fast map for lightweight onboarding only; `next_action` still decides whether complete map work is required before project setup. +- `--text` forces text-mode choices for runtimes without `AskUserQuestion`. -Run the init projection: - -```bash -_GSD_SHIM_NAME="gsd-tools.cjs"; _GSD_RUNTIME_ROOT="${RUNTIME_DIR:-$(git rev-parse --show-toplevel 2>/dev/null || pwd)}"; GSD_TOOLS="${_GSD_RUNTIME_ROOT}/gsd-core/bin/${_GSD_SHIM_NAME}"; if [ -f "$GSD_TOOLS" ]; then gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${_GSD_RUNTIME_ROOT}/.claude/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${_GSD_RUNTIME_ROOT}/.claude/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${_GSD_RUNTIME_ROOT}/.codex/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${_GSD_RUNTIME_ROOT}/.codex/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif command -v gsd-tools >/dev/null 2>&1; then GSD_TOOLS="$(command -v gsd-tools)"; gsd_run() { "$GSD_TOOLS" "$@"; }; elif [ -f "$HOME/.claude/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="$HOME/.claude/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${HERMES_HOME:-$HOME/.hermes}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${HERMES_HOME:-$HOME/.hermes}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${CURSOR_CONFIG_DIR:-$HOME/.cursor}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${CURSOR_CONFIG_DIR:-$HOME/.cursor}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${CODEX_HOME:-$HOME/.codex}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${CODEX_HOME:-$HOME/.codex}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${GEMINI_CONFIG_DIR:-$HOME/.gemini}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${GEMINI_CONFIG_DIR:-$HOME/.gemini}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${COPILOT_CONFIG_DIR:-$HOME/.copilot}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${COPILOT_CONFIG_DIR:-$HOME/.copilot}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${WINDSURF_CONFIG_DIR:-$HOME/.codeium/windsurf}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${WINDSURF_CONFIG_DIR:-$HOME/.codeium/windsurf}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${AUGMENT_CONFIG_DIR:-$HOME/.augment}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${AUGMENT_CONFIG_DIR:-$HOME/.augment}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${TRAE_CONFIG_DIR:-$HOME/.trae}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${TRAE_CONFIG_DIR:-$HOME/.trae}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${QWEN_CONFIG_DIR:-$HOME/.qwen}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${QWEN_CONFIG_DIR:-$HOME/.qwen}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${CODEBUDDY_CONFIG_DIR:-$HOME/.codebuddy}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${CODEBUDDY_CONFIG_DIR:-$HOME/.codebuddy}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${CLINE_CONFIG_DIR:-$HOME/.cline}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${CLINE_CONFIG_DIR:-$HOME/.cline}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${GROK_AGENTS_HOME:-$HOME/.agents}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${GROK_AGENTS_HOME:-$HOME/.agents}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${ANTIGRAVITY_CONFIG_DIR:-$HOME/.gemini/antigravity}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${ANTIGRAVITY_CONFIG_DIR:-$HOME/.gemini/antigravity}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${OPENCODE_CONFIG_DIR:-${XDG_CONFIG_HOME:-$HOME/.config}/opencode}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${OPENCODE_CONFIG_DIR:-${XDG_CONFIG_HOME:-$HOME/.config}/opencode}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${KILO_CONFIG_DIR:-${XDG_CONFIG_HOME:-$HOME/.config}/kilo}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${KILO_CONFIG_DIR:-${XDG_CONFIG_HOME:-$HOME/.config}/kilo}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; else echo "ERROR: gsd-tools.cjs not found at $GSD_TOOLS and gsd-tools is not on PATH. Run: npx -y @opengsd/gsd-core@latest --claude --local" >&2; exit 1; fi; if [ -n "${CLAUDE_ENV_FILE:-}" ] && [ -n "${GSD_TOOLS:-}" ]; then printf "export PATH='%s':\"\$PATH\"\n" "${GSD_TOOLS%/*}" >> "$CLAUDE_ENV_FILE" 2>/dev/null || true; fi -``` - -Run init from parsed prompt args, not shell `$ARGUMENTS`: `--fast` => `INIT=$(gsd_run --cwd "$_GSD_RUNTIME_ROOT" init onboard --fast)`; default omits `--fast`. +Run the standard `gsd_run` resolver from the reference above, then run the projection from the runtime root: ```bash +# If --fast was parsed from $ARGUMENTS: +INIT=$(gsd_run --cwd "$_GSD_RUNTIME_ROOT" init onboard --fast --raw) +# Otherwise: +INIT=$(gsd_run --cwd "$_GSD_RUNTIME_ROOT" init onboard --raw) if [[ "$INIT" == @file:* ]]; then INIT=$(cat "${INIT#@file:}"); fi ``` -Parse JSON fields: `planning_exists`, `project_exists`, `requirements_exists`, -`roadmap_exists`, `state_exists`, `has_existing_code`, `has_package_file`, -`is_brownfield`, `fast_mode`, `has_codebase_map`, `has_fast_codebase_map`, -`codebase_map_files_present`, `missing_codebase_map_files`, `missing_fast_codebase_map_files`, -`has_docs_candidates`, -`doc_candidate_count`, `onboarding_summary_exists`, `text_mode`, `commit_docs`, `agents_installed`, -`missing_agents`, `has_git`, `git_worktree_root`, `in_nested_subdir`. +Parse JSON fields from `INIT`: -Set `FAST_MODE=fast_mode` from INIT. -Set `TEXT_MODE=true` if `--text` is present OR `text_mode` from INIT is true. -Set `CODEBASE_MAP_READY=has_fast_codebase_map` when `FAST_MODE` is true; otherwise set -`CODEBASE_MAP_READY=has_codebase_map`. +- `next_action.kind`, `next_action.command`, `next_action.reason`, `next_action.missing`, `next_action.summary_path` +- `map_readiness`, `codebase_map_summary_status`, `codebase_map_final_status` +- `planning_exists`, `project_exists`, `requirements_exists`, `roadmap_exists`, `state_exists` +- `is_brownfield`, `fast_mode`, `has_codebase_map`, `has_fast_codebase_map` +- `missing_codebase_map_files`, `missing_fast_codebase_map_files` +- `has_docs_candidates`, `doc_candidate_count`, `onboarding_summary_exists` +- `commit_docs`, `text_mode`, `has_git`, `git_worktree_root`, `in_nested_subdir` -**Text mode (`workflow.text_mode: true` in config or `--text` flag):** When `TEXT_MODE` is active, replace every `AskUserQuestion` call in this workflow with a plain-text numbered list and ask the user to type their choice number. This is required for non-Claude runtimes (OpenAI Codex, Gemini CLI, etc.) where `AskUserQuestion` is not available and would otherwise render as an inert code block. +Set: +- `TEXT_MODE=true` if `--text` is present or `text_mode` is true. +- `ONBOARDING_ROOT={git_worktree_root || _GSD_RUNTIME_ROOT}`. -## 2. Git and Existing Planning Safety +If `has_git` and `in_nested_subdir` are true, warn that onboarding artifacts belong to the outer worktree at `git_worktree_root`. Do not run `git init`. -If `has_git` is true and `in_nested_subdir` is true, warn that onboarding artifacts will -belong to the outer worktree at `git_worktree_root`. Do not run `git init` here. +## 2. Execute `next_action` -If `planning_exists` is true, do not overwrite PROJECT/ROADMAP/STATE. Onboarding is -idempotent and must only confirm or summarize existing files unless the user explicitly -runs the lower-level refresh commands. +### `map-codebase` -## 3. Codebase Mapping Gate - -If `is_brownfield` is true and `CODEBASE_MAP_READY` is false: +If `next_action.kind == "map-codebase"`: - If `TEXT_MODE=true`, print: ```text -Existing code was detected, but the required .planning/codebase/ map is missing. -Missing map files: {--fast ? missing_fast_codebase_map_files : missing_codebase_map_files} +{next_action.reason} +Missing map files: {fast_mode ? missing_fast_codebase_map_files : missing_codebase_map_files} -1. Map codebase first — run {MAP_COMMAND} from worktree root {git_worktree_root || _GSD_RUNTIME_ROOT} to understand the repo before project setup (Recommended) +1. Map codebase first — run {next_action.command} from worktree root {ONBOARDING_ROOT} (Recommended) 2. Skip mapping — continue with weaker onboarding context Enter number: ``` -Stop and wait for the user's reply. - - Otherwise use AskUserQuestion: - header: "Codebase" - - question: "Existing code was detected, but the required .planning/codebase/ map is missing. Map it first?" + - question: "{next_action.reason} Map it first?" - options: - - "Map codebase first" — Run `{MAP_COMMAND}` from worktree root `{git_worktree_root || _GSD_RUNTIME_ROOT}` to understand the repo before project setup (Recommended) + - "Map codebase first" — Run `{next_action.command}` from worktree root `{ONBOARDING_ROOT}` (Recommended) - "Skip mapping" — Continue with weaker onboarding context -If the user chooses mapping, do not nest the interactive map-codebase workflow. Print: +If the user chooses mapping, do not nest the interactive workflow. Print: ```text -Run from worktree root {git_worktree_root || _GSD_RUNTIME_ROOT}: +Run from worktree root {ONBOARDING_ROOT}: -{MAP_COMMAND} +{next_action.command} Then rerun /gsd:onboard from the same worktree root. ``` -Exit. +Exit. If the user skips mapping, continue with a warning. -If the user skips mapping, continue with a warning. +### `ingest-docs` -If `is_brownfield` is false and `planning_exists` is false and `has_docs_candidates` is false, print: - -```text -No existing code was detected. For a greenfield project, run: - -Run from worktree root {git_worktree_root || _GSD_RUNTIME_ROOT}: - -/gsd:new-project -``` - -Exit. - -## 4. Existing Docs Gate - -If `has_docs_candidates` is true and `project_exists` is false: +If `next_action.kind == "ingest-docs"`: - If `TEXT_MODE=true`, print: ```text +{next_action.reason} Detected {doc_candidate_count} possible ADR/PRD/SPEC/RFC document(s). -1. Ingest docs first — run /gsd:ingest-docs from worktree root {git_worktree_root || _GSD_RUNTIME_ROOT} to bootstrap planning from existing docs (Recommended) +1. Ingest docs first — run {next_action.command} from worktree root {ONBOARDING_ROOT} (Recommended) 2. Skip docs ingest — continue to /gsd:new-project Enter number: ``` -Stop and wait for the user's reply. - - Otherwise use AskUserQuestion: - header: "Docs" - question: "Detected {doc_candidate_count} possible ADR/PRD/SPEC/RFC document(s). Ingest them first?" - options: - - "Ingest docs first" — Run `/gsd:ingest-docs` from worktree root `{git_worktree_root || _GSD_RUNTIME_ROOT}` to bootstrap planning from existing docs (Recommended) + - "Ingest docs first" — Run `{next_action.command}` from worktree root `{ONBOARDING_ROOT}` (Recommended) - "Skip docs ingest" — Continue to `/gsd:new-project` -If the user chooses ingest, do not nest the interactive ingest-docs workflow. Print: +If the user chooses ingest, print: ```text -Run from worktree root {git_worktree_root || _GSD_RUNTIME_ROOT}: +Run from worktree root {ONBOARDING_ROOT}: -/gsd:ingest-docs +{next_action.command} + +Then rerun /gsd:onboard from the same worktree root. +``` + +Exit. If the user skips docs ingest, continue to the new-project handoff below. + +### `complete-map-before-new-project` + +If `next_action.kind == "complete-map-before-new-project"`, print: + +```text +{next_action.reason} + +Run from worktree root {ONBOARDING_ROOT}: + +{next_action.command} Then rerun /gsd:onboard from the same worktree root. ``` Exit. -## 5. Project Initialization Gate +### `new-project` -If `project_exists` is false and `fast_mode && has_fast_codebase_map && !has_codebase_map` is true: - -Print: +If `next_action.kind == "new-project"`, print: ```text -Fast codebase context is accepted for onboarding, but /gsd:new-project still requires the complete codebase map. +{next_action.reason} -Run from worktree root {git_worktree_root || _GSD_RUNTIME_ROOT}: +Run from worktree root {ONBOARDING_ROOT}: -/gsd:map-codebase - -Then rerun /gsd:onboard from the same worktree root. +{next_action.command} ``` Exit. -If `project_exists` is false: +### `partial-planning` -Print: +If `next_action.kind == "partial-planning"`, print: ```text -Codebase context is ready for project initialization. +Project planning exists but is incomplete. -Run from worktree root {git_worktree_root || _GSD_RUNTIME_ROOT}: +Missing files: {next_action.missing} +REQUIREMENTS.md: {requirements_exists ? "present" : "missing"} +ROADMAP.md: {roadmap_exists ? "present" : "missing"} +STATE.md: {state_exists ? "present" : "missing"} -/gsd:new-project - -Then rerun /gsd:onboard from the same worktree root. +Run the appropriate lower-level command to fill the missing planning artifact(s), then rerun /gsd:onboard. ``` Exit. -If `project_exists` is true and either `requirements_exists`, `roadmap_exists`, or -`state_exists` is false, print: +### `ready` -```text -Existing PROJECT.md was found, but planning is incomplete. +If `next_action.kind == "ready"`, print the final status section and exit. -Planning file status: -- REQUIREMENTS.md: {requirements_exists ? "present" : "missing"} -- ROADMAP.md: {roadmap_exists ? "present" : "missing"} -- STATE.md: {state_exists ? "present" : "missing"} +### `write-summary` -Run one of these top-level commands from worktree root {git_worktree_root || _GSD_RUNTIME_ROOT}: +If `next_action.kind == "write-summary"`, continue to summary creation. -/gsd:ingest-docs --mode merge -/gsd:new-milestone +## 3. Create Onboarding Summary -Then rerun /gsd:onboard from the same worktree root. -``` +Create `{ONBOARDING_ROOT}/{next_action.summary_path}`. Do not overwrite an existing summary; the projection should only route here when the summary is missing. -Exit. Do not write `.planning/onboarding/SUMMARY.md` and do not print the onboarding -complete status for partial planning. - -If `project_exists`, `requirements_exists`, `roadmap_exists`, and `state_exists` are all -true, continue. - -## 6. Write Onboarding Summary - -Resolve `ONBOARDING_ROOT={git_worktree_root || _GSD_RUNTIME_ROOT}` before this step. -Use `ONBOARDING_ROOT` for every filesystem write and commit in this step so nested-cwd -invocations do not create `subdir/.planning` artifacts. - -Create `{ONBOARDING_ROOT}/.planning/onboarding/SUMMARY.md` only after PROJECT.md exists. -If it already exists, update it only after confirmation; do not overwrite silently. - -Before summary keep/update choices, derive map status values safely: - -- If `has_codebase_map` is true: - - `CODEBASE_MAP_SUMMARY_STATUS=.planning/codebase/ (complete)` - - `CODEBASE_MAP_FINAL_STATUS=(complete)` -- Else if `fast_mode && has_fast_codebase_map` is true: - - `CODEBASE_MAP_SUMMARY_STATUS=.planning/codebase/ (fast/partial-but-accepted codebase map)` - - `CODEBASE_MAP_FINAL_STATUS=(fast/partial-but-accepted; required fast files present)` -- Else: - - `CODEBASE_MAP_SUMMARY_STATUS=.planning/codebase/ (incomplete or skipped)` - - `CODEBASE_MAP_FINAL_STATUS=(incomplete or skipped; missing: {missing_codebase_map_files})` - -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: +Summary template: ```markdown # Onboarding Summary -**Generated:** {YYYY-MM-DD} -**Status:** Ready for GSD workflow +## Project State +- PROJECT.md: {project_exists ? "present" : "missing"} +- REQUIREMENTS.md: {requirements_exists ? "present" : "missing"} +- ROADMAP.md: {roadmap_exists ? "present" : "missing"} +- STATE.md: {state_exists ? "present" : "missing"} -## Artifact Status +## Codebase Context +- Brownfield repo: {is_brownfield ? "yes" : "no"} +- Map readiness: {map_readiness} +- Codebase map: {codebase_map_summary_status} +- Fast map available: {has_fast_codebase_map ? "yes" : "no"} -- Project: .planning/PROJECT.md -- Requirements: .planning/REQUIREMENTS.md -- Roadmap: .planning/ROADMAP.md -- State: .planning/STATE.md -- Codebase map: {CODEBASE_MAP_SUMMARY_STATUS} - -## Codebase Map - -{if has_codebase_map} -Confirmed files: -- STACK.md -- ARCHITECTURE.md -- STRUCTURE.md -- CONVENTIONS.md -- TESTING.md -- INTEGRATIONS.md -- CONCERNS.md -{else if fast_mode && has_fast_codebase_map} -Accepted fast map files: -- STACK.md -- INTEGRATIONS.md -- ARCHITECTURE.md -- STRUCTURE.md -Context strength: fast/partial-but-accepted codebase map; not all seven map files are present. -{else} -Present files: {codebase_map_files_present} -Missing files: {missing_codebase_map_files} -Context strength: weaker because codebase mapping was skipped or is incomplete. -{endif} - -## Existing Docs - -Detected planning docs: {doc_candidate_count} +## Docs Context +- Existing ADR/PRD/SPEC/RFC candidates: {has_docs_candidates ? doc_candidate_count : 0} ## Recommended Next Step - -/gsd:discuss-phase 1 +- {next_action.reason} ``` -Commit the summary if `commit_docs` is true: +If `commit_docs` is true, commit only the summary path from the onboarding root: ```bash gsd_run --cwd "$ONBOARDING_ROOT" query commit "docs: create onboarding summary" --files .planning/onboarding/SUMMARY.md ``` -## 7. Final Status +Continue to final status. + +## 4. Final Status Print: -``` -━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - GSD ► ONBOARDING COMPLETE ✓ -━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ +```text +Onboarding status: +- PROJECT.md: {project_exists ? "present" : "missing"} +- REQUIREMENTS.md: {requirements_exists ? "present" : "missing"} +- ROADMAP.md: {roadmap_exists ? "present" : "missing"} +- STATE.md: {state_exists ? "present" : "missing"} +- Codebase map: {codebase_map_final_status} +- Onboarding summary: present -Created / confirmed / status: -- .planning/codebase/ {CODEBASE_MAP_FINAL_STATUS} -- .planning/PROJECT.md -- .planning/REQUIREMENTS.md {requirements_exists ? "(present)" : "(missing; onboarding incomplete)"} -- .planning/ROADMAP.md -- .planning/STATE.md -- .planning/onboarding/SUMMARY.md - -─────────────────────────────────────────────────────────────── - -## ▶ Next Up - -**Discuss Phase 1** — capture implementation decisions before planning. - -`/gsd:discuss-phase 1` - -─────────────────────────────────────────────────────────────── - -**Also available:** -- `/gsd:map-codebase` — refresh the codebase map after significant changes -- `/gsd:ingest-docs --mode merge` — merge new ADR/PRD/SPEC docs into planning -- `/gsd:progress` — inspect current workflow state - -─────────────────────────────────────────────────────────────── +Next recommended command: /gsd:manager ``` - - - -- [ ] Existing codebase detected before project initialization -- [ ] Missing codebase map routes to `/gsd:map-codebase` or `/gsd:map-codebase --fast` -- [ ] Existing planning docs route to `/gsd:ingest-docs` -- [ ] Missing project setup routes to `/gsd:new-project` -- [ ] Existing `.planning/` files are not overwritten silently -- [ ] Text mode stops and waits at numbered-list gates -- [ ] `.planning/onboarding/SUMMARY.md` is created only after PROJECT.md exists -- [ ] User sees next command - +Do not run implementation execution or shipping from onboarding. diff --git a/src/init.cts b/src/init.cts index 853e186cf..5c781ba25 100644 --- a/src/init.cts +++ b/src/init.cts @@ -51,6 +51,15 @@ const { checkAgentsInstalled } = agentInstallCheck; import gitBaseBranch = require('./git-base-branch.cjs'); const { gitWorktreeInfoInternal } = gitBaseBranch; import { makeResolution } from './resolution.cjs'; +// eslint-disable-next-line @typescript-eslint/no-require-imports -- onboard-projection.cjs is an export= CommonJS module +import onboardProjection = require('./onboard-projection.cjs'); +const { + REQUIRED_CODEBASE_MAP_FILES, + buildOnboardProjection, + hasCodeFilesInternal, + hasPackageFileInternal, + listCodebaseMapFiles, +} = onboardProjection; const { output, error } = io; const { loadConfig, loadConfigResolved } = configLoader; @@ -86,130 +95,6 @@ void stripShippedMilestones; // Accept all bold/colon variants of the Requirements header (#2769) const REQUIREMENTS_HEADER_RE = /^\*\*Requirements:?\*\*[^\S\n]*:?[^\S\n]*([^\n]*)$/m; -const CODE_EXTENSIONS = new Set([ - '.ts', '.tsx', '.js', '.jsx', '.mjs', '.cjs', '.py', '.go', '.rs', '.swift', '.java', - '.kt', '.kts', '.c', '.cpp', '.cc', '.h', '.hpp', '.cs', '.rb', '.php', '.dart', - '.m', '.mm', '.scala', '.groovy', '.lua', '.r', '.R', '.zig', '.ex', '.exs', '.clj', -]); - -const CODE_SCAN_SKIP_DIRS = new Set([ - 'node_modules', '.git', '.planning', '.claude', '.codex', '__pycache__', 'target', - 'dist', 'build', '.next', '.nuxt', '.svelte-kit', 'coverage', 'vendor', '.venv', 'venv', -]); - -const PACKAGE_FILES = [ - 'package.json', 'requirements.txt', 'pyproject.toml', 'Cargo.toml', 'go.mod', - 'Package.swift', 'build.gradle', 'build.gradle.kts', 'pom.xml', 'Gemfile', - 'composer.json', 'pubspec.yaml', 'CMakeLists.txt', 'Makefile', 'build.zig', - 'mix.exs', 'project.clj', -]; - -const REQUIRED_CODEBASE_MAP_FILES = [ - 'STACK.md', 'ARCHITECTURE.md', 'STRUCTURE.md', 'CONVENTIONS.md', 'TESTING.md', - 'INTEGRATIONS.md', 'CONCERNS.md', -]; - -const FAST_CODEBASE_MAP_FILES = [ - 'STACK.md', 'INTEGRATIONS.md', 'ARCHITECTURE.md', 'STRUCTURE.md', -]; - -const PLANNING_DOC_SEGMENTS = new Set([ - 'adr', 'adrs', 'prd', 'prds', 'spec', 'specs', 'rfc', 'rfcs', -]); - -function hasCodeFilesInternal(dir: string, depth = 0): boolean { - if (depth > 3) return false; - let entries: fs.Dirent[]; - try { - entries = fs.readdirSync(dir, { withFileTypes: true }); - } catch { - return false; - } - - for (const entry of entries) { - if (entry.isFile() && CODE_EXTENSIONS.has(path.extname(entry.name))) return true; - if (entry.isDirectory() && !CODE_SCAN_SKIP_DIRS.has(entry.name)) { - if (hasCodeFilesInternal(path.join(dir, entry.name), depth + 1)) return true; - } - } - - return false; -} - -function hasPackageFileInternal(cwd: string): boolean { - return PACKAGE_FILES.some((file) => pathExistsInternal(cwd, file)); -} - -function listPlanningDocCandidates(cwd: string): string[] { - const roots = ['docs', 'adr', 'adrs', 'prd', 'prds', 'spec', 'specs', 'rfc', 'rfcs']; - const candidates = new Set(); - - const isPlanningDocCandidate = (rel: string, name: string): boolean => { - const upperName = name.toUpperCase(); - const relLower = rel.toLowerCase(); - const pathSegments = relLower.split('/'); - return ( - /(^|[-_ ])(ADR|PRD|SPEC|RFC)([-_ ]|\.)/i.test(name) || - /^\d{4}[-_].+\.md$/i.test(name) || - pathSegments.some((segment) => PLANNING_DOC_SEGMENTS.has(segment)) || - upperName === 'REQUIREMENTS.MD' - ); - }; - - const addCandidate = (rel: string, name: string): void => { - if (name.toLowerCase().endsWith('.md') && isPlanningDocCandidate(rel, name)) { - candidates.add(toPosixPath(rel)); - } - }; - - const visit = (dir: string, relDir: string, depth: number): void => { - if (depth > 3) return; - let entries: fs.Dirent[]; - try { - entries = fs.readdirSync(dir, { withFileTypes: true }); - } catch { - return; - } - - for (const entry of entries) { - const rel = relDir ? `${relDir}/${entry.name}` : entry.name; - if (entry.isDirectory()) { - if (!CODE_SCAN_SKIP_DIRS.has(entry.name)) { - visit(path.join(dir, entry.name), rel, depth + 1); - } - continue; - } - - if (entry.isFile()) addCandidate(rel, entry.name); - } - }; - - let rootEntries: fs.Dirent[] = []; - try { - rootEntries = fs.readdirSync(cwd, { withFileTypes: true }); - } catch { - rootEntries = []; - } - for (const entry of rootEntries) { - if (entry.isFile()) addCandidate(entry.name, entry.name); - } - - for (const root of roots) { - const full = path.join(cwd, root); - if (fs.existsSync(full)) visit(full, root, 0); - } - - return [...candidates].sort(); -} - -function listCodebaseMapFiles(cwd: string): string[] { - const codebaseDir = path.join(planningRoot(cwd), 'codebase'); - if (!fs.existsSync(codebaseDir)) return []; - return REQUIRED_CODEBASE_MAP_FILES.filter((file) => - fs.existsSync(path.join(codebaseDir, file)), - ); -} - function listPhaseSummaryFiles(phaseDir: string): string[] { return (scanPhasePlans(phaseDir) as unknown as Record)['summaryFiles']; } @@ -912,65 +797,13 @@ function cmdInitOnboard( options: Record = {}, ): void { const config = loadConfig(cwd); - const codebaseMapFiles = listCodebaseMapFiles(cwd); - const missingCodebaseMapFiles = REQUIRED_CODEBASE_MAP_FILES.filter( - (file) => !codebaseMapFiles.includes(file), - ); - const missingFastCodebaseMapFiles = FAST_CODEBASE_MAP_FILES.filter( - (file) => !codebaseMapFiles.includes(file), - ); - const docCandidates = listPlanningDocCandidates(cwd); - const hasCode = hasCodeFilesInternal(cwd); - const hasPackageFile = hasPackageFileInternal(cwd); - const isBrownfield = hasCode || hasPackageFile; - const hasCodebaseMap = codebaseMapFiles.length === REQUIRED_CODEBASE_MAP_FILES.length; - const fastMode = options['fast'] === true; - const hasFastCodebaseMap = missingFastCodebaseMapFiles.length === 0; - const needsCodebaseMap = isBrownfield && ( - fastMode ? !hasFastCodebaseMap : !hasCodebaseMap - ); - - const result: Record = { - commit_docs: config.commit_docs, - text_mode: - !!config.text_mode || !!((config.workflow ?? {}) as Record)['text_mode'], - - project_exists: pathExistsInternal(cwd, '.planning/PROJECT.md'), - planning_exists: fs.existsSync(planningRoot(cwd)), - requirements_exists: fs.existsSync(path.join(planningDir(cwd), 'REQUIREMENTS.md')), - roadmap_exists: fs.existsSync(path.join(planningDir(cwd), 'ROADMAP.md')), - state_exists: fs.existsSync(path.join(planningDir(cwd), 'STATE.md')), - config_exists: fs.existsSync(path.join(planningDir(cwd), 'config.json')), - - has_existing_code: hasCode, - has_package_file: hasPackageFile, - is_brownfield: isBrownfield, - fast_mode: fastMode, - needs_codebase_map: needsCodebaseMap, - has_codebase_map: hasCodebaseMap, - has_fast_codebase_map: hasFastCodebaseMap, - codebase_dir_exists: fs.existsSync(path.join(planningRoot(cwd), 'codebase')), - fast_codebase_map_files_required: FAST_CODEBASE_MAP_FILES, - codebase_map_files_present: codebaseMapFiles, - missing_codebase_map_files: missingCodebaseMapFiles, - missing_fast_codebase_map_files: missingFastCodebaseMapFiles, - - has_docs_candidates: docCandidates.length > 0, - doc_candidate_count: docCandidates.length, - doc_candidates: docCandidates, - - onboarding_summary_exists: pathExistsInternal(cwd, '.planning/onboarding/SUMMARY.md'), - onboarding_summary_path: '.planning/onboarding/SUMMARY.md', - - project_path: '.planning/PROJECT.md', - requirements_path: toPosixPath( - path.relative(cwd, path.join(planningDir(cwd), 'REQUIREMENTS.md')), - ), - roadmap_path: toPosixPath(path.relative(cwd, path.join(planningDir(cwd), 'ROADMAP.md'))), - state_path: toPosixPath(path.relative(cwd, path.join(planningDir(cwd), 'STATE.md'))), - codebase_dir: toPosixPath(path.relative(cwd, path.join(planningRoot(cwd), 'codebase'))), - onboarding_dir: toPosixPath(path.relative(cwd, path.join(planningRoot(cwd), 'onboarding'))), - + const workflowConfig = (config.workflow ?? {}) as Record; + const result = { + ...buildOnboardProjection(cwd, { + commitDocs: !!config.commit_docs, + fast: options['fast'] === true, + textMode: !!config.text_mode || !!workflowConfig['text_mode'], + }), ...getInitGitState(cwd), }; diff --git a/src/onboard-projection.cts b/src/onboard-projection.cts new file mode 100644 index 000000000..26ba11305 --- /dev/null +++ b/src/onboard-projection.cts @@ -0,0 +1,383 @@ +import fs from 'node:fs'; +import path from 'node:path'; + +// eslint-disable-next-line @typescript-eslint/no-require-imports -- core-utils.cjs is an export= CommonJS module +import coreUtils = require('./core-utils.cjs'); +// eslint-disable-next-line @typescript-eslint/no-require-imports -- planning-workspace.cjs is an export= CommonJS module +import planningWorkspace = require('./planning-workspace.cjs'); + +const { pathExistsInternal, toPosixPath } = coreUtils; +const { planningDir, planningRoot } = planningWorkspace; + +const CODE_EXTENSIONS = new Set([ + '.ts', '.tsx', '.js', '.jsx', '.mjs', '.cjs', '.py', '.go', '.rs', '.swift', '.java', + '.kt', '.kts', '.c', '.cpp', '.cc', '.h', '.hpp', '.cs', '.rb', '.php', '.dart', + '.m', '.mm', '.scala', '.groovy', '.lua', '.r', '.R', '.zig', '.ex', '.exs', '.clj', +]); + +const CODE_SCAN_SKIP_DIRS = new Set([ + 'node_modules', '.git', '.planning', '.claude', '.codex', '__pycache__', 'target', + 'dist', 'build', '.next', '.nuxt', '.svelte-kit', 'coverage', 'vendor', '.venv', 'venv', +]); + +const PACKAGE_FILES = [ + 'package.json', 'requirements.txt', 'pyproject.toml', 'Cargo.toml', 'go.mod', + 'Package.swift', 'build.gradle', 'build.gradle.kts', 'pom.xml', 'Gemfile', + 'composer.json', 'pubspec.yaml', 'CMakeLists.txt', 'Makefile', 'build.zig', + 'mix.exs', 'project.clj', +]; + +const REQUIRED_CODEBASE_MAP_FILES = [ + 'STACK.md', 'ARCHITECTURE.md', 'STRUCTURE.md', 'CONVENTIONS.md', 'TESTING.md', + 'INTEGRATIONS.md', 'CONCERNS.md', +]; + +const FAST_CODEBASE_MAP_FILES = [ + 'STACK.md', 'INTEGRATIONS.md', 'ARCHITECTURE.md', 'STRUCTURE.md', +]; + +const PLANNING_DOC_SEGMENTS = new Set([ + 'adr', 'adrs', 'prd', 'prds', 'spec', 'specs', 'rfc', 'rfcs', +]); + +type MapReadiness = 'none' | 'fast' | 'complete'; + +type OnboardNextAction = + | { kind: 'map-codebase'; command: string; reason: string } + | { kind: 'ingest-docs'; command: string; reason: string } + | { kind: 'new-project'; command: string; reason: string } + | { kind: 'complete-map-before-new-project'; command: string; reason: string } + | { kind: 'partial-planning'; missing: string[]; reason: string } + | { kind: 'write-summary'; summary_path: string; reason: string } + | { kind: 'ready'; reason: string }; + +interface BuildOnboardProjectionOptions { + commitDocs: boolean; + fast: boolean; + textMode: boolean; +} + +interface OnboardProjection { + commit_docs: boolean; + text_mode: boolean; + + project_exists: boolean; + planning_exists: boolean; + requirements_exists: boolean; + roadmap_exists: boolean; + state_exists: boolean; + config_exists: boolean; + + has_existing_code: boolean; + has_package_file: boolean; + is_brownfield: boolean; + fast_mode: boolean; + map_readiness: MapReadiness; + next_action: OnboardNextAction; + needs_codebase_map: boolean; + has_codebase_map: boolean; + has_fast_codebase_map: boolean; + codebase_dir_exists: boolean; + fast_codebase_map_files_required: string[]; + codebase_map_files_present: string[]; + missing_codebase_map_files: string[]; + missing_fast_codebase_map_files: string[]; + codebase_map_summary_status: string; + codebase_map_final_status: string; + + has_docs_candidates: boolean; + doc_candidate_count: number; + doc_candidates: string[]; + + onboarding_summary_exists: boolean; + onboarding_summary_path: string; + + project_path: string; + requirements_path: string; + roadmap_path: string; + state_path: string; + codebase_dir: string; + onboarding_dir: string; +} + +function hasCodeFilesInternal(dir: string, depth = 0): boolean { + if (depth > 3) return false; + let entries: fs.Dirent[]; + try { + entries = fs.readdirSync(dir, { withFileTypes: true }); + } catch { + return false; + } + + for (const entry of entries) { + if (entry.isFile() && CODE_EXTENSIONS.has(path.extname(entry.name))) return true; + if (entry.isDirectory() && !CODE_SCAN_SKIP_DIRS.has(entry.name)) { + if (hasCodeFilesInternal(path.join(dir, entry.name), depth + 1)) return true; + } + } + + return false; +} + +function hasPackageFileInternal(cwd: string): boolean { + return PACKAGE_FILES.some((file) => pathExistsInternal(cwd, file)); +} + +function listPlanningDocCandidates(cwd: string): string[] { + const roots = ['docs', 'adr', 'adrs', 'prd', 'prds', 'spec', 'specs', 'rfc', 'rfcs']; + const candidates = new Set(); + + function isPlanningDocCandidate(rel: string, name: string): boolean { + const upperName = name.toUpperCase(); + const relLower = rel.toLowerCase(); + const pathSegments = relLower.split('/'); + return ( + /(^|[-_ ])(ADR|PRD|SPEC|RFC)([-_ ]|\.)/i.test(name) || + /^\d{4}[-_].+\.md$/i.test(name) || + pathSegments.some((segment) => PLANNING_DOC_SEGMENTS.has(segment)) || + upperName === 'REQUIREMENTS.MD' + ); + } + + function addCandidate(rel: string, name: string): void { + if (name.toLowerCase().endsWith('.md') && isPlanningDocCandidate(rel, name)) { + candidates.add(toPosixPath(rel)); + } + } + + function visit(dir: string, relDir: string, depth: number): void { + if (depth > 3) return; + let entries: fs.Dirent[]; + try { + entries = fs.readdirSync(dir, { withFileTypes: true }); + } catch { + return; + } + + for (const entry of entries) { + const rel = relDir ? `${relDir}/${entry.name}` : entry.name; + if (entry.isDirectory()) { + if (!CODE_SCAN_SKIP_DIRS.has(entry.name)) { + visit(path.join(dir, entry.name), rel, depth + 1); + } + continue; + } + + if (entry.isFile()) addCandidate(rel, entry.name); + } + } + + let rootEntries: fs.Dirent[] = []; + try { + rootEntries = fs.readdirSync(cwd, { withFileTypes: true }); + } catch { + rootEntries = []; + } + + for (const entry of rootEntries) { + if (entry.isFile()) addCandidate(entry.name, entry.name); + } + + for (const root of roots) { + const full = path.join(cwd, root); + if (fs.existsSync(full)) visit(full, root, 0); + } + + return [...candidates].sort(); +} + +function listCodebaseMapFiles(cwd: string): string[] { + const codebaseDir = path.join(planningRoot(cwd), 'codebase'); + if (!fs.existsSync(codebaseDir)) return []; + return REQUIRED_CODEBASE_MAP_FILES.filter((file) => + fs.existsSync(path.join(codebaseDir, file)), + ); +} + +function getMapReadiness(hasCompleteMap: boolean, hasFastMap: boolean): MapReadiness { + if (hasCompleteMap) return 'complete'; + if (hasFastMap) return 'fast'; + return 'none'; +} + +function mapSummaryStatus(mapReadiness: MapReadiness): string { + if (mapReadiness === 'complete') return '.planning/codebase/ (complete codebase map)'; + if (mapReadiness === 'fast') return '.planning/codebase/ (fast/partial codebase map; complete map still required for project setup)'; + return 'missing'; +} + +function mapFinalStatus(mapReadiness: MapReadiness): string { + if (mapReadiness === 'complete') return 'complete'; + if (mapReadiness === 'fast') return 'fast/partial; complete map still required for project setup'; + return 'missing'; +} + +function planningMissing(requirementsExists: boolean, roadmapExists: boolean, stateExists: boolean): string[] { + const missing: string[] = []; + if (!requirementsExists) missing.push('REQUIREMENTS.md'); + if (!roadmapExists) missing.push('ROADMAP.md'); + if (!stateExists) missing.push('STATE.md'); + return missing; +} + +function nextAction(params: { + fastMode: boolean; + isBrownfield: boolean; + needsCodebaseMap: boolean; + hasDocsCandidates: boolean; + projectExists: boolean; + mapReadiness: MapReadiness; + onboardingSummaryExists: boolean; + missingPlanningFiles: string[]; +}): OnboardNextAction { + if (params.isBrownfield && params.needsCodebaseMap) { + return { + kind: 'map-codebase', + command: params.fastMode ? '/gsd:map-codebase --fast' : '/gsd:map-codebase', + reason: 'Existing code was detected, but the required .planning/codebase/ map is missing.', + }; + } + + if (params.hasDocsCandidates && !params.projectExists) { + return { + kind: 'ingest-docs', + command: '/gsd:ingest-docs', + reason: 'Detected existing ADR/PRD/SPEC/RFC document(s) before project setup.', + }; + } + + if (!params.isBrownfield && !params.projectExists && !params.hasDocsCandidates) { + return { + kind: 'new-project', + command: '/gsd:new-project', + reason: 'No existing code or planning docs were detected.', + }; + } + + if (!params.projectExists && params.fastMode && params.mapReadiness === 'fast') { + return { + kind: 'complete-map-before-new-project', + command: '/gsd:map-codebase', + reason: 'The fast map is enough for lightweight onboarding, but project setup still requires the complete codebase map.', + }; + } + + if (!params.projectExists) { + return { + kind: 'new-project', + command: '/gsd:new-project', + reason: 'Codebase context is ready for project initialization.', + }; + } + + if (params.missingPlanningFiles.length > 0) { + return { + kind: 'partial-planning', + missing: params.missingPlanningFiles, + reason: 'Project planning exists but required planning files are missing.', + }; + } + + if (!params.onboardingSummaryExists) { + return { + kind: 'write-summary', + summary_path: '.planning/onboarding/SUMMARY.md', + reason: 'Onboarding summary is missing.', + }; + } + + return { + kind: 'ready', + reason: 'Onboarding summary already exists.', + }; +} + +function buildOnboardProjection(cwd: string, options: BuildOnboardProjectionOptions): OnboardProjection { + const codebaseMapFiles = listCodebaseMapFiles(cwd); + const missingCodebaseMapFiles = REQUIRED_CODEBASE_MAP_FILES.filter( + (file) => !codebaseMapFiles.includes(file), + ); + const missingFastCodebaseMapFiles = FAST_CODEBASE_MAP_FILES.filter( + (file) => !codebaseMapFiles.includes(file), + ); + const docCandidates = listPlanningDocCandidates(cwd); + const hasCode = hasCodeFilesInternal(cwd); + const hasPackageFile = hasPackageFileInternal(cwd); + const isBrownfield = hasCode || hasPackageFile; + const hasCodebaseMap = codebaseMapFiles.length === REQUIRED_CODEBASE_MAP_FILES.length; + const hasFastCodebaseMap = missingFastCodebaseMapFiles.length === 0; + const mapReadinessValue = getMapReadiness(hasCodebaseMap, hasFastCodebaseMap); + const needsCodebaseMap = isBrownfield && ( + options.fast ? !hasFastCodebaseMap : !hasCodebaseMap + ); + const projectExists = pathExistsInternal(cwd, '.planning/PROJECT.md'); + 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 missingPlanningFiles = planningMissing(requirementsExists, roadmapExists, stateExists); + + return { + commit_docs: options.commitDocs, + text_mode: options.textMode, + + project_exists: projectExists, + planning_exists: fs.existsSync(planningRoot(cwd)), + requirements_exists: requirementsExists, + roadmap_exists: roadmapExists, + state_exists: stateExists, + config_exists: fs.existsSync(path.join(planningDir(cwd), 'config.json')), + + has_existing_code: hasCode, + has_package_file: hasPackageFile, + is_brownfield: isBrownfield, + fast_mode: options.fast, + map_readiness: mapReadinessValue, + next_action: nextAction({ + fastMode: options.fast, + isBrownfield, + needsCodebaseMap, + hasDocsCandidates: docCandidates.length > 0, + projectExists, + mapReadiness: mapReadinessValue, + onboardingSummaryExists, + missingPlanningFiles, + }), + needs_codebase_map: needsCodebaseMap, + has_codebase_map: hasCodebaseMap, + has_fast_codebase_map: hasFastCodebaseMap, + codebase_dir_exists: fs.existsSync(path.join(planningRoot(cwd), 'codebase')), + fast_codebase_map_files_required: FAST_CODEBASE_MAP_FILES, + codebase_map_files_present: codebaseMapFiles, + missing_codebase_map_files: missingCodebaseMapFiles, + missing_fast_codebase_map_files: missingFastCodebaseMapFiles, + codebase_map_summary_status: mapSummaryStatus(mapReadinessValue), + codebase_map_final_status: mapFinalStatus(mapReadinessValue), + + has_docs_candidates: docCandidates.length > 0, + doc_candidate_count: docCandidates.length, + doc_candidates: docCandidates, + + onboarding_summary_exists: onboardingSummaryExists, + onboarding_summary_path: '.planning/onboarding/SUMMARY.md', + + project_path: '.planning/PROJECT.md', + requirements_path: toPosixPath( + path.relative(cwd, path.join(planningDir(cwd), 'REQUIREMENTS.md')), + ), + roadmap_path: toPosixPath(path.relative(cwd, path.join(planningDir(cwd), 'ROADMAP.md'))), + state_path: toPosixPath(path.relative(cwd, path.join(planningDir(cwd), 'STATE.md'))), + codebase_dir: toPosixPath(path.relative(cwd, path.join(planningRoot(cwd), 'codebase'))), + onboarding_dir: toPosixPath(path.relative(cwd, path.join(planningRoot(cwd), 'onboarding'))), + }; +} + +export = { + REQUIRED_CODEBASE_MAP_FILES, + FAST_CODEBASE_MAP_FILES, + buildOnboardProjection, + hasCodeFilesInternal, + hasPackageFileInternal, + listCodebaseMapFiles, + listPlanningDocCandidates, +}; diff --git a/tests/onboard-command.test.cjs b/tests/onboard-command.test.cjs index 2201b3730..30bb98716 100644 --- a/tests/onboard-command.test.cjs +++ b/tests/onboard-command.test.cjs @@ -138,7 +138,7 @@ describe('init onboard public CLI projection', () => { assert.strictEqual(parsed.text_mode, true); }); - test('reports fast codebase map readiness for the default fast subset', () => { + test('reports fast codebase map readiness and a complete-map handoff before new-project', () => { fs.mkdirSync(path.join(tmpDir, '.planning', 'codebase'), { recursive: true }); for (const name of ['STACK', 'INTEGRATIONS', 'ARCHITECTURE', 'STRUCTURE']) { fs.writeFileSync(path.join(tmpDir, '.planning', 'codebase', `${name}.md`), `# ${name}\n`); @@ -149,9 +149,13 @@ describe('init onboard public CLI projection', () => { assert.ok(result.success, `init onboard should succeed: ${result.error}`); const parsed = JSON.parse(result.output); + assert.strictEqual(parsed.map_readiness, 'fast'); assert.strictEqual(parsed.has_codebase_map, false); assert.strictEqual(parsed.has_fast_codebase_map, true); assert.strictEqual(parsed.needs_codebase_map, false); + assert.strictEqual(parsed.next_action.kind, 'complete-map-before-new-project'); + assert.strictEqual(parsed.next_action.command, '/gsd:map-codebase'); + assert.match(parsed.next_action.reason, /complete codebase map/i); assert.deepStrictEqual(parsed.fast_codebase_map_files_required, [ 'STACK.md', 'INTEGRATIONS.md', @@ -161,6 +165,74 @@ describe('init onboard public CLI projection', () => { assert.deepStrictEqual(parsed.missing_fast_codebase_map_files, []); }); + test('projects the next action for code, docs, greenfield, partial planning, and summary states', () => { + fs.mkdirSync(path.join(tmpDir, 'src'), { recursive: true }); + fs.writeFileSync(path.join(tmpDir, 'src', 'server.ts'), 'export const server = true;\n'); + let result = runGsdTools('init onboard --raw', tmpDir, { HOME: tmpDir }); + assert.ok(result.success, `init onboard should succeed: ${result.error}`); + assert.deepStrictEqual(JSON.parse(result.output).next_action, { + kind: 'map-codebase', + command: '/gsd:map-codebase', + reason: 'Existing code was detected, but the required .planning/codebase/ map is missing.', + }); + + cleanup(tmpDir); + tmpDir = createFixture({ planning: false, projectDoc: false }); + fs.mkdirSync(path.join(tmpDir, 'docs', 'adr'), { recursive: true }); + fs.writeFileSync(path.join(tmpDir, 'docs', 'adr', '0001-runtime.md'), '# ADR: Runtime\n'); + result = runGsdTools('init onboard --raw', tmpDir, { HOME: tmpDir }); + assert.ok(result.success, `init onboard should succeed: ${result.error}`); + assert.deepStrictEqual(JSON.parse(result.output).next_action, { + kind: 'ingest-docs', + command: '/gsd:ingest-docs', + reason: 'Detected existing ADR/PRD/SPEC/RFC document(s) before project setup.', + }); + + cleanup(tmpDir); + tmpDir = createFixture({ planning: false, projectDoc: false }); + result = runGsdTools('init onboard --raw', tmpDir, { HOME: tmpDir }); + assert.ok(result.success, `init onboard should succeed: ${result.error}`); + assert.deepStrictEqual(JSON.parse(result.output).next_action, { + kind: 'new-project', + command: '/gsd:new-project', + reason: 'No existing code or planning docs were detected.', + }); + + cleanup(tmpDir); + tmpDir = createFixture({ planning: false, projectDoc: false }); + fs.mkdirSync(path.join(tmpDir, '.planning'), { recursive: true }); + fs.writeFileSync(path.join(tmpDir, '.planning', 'PROJECT.md'), '# Project\n'); + fs.writeFileSync(path.join(tmpDir, '.planning', 'ROADMAP.md'), '# Roadmap\n'); + fs.writeFileSync(path.join(tmpDir, '.planning', 'STATE.md'), '# State\n'); + result = runGsdTools('init onboard --raw', tmpDir, { HOME: tmpDir }); + assert.ok(result.success, `init onboard should succeed: ${result.error}`); + const partial = JSON.parse(result.output); + assert.strictEqual(partial.next_action.kind, 'partial-planning'); + assert.deepStrictEqual(partial.next_action.missing, ['REQUIREMENTS.md']); + + 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`); + } + fs.writeFileSync(path.join(tmpDir, '.planning', 'REQUIREMENTS.md'), '# Requirements\n'); + result = runGsdTools('init onboard --raw', tmpDir, { HOME: tmpDir }); + assert.ok(result.success, `init onboard should succeed: ${result.error}`); + assert.deepStrictEqual(JSON.parse(result.output).next_action, { + kind: 'write-summary', + summary_path: '.planning/onboarding/SUMMARY.md', + reason: 'Onboarding summary is missing.', + }); + + fs.mkdirSync(path.join(tmpDir, '.planning', 'onboarding'), { recursive: true }); + fs.writeFileSync(path.join(tmpDir, '.planning', 'onboarding', 'SUMMARY.md'), '# Onboarding Summary\n'); + result = runGsdTools('init onboard --raw', tmpDir, { HOME: tmpDir }); + assert.ok(result.success, `init onboard should succeed: ${result.error}`); + assert.deepStrictEqual(JSON.parse(result.output).next_action, { + kind: 'ready', + reason: 'Onboarding summary already exists.', + }); + }); + test('reports missing requirements in otherwise existing planning', () => { fs.mkdirSync(path.join(tmpDir, '.planning'), { recursive: true }); fs.writeFileSync(path.join(tmpDir, '.planning', 'PROJECT.md'), '# Project\n'); @@ -230,101 +302,37 @@ describe('/gsd:onboard command contract', () => { assert.ok(content.includes('@~/.claude/gsd-core/references/gate-prompts.md')); }); - test('workflow routes through existing primitives and protects existing planning', () => { + test('workflow renders the init projection without owning the route state machine', () => { const content = fs.readFileSync(WF_PATH, 'utf8'); - assert.ok(content.includes('init onboard'), 'workflow must use init onboard projection'); - assert.match(content, /gsd_run --cwd "\$_GSD_RUNTIME_ROOT" init onboard/, 'workflow must anchor init onboard at runtime root'); + assert.ok(content.includes('@~/.claude/gsd-core/references/gsd-run-resolver.md')); assert.ok( - !content.includes('ARGUMENTS:-'), - 'workflow must not depend on an unexported shell ARGUMENTS variable', + !content.includes('_GSD_SHIM_NAME="gsd-tools.cjs"'), + 'workflow must reference the shared resolver instead of inlining it', ); - assert.match( - content, - /Run init from parsed prompt args, not shell `\$ARGUMENTS`/, - 'workflow must forward fast mode from parsed prompt arguments into init onboard', - ); - assert.match( - content, - /gsd_run --cwd "\$_GSD_RUNTIME_ROOT" init onboard --fast/, - 'workflow must provide a literal fast init command', - ); - assert.ok(content.includes('has_fast_codebase_map'), 'workflow must parse fast map readiness'); - assert.match(content, /CODEBASE_MAP_READY=.*has_fast_codebase_map/s, 'workflow must treat the fast subset as acceptable in fast mode'); - assert.ok(content.includes('Run from worktree root'), 'workflow handoffs must be anchored at the worktree root'); - for (const runtimeHome of [ - 'HERMES_HOME', - 'CURSOR_CONFIG_DIR', - 'CODEX_HOME', - 'GEMINI_CONFIG_DIR', - 'WINDSURF_CONFIG_DIR', - 'OPENCODE_CONFIG_DIR', + assert.match(content, /init onboard --fast --raw/); + assert.match(content, /init onboard --raw/); + assert.match(content, /next_action\.kind/); + assert.match(content, /map_readiness/); + assert.match(content, /codebase_map_summary_status/); + assert.match(content, /ONBOARDING_ROOT=\{git_worktree_root \|\| _GSD_RUNTIME_ROOT\}/); + + for (const action of [ + 'map-codebase', + 'ingest-docs', + 'complete-map-before-new-project', + 'new-project', + 'partial-planning', + 'write-summary', + 'ready', ]) { - assert.ok(content.includes(runtimeHome), `workflow resolver must include ${runtimeHome}`); + assert.ok(content.includes(`next_action.kind == "${action}"`), `workflow must render ${action}`); } - assert.match(content, /Parse JSON fields:.*`commit_docs`/s, 'workflow must parse commit_docs before using it'); - assert.ok(content.includes('map-codebase'), 'workflow must route to map-codebase'); - assert.ok(content.includes('ingest-docs'), 'workflow must route to ingest-docs'); - assert.match( - content, - /If `has_docs_candidates` is true and `project_exists` is false:/, - 'workflow must offer docs ingest before project setup even when codebase mapping already created .planning', - ); - assert.match( - content, - /If `is_brownfield` is false and `planning_exists` is false and `has_docs_candidates` is false, print:/, - 'workflow must not send doc-only repos to new-project before the docs ingest gate', - ); - assert.ok(content.includes('new-project'), 'workflow must route to new-project'); - assert.ok(content.includes('.planning/onboarding/SUMMARY.md'), 'workflow must create onboarding summary'); - assert.match( - content, - /ONBOARDING_ROOT=\{git_worktree_root \|\| _GSD_RUNTIME_ROOT\}/, - 'workflow must resolve a single root for summary writes', - ); - assert.match( - content, - /Create `\{ONBOARDING_ROOT\}\/\.planning\/onboarding\/SUMMARY\.md`/, - 'workflow must anchor summary writes at onboarding root', - ); - assert.match( - content, - /gsd_run --cwd "\$ONBOARDING_ROOT" query commit "docs: create onboarding summary" --files \.planning\/onboarding\/SUMMARY\.md/, - 'workflow must commit the root-relative summary path from onboarding root', - ); - assert.match( - content, - /CODEBASE_MAP_SUMMARY_STATUS=\.planning\/codebase\/ \(fast\/partial-but-accepted codebase map\)/, - 'workflow summary must label fast accepted maps without implying a complete map', - ); - assert.match( - content, - /CODEBASE_MAP_FINAL_STATUS=\(fast\/partial-but-accepted; required fast files present\)/, - 'final status must distinguish complete maps from accepted fast maps', - ); - assert.match( - content, - /If `project_exists` is false and `fast_mode && has_fast_codebase_map && !has_codebase_map` is true:/, - 'workflow must not hand fast-partial maps directly to new-project', - ); - assert.match( - content, - /Fast codebase context is accepted for onboarding, but \/gsd:new-project still requires the complete codebase map\./, - 'workflow must explain why fast-partial onboarding stops before new-project', - ); - const deriveMapStatusIndex = content.indexOf('Before summary keep/update choices, derive map status values safely:'); - const keepExistingSummaryIndex = content.indexOf('If `onboarding_summary_exists` is true:'); - assert.ok(deriveMapStatusIndex >= 0, 'workflow must derive map status values'); - assert.ok(keepExistingSummaryIndex >= 0, 'workflow must define the existing-summary branch'); - assert.ok( - deriveMapStatusIndex < keepExistingSummaryIndex, - 'workflow must derive final map status before a keep-existing-summary path can skip to final status', - ); - assert.match(content, /overwrite|idempotent|do not overwrite/i, 'workflow must protect existing planning'); - assert.ok(content.includes('requirements_exists'), 'workflow must parse requirements existence'); - assert.match(content, /REQUIREMENTS\.md: \{requirements_exists \? "present" : "missing"\}/, 'workflow must report missing requirements in partial planning'); - assert.match(content, /If `project_exists` is true and .*`requirements_exists`.* is false/s, 'workflow must gate partial planning on missing requirements'); + + assert.ok(content.includes('AskUserQuestion'), 'workflow must still support interactive choices'); assert.ok(content.includes('--text'), 'workflow must document text-mode fallback'); + assert.match(content, /do not overwrite/i, 'workflow must protect existing summary/planning'); + assert.match(content, /query commit "docs: create onboarding summary" --files \.planning\/onboarding\/SUMMARY\.md/); assert.ok(!content.includes('execute-phase'), 'onboarding must not execute implementation phases'); assert.ok(!content.includes('gsd:ship'), 'onboarding must not ship work'); }); From 2a38ea5331698d2a991d5bfd79de4e3b21a8623f Mon Sep 17 00:00:00 2001 From: Jeremy McSpadden Date: Fri, 3 Jul 2026 15:04:10 -0500 Subject: [PATCH 22/48] no-mistakes(review): Harden onboarding projection routing --- src/onboard-projection.cts | 50 ++++++++++++++++++++++------------ tests/onboard-command.test.cjs | 31 +++++++++++++++++++++ 2 files changed, 63 insertions(+), 18 deletions(-) diff --git a/src/onboard-projection.cts b/src/onboard-projection.cts index 26ba11305..8e4ec8f7f 100644 --- a/src/onboard-projection.cts +++ b/src/onboard-projection.cts @@ -212,8 +212,14 @@ function mapFinalStatus(mapReadiness: MapReadiness): string { return 'missing'; } -function planningMissing(requirementsExists: boolean, roadmapExists: boolean, stateExists: boolean): string[] { +function planningMissing( + projectExists: boolean, + requirementsExists: boolean, + roadmapExists: boolean, + stateExists: boolean, +): string[] { const missing: string[] = []; + if (!projectExists) missing.push('PROJECT.md'); if (!requirementsExists) missing.push('REQUIREMENTS.md'); if (!roadmapExists) missing.push('ROADMAP.md'); if (!stateExists) missing.push('STATE.md'); @@ -228,6 +234,7 @@ function nextAction(params: { projectExists: boolean; mapReadiness: MapReadiness; onboardingSummaryExists: boolean; + hasPlanningArtifacts: boolean; missingPlanningFiles: string[]; }): OnboardNextAction { if (params.isBrownfield && params.needsCodebaseMap) { @@ -238,6 +245,22 @@ function nextAction(params: { }; } + if (!params.projectExists && params.fastMode && params.mapReadiness === 'fast') { + return { + kind: 'complete-map-before-new-project', + command: '/gsd:map-codebase', + reason: 'The fast map is enough for lightweight onboarding, but project setup still requires the complete codebase map.', + }; + } + + if (params.hasPlanningArtifacts && params.missingPlanningFiles.length > 0) { + return { + kind: 'partial-planning', + missing: params.missingPlanningFiles, + reason: 'Project planning exists but required planning files are missing.', + }; + } + if (params.hasDocsCandidates && !params.projectExists) { return { kind: 'ingest-docs', @@ -254,14 +277,6 @@ function nextAction(params: { }; } - if (!params.projectExists && params.fastMode && params.mapReadiness === 'fast') { - return { - kind: 'complete-map-before-new-project', - command: '/gsd:map-codebase', - reason: 'The fast map is enough for lightweight onboarding, but project setup still requires the complete codebase map.', - }; - } - if (!params.projectExists) { return { kind: 'new-project', @@ -270,14 +285,6 @@ function nextAction(params: { }; } - if (params.missingPlanningFiles.length > 0) { - return { - kind: 'partial-planning', - missing: params.missingPlanningFiles, - reason: 'Project planning exists but required planning files are missing.', - }; - } - if (!params.onboardingSummaryExists) { return { kind: 'write-summary', @@ -315,7 +322,13 @@ function buildOnboardProjection(cwd: string, options: BuildOnboardProjectionOpti 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 missingPlanningFiles = planningMissing(requirementsExists, roadmapExists, stateExists); + const hasPlanningArtifacts = projectExists || requirementsExists || roadmapExists || stateExists; + const missingPlanningFiles = planningMissing( + projectExists, + requirementsExists, + roadmapExists, + stateExists, + ); return { commit_docs: options.commitDocs, @@ -341,6 +354,7 @@ function buildOnboardProjection(cwd: string, options: BuildOnboardProjectionOpti projectExists, mapReadiness: mapReadinessValue, onboardingSummaryExists, + hasPlanningArtifacts, missingPlanningFiles, }), needs_codebase_map: needsCodebaseMap, diff --git a/tests/onboard-command.test.cjs b/tests/onboard-command.test.cjs index 30bb98716..563a87967 100644 --- a/tests/onboard-command.test.cjs +++ b/tests/onboard-command.test.cjs @@ -165,6 +165,37 @@ describe('init onboard public CLI projection', () => { assert.deepStrictEqual(parsed.missing_fast_codebase_map_files, []); }); + test('routes fast mapped repositories with planning docs to complete map before ingest', () => { + fs.mkdirSync(path.join(tmpDir, '.planning', 'codebase'), { recursive: true }); + for (const name of ['STACK', 'INTEGRATIONS', 'ARCHITECTURE', 'STRUCTURE']) { + fs.writeFileSync(path.join(tmpDir, '.planning', 'codebase', `${name}.md`), `# ${name}\n`); + } + fs.writeFileSync(path.join(tmpDir, 'package.json'), '{"name":"fixture"}\n'); + fs.mkdirSync(path.join(tmpDir, 'docs', 'adr'), { recursive: true }); + fs.writeFileSync(path.join(tmpDir, 'docs', 'adr', '0001-runtime.md'), '# ADR: Runtime\n'); + + const result = runGsdTools(['init', 'onboard', '--fast', '--raw'], tmpDir, { HOME: tmpDir }); + assert.ok(result.success, `init onboard should succeed: ${result.error}`); + + const parsed = JSON.parse(result.output); + assert.strictEqual(parsed.next_action.kind, 'complete-map-before-new-project'); + assert.strictEqual(parsed.next_action.command, '/gsd:map-codebase'); + }); + + test('routes planning artifacts without PROJECT.md to partial planning', () => { + fs.mkdirSync(path.join(tmpDir, '.planning'), { recursive: true }); + fs.writeFileSync(path.join(tmpDir, '.planning', 'REQUIREMENTS.md'), '# Requirements\n'); + fs.writeFileSync(path.join(tmpDir, '.planning', 'ROADMAP.md'), '# Roadmap\n'); + fs.writeFileSync(path.join(tmpDir, '.planning', 'STATE.md'), '# State\n'); + + const result = runGsdTools('init onboard --raw', tmpDir, { HOME: tmpDir }); + assert.ok(result.success, `init onboard should succeed: ${result.error}`); + + const parsed = JSON.parse(result.output); + assert.strictEqual(parsed.next_action.kind, 'partial-planning'); + assert.deepStrictEqual(parsed.next_action.missing, ['PROJECT.md']); + }); + test('projects the next action for code, docs, greenfield, partial planning, and summary states', () => { fs.mkdirSync(path.join(tmpDir, 'src'), { recursive: true }); fs.writeFileSync(path.join(tmpDir, 'src', 'server.ts'), 'export const server = true;\n'); From cd5971fd3f246d1235252241e82191b2964e4aa1 Mon Sep 17 00:00:00 2001 From: Jeremy McSpadden Date: Fri, 3 Jul 2026 15:12:07 -0500 Subject: [PATCH 23/48] no-mistakes(review): Fix onboard skip handoffs --- gsd-core/workflows/onboard.md | 24 ++++++++++++++++++++++-- tests/onboard-command.test.cjs | 16 ++++++++++++++++ 2 files changed, 38 insertions(+), 2 deletions(-) diff --git a/gsd-core/workflows/onboard.md b/gsd-core/workflows/onboard.md index d955e3048..f1896fbfe 100644 --- a/gsd-core/workflows/onboard.md +++ b/gsd-core/workflows/onboard.md @@ -72,7 +72,17 @@ Run from worktree root {ONBOARDING_ROOT}: Then rerun /gsd:onboard from the same worktree root. ``` -Exit. If the user skips mapping, continue with a warning. +Exit. If the user skips mapping, print: + +```text +Skipping codebase mapping may give /gsd:new-project weaker context. + +Run from worktree root {ONBOARDING_ROOT}: + +/gsd:new-project +``` + +Exit. ### `ingest-docs` @@ -107,7 +117,17 @@ Run from worktree root {ONBOARDING_ROOT}: Then rerun /gsd:onboard from the same worktree root. ``` -Exit. If the user skips docs ingest, continue to the new-project handoff below. +Exit. If the user skips docs ingest, print: + +```text +Skipping docs ingest may omit existing ADR/PRD/SPEC/RFC context from /gsd:new-project. + +Run from worktree root {ONBOARDING_ROOT}: + +/gsd:new-project +``` + +Exit. ### `complete-map-before-new-project` diff --git a/tests/onboard-command.test.cjs b/tests/onboard-command.test.cjs index 563a87967..10851d5e5 100644 --- a/tests/onboard-command.test.cjs +++ b/tests/onboard-command.test.cjs @@ -362,6 +362,22 @@ describe('/gsd:onboard command contract', () => { assert.ok(content.includes('AskUserQuestion'), 'workflow must still support interactive choices'); assert.ok(content.includes('--text'), 'workflow must document text-mode fallback'); + assert.ok( + content.includes('Exit. If the user skips mapping, print:'), + 'skip mapping must hand off explicitly instead of falling through to summary creation', + ); + assert.ok( + content.includes('Skipping codebase mapping may give /gsd:new-project weaker context.'), + 'skip mapping must warn about weaker context', + ); + assert.ok( + content.includes('Exit. If the user skips docs ingest, print:'), + 'skip docs ingest must hand off explicitly instead of falling through to summary creation', + ); + assert.ok( + content.includes('Skipping docs ingest may omit existing ADR/PRD/SPEC/RFC context from /gsd:new-project.'), + 'skip docs ingest must warn about omitted docs context', + ); assert.match(content, /do not overwrite/i, 'workflow must protect existing summary/planning'); assert.match(content, /query commit "docs: create onboarding summary" --files \.planning\/onboarding\/SUMMARY\.md/); assert.ok(!content.includes('execute-phase'), 'onboarding must not execute implementation phases'); From c9d964243a70e2e1d00b1c93c2259aaddce7c049 Mon Sep 17 00:00:00 2001 From: Jeremy McSpadden Date: Fri, 3 Jul 2026 15:22:16 -0500 Subject: [PATCH 24/48] no-mistakes(review): Fix onboard fast-map and skip routing --- gsd-core/workflows/onboard.md | 16 +++++++++++++++- src/onboard-projection.cts | 14 ++++++++------ tests/onboard-command.test.cjs | 13 +++++++++++-- 3 files changed, 34 insertions(+), 9 deletions(-) diff --git a/gsd-core/workflows/onboard.md b/gsd-core/workflows/onboard.md index f1896fbfe..7166317f5 100644 --- a/gsd-core/workflows/onboard.md +++ b/gsd-core/workflows/onboard.md @@ -72,7 +72,21 @@ Run from worktree root {ONBOARDING_ROOT}: Then rerun /gsd:onboard from the same worktree root. ``` -Exit. If the user skips mapping, print: +Exit. If the user skips mapping: + +- If `has_docs_candidates && !project_exists`, route the skip to docs ingest instead: + +```text +Skipping codebase mapping may give downstream steps weaker context, but existing ADR/PRD/SPEC/RFC documents should still be ingested before /gsd:new-project. + +Run from worktree root {ONBOARDING_ROOT}: + +/gsd:ingest-docs +``` + +Exit. + +- Otherwise print: ```text Skipping codebase mapping may give /gsd:new-project weaker context. diff --git a/src/onboard-projection.cts b/src/onboard-projection.cts index 8e4ec8f7f..c2501a210 100644 --- a/src/onboard-projection.cts +++ b/src/onboard-projection.cts @@ -75,6 +75,7 @@ interface OnboardProjection { map_readiness: MapReadiness; next_action: OnboardNextAction; needs_codebase_map: boolean; + needs_fast_codebase_map: boolean; has_codebase_map: boolean; has_fast_codebase_map: boolean; codebase_dir_exists: boolean; @@ -229,7 +230,7 @@ function planningMissing( function nextAction(params: { fastMode: boolean; isBrownfield: boolean; - needsCodebaseMap: boolean; + needsOnboardCodebaseMap: boolean; hasDocsCandidates: boolean; projectExists: boolean; mapReadiness: MapReadiness; @@ -237,7 +238,7 @@ function nextAction(params: { hasPlanningArtifacts: boolean; missingPlanningFiles: string[]; }): OnboardNextAction { - if (params.isBrownfield && params.needsCodebaseMap) { + if (params.isBrownfield && params.needsOnboardCodebaseMap) { return { kind: 'map-codebase', command: params.fastMode ? '/gsd:map-codebase --fast' : '/gsd:map-codebase', @@ -314,9 +315,9 @@ function buildOnboardProjection(cwd: string, options: BuildOnboardProjectionOpti const hasCodebaseMap = codebaseMapFiles.length === REQUIRED_CODEBASE_MAP_FILES.length; const hasFastCodebaseMap = missingFastCodebaseMapFiles.length === 0; const mapReadinessValue = getMapReadiness(hasCodebaseMap, hasFastCodebaseMap); - const needsCodebaseMap = isBrownfield && ( - options.fast ? !hasFastCodebaseMap : !hasCodebaseMap - ); + const needsCodebaseMap = isBrownfield && !hasCodebaseMap; + const needsFastCodebaseMap = isBrownfield && !hasFastCodebaseMap; + const needsOnboardCodebaseMap = options.fast ? needsFastCodebaseMap : needsCodebaseMap; const projectExists = pathExistsInternal(cwd, '.planning/PROJECT.md'); const requirementsExists = fs.existsSync(path.join(planningDir(cwd), 'REQUIREMENTS.md')); const roadmapExists = fs.existsSync(path.join(planningDir(cwd), 'ROADMAP.md')); @@ -349,7 +350,7 @@ function buildOnboardProjection(cwd: string, options: BuildOnboardProjectionOpti next_action: nextAction({ fastMode: options.fast, isBrownfield, - needsCodebaseMap, + needsOnboardCodebaseMap, hasDocsCandidates: docCandidates.length > 0, projectExists, mapReadiness: mapReadinessValue, @@ -358,6 +359,7 @@ function buildOnboardProjection(cwd: string, options: BuildOnboardProjectionOpti missingPlanningFiles, }), needs_codebase_map: needsCodebaseMap, + needs_fast_codebase_map: needsFastCodebaseMap, has_codebase_map: hasCodebaseMap, has_fast_codebase_map: hasFastCodebaseMap, codebase_dir_exists: fs.existsSync(path.join(planningRoot(cwd), 'codebase')), diff --git a/tests/onboard-command.test.cjs b/tests/onboard-command.test.cjs index 10851d5e5..762068b74 100644 --- a/tests/onboard-command.test.cjs +++ b/tests/onboard-command.test.cjs @@ -152,7 +152,8 @@ describe('init onboard public CLI projection', () => { assert.strictEqual(parsed.map_readiness, 'fast'); assert.strictEqual(parsed.has_codebase_map, false); assert.strictEqual(parsed.has_fast_codebase_map, true); - assert.strictEqual(parsed.needs_codebase_map, false); + assert.strictEqual(parsed.needs_codebase_map, true); + assert.strictEqual(parsed.needs_fast_codebase_map, false); assert.strictEqual(parsed.next_action.kind, 'complete-map-before-new-project'); assert.strictEqual(parsed.next_action.command, '/gsd:map-codebase'); assert.match(parsed.next_action.reason, /complete codebase map/i); @@ -363,9 +364,17 @@ describe('/gsd:onboard command contract', () => { assert.ok(content.includes('AskUserQuestion'), 'workflow must still support interactive choices'); assert.ok(content.includes('--text'), 'workflow must document text-mode fallback'); assert.ok( - content.includes('Exit. If the user skips mapping, print:'), + content.includes('Exit. If the user skips mapping:'), 'skip mapping must hand off explicitly instead of falling through to summary creation', ); + assert.ok( + content.includes('If `has_docs_candidates && !project_exists`, route the skip to docs ingest instead:'), + 'skip mapping must preserve the docs-ingest gate when planning docs are present', + ); + assert.ok( + content.includes('/gsd:ingest-docs'), + 'skip mapping docs-preserving handoff must name the docs ingest command', + ); assert.ok( content.includes('Skipping codebase mapping may give /gsd:new-project weaker context.'), 'skip mapping must warn about weaker context', From 64d9f84cf273dfeec938ee74dc80fc3fc122a78f Mon Sep 17 00:00:00 2001 From: Jeremy McSpadden Date: Fri, 3 Jul 2026 15:28:26 -0500 Subject: [PATCH 25/48] no-mistakes(review): Forward onboard text flag --- src/init-command-router.cts | 4 ++-- src/init.cts | 2 +- tests/onboard-command.test.cjs | 8 ++++++++ 3 files changed, 11 insertions(+), 3 deletions(-) diff --git a/src/init-command-router.cts b/src/init-command-router.cts index 90e09e2e6..6ea4b4dac 100644 --- a/src/init-command-router.cts +++ b/src/init-command-router.cts @@ -73,8 +73,8 @@ function routeInitCommand({ init, args, cwd, raw, error }: RouteInitCommandOptio 'new-project': () => init.cmdInitNewProject(cwd, raw), 'new-milestone': () => init.cmdInitNewMilestone(cwd, raw), onboard: () => { - const namedArgs = parseNamedArgs(args, [], ['fast']); - init.cmdInitOnboard(cwd, raw, { fast: namedArgs['fast'] }); + const namedArgs = parseNamedArgs(args, [], ['fast', 'text']); + init.cmdInitOnboard(cwd, raw, { fast: namedArgs['fast'], text: namedArgs['text'] }); }, quick: () => init.cmdInitQuick(cwd, args.slice(2).join(' '), raw), 'ingest-docs': () => init.cmdInitIngestDocs(cwd, raw), diff --git a/src/init.cts b/src/init.cts index 5c781ba25..19d8e6f1c 100644 --- a/src/init.cts +++ b/src/init.cts @@ -802,7 +802,7 @@ function cmdInitOnboard( ...buildOnboardProjection(cwd, { commitDocs: !!config.commit_docs, fast: options['fast'] === true, - textMode: !!config.text_mode || !!workflowConfig['text_mode'], + textMode: options['text'] === true || !!config.text_mode || !!workflowConfig['text_mode'], }), ...getInitGitState(cwd), }; diff --git a/tests/onboard-command.test.cjs b/tests/onboard-command.test.cjs index 762068b74..4904e18c2 100644 --- a/tests/onboard-command.test.cjs +++ b/tests/onboard-command.test.cjs @@ -97,6 +97,14 @@ describe('init onboard public CLI projection', () => { ]); }); + test('forwards the --text flag into the public projection', () => { + const result = runGsdTools(['init', 'onboard', '--text', '--raw'], tmpDir, { HOME: tmpDir }); + assert.ok(result.success, `init onboard should succeed: ${result.error}`); + + const parsed = JSON.parse(result.output); + assert.strictEqual(parsed.text_mode, true); + }); + test('reports complete codebase map and onboarding summary in existing planning', () => { fs.mkdirSync(path.join(tmpDir, '.planning', 'codebase'), { recursive: true }); for (const name of ['STACK', 'ARCHITECTURE', 'STRUCTURE', 'CONVENTIONS', 'TESTING', 'INTEGRATIONS', 'CONCERNS']) { From a845a7d23170909639185fd21093ab40fb651edd Mon Sep 17 00:00:00 2001 From: Jeremy McSpadden Date: Fri, 3 Jul 2026 16:13:26 -0500 Subject: [PATCH 26/48] no-mistakes(review): Preserve partial-planning skip guard --- gsd-core/workflows/onboard.md | 15 +++++++++++++++ tests/onboard-command.test.cjs | 14 +++++++++++++- 2 files changed, 28 insertions(+), 1 deletion(-) diff --git a/gsd-core/workflows/onboard.md b/gsd-core/workflows/onboard.md index 7166317f5..5d6d83187 100644 --- a/gsd-core/workflows/onboard.md +++ b/gsd-core/workflows/onboard.md @@ -74,6 +74,21 @@ Then rerun /gsd:onboard from the same worktree root. Exit. If the user skips mapping: +- If `planning_exists && (!project_exists || !requirements_exists || !roadmap_exists || !state_exists)`, route the skip to the partial planning guard instead: + +```text +Skipping codebase mapping may give downstream steps weaker context, but project planning exists and is incomplete. + +PROJECT.md: {project_exists ? "present" : "missing"} +REQUIREMENTS.md: {requirements_exists ? "present" : "missing"} +ROADMAP.md: {roadmap_exists ? "present" : "missing"} +STATE.md: {state_exists ? "present" : "missing"} + +Run the appropriate lower-level command to fill the missing planning artifact(s), then rerun /gsd:onboard. +``` + +Exit. + - If `has_docs_candidates && !project_exists`, route the skip to docs ingest instead: ```text diff --git a/tests/onboard-command.test.cjs b/tests/onboard-command.test.cjs index 4904e18c2..b3ab7a64b 100644 --- a/tests/onboard-command.test.cjs +++ b/tests/onboard-command.test.cjs @@ -375,10 +375,22 @@ describe('/gsd:onboard command contract', () => { content.includes('Exit. If the user skips mapping:'), 'skip mapping must hand off explicitly instead of falling through to summary creation', ); + const partialPlanningSkipGuard = + 'If `planning_exists && (!project_exists || !requirements_exists || !roadmap_exists || !state_exists)`, route the skip to the partial planning guard instead:'; + const docsIngestSkipGuard = + 'If `has_docs_candidates && !project_exists`, route the skip to docs ingest instead:'; assert.ok( - content.includes('If `has_docs_candidates && !project_exists`, route the skip to docs ingest instead:'), + content.includes(partialPlanningSkipGuard), + 'skip mapping must preserve the partial-planning guard when incomplete planning artifacts are present', + ); + assert.ok( + content.includes(docsIngestSkipGuard), 'skip mapping must preserve the docs-ingest gate when planning docs are present', ); + assert.ok( + content.indexOf(partialPlanningSkipGuard) < content.indexOf(docsIngestSkipGuard), + 'skip mapping must check partial planning before docs ingest', + ); assert.ok( content.includes('/gsd:ingest-docs'), 'skip mapping docs-preserving handoff must name the docs ingest command', From 2f2d33aea7067a7f90614279c9bf7affa85554aa Mon Sep 17 00:00:00 2001 From: Jeremy McSpadden Date: Fri, 3 Jul 2026 17:08:29 -0500 Subject: [PATCH 27/48] no-mistakes(review): Format onboard handoffs by runtime --- gsd-core/workflows/onboard.md | 31 ++++++++++++----------- src/onboard-projection.cts | 39 ++++++++++++++++++++++++---- tests/onboard-command.test.cjs | 46 ++++++++++++++++++++++++++-------- 3 files changed, 86 insertions(+), 30 deletions(-) diff --git a/gsd-core/workflows/onboard.md b/gsd-core/workflows/onboard.md index 5d6d83187..321649fc0 100644 --- a/gsd-core/workflows/onboard.md +++ b/gsd-core/workflows/onboard.md @@ -24,6 +24,7 @@ if [[ "$INIT" == @file:* ]]; then INIT=$(cat "${INIT#@file:}"); fi Parse JSON fields from `INIT`: - `next_action.kind`, `next_action.command`, `next_action.reason`, `next_action.missing`, `next_action.summary_path` +- `handoff_commands.ingest_docs`, `handoff_commands.manager`, `handoff_commands.new_project`, `handoff_commands.onboard` - `map_readiness`, `codebase_map_summary_status`, `codebase_map_final_status` - `planning_exists`, `project_exists`, `requirements_exists`, `roadmap_exists`, `state_exists` - `is_brownfield`, `fast_mode`, `has_codebase_map`, `has_fast_codebase_map` @@ -69,12 +70,12 @@ Run from worktree root {ONBOARDING_ROOT}: {next_action.command} -Then rerun /gsd:onboard from the same worktree root. +Then rerun {handoff_commands.onboard} from the same worktree root. ``` Exit. If the user skips mapping: -- If `planning_exists && (!project_exists || !requirements_exists || !roadmap_exists || !state_exists)`, route the skip to the partial planning guard instead: +- If `(project_exists || requirements_exists || roadmap_exists || state_exists) && (!project_exists || !requirements_exists || !roadmap_exists || !state_exists)`, route the skip to the partial planning guard instead: ```text Skipping codebase mapping may give downstream steps weaker context, but project planning exists and is incomplete. @@ -84,7 +85,7 @@ REQUIREMENTS.md: {requirements_exists ? "present" : "missing"} ROADMAP.md: {roadmap_exists ? "present" : "missing"} STATE.md: {state_exists ? "present" : "missing"} -Run the appropriate lower-level command to fill the missing planning artifact(s), then rerun /gsd:onboard. +Run the appropriate lower-level command to fill the missing planning artifact(s), then rerun {handoff_commands.onboard}. ``` Exit. @@ -92,11 +93,11 @@ Exit. - If `has_docs_candidates && !project_exists`, route the skip to docs ingest instead: ```text -Skipping codebase mapping may give downstream steps weaker context, but existing ADR/PRD/SPEC/RFC documents should still be ingested before /gsd:new-project. +Skipping codebase mapping may give downstream steps weaker context, but existing ADR/PRD/SPEC/RFC documents should still be ingested before {handoff_commands.new_project}. Run from worktree root {ONBOARDING_ROOT}: -/gsd:ingest-docs +{handoff_commands.ingest_docs} ``` Exit. @@ -104,11 +105,11 @@ Exit. - Otherwise print: ```text -Skipping codebase mapping may give /gsd:new-project weaker context. +Skipping codebase mapping may give {handoff_commands.new_project} weaker context. Run from worktree root {ONBOARDING_ROOT}: -/gsd:new-project +{handoff_commands.new_project} ``` Exit. @@ -124,7 +125,7 @@ If `next_action.kind == "ingest-docs"`: Detected {doc_candidate_count} possible ADR/PRD/SPEC/RFC document(s). 1. Ingest docs first — run {next_action.command} from worktree root {ONBOARDING_ROOT} (Recommended) -2. Skip docs ingest — continue to /gsd:new-project +2. Skip docs ingest — continue to {handoff_commands.new_project} Enter number: ``` @@ -134,7 +135,7 @@ Enter number: - question: "Detected {doc_candidate_count} possible ADR/PRD/SPEC/RFC document(s). Ingest them first?" - options: - "Ingest docs first" — Run `{next_action.command}` from worktree root `{ONBOARDING_ROOT}` (Recommended) - - "Skip docs ingest" — Continue to `/gsd:new-project` + - "Skip docs ingest" — Continue to `{handoff_commands.new_project}` If the user chooses ingest, print: @@ -143,17 +144,17 @@ Run from worktree root {ONBOARDING_ROOT}: {next_action.command} -Then rerun /gsd:onboard from the same worktree root. +Then rerun {handoff_commands.onboard} from the same worktree root. ``` Exit. If the user skips docs ingest, print: ```text -Skipping docs ingest may omit existing ADR/PRD/SPEC/RFC context from /gsd:new-project. +Skipping docs ingest may omit existing ADR/PRD/SPEC/RFC context from {handoff_commands.new_project}. Run from worktree root {ONBOARDING_ROOT}: -/gsd:new-project +{handoff_commands.new_project} ``` Exit. @@ -169,7 +170,7 @@ Run from worktree root {ONBOARDING_ROOT}: {next_action.command} -Then rerun /gsd:onboard from the same worktree root. +Then rerun {handoff_commands.onboard} from the same worktree root. ``` Exit. @@ -200,7 +201,7 @@ REQUIREMENTS.md: {requirements_exists ? "present" : "missing"} ROADMAP.md: {roadmap_exists ? "present" : "missing"} STATE.md: {state_exists ? "present" : "missing"} -Run the appropriate lower-level command to fill the missing planning artifact(s), then rerun /gsd:onboard. +Run the appropriate lower-level command to fill the missing planning artifact(s), then rerun {handoff_commands.onboard}. ``` Exit. @@ -262,7 +263,7 @@ Onboarding status: - Codebase map: {codebase_map_final_status} - Onboarding summary: present -Next recommended command: /gsd:manager +Next recommended command: {handoff_commands.manager} ``` Do not run implementation execution or shipping from onboarding. diff --git a/src/onboard-projection.cts b/src/onboard-projection.cts index c2501a210..b327ded57 100644 --- a/src/onboard-projection.cts +++ b/src/onboard-projection.cts @@ -5,6 +5,7 @@ import path from 'node:path'; import coreUtils = require('./core-utils.cjs'); // eslint-disable-next-line @typescript-eslint/no-require-imports -- planning-workspace.cjs is an export= CommonJS module import planningWorkspace = require('./planning-workspace.cjs'); +import { formatGsdSlash, resolveRuntime } from './runtime-slash.cjs'; const { pathExistsInternal, toPosixPath } = coreUtils; const { planningDir, planningRoot } = planningWorkspace; @@ -42,6 +43,15 @@ const PLANNING_DOC_SEGMENTS = new Set([ type MapReadiness = 'none' | 'fast' | 'complete'; +interface OnboardHandoffCommands { + ingest_docs: string; + manager: string; + map_codebase: string; + map_codebase_fast: string; + new_project: string; + onboard: string; +} + type OnboardNextAction = | { kind: 'map-codebase'; command: string; reason: string } | { kind: 'ingest-docs'; command: string; reason: string } @@ -68,6 +78,8 @@ interface OnboardProjection { state_exists: boolean; config_exists: boolean; + handoff_commands: OnboardHandoffCommands; + has_existing_code: boolean; has_package_file: boolean; is_brownfield: boolean; @@ -237,11 +249,12 @@ function nextAction(params: { onboardingSummaryExists: boolean; hasPlanningArtifacts: boolean; missingPlanningFiles: string[]; + handoffCommands: OnboardHandoffCommands; }): OnboardNextAction { if (params.isBrownfield && params.needsOnboardCodebaseMap) { return { kind: 'map-codebase', - command: params.fastMode ? '/gsd:map-codebase --fast' : '/gsd:map-codebase', + command: params.fastMode ? params.handoffCommands.map_codebase_fast : params.handoffCommands.map_codebase, reason: 'Existing code was detected, but the required .planning/codebase/ map is missing.', }; } @@ -249,7 +262,7 @@ function nextAction(params: { if (!params.projectExists && params.fastMode && params.mapReadiness === 'fast') { return { kind: 'complete-map-before-new-project', - command: '/gsd:map-codebase', + command: params.handoffCommands.map_codebase, reason: 'The fast map is enough for lightweight onboarding, but project setup still requires the complete codebase map.', }; } @@ -265,7 +278,7 @@ function nextAction(params: { if (params.hasDocsCandidates && !params.projectExists) { return { kind: 'ingest-docs', - command: '/gsd:ingest-docs', + command: params.handoffCommands.ingest_docs, reason: 'Detected existing ADR/PRD/SPEC/RFC document(s) before project setup.', }; } @@ -273,7 +286,7 @@ function nextAction(params: { if (!params.isBrownfield && !params.projectExists && !params.hasDocsCandidates) { return { kind: 'new-project', - command: '/gsd:new-project', + command: params.handoffCommands.new_project, reason: 'No existing code or planning docs were detected.', }; } @@ -281,7 +294,7 @@ function nextAction(params: { if (!params.projectExists) { return { kind: 'new-project', - command: '/gsd:new-project', + command: params.handoffCommands.new_project, reason: 'Codebase context is ready for project initialization.', }; } @@ -300,7 +313,20 @@ function nextAction(params: { }; } +function buildHandoffCommands(cwd: string): OnboardHandoffCommands { + const runtime = resolveRuntime(cwd); + return { + ingest_docs: formatGsdSlash('ingest-docs', runtime) as string, + manager: formatGsdSlash('manager', runtime) as string, + map_codebase: formatGsdSlash('map-codebase', runtime) as string, + map_codebase_fast: formatGsdSlash('map-codebase --fast', runtime) as string, + new_project: formatGsdSlash('new-project', runtime) as string, + onboard: formatGsdSlash('onboard', runtime) as string, + }; +} + function buildOnboardProjection(cwd: string, options: BuildOnboardProjectionOptions): OnboardProjection { + const handoffCommands = buildHandoffCommands(cwd); const codebaseMapFiles = listCodebaseMapFiles(cwd); const missingCodebaseMapFiles = REQUIRED_CODEBASE_MAP_FILES.filter( (file) => !codebaseMapFiles.includes(file), @@ -342,6 +368,8 @@ function buildOnboardProjection(cwd: string, options: BuildOnboardProjectionOpti state_exists: stateExists, config_exists: fs.existsSync(path.join(planningDir(cwd), 'config.json')), + handoff_commands: handoffCommands, + has_existing_code: hasCode, has_package_file: hasPackageFile, is_brownfield: isBrownfield, @@ -357,6 +385,7 @@ function buildOnboardProjection(cwd: string, options: BuildOnboardProjectionOpti onboardingSummaryExists, hasPlanningArtifacts, missingPlanningFiles, + handoffCommands, }), needs_codebase_map: needsCodebaseMap, needs_fast_codebase_map: needsFastCodebaseMap, diff --git a/tests/onboard-command.test.cjs b/tests/onboard-command.test.cjs index b3ab7a64b..5809f9b32 100644 --- a/tests/onboard-command.test.cjs +++ b/tests/onboard-command.test.cjs @@ -163,7 +163,7 @@ describe('init onboard public CLI projection', () => { assert.strictEqual(parsed.needs_codebase_map, true); assert.strictEqual(parsed.needs_fast_codebase_map, false); assert.strictEqual(parsed.next_action.kind, 'complete-map-before-new-project'); - assert.strictEqual(parsed.next_action.command, '/gsd:map-codebase'); + assert.strictEqual(parsed.next_action.command, '/gsd-map-codebase'); assert.match(parsed.next_action.reason, /complete codebase map/i); assert.deepStrictEqual(parsed.fast_codebase_map_files_required, [ 'STACK.md', @@ -188,7 +188,7 @@ describe('init onboard public CLI projection', () => { const parsed = JSON.parse(result.output); assert.strictEqual(parsed.next_action.kind, 'complete-map-before-new-project'); - assert.strictEqual(parsed.next_action.command, '/gsd:map-codebase'); + assert.strictEqual(parsed.next_action.command, '/gsd-map-codebase'); }); test('routes planning artifacts without PROJECT.md to partial planning', () => { @@ -212,7 +212,7 @@ describe('init onboard public CLI projection', () => { assert.ok(result.success, `init onboard should succeed: ${result.error}`); assert.deepStrictEqual(JSON.parse(result.output).next_action, { kind: 'map-codebase', - command: '/gsd:map-codebase', + command: '/gsd-map-codebase', reason: 'Existing code was detected, but the required .planning/codebase/ map is missing.', }); @@ -224,7 +224,7 @@ describe('init onboard public CLI projection', () => { assert.ok(result.success, `init onboard should succeed: ${result.error}`); assert.deepStrictEqual(JSON.parse(result.output).next_action, { kind: 'ingest-docs', - command: '/gsd:ingest-docs', + command: '/gsd-ingest-docs', reason: 'Detected existing ADR/PRD/SPEC/RFC document(s) before project setup.', }); @@ -234,7 +234,7 @@ describe('init onboard public CLI projection', () => { assert.ok(result.success, `init onboard should succeed: ${result.error}`); assert.deepStrictEqual(JSON.parse(result.output).next_action, { kind: 'new-project', - command: '/gsd:new-project', + command: '/gsd-new-project', reason: 'No existing code or planning docs were detected.', }); @@ -318,6 +318,29 @@ describe('init onboard public CLI projection', () => { assert.strictEqual(parsed.needs_codebase_map, true); }); + + test('formats onboard handoff commands for the resolved runtime', () => { + fs.writeFileSync(path.join(tmpDir, 'package.json'), '{"name":"fixture"}\n'); + + const result = runGsdTools(['init', 'onboard', '--raw'], tmpDir, { + HOME: tmpDir, + GSD_RUNTIME: 'codex', + }); + assert.ok(result.success, `init onboard should succeed: ${result.error}`); + + const parsed = JSON.parse(result.output); + assert.strictEqual(parsed.next_action.kind, 'map-codebase'); + assert.strictEqual(parsed.next_action.command, '$gsd-map-codebase'); + assert.deepStrictEqual(parsed.handoff_commands, { + map_codebase: '$gsd-map-codebase', + map_codebase_fast: '$gsd-map-codebase --fast', + ingest_docs: '$gsd-ingest-docs', + manager: '$gsd-manager', + new_project: '$gsd-new-project', + onboard: '$gsd-onboard', + }); + }); + test('dotted query init.onboard matches direct init onboard', () => { fs.writeFileSync(path.join(tmpDir, 'package.json'), '{"name":"fixture"}\n'); @@ -376,7 +399,7 @@ describe('/gsd:onboard command contract', () => { 'skip mapping must hand off explicitly instead of falling through to summary creation', ); const partialPlanningSkipGuard = - 'If `planning_exists && (!project_exists || !requirements_exists || !roadmap_exists || !state_exists)`, route the skip to the partial planning guard instead:'; + 'If `(project_exists || requirements_exists || roadmap_exists || state_exists) && (!project_exists || !requirements_exists || !roadmap_exists || !state_exists)`, route the skip to the partial planning guard instead:'; const docsIngestSkipGuard = 'If `has_docs_candidates && !project_exists`, route the skip to docs ingest instead:'; assert.ok( @@ -392,11 +415,11 @@ describe('/gsd:onboard command contract', () => { 'skip mapping must check partial planning before docs ingest', ); assert.ok( - content.includes('/gsd:ingest-docs'), - 'skip mapping docs-preserving handoff must name the docs ingest command', + content.includes('{handoff_commands.ingest_docs}'), + 'skip mapping docs-preserving handoff must use the projected docs ingest command', ); assert.ok( - content.includes('Skipping codebase mapping may give /gsd:new-project weaker context.'), + content.includes('Skipping codebase mapping may give {handoff_commands.new_project} weaker context.'), 'skip mapping must warn about weaker context', ); assert.ok( @@ -404,12 +427,15 @@ describe('/gsd:onboard command contract', () => { 'skip docs ingest must hand off explicitly instead of falling through to summary creation', ); assert.ok( - content.includes('Skipping docs ingest may omit existing ADR/PRD/SPEC/RFC context from /gsd:new-project.'), + content.includes('Skipping docs ingest may omit existing ADR/PRD/SPEC/RFC context from {handoff_commands.new_project}.'), 'skip docs ingest must warn about omitted docs context', ); assert.match(content, /do not overwrite/i, 'workflow must protect existing summary/planning'); assert.match(content, /query commit "docs: create onboarding summary" --files \.planning\/onboarding\/SUMMARY\.md/); assert.ok(!content.includes('execute-phase'), 'onboarding must not execute implementation phases'); assert.ok(!content.includes('gsd:ship'), 'onboarding must not ship work'); + assert.ok(content.includes('Next recommended command: {handoff_commands.manager}')); + assert.ok(!content.includes('/gsd:ingest-docs'), 'skip handoffs must not hard-code legacy ingest command'); + assert.ok(!content.includes('/gsd:new-project'), 'skip handoffs must not hard-code legacy new-project command'); }); }); From 2c878c966f65c4e9568dbe33c11cfd7c9da49e86 Mon Sep 17 00:00:00 2001 From: Jeremy McSpadden Date: Fri, 3 Jul 2026 17:20:34 -0500 Subject: [PATCH 28/48] no-mistakes(document): Sync onboarding docs --- commands/gsd/onboard.md | 2 +- docs/CLI-TOOLS.md | 4 ++-- docs/COMMANDS.md | 4 ++-- docs/FEATURES.md | 2 +- docs/ja-JP/CLI-TOOLS.md | 4 ++-- docs/ja-JP/COMMANDS.md | 4 ++-- docs/ja-JP/FEATURES.md | 2 +- docs/ja-JP/tutorials/onboarding-an-existing-codebase.md | 2 +- docs/ko-KR/CLI-TOOLS.md | 4 ++-- docs/ko-KR/COMMANDS.md | 4 ++-- docs/ko-KR/FEATURES.md | 2 +- docs/ko-KR/tutorials/onboarding-an-existing-codebase.md | 2 +- docs/pt-BR/CLI-TOOLS.md | 4 ++-- docs/pt-BR/COMMANDS.md | 4 ++-- docs/pt-BR/tutorials/onboarding-an-existing-codebase.md | 2 +- docs/tutorials/onboarding-an-existing-codebase.md | 2 +- docs/zh-CN/CLI-TOOLS.md | 4 ++-- docs/zh-CN/COMMANDS.md | 4 ++-- docs/zh-CN/FEATURES.md | 2 +- docs/zh-CN/tutorials/onboarding-an-existing-codebase.md | 2 +- skills/gsd-onboard/SKILL.md | 2 +- 21 files changed, 31 insertions(+), 31 deletions(-) diff --git a/commands/gsd/onboard.md b/commands/gsd/onboard.md index ae2517b1c..9211d3cff 100644 --- a/commands/gsd/onboard.md +++ b/commands/gsd/onboard.md @@ -37,7 +37,7 @@ Guide brownfield onboarding for an existing codebase by routing through the exis Arguments: $ARGUMENTS Flags: -- `--fast` — prefer `/gsd:map-codebase --fast` for the mapping handoff. +- `--fast` — prefer `/gsd:map-codebase --fast` for the mapping handoff; the complete map is still required before `/gsd:new-project`. - `--text` — use plain-text numbered lists instead of TUI menus. diff --git a/docs/CLI-TOOLS.md b/docs/CLI-TOOLS.md index e0454074a..923a1f757 100644 --- a/docs/CLI-TOOLS.md +++ b/docs/CLI-TOOLS.md @@ -421,14 +421,14 @@ node gsd-tools.cjs scaffold phase-dir --phase N --name "phase name" ## Init Commands (Compound Context Loading) -Load all context needed for a specific workflow in one call. Returns JSON with project info, config, state, and workflow-specific data. `init onboard [--fast]` reports brownfield signals, planning-doc candidates, codebase-map completeness, fast-map readiness, partial planning state, and onboarding summary status for `/gsd-onboard`. +Load all context needed for a specific workflow in one call. Returns JSON with project info, config, state, and workflow-specific data. `init onboard [--fast] [--text]` reports brownfield signals, planning-doc candidates, codebase-map completeness, fast-map readiness, text-mode routing, partial planning state, and onboarding summary status for `/gsd-onboard`. ```bash node gsd-tools.cjs init execute-phase node gsd-tools.cjs init plan-phase node gsd-tools.cjs init new-project node gsd-tools.cjs init new-milestone -node gsd-tools.cjs init onboard [--fast] +node gsd-tools.cjs init onboard [--fast] [--text] node gsd-tools.cjs init quick node gsd-tools.cjs init resume node gsd-tools.cjs init verify-work diff --git a/docs/COMMANDS.md b/docs/COMMANDS.md index e8d2b9095..22216ff54 100644 --- a/docs/COMMANDS.md +++ b/docs/COMMANDS.md @@ -64,7 +64,7 @@ Guide an existing codebase through first-time GSD onboarding. The command checks | Flag | Description | |------|-------------| -| `--fast` | Prefer the lightweight `/gsd-map-codebase --fast` mapping handoff | +| `--fast` | Prefer the lightweight `/gsd-map-codebase --fast` mapping handoff; a complete map is still required before `/gsd-new-project` | | `--text` | Use numbered plain-text gates instead of TUI menus | **Prerequisites:** Existing repo or planning docs. For empty greenfield projects, use `/gsd-new-project`. @@ -72,7 +72,7 @@ Guide an existing codebase through first-time GSD onboarding. The command checks ```bash /gsd-onboard # Guided brownfield onboarding -/gsd-onboard --fast # Use lightweight codebase mapping first +/gsd-onboard --fast # Use lightweight codebase mapping first, then complete the map before project setup ``` --- diff --git a/docs/FEATURES.md b/docs/FEATURES.md index 8f1b647dd..1a80bd7c3 100644 --- a/docs/FEATURES.md +++ b/docs/FEATURES.md @@ -826,7 +826,7 @@ against the mapping point, not HEAD. **Requirements:** - REQ-ONBOARD-01: System MUST detect existing code, package manifests, planning documents, partial `.planning/` state, and complete or missing codebase-map files. -- REQ-ONBOARD-02: System MUST hand off to `/gsd-map-codebase` or `/gsd-map-codebase --fast` when brownfield code lacks a complete `.planning/codebase/` map. +- REQ-ONBOARD-02: System MUST hand off to `/gsd-map-codebase` or `/gsd-map-codebase --fast` when brownfield code lacks the required `.planning/codebase/` map files; fast-map readiness is partial and MUST NOT be treated as sufficient for `/gsd-new-project`. - REQ-ONBOARD-03: System MUST offer `/gsd-ingest-docs` before `/gsd-new-project` when ADR/PRD/SPEC/RFC candidates exist and no project exists. - REQ-ONBOARD-04: System MUST refuse to report onboarding complete until `PROJECT.md`, `REQUIREMENTS.md`, `ROADMAP.md`, and `STATE.md` all exist. - REQ-ONBOARD-05: System MUST create or confirm `.planning/onboarding/SUMMARY.md` only after project setup exists. diff --git a/docs/ja-JP/CLI-TOOLS.md b/docs/ja-JP/CLI-TOOLS.md index a4165216a..7f893f08b 100644 --- a/docs/ja-JP/CLI-TOOLS.md +++ b/docs/ja-JP/CLI-TOOLS.md @@ -288,14 +288,14 @@ node gsd-tools.cjs scaffold phase-dir --phase N --name "phase name" ## Init コマンド(複合コンテキスト読み込み) -特定のワークフローに必要なすべてのコンテキストを一度に読み込みます。プロジェクト情報、設定、状態、ワークフロー固有のデータを含む JSON を返します。`init onboard [--fast]` は `/gsd-onboard` 用に、brownfield シグナル、計画ドキュメント候補、コードベースマップの完全性、fast マップの準備状況、部分的な planning 状態、オンボーディングサマリー状態を返します。 +特定のワークフローに必要なすべてのコンテキストを一度に読み込みます。プロジェクト情報、設定、状態、ワークフロー固有のデータを含む JSON を返します。`init onboard [--fast] [--text]` は `/gsd-onboard` 用に、brownfield シグナル、計画ドキュメント候補、コードベースマップの完全性、fast マップの準備状況、テキストモードルーティング、部分的な planning 状態、オンボーディングサマリー状態を返します。 ```bash node gsd-tools.cjs init execute-phase node gsd-tools.cjs init plan-phase node gsd-tools.cjs init new-project node gsd-tools.cjs init new-milestone -node gsd-tools.cjs init onboard [--fast] +node gsd-tools.cjs init onboard [--fast] [--text] node gsd-tools.cjs init quick node gsd-tools.cjs init resume node gsd-tools.cjs init verify-work diff --git a/docs/ja-JP/COMMANDS.md b/docs/ja-JP/COMMANDS.md index c3c9ca0a5..9a2bb72f4 100644 --- a/docs/ja-JP/COMMANDS.md +++ b/docs/ja-JP/COMMANDS.md @@ -57,7 +57,7 @@ v1.40 では、最初のステージエントリーポイントとして6つの | フラグ | 説明 | |------|-------------| -| `--fast` | 軽量な `/gsd-map-codebase --fast` マッピングハンドオフを優先 | +| `--fast` | 軽量な `/gsd-map-codebase --fast` マッピングハンドオフを優先。ただし `/gsd-new-project` 前には完全なマップが必要 | | `--text` | TUI メニューではなく番号付きプレーンテキストのゲートを使用 | **前提条件:** 既存リポジトリまたは計画ドキュメント。空のグリーンフィールドプロジェクトには `/gsd-new-project` を使用します。 @@ -65,7 +65,7 @@ v1.40 では、最初のステージエントリーポイントとして6つの ```bash /gsd-onboard # ガイド付き brownfield オンボーディング -/gsd-onboard --fast # 先に軽量コードベースマッピングを使用 +/gsd-onboard --fast # 先に軽量マップを使い、その後プロジェクト設定前に完全マップを作成 ``` --- diff --git a/docs/ja-JP/FEATURES.md b/docs/ja-JP/FEATURES.md index 6e1bb6742..f12493671 100644 --- a/docs/ja-JP/FEATURES.md +++ b/docs/ja-JP/FEATURES.md @@ -814,7 +814,7 @@ **要件:** - REQ-ONBOARD-01: 既存コード、package manifest、計画ドキュメント、部分的な `.planning/`、コードベースマップの不足を検出する。 -- REQ-ONBOARD-02: 完全な `.planning/codebase/` がない brownfield では `/gsd-map-codebase` または `/gsd-map-codebase --fast` へハンドオフする。 +- REQ-ONBOARD-02: 必要な `.planning/codebase/` マップファイルがない brownfield では `/gsd-map-codebase` または `/gsd-map-codebase --fast` へハンドオフする。fast マップの readiness は部分的であり、`/gsd-new-project` に十分として扱ってはならない。 - REQ-ONBOARD-03: ADR/PRD/SPEC/RFC 候補があり project がない場合、`/gsd-new-project` の前に `/gsd-ingest-docs` を提示する。 - REQ-ONBOARD-04: `PROJECT.md`、`REQUIREMENTS.md`、`ROADMAP.md`、`STATE.md` が揃うまで完了扱いにしない。 - REQ-ONBOARD-05: project setup 後にのみ `.planning/onboarding/SUMMARY.md` を作成または確認する。 diff --git a/docs/ja-JP/tutorials/onboarding-an-existing-codebase.md b/docs/ja-JP/tutorials/onboarding-an-existing-codebase.md index a877ff94b..8a730dc98 100644 --- a/docs/ja-JP/tutorials/onboarding-an-existing-codebase.md +++ b/docs/ja-JP/tutorials/onboarding-an-existing-codebase.md @@ -52,7 +52,7 @@ claude --dangerously-skip-permissions /gsd-onboard ``` -オンボーディングがコードベースマップ不足を示したら、推奨オプションを選び、表示された `/gsd-map-codebase` ハンドオフを実行してから `/gsd-onboard` を再実行します。`/gsd-map-codebase` が4つの並行マッパーサブエージェントを生成します(「Spawning 4 parallel codebase mapper agents…」という通知が表示されます。1〜5分かかりますので中断しないでください)。各エージェントはそれぞれ異なる観点に注目します: +オンボーディングがコードベースマップ不足を示したら、推奨オプションを選び、表示された `/gsd-map-codebase` ハンドオフを実行してから `/gsd-onboard` を再実行します。`/gsd-onboard --fast` は軽量な初回パスには使えますが、`/gsd-new-project` の前には完全なマップが必要です。`/gsd-map-codebase` が4つの並行マッパーサブエージェントを生成します(「Spawning 4 parallel codebase mapper agents…」という通知が表示されます。1〜5分かかりますので中断しないでください)。各エージェントはそれぞれ異なる観点に注目します: | エージェント | 観点 | |-------|-------| diff --git a/docs/ko-KR/CLI-TOOLS.md b/docs/ko-KR/CLI-TOOLS.md index 3f375c3ec..7d9f76984 100644 --- a/docs/ko-KR/CLI-TOOLS.md +++ b/docs/ko-KR/CLI-TOOLS.md @@ -288,14 +288,14 @@ node gsd-tools.cjs scaffold phase-dir --phase N --name "phase name" ## Init 명령 (복합 컨텍스트 로딩) -하나의 호출로 특정 워크플로우에 필요한 모든 컨텍스트를 로드합니다. 프로젝트 정보, 설정, 상태, 워크플로우별 데이터가 포함된 JSON을 반환합니다. `init onboard [--fast]`는 `/gsd-onboard`를 위해 brownfield 신호, 계획 문서 후보, 코드베이스 맵 완성도, fast 맵 준비 상태, 부분 planning 상태, 온보딩 요약 상태를 반환합니다. +하나의 호출로 특정 워크플로우에 필요한 모든 컨텍스트를 로드합니다. 프로젝트 정보, 설정, 상태, 워크플로우별 데이터가 포함된 JSON을 반환합니다. `init onboard [--fast] [--text]`는 `/gsd-onboard`를 위해 brownfield 신호, 계획 문서 후보, 코드베이스 맵 완성도, fast 맵 준비 상태, 텍스트 모드 라우팅, 부분 planning 상태, 온보딩 요약 상태를 반환합니다. ```bash node gsd-tools.cjs init execute-phase node gsd-tools.cjs init plan-phase node gsd-tools.cjs init new-project node gsd-tools.cjs init new-milestone -node gsd-tools.cjs init onboard [--fast] +node gsd-tools.cjs init onboard [--fast] [--text] node gsd-tools.cjs init quick node gsd-tools.cjs init resume node gsd-tools.cjs init verify-work diff --git a/docs/ko-KR/COMMANDS.md b/docs/ko-KR/COMMANDS.md index 6c473e2b7..338bb91d9 100644 --- a/docs/ko-KR/COMMANDS.md +++ b/docs/ko-KR/COMMANDS.md @@ -57,7 +57,7 @@ v1.40에서 여섯 개의 네임스페이스 라우터가 1단계 진입점으 | 플래그 | 설명 | |------|-------------| -| `--fast` | 경량 `/gsd-map-codebase --fast` 매핑 handoff 우선 사용 | +| `--fast` | 경량 `/gsd-map-codebase --fast` 매핑 handoff 우선 사용. 단, `/gsd-new-project` 전에는 완전한 맵이 필요 | | `--text` | TUI 메뉴 대신 번호가 있는 plain-text gate 사용 | **전제 조건:** 기존 저장소 또는 계획 문서. 빈 greenfield 프로젝트는 `/gsd-new-project`를 사용하세요. @@ -65,7 +65,7 @@ v1.40에서 여섯 개의 네임스페이스 라우터가 1단계 진입점으 ```bash /gsd-onboard # 안내형 brownfield 온보딩 -/gsd-onboard --fast # 먼저 경량 코드베이스 매핑 사용 +/gsd-onboard --fast # 먼저 경량 맵을 사용하고, 프로젝트 설정 전 완전한 맵 작성 ``` --- diff --git a/docs/ko-KR/FEATURES.md b/docs/ko-KR/FEATURES.md index 7556310c5..d1afde110 100644 --- a/docs/ko-KR/FEATURES.md +++ b/docs/ko-KR/FEATURES.md @@ -745,7 +745,7 @@ **요구사항.** - REQ-ONBOARD-01: 기존 코드, package manifest, planning 문서, 부분 `.planning/` 상태, 코드베이스 맵 누락을 감지해야 합니다. -- REQ-ONBOARD-02: 완전한 `.planning/codebase/`가 없는 brownfield에서는 `/gsd-map-codebase` 또는 `/gsd-map-codebase --fast`로 handoff해야 합니다. +- REQ-ONBOARD-02: 필요한 `.planning/codebase/` 맵 파일이 없는 brownfield에서는 `/gsd-map-codebase` 또는 `/gsd-map-codebase --fast`로 handoff해야 합니다. fast 맵 readiness는 부분 상태이며 `/gsd-new-project`에 충분한 것으로 취급해서는 안 됩니다. - REQ-ONBOARD-03: ADR/PRD/SPEC/RFC 후보가 있고 project가 없으면 `/gsd-new-project` 전에 `/gsd-ingest-docs`를 제안해야 합니다. - REQ-ONBOARD-04: `PROJECT.md`, `REQUIREMENTS.md`, `ROADMAP.md`, `STATE.md`가 모두 있을 때까지 완료로 보고하지 않아야 합니다. - REQ-ONBOARD-05: project setup 후에만 `.planning/onboarding/SUMMARY.md`를 만들거나 확인해야 합니다. diff --git a/docs/ko-KR/tutorials/onboarding-an-existing-codebase.md b/docs/ko-KR/tutorials/onboarding-an-existing-codebase.md index c1a058550..6fe4b7c51 100644 --- a/docs/ko-KR/tutorials/onboarding-an-existing-codebase.md +++ b/docs/ko-KR/tutorials/onboarding-an-existing-codebase.md @@ -52,7 +52,7 @@ claude --dangerously-skip-permissions /gsd-onboard ``` -온보딩이 코드베이스 맵 누락을 보고하면 권장 옵션을 선택하고 출력된 `/gsd-map-codebase` handoff를 실행한 뒤 `/gsd-onboard`를 다시 실행합니다. `/gsd-map-codebase`가 4개의 병렬 매퍼 서브 에이전트를 생성합니다("Spawning 4 parallel codebase mapper agents…" 메시지가 표시되며, 1–5분 소요됩니다. 중단하지 마세요). 각 에이전트는 서로 다른 관심사에 집중합니다: +온보딩이 코드베이스 맵 누락을 보고하면 권장 옵션을 선택하고 출력된 `/gsd-map-codebase` handoff를 실행한 뒤 `/gsd-onboard`를 다시 실행합니다. `/gsd-onboard --fast`는 가벼운 첫 패스에는 충분하지만, `/gsd-new-project` 전에는 완전한 맵이 필요합니다. `/gsd-map-codebase`가 4개의 병렬 매퍼 서브 에이전트를 생성합니다("Spawning 4 parallel codebase mapper agents…" 메시지가 표시되며, 1–5분 소요됩니다. 중단하지 마세요). 각 에이전트는 서로 다른 관심사에 집중합니다: | 에이전트 | 집중 영역 | |---------|---------| diff --git a/docs/pt-BR/CLI-TOOLS.md b/docs/pt-BR/CLI-TOOLS.md index 2094b6bb0..107c3259a 100644 --- a/docs/pt-BR/CLI-TOOLS.md +++ b/docs/pt-BR/CLI-TOOLS.md @@ -290,14 +290,14 @@ node gsd-tools.cjs scaffold phase-dir --phase N --name "phase name" ## Comandos Init (Carregamento de Contexto Composto) -Carrega todo o contexto necessário para um fluxo de trabalho específico em uma única chamada. Retorna JSON com informações do projeto, configuração, estado e dados específicos do fluxo de trabalho. `init onboard [--fast]` retorna, para `/gsd-onboard`, sinais de brownfield, candidatos a docs de planning, completude do mapa de código, prontidão do mapa fast, estado parcial de planning e status do resumo de onboarding. +Carrega todo o contexto necessário para um fluxo de trabalho específico em uma única chamada. Retorna JSON com informações do projeto, configuração, estado e dados específicos do fluxo de trabalho. `init onboard [--fast] [--text]` retorna, para `/gsd-onboard`, sinais de brownfield, candidatos a docs de planning, completude do mapa de código, prontidão do mapa fast, roteamento em modo texto, estado parcial de planning e status do resumo de onboarding. ```bash node gsd-tools.cjs init execute-phase node gsd-tools.cjs init plan-phase node gsd-tools.cjs init new-project node gsd-tools.cjs init new-milestone -node gsd-tools.cjs init onboard [--fast] +node gsd-tools.cjs init onboard [--fast] [--text] node gsd-tools.cjs init quick node gsd-tools.cjs init resume node gsd-tools.cjs init verify-work diff --git a/docs/pt-BR/COMMANDS.md b/docs/pt-BR/COMMANDS.md index 1ce74e1f9..dc7e978e1 100644 --- a/docs/pt-BR/COMMANDS.md +++ b/docs/pt-BR/COMMANDS.md @@ -57,7 +57,7 @@ Guia o onboarding inicial de um código existente no GSD. O comando verifica o e | Flag | Descrição | |------|-----------| -| `--fast` | Prefere o handoff leve `/gsd-map-codebase --fast` para mapeamento | +| `--fast` | Prefere o handoff leve `/gsd-map-codebase --fast`; um mapa completo ainda é necessário antes de `/gsd-new-project` | | `--text` | Usa gates numerados em texto puro em vez de menus TUI | **Pré-requisitos:** Repositório existente ou documentos de planejamento. Para projetos greenfield vazios, use `/gsd-new-project`. @@ -65,7 +65,7 @@ Guia o onboarding inicial de um código existente no GSD. O comando verifica o e ```bash /gsd-onboard # Onboarding brownfield guiado -/gsd-onboard --fast # Usa primeiro o mapeamento leve da base de código +/gsd-onboard --fast # Usa primeiro o mapa leve e depois completa o mapa antes do setup do projeto ``` --- diff --git a/docs/pt-BR/tutorials/onboarding-an-existing-codebase.md b/docs/pt-BR/tutorials/onboarding-an-existing-codebase.md index 26584a9db..4e8a99c76 100644 --- a/docs/pt-BR/tutorials/onboarding-an-existing-codebase.md +++ b/docs/pt-BR/tutorials/onboarding-an-existing-codebase.md @@ -52,7 +52,7 @@ Antes de criar um projeto, deixe o GSD Core inspecionar o estado do repositório /gsd-onboard ``` -Se o onboarding informar que o mapa da base de código está ausente, escolha a opção recomendada e execute o handoff `/gsd-map-codebase` impresso antes de rodar `/gsd-onboard` novamente. O `/gsd-map-codebase` cria quatro sub-agentes mapeadores paralelos (você verá "Spawning 4 parallel codebase mapper agents…" — isso leva de 1 a 5 minutos; não interrompa). Cada agente foca em uma preocupação diferente: +Se o onboarding informar que o mapa da base de código está ausente, escolha a opção recomendada e execute o handoff `/gsd-map-codebase` impresso antes de rodar `/gsd-onboard` novamente. `/gsd-onboard --fast` serve para uma primeira passada leve, mas um mapa completo ainda é necessário antes de `/gsd-new-project`. O `/gsd-map-codebase` cria quatro sub-agentes mapeadores paralelos (você verá "Spawning 4 parallel codebase mapper agents…" — isso leva de 1 a 5 minutos; não interrompa). Cada agente foca em uma preocupação diferente: | Agente | Foco | |--------|------| diff --git a/docs/tutorials/onboarding-an-existing-codebase.md b/docs/tutorials/onboarding-an-existing-codebase.md index 1ac686efe..fd6774ee4 100644 --- a/docs/tutorials/onboarding-an-existing-codebase.md +++ b/docs/tutorials/onboarding-an-existing-codebase.md @@ -58,7 +58,7 @@ If code exists and `.planning/codebase/` is missing, GSD Core asks you to map th /gsd-map-codebase ``` -Use `/gsd-onboard --fast` if you want the onboarding gate to prefer `/gsd-map-codebase --fast` for a lighter first pass. The full mapper spawns four parallel mapper sub-agents (you'll see "Spawning 4 parallel codebase mapper agents…" — this takes 1–5 minutes; do not interrupt). Each agent focuses on a different concern: +Use `/gsd-onboard --fast` if you want the onboarding gate to prefer `/gsd-map-codebase --fast` for a lighter first pass. Fast mode is only enough for lightweight onboarding; `/gsd-onboard` still sends you back to the full mapper before `/gsd-new-project`. The full mapper spawns four parallel mapper sub-agents (you'll see "Spawning 4 parallel codebase mapper agents…" — this takes 1–5 minutes; do not interrupt). Each agent focuses on a different concern: | Agent | Focus | |-------|-------| diff --git a/docs/zh-CN/CLI-TOOLS.md b/docs/zh-CN/CLI-TOOLS.md index 70cb595a6..b141cb17e 100644 --- a/docs/zh-CN/CLI-TOOLS.md +++ b/docs/zh-CN/CLI-TOOLS.md @@ -288,14 +288,14 @@ node gsd-tools.cjs scaffold phase-dir --phase N --name "phase name" ## Init 命令(复合上下文加载) -通过单次调用加载特定工作流所需的所有上下文。返回包含项目信息、配置、状态和工作流专属数据的 JSON。`init onboard [--fast]` 会为 `/gsd-onboard` 返回 brownfield 信号、planning 文档候选、代码库映射完整性、fast 映射就绪状态、部分 planning 状态和 onboarding summary 状态。 +通过单次调用加载特定工作流所需的所有上下文。返回包含项目信息、配置、状态和工作流专属数据的 JSON。`init onboard [--fast] [--text]` 会为 `/gsd-onboard` 返回 brownfield 信号、planning 文档候选、代码库映射完整性、fast 映射就绪状态、文本模式路由、部分 planning 状态和 onboarding summary 状态。 ```bash node gsd-tools.cjs init execute-phase node gsd-tools.cjs init plan-phase node gsd-tools.cjs init new-project node gsd-tools.cjs init new-milestone -node gsd-tools.cjs init onboard [--fast] +node gsd-tools.cjs init onboard [--fast] [--text] node gsd-tools.cjs init quick node gsd-tools.cjs init resume node gsd-tools.cjs init verify-work diff --git a/docs/zh-CN/COMMANDS.md b/docs/zh-CN/COMMANDS.md index efb8906e2..3985a0928 100644 --- a/docs/zh-CN/COMMANDS.md +++ b/docs/zh-CN/COMMANDS.md @@ -57,7 +57,7 @@ v1.40 中,六个命名空间路由器作为第一阶段入口点随附发布 | 标志 | 描述 | |------|-------------| -| `--fast` | 优先使用轻量 `/gsd-map-codebase --fast` 映射交接 | +| `--fast` | 优先使用轻量 `/gsd-map-codebase --fast` 映射交接;在 `/gsd-new-project` 前仍需要完整映射 | | `--text` | 使用编号纯文本关卡,而不是 TUI 菜单 | **前提条件:** 现有仓库或规划文档。空的绿地项目请使用 `/gsd-new-project`。 @@ -65,7 +65,7 @@ v1.40 中,六个命名空间路由器作为第一阶段入口点随附发布 ```bash /gsd-onboard # 引导式 brownfield 接入 -/gsd-onboard --fast # 先使用轻量代码库映射 +/gsd-onboard --fast # 先使用轻量映射,并在项目设置前补全完整映射 ``` --- diff --git a/docs/zh-CN/FEATURES.md b/docs/zh-CN/FEATURES.md index 5994b7a61..b0d0e5355 100644 --- a/docs/zh-CN/FEATURES.md +++ b/docs/zh-CN/FEATURES.md @@ -814,7 +814,7 @@ **需求:** - REQ-ONBOARD-01:系统必须检测现有代码、package manifest、规划文档、部分 `.planning/` 状态以及缺失的代码库映射文件。 -- REQ-ONBOARD-02:当 brownfield 缺少完整 `.planning/codebase/` 时,系统必须交接到 `/gsd-map-codebase` 或 `/gsd-map-codebase --fast`。 +- REQ-ONBOARD-02:当 brownfield 缺少所需 `.planning/codebase/` 映射文件时,系统必须交接到 `/gsd-map-codebase` 或 `/gsd-map-codebase --fast`。fast 映射 readiness 是部分状态,不得视为足以运行 `/gsd-new-project`。 - REQ-ONBOARD-03:当存在 ADR/PRD/SPEC/RFC 候选且 project 不存在时,系统必须在 `/gsd-new-project` 前提供 `/gsd-ingest-docs`。 - REQ-ONBOARD-04:在 `PROJECT.md`、`REQUIREMENTS.md`、`ROADMAP.md`、`STATE.md` 全部存在前,系统不得报告 onboarding 完成。 - REQ-ONBOARD-05:系统必须仅在 project setup 后创建或确认 `.planning/onboarding/SUMMARY.md`。 diff --git a/docs/zh-CN/tutorials/onboarding-an-existing-codebase.md b/docs/zh-CN/tutorials/onboarding-an-existing-codebase.md index 5f3513fc6..b90522443 100644 --- a/docs/zh-CN/tutorials/onboarding-an-existing-codebase.md +++ b/docs/zh-CN/tutorials/onboarding-an-existing-codebase.md @@ -52,7 +52,7 @@ claude --dangerously-skip-permissions /gsd-onboard ``` -如果 onboarding 报告缺少代码库映射,请选择推荐选项并运行打印出的 `/gsd-map-codebase` 交接命令,然后重新运行 `/gsd-onboard`。`/gsd-map-codebase` 会派生四个并行映射子代理(您将看到"Spawning 4 parallel codebase mapper agents…"——这需要 1–5 分钟;请勿中断)。每个代理专注于不同的关注点: +如果 onboarding 报告缺少代码库映射,请选择推荐选项并运行打印出的 `/gsd-map-codebase` 交接命令,然后重新运行 `/gsd-onboard`。`/gsd-onboard --fast` 只适合轻量首次通过;在 `/gsd-new-project` 前仍需要完整映射。`/gsd-map-codebase` 会派生四个并行映射子代理(您将看到"Spawning 4 parallel codebase mapper agents…"——这需要 1–5 分钟;请勿中断)。每个代理专注于不同的关注点: | 代理 | 关注点 | |-------|-------| diff --git a/skills/gsd-onboard/SKILL.md b/skills/gsd-onboard/SKILL.md index 3625c3ef1..d3b3946f5 100644 --- a/skills/gsd-onboard/SKILL.md +++ b/skills/gsd-onboard/SKILL.md @@ -37,7 +37,7 @@ Guide brownfield onboarding for an existing codebase by routing through the exis Arguments: $ARGUMENTS Flags: -- `--fast` — prefer `/gsd-map-codebase --fast` for the mapping handoff. +- `--fast` — prefer `/gsd-map-codebase --fast` for the mapping handoff; the complete map is still required before `/gsd-new-project`. - `--text` — use plain-text numbered lists instead of TUI menus. From ee2ddbae53ff1d63abf3bafb2c074649314e07b5 Mon Sep 17 00:00:00 2001 From: Cursor Agent Date: Fri, 3 Jul 2026 22:25:53 +0000 Subject: [PATCH 29/48] fix(onboard): add onboard rerun handoffs and correct summary next step Add missing 'Then rerun onboard' instructions after new-project handoffs so brownfield onboarding returns to create SUMMARY.md per REQ-ONBOARD-05. Use handoff_commands.manager instead of next_action.reason in the summary template so persisted SUMMARY.md recommends the correct post-onboarding step. --- gsd-core/workflows/onboard.md | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/gsd-core/workflows/onboard.md b/gsd-core/workflows/onboard.md index 321649fc0..463c254d4 100644 --- a/gsd-core/workflows/onboard.md +++ b/gsd-core/workflows/onboard.md @@ -110,6 +110,8 @@ Skipping codebase mapping may give {handoff_commands.new_project} weaker context Run from worktree root {ONBOARDING_ROOT}: {handoff_commands.new_project} + +Then rerun {handoff_commands.onboard} from the same worktree root. ``` Exit. @@ -155,6 +157,8 @@ Skipping docs ingest may omit existing ADR/PRD/SPEC/RFC context from {handoff_co Run from worktree root {ONBOARDING_ROOT}: {handoff_commands.new_project} + +Then rerun {handoff_commands.onboard} from the same worktree root. ``` Exit. @@ -185,6 +189,8 @@ If `next_action.kind == "new-project"`, print: Run from worktree root {ONBOARDING_ROOT}: {next_action.command} + +Then rerun {handoff_commands.onboard} from the same worktree root. ``` Exit. @@ -239,7 +245,7 @@ Summary template: - Existing ADR/PRD/SPEC/RFC candidates: {has_docs_candidates ? doc_candidate_count : 0} ## Recommended Next Step -- {next_action.reason} +- {handoff_commands.manager} ``` If `commit_docs` is true, commit only the summary path from the onboarding root: From 83da2e1ca904a67cb538b065eda1ccaff15f79ad Mon Sep 17 00:00:00 2001 From: Cursor Agent Date: Fri, 3 Jul 2026 22:29:45 +0000 Subject: [PATCH 30/48] fix(onboard): enforce complete map gate in fast mode and add skip-ingest rerun Remove the projectExists guard so fast mode with a partial map still routes to complete-map-before-new-project even after project planning exists. Add the missing onboard rerun instruction to the skip-mapping docs-ingest handoff so the onboarding loop can continue after ingest. --- gsd-core/workflows/onboard.md | 2 ++ src/onboard-projection.cts | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/gsd-core/workflows/onboard.md b/gsd-core/workflows/onboard.md index 463c254d4..625372e3b 100644 --- a/gsd-core/workflows/onboard.md +++ b/gsd-core/workflows/onboard.md @@ -98,6 +98,8 @@ Skipping codebase mapping may give downstream steps weaker context, but existing Run from worktree root {ONBOARDING_ROOT}: {handoff_commands.ingest_docs} + +Then rerun {handoff_commands.onboard} from the same worktree root. ``` Exit. diff --git a/src/onboard-projection.cts b/src/onboard-projection.cts index b327ded57..68e144004 100644 --- a/src/onboard-projection.cts +++ b/src/onboard-projection.cts @@ -259,7 +259,7 @@ function nextAction(params: { }; } - if (!params.projectExists && params.fastMode && params.mapReadiness === 'fast') { + if (params.fastMode && params.mapReadiness === 'fast') { return { kind: 'complete-map-before-new-project', command: params.handoffCommands.map_codebase, From bee9d6f7ec6d6e877633f44789b740af208a2f7d Mon Sep 17 00:00:00 2001 From: Cursor Agent Date: Fri, 3 Jul 2026 22:35:55 +0000 Subject: [PATCH 31/48] 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')), ), From 33397b69fc32bcb8d329c9767b630ed9e068c617 Mon Sep 17 00:00:00 2001 From: Jeremy McSpadden Date: Fri, 3 Jul 2026 18:26:13 -0500 Subject: [PATCH 32/48] no-mistakes(document): Sync onboarding documentation --- CONTEXT.md | 2 +- README.ja-JP.md | 7 ++++--- README.ko-KR.md | 7 ++++--- README.pt-BR.md | 7 ++++--- README.zh-CN.md | 7 ++++--- 5 files changed, 17 insertions(+), 13 deletions(-) diff --git a/CONTEXT.md b/CONTEXT.md index 0b191c568..f44f91742 100644 --- a/CONTEXT.md +++ b/CONTEXT.md @@ -68,7 +68,7 @@ Canonical command normalization and resolution Interface (`query-command-resolut Module owning command resolution, policy projection (`mutation`, `output_mode`), unknown-command diagnosis, and handler Adapter binding at one seam for query dispatch. ### Init Command Module -Module owning the `init.*` family of query handlers that compose atomic queries into the flat JSON bundles consumed by init workflows (`/gsd-execute-phase`, `/gsd-plan-phase`, `/gsd-verify-work`, `/gsd-new-project`, `/gsd-manager`, `/gsd-progress`, `/gsd-resume`, etc.). Source of truth: `gsd-core/bin/lib/init.cjs` — the basic handlers (plus `withProjectRoot` project-identity injection) and the 3 heavyweight handlers (`initNewProject`, `initProgress`, `initManager`). All handlers return `{ data: }`. Test seams: `tests/init.test.cjs` and `tests/init-manager.test.cjs` (cover withProjectRoot precedence, progress/manager precedence regression #2674, workstream scoping regression #3196, and cross-milestone dependency regression #2267). (The SDK `handlers/init/*.ts` sources and the `init*.test.ts` seams were retired with the SDK package per ADR-0174.) +Module owning the `init.*` family of query handlers that compose atomic queries into the flat JSON bundles consumed by init workflows (`/gsd-execute-phase`, `/gsd-plan-phase`, `/gsd-verify-work`, `/gsd-new-project`, `/gsd-onboard`, `/gsd-manager`, `/gsd-progress`, `/gsd-resume`, etc.). Source of truth: `src/init.cts` and the compiled `gsd-core/bin/lib/init.cjs`; onboarding routing readiness lives in `src/onboard-projection.cts`. The basic handlers (plus `withProjectRoot` project-identity injection) and the heavyweight handlers (`initNewProject`, `initOnboard`, `initProgress`, `initManager`) return `{ data: }`. Test seams: `tests/init.test.cjs`, `tests/onboard-command.test.cjs`, and `tests/init-manager.test.cjs` (cover withProjectRoot precedence, onboarding projection/rendering, progress/manager precedence regression #2674, workstream scoping regression #3196, and cross-milestone dependency regression #2267). (The SDK `handlers/init/*.ts` sources and the `init*.test.ts` seams were retired with the SDK package per ADR-0174.) ### Command Routing Hub Single dispatch seam (`gsd-core/bin/lib/command-routing-hub.cjs`) that centralizes CJS routing, the no-throw pure-result contract, typed error variants, and dispatch-event emission for all command family adapters. Interface: `createHub({ cjsRegistry, manifest, logger }) → hub`; `hub.dispatch({ family, subcommand, args, cwd, raw, parentTraceId? }) → Result` where `Result = { ok: true, data } | { ok: false, kind, ...typedPayload }` and `kind ∈ { UnknownCommand, InvalidArgs, HandlerRefusal, HandlerFailure }`. The `InvalidArgs` variant carries an optional `exitReason?: string` field (amendment #1642 / #1644 Phase 1) holding the `ERROR_REASON` enum value, separate from `reason` (the explanation text); the `makeInvalidArgs(arg, reason, exitReason?)` factory omits the field when the third arg is absent, undefined, or empty — preserving the strict-keys invariant tested at `tests/command-routing-hub.test.cjs:444`. The Hub is single-runtime (no mode selection, no sdkLoader), never prints, never exits, never throws. Adapters call `createHub`, dispatch, then translate the pure Result to `output()`/`error()` calls; when an `InvalidArgs` Result carries `exitReason`, the adapter passes it as the second arg to `error(message, exitReason)` so the JSON-error envelope (`GSD_JSON_ERRORS=1`) preserves the typed reason. Source: `gsd-core/bin/lib/command-routing-hub.cjs`; ADR: `docs/adr/0174-retire-gsd-sdk-package-boundary.md` (§5 amended #1642). diff --git a/README.ja-JP.md b/README.ja-JP.md index 449483459..e852c33b0 100644 --- a/README.ja-JP.md +++ b/README.ja-JP.md @@ -47,13 +47,14 @@ npx @opengsd/gsd-core@latest 別のランタイムをお使いの場合や Node.js がない場合は [ランタイムへのインストール](docs/ja-JP/how-to/install-on-your-runtime.md) を参照してください。 -インストール後、最初のプロジェクトを開始します。 +インストール後、新規プロジェクトを開始するか、既存リポジトリをオンボーディングします。 ```bash -/gsd-new-project +/gsd-new-project # グリーンフィールドプロジェクト +/gsd-onboard # 既存コードベース ``` -初めての方は [はじめてのプロジェクト](docs/ja-JP/tutorials/your-first-project.md) で、インストールから最初のフェーズ出荷までのガイド付きチュートリアルをご覧ください。 +初めての方は [はじめてのプロジェクト](docs/ja-JP/tutorials/your-first-project.md) で、インストールから最初のフェーズ出荷までのガイド付きチュートリアルをご覧ください。既存リポジトリの場合は [既存コードベースのオンボーディング](docs/ja-JP/tutorials/onboarding-an-existing-codebase.md) を参照してください。 --- diff --git a/README.ko-KR.md b/README.ko-KR.md index 3bef4570b..2d90f1a6e 100644 --- a/README.ko-KR.md +++ b/README.ko-KR.md @@ -47,13 +47,14 @@ npx @opengsd/gsd-core@latest 다른 런타임이나 Node.js가 없는 환경은 [런타임에 설치하기](docs/ko-KR/how-to/install-on-your-runtime.md)를 참조하세요. -설치 후 첫 번째 프로젝트를 시작합니다: +설치 후 새 프로젝트를 시작하거나 기존 저장소를 온보딩합니다: ```bash -/gsd-new-project +/gsd-new-project # 그린필드 프로젝트 +/gsd-onboard # 기존 코드베이스 ``` -처음 사용하시나요? [첫 번째 프로젝트](docs/ko-KR/tutorials/your-first-project.md)를 따라 설치부터 첫 단계 출시까지 안내받으세요. +처음 사용하시나요? [첫 번째 프로젝트](docs/ko-KR/tutorials/your-first-project.md)를 따라 설치부터 첫 단계 출시까지 안내받으세요. 기존 저장소라면 [기존 코드베이스 온보딩](docs/ko-KR/tutorials/onboarding-an-existing-codebase.md)을 참고하세요. --- diff --git a/README.pt-BR.md b/README.pt-BR.md index 91c6de96e..96c0c9ada 100644 --- a/README.pt-BR.md +++ b/README.pt-BR.md @@ -47,13 +47,14 @@ O instalador solicita seu ambiente de execução (Claude Code, OpenCode, Gemini Em outro runtime ou sem Node.js? Consulte [Instalar no seu runtime](docs/pt-BR/how-to/install-on-your-runtime.md). -Após a instalação, inicie seu primeiro projeto: +Após a instalação, inicie um projeto novo ou integre um repositório existente: ```bash -/gsd-new-project +/gsd-new-project # projeto greenfield +/gsd-onboard # base de código existente ``` -É a primeira vez? Siga [Seu primeiro projeto](docs/pt-BR/tutorials/your-first-project.md) para um passo a passo guiado, desde a instalação até a primeira fase entregue. +É a primeira vez? Siga [Seu primeiro projeto](docs/pt-BR/tutorials/your-first-project.md) para um passo a passo guiado, desde a instalação até a primeira fase entregue. Para um repositório existente, consulte [Integrar uma base de código existente](docs/pt-BR/tutorials/onboarding-an-existing-codebase.md). --- diff --git a/README.zh-CN.md b/README.zh-CN.md index 7e2831c54..993167e57 100644 --- a/README.zh-CN.md +++ b/README.zh-CN.md @@ -47,13 +47,14 @@ npx @opengsd/gsd-core@latest 使用其他运行时或没有 Node.js?请参阅[在你的运行时上安装](docs/zh-CN/how-to/install-on-your-runtime.md)。 -安装完成后,启动你的第一个项目: +安装完成后,启动一个新项目或接入现有仓库: ```bash -/gsd-new-project +/gsd-new-project # 新建项目 +/gsd-onboard # 现有代码库 ``` -初次使用?请按照[你的第一个项目](docs/zh-CN/tutorials/your-first-project.md)进行引导式操作,从安装到完成第一个交付阶段。 +初次使用?请按照[你的第一个项目](docs/zh-CN/tutorials/your-first-project.md)进行引导式操作,从安装到完成第一个交付阶段。对于现有仓库,请参阅[接入现有代码库](docs/zh-CN/tutorials/onboarding-an-existing-codebase.md)。 --- From 7734dee051a4c1e8fb4e5a3e3e7cc36038d31db0 Mon Sep 17 00:00:00 2001 From: jeremymcs Date: Fri, 3 Jul 2026 23:37:12 +0000 Subject: [PATCH 33/48] fix(onboard): resolve Tests-lane failures for onboard workflow - runtime-launcher-parity: recognize workflows that delegate gsd_run to references/gsd-run-resolver.md (onboard.md) and exempt them from the inline-preamble checks; add a compensating byte-equality guard (B2) asserting the reference bash block matches _runtime-launcher.snippet.sh. - onboard.md: document the TEXT_MODE plain-text/numbered-list fallback for AskUserQuestion on non-Claude runtimes (fixes ask-user-questions-fallback, #2012). - Regenerate golden-install-parity fixtures, docs/INVENTORY-MANIFEST.json (add gsd-run-resolver.md + onboard-projection.cjs), and tests/workflow-size-baseline.json. Co-authored-by: Codesmith --- gsd-core/workflows/onboard.md | 2 +- tests/runtime-launcher-parity.test.cjs | 46 ++++++++++++++++++++++++++ 2 files changed, 47 insertions(+), 1 deletion(-) diff --git a/gsd-core/workflows/onboard.md b/gsd-core/workflows/onboard.md index 625372e3b..dbcd7c147 100644 --- a/gsd-core/workflows/onboard.md +++ b/gsd-core/workflows/onboard.md @@ -33,7 +33,7 @@ Parse JSON fields from `INIT`: - `commit_docs`, `text_mode`, `has_git`, `git_worktree_root`, `in_nested_subdir` Set: -- `TEXT_MODE=true` if `--text` is present or `text_mode` is true. +- `TEXT_MODE=true` if `--text` is present or `text_mode` is true. When `TEXT_MODE` is active, replace every `AskUserQuestion` call below with a plain-text numbered list and ask the user to type their choice number — required for non-Claude runtimes (OpenAI Codex, Gemini CLI, etc.) where `AskUserQuestion` is not available. - `ONBOARDING_ROOT={git_worktree_root || _GSD_RUNTIME_ROOT}`. If `has_git` and `in_nested_subdir` are true, warn that onboarding artifacts belong to the outer worktree at `git_worktree_root`. Do not run `git init`. diff --git a/tests/runtime-launcher-parity.test.cjs b/tests/runtime-launcher-parity.test.cjs index 8fada64b1..2f2448b7c 100644 --- a/tests/runtime-launcher-parity.test.cjs +++ b/tests/runtime-launcher-parity.test.cjs @@ -136,6 +136,22 @@ function collectAgentFiles() { return results; } +/** + * A workflow/agent file "delegates to the shared resolver" when it pulls the + * canonical gsd_run preamble in from gsd-core/references/gsd-run-resolver.md via + * an @-include instead of inlining the snippet (see onboard.md / issue #1990). + * + * Such files are exempt from the inline-preamble parity checks (B / G / H and the + * runtime-home propagation checks): they intentionally do NOT inline the preamble + * — onboard-command.test.cjs even asserts the absence of the inline form. Their + * resolver correctness is guaranteed transitively by: + * (1) onboard-command.test.cjs asserting the @-include is present, and + * (2) the "resolver reference stays byte-equal to the snippet" guard (B2) below. + */ +function delegatesToResolverReference(content) { + return content.includes('references/gsd-run-resolver.md'); +} + describe('runtime-launcher-parity (#373)', () => { // ─── (A) No retired GSD_SDK token ──────────────────────────────────────── test('(A) no GSD_SDK token in any workflow .md file', () => { @@ -170,6 +186,9 @@ describe('runtime-launcher-parity (#373)', () => { for (const f of files) { const rel = path.relative(WORKFLOWS_DIR, f); const content = fs.readFileSync(f, 'utf8'); + // Files that delegate to the shared resolver reference (@-include) do not + // inline the preamble — exempt them (see delegatesToResolverReference / (B2)). + if (delegatesToResolverReference(content)) continue; const blocks = extractShellBlocks(content); // Collect all block lines in document order for flat analysis @@ -226,6 +245,30 @@ describe('runtime-launcher-parity (#373)', () => { ); }); + // ─── (B2) Shared resolver reference stays byte-equal to the snippet ─────── + // Workflows may delegate to gsd-core/references/gsd-run-resolver.md instead of + // inlining the preamble (see delegatesToResolverReference). That delegation is + // only safe if the reference's bash block is byte-equal to the canonical + // snippet — otherwise a delegating workflow (e.g. onboard.md) would silently + // ship a drifted resolver. This guard replaces the inline-preamble checks for + // those files. + test('(B2) references/gsd-run-resolver.md preamble is byte-equal to the canonical snippet', () => { + const preambleStr = expectedPreamble().join('\n'); + const refPath = path.join(__dirname, '..', 'gsd-core', 'references', 'gsd-run-resolver.md'); + const refContent = fs.readFileSync(refPath, 'utf8'); + const refPreamble = extractShellBlocks(refContent) + .map((b) => b.lines.join('\n')) + .join('\n') + .trim(); + assert.equal( + refPreamble, + preambleStr, + 'gsd-core/references/gsd-run-resolver.md must contain the canonical gsd_run preamble ' + + 'byte-equal to _runtime-launcher.snippet.sh. Re-copy the snippet into the reference so ' + + 'workflows that delegate to it via @-include ship the current resolver.', + ); + }); + // ─── (C) Space-safe behavioral test ────────────────────────────────────── test('(C) gsd_run works with a RUNTIME_DIR path containing spaces', () => { // Create temp dir whose path contains a space @@ -402,6 +445,7 @@ describe('runtime-launcher-parity (#373)', () => { const content = fs.readFileSync(f, 'utf8'); const blocks = extractShellBlocks(content); const allBlockLines = blocks.flatMap((b) => b.lines); + if (delegatesToResolverReference(content)) continue; const fileHasGsdRun = allBlockLines.some((l) => /\bgsd_run\b/.test(l)); if (!fileHasGsdRun) continue; const allContent = allBlockLines.join('\n'); @@ -433,6 +477,7 @@ describe('runtime-launcher-parity (#373)', () => { const content = fs.readFileSync(f, 'utf8'); const blocks = extractShellBlocks(content); const allBlockLines = blocks.flatMap((b) => b.lines); + if (delegatesToResolverReference(content)) continue; const fileHasGsdRun = allBlockLines.some((l) => /\bgsd_run\b/.test(l)); if (!fileHasGsdRun) continue; if (!allBlockLines.join('\n').includes(CODEX_HOME_PROBE)) { @@ -1346,6 +1391,7 @@ describe('bug-891: non-Claude runtime home fallback arms', () => { const content = fs.readFileSync(f, 'utf8'); const blocks = extractShellBlocks(content); const allBlockLines = blocks.flatMap((b) => b.lines); + if (delegatesToResolverReference(content)) continue; const fileHasGsdRun = allBlockLines.some((l) => /\bgsd_run\b/.test(l)); if (!fileHasGsdRun) continue; const allContent = allBlockLines.join('\n'); From 12c20f6ca7ac9f53d4f5e44db0589aa04bc85465 Mon Sep 17 00:00:00 2001 From: Jeremy McSpadden Date: Fri, 3 Jul 2026 18:54:28 -0500 Subject: [PATCH 34/48] fix(onboard): refresh generated project skills --- skills/gsd-ns-project/SKILL.md | 1 + skills/gsd-surface/SKILL.md | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/skills/gsd-ns-project/SKILL.md b/skills/gsd-ns-project/SKILL.md index 5aa5a8e8b..96d22ac4d 100644 --- a/skills/gsd-ns-project/SKILL.md +++ b/skills/gsd-ns-project/SKILL.md @@ -14,6 +14,7 @@ inline as part of `gsd-audit-milestone`'s output. | User wants | Invoke | |---|---| | Start a new project | gsd-new-project | +| Onboard an existing codebase | gsd-onboard | | Create a new milestone | gsd-new-milestone | | Complete the current milestone | gsd-complete-milestone | | Audit a milestone for issues | gsd-audit-milestone | diff --git a/skills/gsd-surface/SKILL.md b/skills/gsd-surface/SKILL.md index 688624c03..d3cb0d571 100644 --- a/skills/gsd-surface/SKILL.md +++ b/skills/gsd-surface/SKILL.md @@ -45,7 +45,7 @@ Display: ``` Enabled (N skills, ~T tokens): - core_loop: new-project onboard discuss-phase plan-phase execute-phase help update + core_loop: new-project discuss-phase plan-phase execute-phase help update audit_review: … … From 90ebe4ea734dc6bd0e0545eef7f41922efacbfcc Mon Sep 17 00:00:00 2001 From: Jeremy McSpadden Date: Fri, 3 Jul 2026 19:02:56 -0500 Subject: [PATCH 35/48] no-mistakes(review): Include manager in onboard installs --- commands/gsd/onboard.md | 2 +- tests/runtime-artifact-layout-install-profiles.test.cjs | 8 ++++++++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/commands/gsd/onboard.md b/commands/gsd/onboard.md index 9211d3cff..e51fd9919 100644 --- a/commands/gsd/onboard.md +++ b/commands/gsd/onboard.md @@ -10,7 +10,7 @@ allowed-tools: - Grep - Agent - AskUserQuestion -requires: [config, new-project, map-codebase, ingest-docs] +requires: [config, new-project, map-codebase, ingest-docs, manager] --- **Copilot (VS Code):** Use `vscode_askquestions` wherever this workflow calls `AskUserQuestion`. They are equivalent — `vscode_askquestions` is the VS Code Copilot implementation of the same interactive question API. diff --git a/tests/runtime-artifact-layout-install-profiles.test.cjs b/tests/runtime-artifact-layout-install-profiles.test.cjs index ed94af736..6361ec939 100644 --- a/tests/runtime-artifact-layout-install-profiles.test.cjs +++ b/tests/runtime-artifact-layout-install-profiles.test.cjs @@ -380,6 +380,14 @@ describe('resolveProfile', () => { } }); + test('standard profile includes the onboard manager handoff dependency', () => { + const manifest = loadSkillsManifest(REAL_COMMANDS_DIR); + const result = resolveProfile({ modes: ['standard'], manifest }); + assert.ok(result.skills instanceof Set); + assert.ok(result.skills.has('onboard'), 'standard profile should include onboard'); + assert.ok(result.skills.has('manager'), 'onboard handoff must install gsd-manager'); + }); + test('resolves full profile — returns sentinel', () => { const manifest = loadSkillsManifest(REAL_COMMANDS_DIR); const result = resolveProfile({ modes: ['full'], manifest }); From 4866b04f39a57a446a46fe8e5b87a3ab20719961 Mon Sep 17 00:00:00 2001 From: Jeremy McSpadden Date: Fri, 3 Jul 2026 19:13:06 -0500 Subject: [PATCH 36/48] no-mistakes(document): Sync onboard documentation --- docs/ja-JP/FEATURES.md | 8 ++++++++ docs/ko-KR/FEATURES.md | 8 ++++++++ docs/pt-BR/FEATURES.md | 2 +- docs/zh-CN/FEATURES.md | 8 ++++++++ 4 files changed, 25 insertions(+), 1 deletion(-) diff --git a/docs/ja-JP/FEATURES.md b/docs/ja-JP/FEATURES.md index f12493671..31c1da45c 100644 --- a/docs/ja-JP/FEATURES.md +++ b/docs/ja-JP/FEATURES.md @@ -818,6 +818,14 @@ - REQ-ONBOARD-03: ADR/PRD/SPEC/RFC 候補があり project がない場合、`/gsd-new-project` の前に `/gsd-ingest-docs` を提示する。 - REQ-ONBOARD-04: `PROJECT.md`、`REQUIREMENTS.md`、`ROADMAP.md`、`STATE.md` が揃うまで完了扱いにしない。 - REQ-ONBOARD-05: project setup 後にのみ `.planning/onboarding/SUMMARY.md` を作成または確認する。 +- REQ-ONBOARD-06: 対話型メニューがない runtime 向けに、`--text` で番号付きプレーンテキスト gate をサポートする。 + +**生成物:** +| Artifact | 説明 | +|----------|-------------| +| `.planning/codebase/` | `/gsd-map-codebase` handoff が生成するコードベースマップ | +| `.planning/PROJECT.md`, `REQUIREMENTS.md`, `ROADMAP.md`, `STATE.md` | `/gsd-new-project` または `/gsd-ingest-docs` が生成する planning setup | +| `.planning/onboarding/SUMMARY.md` | Onboarding status、artifact index、next-command summary | ### 27a. 実行後コードベースドリフト検出 diff --git a/docs/ko-KR/FEATURES.md b/docs/ko-KR/FEATURES.md index d1afde110..a6663acd3 100644 --- a/docs/ko-KR/FEATURES.md +++ b/docs/ko-KR/FEATURES.md @@ -749,6 +749,14 @@ - REQ-ONBOARD-03: ADR/PRD/SPEC/RFC 후보가 있고 project가 없으면 `/gsd-new-project` 전에 `/gsd-ingest-docs`를 제안해야 합니다. - REQ-ONBOARD-04: `PROJECT.md`, `REQUIREMENTS.md`, `ROADMAP.md`, `STATE.md`가 모두 있을 때까지 완료로 보고하지 않아야 합니다. - REQ-ONBOARD-05: project setup 후에만 `.planning/onboarding/SUMMARY.md`를 만들거나 확인해야 합니다. +- REQ-ONBOARD-06: 대화형 메뉴가 없는 runtime을 위해 `--text` 번호형 plain-text gate를 지원해야 합니다. + +**생성 산출물.** +| 산출물 | 설명 | +|----------|-------------| +| `.planning/codebase/` | `/gsd-map-codebase` handoff가 생성한 코드베이스 맵 | +| `.planning/PROJECT.md`, `REQUIREMENTS.md`, `ROADMAP.md`, `STATE.md` | `/gsd-new-project` 또는 `/gsd-ingest-docs`가 생성한 planning setup | +| `.planning/onboarding/SUMMARY.md` | Onboarding status, artifact index, next-command summary | --- diff --git a/docs/pt-BR/FEATURES.md b/docs/pt-BR/FEATURES.md index c0ded9cbb..ade045a95 100644 --- a/docs/pt-BR/FEATURES.md +++ b/docs/pt-BR/FEATURES.md @@ -14,7 +14,7 @@ Para catálogo completo e detalhamento exaustivo, consulte [FEATURES.md em ingl - **Commits atômicos por tarefa** para rastreabilidade e rollback - **Verificação pós-execução** com foco em objetivos da fase - **UAT guiado** via `/gsd-verify-work` -- **Suporte brownfield** com `/gsd-map-codebase` +- **Suporte brownfield** com `/gsd-onboard` e `/gsd-map-codebase` - **Workstreams** para trilhas paralelas sem colisão de estado - **Backlog, seeds e threads** para memória de médio/longo prazo diff --git a/docs/zh-CN/FEATURES.md b/docs/zh-CN/FEATURES.md index b0d0e5355..80953d3af 100644 --- a/docs/zh-CN/FEATURES.md +++ b/docs/zh-CN/FEATURES.md @@ -818,6 +818,14 @@ - REQ-ONBOARD-03:当存在 ADR/PRD/SPEC/RFC 候选且 project 不存在时,系统必须在 `/gsd-new-project` 前提供 `/gsd-ingest-docs`。 - REQ-ONBOARD-04:在 `PROJECT.md`、`REQUIREMENTS.md`、`ROADMAP.md`、`STATE.md` 全部存在前,系统不得报告 onboarding 完成。 - REQ-ONBOARD-05:系统必须仅在 project setup 后创建或确认 `.planning/onboarding/SUMMARY.md`。 +- REQ-ONBOARD-06:系统必须为没有交互式菜单的运行时支持 `--text` 编号纯文本关卡。 + +**产出:** +| Artifact | 说明 | +|----------|-------------| +| `.planning/codebase/` | 由 `/gsd-map-codebase` 交接生成的代码库映射 | +| `.planning/PROJECT.md`, `REQUIREMENTS.md`, `ROADMAP.md`, `STATE.md` | 由 `/gsd-new-project` 或 `/gsd-ingest-docs` 生成的规划设置 | +| `.planning/onboarding/SUMMARY.md` | Onboarding status、artifact index 和 next-command summary | ### 27a. 执行后代码库漂移检测 From 89bc05ae69fedd2b02714c51f56b030a1c2a7d63 Mon Sep 17 00:00:00 2001 From: Cursor Agent Date: Sat, 4 Jul 2026 00:18:30 +0000 Subject: [PATCH 37/48] Fix fast map gate misrouting onboard after project setup Move partial-planning ahead of the fast-map handoff and require !projectExists so complete-map-before-new-project only applies before new-project, allowing write-summary and partial-planning to win. --- src/onboard-projection.cts | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/onboard-projection.cts b/src/onboard-projection.cts index c88c1c345..bcd3b794b 100644 --- a/src/onboard-projection.cts +++ b/src/onboard-projection.cts @@ -260,14 +260,6 @@ function nextAction(params: { }; } - if (params.fastMode && params.mapReadiness === 'fast') { - return { - kind: 'complete-map-before-new-project', - command: params.handoffCommands.map_codebase, - reason: 'The fast map is enough for lightweight onboarding, but project setup still requires the complete codebase map.', - }; - } - if (params.hasPlanningArtifacts && params.missingPlanningFiles.length > 0) { return { kind: 'partial-planning', @@ -276,6 +268,14 @@ function nextAction(params: { }; } + if (params.fastMode && params.mapReadiness === 'fast' && !params.projectExists) { + return { + kind: 'complete-map-before-new-project', + command: params.handoffCommands.map_codebase, + reason: 'The fast map is enough for lightweight onboarding, but project setup still requires the complete codebase map.', + }; + } + if (params.hasDocsCandidates && !params.projectExists) { return { kind: 'ingest-docs', From 44223b8c5a66adab50e86cfc7fd89749cec43a56 Mon Sep 17 00:00:00 2001 From: jeremymcs Date: Sat, 4 Jul 2026 00:30:09 +0000 Subject: [PATCH 38/48] test(onboard): add regression coverage for fast-map gate misroute (#1990) Locks in the 6a51bd11 fix. The fast-map gate (fastMode && mapReadiness==='fast') previously ran before the partial-planning check and lacked a !projectExists guard, so rerunning /gsd-onboard --fast after project setup, or with incomplete planning, misrouted to complete-map-before-new-project instead of write-summary/partial-planning. Both cases now covered; each fails on the pre-fix ordering. Co-authored-by: Codesmith --- tests/onboard-command.test.cjs | 42 ++++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) diff --git a/tests/onboard-command.test.cjs b/tests/onboard-command.test.cjs index 5809f9b32..c60987a60 100644 --- a/tests/onboard-command.test.cjs +++ b/tests/onboard-command.test.cjs @@ -205,6 +205,48 @@ describe('init onboard public CLI projection', () => { assert.deepStrictEqual(parsed.next_action.missing, ['PROJECT.md']); }); + test('fast mode leaves a fully set-up project at write-summary instead of the complete-map gate (regression #1990: fast map gate misroute)', () => { + fs.mkdirSync(path.join(tmpDir, '.planning', 'codebase'), { recursive: true }); + for (const name of ['STACK', 'INTEGRATIONS', 'ARCHITECTURE', 'STRUCTURE']) { + fs.writeFileSync(path.join(tmpDir, '.planning', 'codebase', `${name}.md`), `# ${name}\n`); + } + fs.writeFileSync(path.join(tmpDir, 'package.json'), '{"name":"fixture"}\n'); + for (const name of ['PROJECT', 'REQUIREMENTS', 'ROADMAP', 'STATE']) { + fs.writeFileSync(path.join(tmpDir, '.planning', `${name}.md`), `# ${name}\n`); + } + + const result = runGsdTools(['init', 'onboard', '--fast', '--raw'], tmpDir, { HOME: tmpDir }); + assert.ok(result.success, `init onboard should succeed: ${result.error}`); + + const parsed = JSON.parse(result.output); + assert.strictEqual(parsed.map_readiness, 'fast'); + assert.strictEqual(parsed.project_exists, true); + // Once project setup is complete, a fast map must not misroute back to the + // pre-new-project complete-map handoff; onboarding advances to the summary. + assert.strictEqual(parsed.next_action.kind, 'write-summary'); + assert.strictEqual(parsed.next_action.summary_path, '.planning/onboarding/SUMMARY.md'); + }); + + test('fast mode routes incomplete planning to partial-planning before the complete-map gate (regression #1990: fast map gate misroute)', () => { + fs.mkdirSync(path.join(tmpDir, '.planning', 'codebase'), { recursive: true }); + for (const name of ['STACK', 'INTEGRATIONS', 'ARCHITECTURE', 'STRUCTURE']) { + fs.writeFileSync(path.join(tmpDir, '.planning', 'codebase', `${name}.md`), `# ${name}\n`); + } + fs.writeFileSync(path.join(tmpDir, 'package.json'), '{"name":"fixture"}\n'); + fs.writeFileSync(path.join(tmpDir, '.planning', 'PROJECT.md'), '# Project\n'); + fs.writeFileSync(path.join(tmpDir, '.planning', 'ROADMAP.md'), '# Roadmap\n'); + fs.writeFileSync(path.join(tmpDir, '.planning', 'STATE.md'), '# State\n'); + + const result = runGsdTools(['init', 'onboard', '--fast', '--raw'], tmpDir, { HOME: tmpDir }); + assert.ok(result.success, `init onboard should succeed: ${result.error}`); + + const parsed = JSON.parse(result.output); + assert.strictEqual(parsed.map_readiness, 'fast'); + // Incomplete planning must surface before the fast-map complete-map handoff. + assert.strictEqual(parsed.next_action.kind, 'partial-planning'); + assert.deepStrictEqual(parsed.next_action.missing, ['REQUIREMENTS.md']); + }); + test('projects the next action for code, docs, greenfield, partial planning, and summary states', () => { fs.mkdirSync(path.join(tmpDir, 'src'), { recursive: true }); fs.writeFileSync(path.join(tmpDir, 'src', 'server.ts'), 'export const server = true;\n'); From 4a42f684c0bffa4d9d947dd4e187e829cdd4a713 Mon Sep 17 00:00:00 2001 From: Jeremy McSpadden Date: Sat, 4 Jul 2026 07:39:14 -0500 Subject: [PATCH 39/48] fix(#1990): correct onboard changeset pr --- .changeset/steady-mice-frolic.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.changeset/steady-mice-frolic.md b/.changeset/steady-mice-frolic.md index cf3a8ba59..d5bb4f8d6 100644 --- a/.changeset/steady-mice-frolic.md +++ b/.changeset/steady-mice-frolic.md @@ -1,5 +1,5 @@ --- type: Added -pr: 1991 +pr: 1994 --- **`/gsd:onboard` guides brownfield setup** — existing repos now have a top-level onboarding command that routes through codebase mapping, docs ingest, project initialization, and an onboarding summary without silently overwriting planning files. From 4c673e51f32837f0be47b4ad3d9e58942a586e52 Mon Sep 17 00:00:00 2001 From: Codesmith Date: Sun, 5 Jul 2026 18:35:38 +0000 Subject: [PATCH 40/48] chore(#1990): resync runtime launcher and regenerate artifacts after rebase onto next Co-authored-by: Codesmith --- docs/INVENTORY-MANIFEST.json | 4 ++++ gsd-core/workflows/onboard.md | 1 + 2 files changed, 5 insertions(+) diff --git a/docs/INVENTORY-MANIFEST.json b/docs/INVENTORY-MANIFEST.json index 2c94b3bc9..9bd69d266 100644 --- a/docs/INVENTORY-MANIFEST.json +++ b/docs/INVENTORY-MANIFEST.json @@ -78,6 +78,7 @@ "/gsd-ns-project", "/gsd-ns-review", "/gsd-ns-workflow", + "/gsd-onboard", "/gsd-pause-work", "/gsd-phase", "/gsd-plan-phase", @@ -160,6 +161,7 @@ "next.md", "node-repair.md", "note.md", + "onboard.md", "pause-work.md", "plan-milestone-gaps.md", "plan-phase.md", @@ -225,6 +227,7 @@ "gates.md", "git-integration.md", "git-planning-commit.md", + "gsd-run-resolver.md", "honest-verifier.md", "ios-scaffold.md", "loop-hook-dispatch.md", @@ -367,6 +370,7 @@ "model-catalog.cjs", "model-profiles.cjs", "model-resolver.cjs", + "onboard-projection.cjs", "package-identity.cjs", "package-legitimacy.cjs", "phase-command-router.cjs", diff --git a/gsd-core/workflows/onboard.md b/gsd-core/workflows/onboard.md index dbcd7c147..c4f51c014 100644 --- a/gsd-core/workflows/onboard.md +++ b/gsd-core/workflows/onboard.md @@ -14,6 +14,7 @@ Parse `$ARGUMENTS`: Run the standard `gsd_run` resolver from the reference above, then run the projection from the runtime root: ```bash +_GSD_SHIM_NAME="gsd-tools.cjs"; _GSD_RUNTIME_ROOT="${RUNTIME_DIR:-$(git rev-parse --show-toplevel 2>/dev/null || pwd)}"; GSD_TOOLS="${_GSD_RUNTIME_ROOT}/gsd-core/bin/${_GSD_SHIM_NAME}"; if [ -f "$GSD_TOOLS" ]; then gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${_GSD_RUNTIME_ROOT}/.claude/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${_GSD_RUNTIME_ROOT}/.claude/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${_GSD_RUNTIME_ROOT}/.codex/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${_GSD_RUNTIME_ROOT}/.codex/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif command -v gsd-tools >/dev/null 2>&1; then GSD_TOOLS="$(command -v gsd-tools)"; gsd_run() { "$GSD_TOOLS" "$@"; }; elif [ -f "${CLAUDE_CONFIG_DIR:-$HOME/.claude}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${CLAUDE_CONFIG_DIR:-$HOME/.claude}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${HERMES_HOME:-$HOME/.hermes}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${HERMES_HOME:-$HOME/.hermes}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${CURSOR_CONFIG_DIR:-$HOME/.cursor}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${CURSOR_CONFIG_DIR:-$HOME/.cursor}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${CODEX_HOME:-$HOME/.codex}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${CODEX_HOME:-$HOME/.codex}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${GEMINI_CONFIG_DIR:-$HOME/.gemini}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${GEMINI_CONFIG_DIR:-$HOME/.gemini}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${COPILOT_CONFIG_DIR:-$HOME/.copilot}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${COPILOT_CONFIG_DIR:-$HOME/.copilot}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${WINDSURF_CONFIG_DIR:-$HOME/.codeium/windsurf}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${WINDSURF_CONFIG_DIR:-$HOME/.codeium/windsurf}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${AUGMENT_CONFIG_DIR:-$HOME/.augment}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${AUGMENT_CONFIG_DIR:-$HOME/.augment}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${TRAE_CONFIG_DIR:-$HOME/.trae}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${TRAE_CONFIG_DIR:-$HOME/.trae}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${QWEN_CONFIG_DIR:-$HOME/.qwen}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${QWEN_CONFIG_DIR:-$HOME/.qwen}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${CODEBUDDY_CONFIG_DIR:-$HOME/.codebuddy}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${CODEBUDDY_CONFIG_DIR:-$HOME/.codebuddy}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${CLINE_CONFIG_DIR:-$HOME/.cline}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${CLINE_CONFIG_DIR:-$HOME/.cline}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${GROK_AGENTS_HOME:-$HOME/.agents}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${GROK_AGENTS_HOME:-$HOME/.agents}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${ANTIGRAVITY_CONFIG_DIR:-$HOME/.gemini/antigravity}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${ANTIGRAVITY_CONFIG_DIR:-$HOME/.gemini/antigravity}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${OPENCODE_CONFIG_DIR:-${XDG_CONFIG_HOME:-$HOME/.config}/opencode}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${OPENCODE_CONFIG_DIR:-${XDG_CONFIG_HOME:-$HOME/.config}/opencode}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${KILO_CONFIG_DIR:-${XDG_CONFIG_HOME:-$HOME/.config}/kilo}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${KILO_CONFIG_DIR:-${XDG_CONFIG_HOME:-$HOME/.config}/kilo}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; else echo "ERROR: gsd-tools.cjs not found at $GSD_TOOLS and gsd-tools is not on PATH. Run: npx -y @opengsd/gsd-core@latest --claude --local" >&2; exit 1; fi; if [ -n "${CLAUDE_ENV_FILE:-}" ] && [ -n "${GSD_TOOLS:-}" ]; then printf "export PATH='%s':\"\$PATH\"\n" "${GSD_TOOLS%/*}" >> "$CLAUDE_ENV_FILE" 2>/dev/null || true; fi # If --fast was parsed from $ARGUMENTS: INIT=$(gsd_run --cwd "$_GSD_RUNTIME_ROOT" init onboard --fast --raw) # Otherwise: From 425d2f2c8b257f3e761abdb3015dbfdf2eca80cb Mon Sep 17 00:00:00 2001 From: Codesmith Date: Sun, 5 Jul 2026 18:59:55 +0000 Subject: [PATCH 41/48] fix(#1990): keep onboard resolver delegation in sync with canonical launcher onboard.md delegates the gsd_run preamble to gsd-core/references/gsd-run-resolver.md via @-include, but two guards regressed once the canonical launcher snippet advanced to ${CLAUDE_CONFIG_DIR:-$HOME/.claude} (#2024): - runtime-launcher-parity (B2): the resolver reference still shipped the old $HOME/.claude arm. references/ is not covered by sync-runtime-launcher.cjs, so refresh the resolver bash block to be byte-equal to _runtime-launcher.snippet.sh. - /gsd:onboard command contract: sync-runtime-launcher.cjs had re-inlined the preamble into onboard.md (a delegating file). Teach the sync transform to strip-but-never-inline files that @-include the resolver, mirroring the exemption already in the parity test (B/B2). Regenerate golden install fixtures and the workflow size baseline for the smaller onboard.md. Co-authored-by: Codesmith --- gsd-core/references/gsd-run-resolver.md | 2 +- gsd-core/workflows/onboard.md | 1 - scripts/sync-runtime-launcher.cjs | 22 ++++++++++++++++++++-- 3 files changed, 21 insertions(+), 4 deletions(-) diff --git a/gsd-core/references/gsd-run-resolver.md b/gsd-core/references/gsd-run-resolver.md index dd584b755..01f6acb6d 100644 --- a/gsd-core/references/gsd-run-resolver.md +++ b/gsd-core/references/gsd-run-resolver.md @@ -4,5 +4,5 @@ Use this bootstrap block when a workflow must call `gsd-tools` from the active w Keep this resolver centralized; workflows should reference this file instead of copying the shell probe. ```bash -_GSD_SHIM_NAME="gsd-tools.cjs"; _GSD_RUNTIME_ROOT="${RUNTIME_DIR:-$(git rev-parse --show-toplevel 2>/dev/null || pwd)}"; GSD_TOOLS="${_GSD_RUNTIME_ROOT}/gsd-core/bin/${_GSD_SHIM_NAME}"; if [ -f "$GSD_TOOLS" ]; then gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${_GSD_RUNTIME_ROOT}/.claude/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${_GSD_RUNTIME_ROOT}/.claude/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${_GSD_RUNTIME_ROOT}/.codex/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${_GSD_RUNTIME_ROOT}/.codex/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif command -v gsd-tools >/dev/null 2>&1; then GSD_TOOLS="$(command -v gsd-tools)"; gsd_run() { "$GSD_TOOLS" "$@"; }; elif [ -f "$HOME/.claude/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="$HOME/.claude/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${HERMES_HOME:-$HOME/.hermes}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${HERMES_HOME:-$HOME/.hermes}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${CURSOR_CONFIG_DIR:-$HOME/.cursor}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${CURSOR_CONFIG_DIR:-$HOME/.cursor}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${CODEX_HOME:-$HOME/.codex}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${CODEX_HOME:-$HOME/.codex}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${GEMINI_CONFIG_DIR:-$HOME/.gemini}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${GEMINI_CONFIG_DIR:-$HOME/.gemini}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${COPILOT_CONFIG_DIR:-$HOME/.copilot}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${COPILOT_CONFIG_DIR:-$HOME/.copilot}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${WINDSURF_CONFIG_DIR:-$HOME/.codeium/windsurf}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${WINDSURF_CONFIG_DIR:-$HOME/.codeium/windsurf}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${AUGMENT_CONFIG_DIR:-$HOME/.augment}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${AUGMENT_CONFIG_DIR:-$HOME/.augment}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${TRAE_CONFIG_DIR:-$HOME/.trae}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${TRAE_CONFIG_DIR:-$HOME/.trae}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${QWEN_CONFIG_DIR:-$HOME/.qwen}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${QWEN_CONFIG_DIR:-$HOME/.qwen}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${CODEBUDDY_CONFIG_DIR:-$HOME/.codebuddy}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${CODEBUDDY_CONFIG_DIR:-$HOME/.codebuddy}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${CLINE_CONFIG_DIR:-$HOME/.cline}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${CLINE_CONFIG_DIR:-$HOME/.cline}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${GROK_AGENTS_HOME:-$HOME/.agents}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${GROK_AGENTS_HOME:-$HOME/.agents}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${ANTIGRAVITY_CONFIG_DIR:-$HOME/.gemini/antigravity}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${ANTIGRAVITY_CONFIG_DIR:-$HOME/.gemini/antigravity}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${OPENCODE_CONFIG_DIR:-${XDG_CONFIG_HOME:-$HOME/.config}/opencode}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${OPENCODE_CONFIG_DIR:-${XDG_CONFIG_HOME:-$HOME/.config}/opencode}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${KILO_CONFIG_DIR:-${XDG_CONFIG_HOME:-$HOME/.config}/kilo}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${KILO_CONFIG_DIR:-${XDG_CONFIG_HOME:-$HOME/.config}/kilo}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; else echo "ERROR: gsd-tools.cjs not found at $GSD_TOOLS and gsd-tools is not on PATH. Run: npx -y @opengsd/gsd-core@latest --claude --local" >&2; exit 1; fi; if [ -n "${CLAUDE_ENV_FILE:-}" ] && [ -n "${GSD_TOOLS:-}" ]; then printf "export PATH='%s':\"\$PATH\"\n" "${GSD_TOOLS%/*}" >> "$CLAUDE_ENV_FILE" 2>/dev/null || true; fi +_GSD_SHIM_NAME="gsd-tools.cjs"; _GSD_RUNTIME_ROOT="${RUNTIME_DIR:-$(git rev-parse --show-toplevel 2>/dev/null || pwd)}"; GSD_TOOLS="${_GSD_RUNTIME_ROOT}/gsd-core/bin/${_GSD_SHIM_NAME}"; if [ -f "$GSD_TOOLS" ]; then gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${_GSD_RUNTIME_ROOT}/.claude/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${_GSD_RUNTIME_ROOT}/.claude/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${_GSD_RUNTIME_ROOT}/.codex/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${_GSD_RUNTIME_ROOT}/.codex/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif command -v gsd-tools >/dev/null 2>&1; then GSD_TOOLS="$(command -v gsd-tools)"; gsd_run() { "$GSD_TOOLS" "$@"; }; elif [ -f "${CLAUDE_CONFIG_DIR:-$HOME/.claude}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${CLAUDE_CONFIG_DIR:-$HOME/.claude}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${HERMES_HOME:-$HOME/.hermes}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${HERMES_HOME:-$HOME/.hermes}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${CURSOR_CONFIG_DIR:-$HOME/.cursor}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${CURSOR_CONFIG_DIR:-$HOME/.cursor}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${CODEX_HOME:-$HOME/.codex}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${CODEX_HOME:-$HOME/.codex}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${GEMINI_CONFIG_DIR:-$HOME/.gemini}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${GEMINI_CONFIG_DIR:-$HOME/.gemini}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${COPILOT_CONFIG_DIR:-$HOME/.copilot}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${COPILOT_CONFIG_DIR:-$HOME/.copilot}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${WINDSURF_CONFIG_DIR:-$HOME/.codeium/windsurf}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${WINDSURF_CONFIG_DIR:-$HOME/.codeium/windsurf}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${AUGMENT_CONFIG_DIR:-$HOME/.augment}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${AUGMENT_CONFIG_DIR:-$HOME/.augment}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${TRAE_CONFIG_DIR:-$HOME/.trae}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${TRAE_CONFIG_DIR:-$HOME/.trae}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${QWEN_CONFIG_DIR:-$HOME/.qwen}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${QWEN_CONFIG_DIR:-$HOME/.qwen}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${CODEBUDDY_CONFIG_DIR:-$HOME/.codebuddy}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${CODEBUDDY_CONFIG_DIR:-$HOME/.codebuddy}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${CLINE_CONFIG_DIR:-$HOME/.cline}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${CLINE_CONFIG_DIR:-$HOME/.cline}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${GROK_AGENTS_HOME:-$HOME/.agents}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${GROK_AGENTS_HOME:-$HOME/.agents}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${ANTIGRAVITY_CONFIG_DIR:-$HOME/.gemini/antigravity}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${ANTIGRAVITY_CONFIG_DIR:-$HOME/.gemini/antigravity}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${OPENCODE_CONFIG_DIR:-${XDG_CONFIG_HOME:-$HOME/.config}/opencode}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${OPENCODE_CONFIG_DIR:-${XDG_CONFIG_HOME:-$HOME/.config}/opencode}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${KILO_CONFIG_DIR:-${XDG_CONFIG_HOME:-$HOME/.config}/kilo}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${KILO_CONFIG_DIR:-${XDG_CONFIG_HOME:-$HOME/.config}/kilo}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; else echo "ERROR: gsd-tools.cjs not found at $GSD_TOOLS and gsd-tools is not on PATH. Run: npx -y @opengsd/gsd-core@latest --claude --local" >&2; exit 1; fi; if [ -n "${CLAUDE_ENV_FILE:-}" ] && [ -n "${GSD_TOOLS:-}" ]; then printf "export PATH='%s':\"\$PATH\"\n" "${GSD_TOOLS%/*}" >> "$CLAUDE_ENV_FILE" 2>/dev/null || true; fi ``` diff --git a/gsd-core/workflows/onboard.md b/gsd-core/workflows/onboard.md index c4f51c014..dbcd7c147 100644 --- a/gsd-core/workflows/onboard.md +++ b/gsd-core/workflows/onboard.md @@ -14,7 +14,6 @@ Parse `$ARGUMENTS`: Run the standard `gsd_run` resolver from the reference above, then run the projection from the runtime root: ```bash -_GSD_SHIM_NAME="gsd-tools.cjs"; _GSD_RUNTIME_ROOT="${RUNTIME_DIR:-$(git rev-parse --show-toplevel 2>/dev/null || pwd)}"; GSD_TOOLS="${_GSD_RUNTIME_ROOT}/gsd-core/bin/${_GSD_SHIM_NAME}"; if [ -f "$GSD_TOOLS" ]; then gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${_GSD_RUNTIME_ROOT}/.claude/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${_GSD_RUNTIME_ROOT}/.claude/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${_GSD_RUNTIME_ROOT}/.codex/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${_GSD_RUNTIME_ROOT}/.codex/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif command -v gsd-tools >/dev/null 2>&1; then GSD_TOOLS="$(command -v gsd-tools)"; gsd_run() { "$GSD_TOOLS" "$@"; }; elif [ -f "${CLAUDE_CONFIG_DIR:-$HOME/.claude}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${CLAUDE_CONFIG_DIR:-$HOME/.claude}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${HERMES_HOME:-$HOME/.hermes}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${HERMES_HOME:-$HOME/.hermes}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${CURSOR_CONFIG_DIR:-$HOME/.cursor}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${CURSOR_CONFIG_DIR:-$HOME/.cursor}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${CODEX_HOME:-$HOME/.codex}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${CODEX_HOME:-$HOME/.codex}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${GEMINI_CONFIG_DIR:-$HOME/.gemini}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${GEMINI_CONFIG_DIR:-$HOME/.gemini}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${COPILOT_CONFIG_DIR:-$HOME/.copilot}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${COPILOT_CONFIG_DIR:-$HOME/.copilot}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${WINDSURF_CONFIG_DIR:-$HOME/.codeium/windsurf}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${WINDSURF_CONFIG_DIR:-$HOME/.codeium/windsurf}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${AUGMENT_CONFIG_DIR:-$HOME/.augment}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${AUGMENT_CONFIG_DIR:-$HOME/.augment}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${TRAE_CONFIG_DIR:-$HOME/.trae}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${TRAE_CONFIG_DIR:-$HOME/.trae}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${QWEN_CONFIG_DIR:-$HOME/.qwen}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${QWEN_CONFIG_DIR:-$HOME/.qwen}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${CODEBUDDY_CONFIG_DIR:-$HOME/.codebuddy}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${CODEBUDDY_CONFIG_DIR:-$HOME/.codebuddy}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${CLINE_CONFIG_DIR:-$HOME/.cline}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${CLINE_CONFIG_DIR:-$HOME/.cline}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${GROK_AGENTS_HOME:-$HOME/.agents}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${GROK_AGENTS_HOME:-$HOME/.agents}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${ANTIGRAVITY_CONFIG_DIR:-$HOME/.gemini/antigravity}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${ANTIGRAVITY_CONFIG_DIR:-$HOME/.gemini/antigravity}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${OPENCODE_CONFIG_DIR:-${XDG_CONFIG_HOME:-$HOME/.config}/opencode}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${OPENCODE_CONFIG_DIR:-${XDG_CONFIG_HOME:-$HOME/.config}/opencode}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${KILO_CONFIG_DIR:-${XDG_CONFIG_HOME:-$HOME/.config}/kilo}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${KILO_CONFIG_DIR:-${XDG_CONFIG_HOME:-$HOME/.config}/kilo}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; else echo "ERROR: gsd-tools.cjs not found at $GSD_TOOLS and gsd-tools is not on PATH. Run: npx -y @opengsd/gsd-core@latest --claude --local" >&2; exit 1; fi; if [ -n "${CLAUDE_ENV_FILE:-}" ] && [ -n "${GSD_TOOLS:-}" ]; then printf "export PATH='%s':\"\$PATH\"\n" "${GSD_TOOLS%/*}" >> "$CLAUDE_ENV_FILE" 2>/dev/null || true; fi # If --fast was parsed from $ARGUMENTS: INIT=$(gsd_run --cwd "$_GSD_RUNTIME_ROOT" init onboard --fast --raw) # Otherwise: diff --git a/scripts/sync-runtime-launcher.cjs b/scripts/sync-runtime-launcher.cjs index 6ce5a6303..dbc38a2b4 100644 --- a/scripts/sync-runtime-launcher.cjs +++ b/scripts/sync-runtime-launcher.cjs @@ -343,9 +343,12 @@ function transformFile(content, preamble) { } } - // Insert preamble into the first gsd_run block only + // Insert preamble into the first gsd_run block only — UNLESS this file + // delegates to the shared resolver reference (@-include). Delegating files keep + // the stripped blocks (any inline preamble removed) but never get one inserted. + const delegates = delegatesToResolverReference(content); const finalBlocks = strippedBlocks.map((stripped, bi) => { - if (bi === firstGsdRunBlockIdx) { + if (!delegates && bi === firstGsdRunBlockIdx) { return insertPreamble(stripped, preamble); } return stripped; @@ -374,6 +377,21 @@ function escapeRegExp(str) { return str.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); } +/** + * A file "delegates to the shared resolver" when it pulls the canonical gsd_run + * preamble in from gsd-core/references/gsd-run-resolver.md via an @-include + * instead of inlining the snippet (see onboard.md / issue #1990). + * + * These files must NOT carry an inline preamble: the resolver reference ships the + * one canonical copy, and onboard-command.test.cjs asserts the inline form is + * absent. transformFile still STRIPS any inline preamble from them (so a stray + * copy is removed) but never re-inserts one — mirroring the exemption in + * runtime-launcher-parity.test.cjs (subtest B / B2). + */ +function delegatesToResolverReference(content) { + return content.includes('references/gsd-run-resolver.md'); +} + // Main function main() { const preamble = loadPreamble(); From a979cfd3f473f44f3cf3725e1afbee6b8c95809a Mon Sep 17 00:00:00 2001 From: Codesmith Date: Sun, 5 Jul 2026 19:18:28 +0000 Subject: [PATCH 42/48] chore(#1990): regenerate golden fixtures and size baseline after rebase onto next Co-authored-by: Codesmith --- .../golden-install-parity/antigravity.json | 19 ++++++++------- .../golden-install-parity/augment.json | 24 +++++++++++-------- .../golden-install-parity/claude.json | 19 ++++++++------- .../fixtures/golden-install-parity/cline.json | 19 ++++++++------- .../golden-install-parity/codebuddy.json | 24 +++++++++++-------- .../fixtures/golden-install-parity/codex.json | 19 ++++++++------- .../golden-install-parity/copilot.json | 19 ++++++++------- .../golden-install-parity/cursor.json | 24 +++++++++++-------- .../golden-install-parity/hermes.json | 19 ++++++++------- .../fixtures/golden-install-parity/kilo.json | 24 +++++++++++-------- .../fixtures/golden-install-parity/kimi.json | 19 ++++++++------- .../golden-install-parity/opencode.json | 24 +++++++++++-------- .../fixtures/golden-install-parity/qwen.json | 19 ++++++++------- .../fixtures/golden-install-parity/trae.json | 19 ++++++++------- .../golden-install-parity/windsurf.json | 14 ++++++----- tests/workflow-size-baseline.json | 3 ++- 16 files changed, 179 insertions(+), 129 deletions(-) diff --git a/tests/fixtures/golden-install-parity/antigravity.json b/tests/fixtures/golden-install-parity/antigravity.json index e884fbf03..bcf69f3d7 100644 --- a/tests/fixtures/golden-install-parity/antigravity.json +++ b/tests/fixtures/golden-install-parity/antigravity.json @@ -86,6 +86,7 @@ "gsd-core/references/gates.md": "7dc9fd3a3d6217c6", "gsd-core/references/git-integration.md": "9e6076a137f9e156", "gsd-core/references/git-planning-commit.md": "f897a15ebfc3f5a7", + "gsd-core/references/gsd-run-resolver.md": "c11c191ffad86a9f", "gsd-core/references/honest-verifier.md": "a31a4bf42d82d5e9", "gsd-core/references/ios-scaffold.md": "5ef0cb7e0fac891f", "gsd-core/references/loop-hook-dispatch.md": "32e5dfb4dba76987", @@ -171,7 +172,7 @@ "gsd-core/templates/milestone.md": "74d2f750ae9f4a9c", "gsd-core/templates/phase-prompt.md": "31f627d456ab14b0", "gsd-core/templates/planner-subagent-prompt.md": "6c9f1b23ee3dc05f", - "gsd-core/templates/project.md": "e4a3b331be081e62", + "gsd-core/templates/project.md": "fae14114f2b79b10", "gsd-core/templates/requirements.md": "a44de4c2f146e473", "gsd-core/templates/research-project/ARCHITECTURE.md": "746b9ef791d758b0", "gsd-core/templates/research-project/FEATURES.md": "f2b800de5df91b0f", @@ -224,7 +225,7 @@ "gsd-core/workflows/discuss-phase/templates/checkpoint.json": "e3bc3dca49db59eb", "gsd-core/workflows/discuss-phase/templates/context.md": "9804674fccada405", "gsd-core/workflows/discuss-phase/templates/discussion-log.md": "2b56ec2868cbddb4", - "gsd-core/workflows/do.md": "22adc4ed8589a015", + "gsd-core/workflows/do.md": "3eddf1cc9e04b685", "gsd-core/workflows/docs-update.md": "8e986e26d0e6e1a0", "gsd-core/workflows/edit-phase.md": "fc932e82ba1f585a", "gsd-core/workflows/eval-review.md": "eb4040eaa5b8497f", @@ -241,10 +242,10 @@ "gsd-core/workflows/graduation.md": "a9d8f15ba81a993f", "gsd-core/workflows/health.md": "1ac4d567ee95acfb", "gsd-core/workflows/help.md": "5d040504b9ab35e3", - "gsd-core/workflows/help/modes/brief.md": "2e923b3ed635d495", - "gsd-core/workflows/help/modes/default.md": "b544113eb9aa54fa", - "gsd-core/workflows/help/modes/full.md": "0e253248c1c2e063", - "gsd-core/workflows/help/modes/topic.md": "19a279fe91922d3b", + "gsd-core/workflows/help/modes/brief.md": "fa2675516b40e2e3", + "gsd-core/workflows/help/modes/default.md": "be05e56b2c5ee2c0", + "gsd-core/workflows/help/modes/full.md": "c8ffd141e28f5111", + "gsd-core/workflows/help/modes/topic.md": "0bf9ab39d7044d69", "gsd-core/workflows/import.md": "41c62ae199209a68", "gsd-core/workflows/inbox.md": "a448220c548f27bc", "gsd-core/workflows/ingest-docs.md": "e2707f28f67d128b", @@ -262,6 +263,7 @@ "gsd-core/workflows/next.md": "8beefb4335dd7c41", "gsd-core/workflows/node-repair.md": "07a1628e5a1ff96b", "gsd-core/workflows/note.md": "3ce09c0aa0a20599", + "gsd-core/workflows/onboard.md": "69d871aa53a1a859", "gsd-core/workflows/pause-work.md": "564de32981a24337", "gsd-core/workflows/plan-milestone-gaps.md": "dd6a4b3a8b05ab6e", "gsd-core/workflows/plan-phase.md": "cb56e635fef4d3f3", @@ -366,7 +368,7 @@ "skills/gsd-inbox/SKILL.md": "4ec0198966ac4f7d", "skills/gsd-ingest-docs/SKILL.md": "f4e43968af317ed8", "skills/gsd-manager/SKILL.md": "6e51785860784d8c", - "skills/gsd-map-codebase/SKILL.md": "e10431a9386c6aec", + "skills/gsd-map-codebase/SKILL.md": "552f914f43b2181c", "skills/gsd-mempalace-capture/SKILL.md": "588ddf4fbf3ebe65", "skills/gsd-mempalace-recall/SKILL.md": "2d95e385fee26dee", "skills/gsd-milestone-summary/SKILL.md": "2955ab3e3a444ca3", @@ -377,9 +379,10 @@ "skills/gsd-ns-context/SKILL.md": "e791bc60e4cf124e", "skills/gsd-ns-ideate/SKILL.md": "b85f270e8415f595", "skills/gsd-ns-manage/SKILL.md": "d55c53b5b0513033", - "skills/gsd-ns-project/SKILL.md": "64844073a6115c45", + "skills/gsd-ns-project/SKILL.md": "905eff81dbb98b38", "skills/gsd-ns-review/SKILL.md": "2e30158e112d173c", "skills/gsd-ns-workflow/SKILL.md": "529e21833a6a8831", + "skills/gsd-onboard/SKILL.md": "1447665c64c8ade8", "skills/gsd-pause-work/SKILL.md": "9d3cc6bd70b03df1", "skills/gsd-phase/SKILL.md": "00676bbea61410bf", "skills/gsd-plan-phase/SKILL.md": "168046ccf9702532", diff --git a/tests/fixtures/golden-install-parity/augment.json b/tests/fixtures/golden-install-parity/augment.json index e3557f981..8e977c425 100644 --- a/tests/fixtures/golden-install-parity/augment.json +++ b/tests/fixtures/golden-install-parity/augment.json @@ -62,7 +62,7 @@ "commands/gsd-inbox.md": "c218298db8b36e31", "commands/gsd-ingest-docs.md": "6718b04c597a5428", "commands/gsd-manager.md": "8f4ae79774902293", - "commands/gsd-map-codebase.md": "f3a06c4c7503f243", + "commands/gsd-map-codebase.md": "e4e170d4ef2d46c6", "commands/gsd-mempalace-capture.md": "2e610f3ebe2eb5b4", "commands/gsd-mempalace-recall.md": "38716c0983a3ef9c", "commands/gsd-milestone-summary.md": "ff5e11e6b33d4b5e", @@ -73,9 +73,10 @@ "commands/gsd-ns-context.md": "011c44e7aa46e64a", "commands/gsd-ns-ideate.md": "edc5e543512dd48a", "commands/gsd-ns-manage.md": "0409d810e499357f", - "commands/gsd-ns-project.md": "8dfd1b9a2ffe86ac", + "commands/gsd-ns-project.md": "ff67e85bc6f7fc5a", "commands/gsd-ns-review.md": "3766ed10827882a0", "commands/gsd-ns-workflow.md": "c3b3c046a74ec0ee", + "commands/gsd-onboard.md": "1e8acf7be31834be", "commands/gsd-pause-work.md": "4fb032f72238fe33", "commands/gsd-phase.md": "4920d15d779329eb", "commands/gsd-plan-phase.md": "e74f3cb7a10cbb83", @@ -156,6 +157,7 @@ "gsd-core/references/gates.md": "bd79c7f90c8cb8d7", "gsd-core/references/git-integration.md": "77bf9dff38b2c9d4", "gsd-core/references/git-planning-commit.md": "f897a15ebfc3f5a7", + "gsd-core/references/gsd-run-resolver.md": "e71eb728b84641b1", "gsd-core/references/honest-verifier.md": "8815c9fc18c35719", "gsd-core/references/ios-scaffold.md": "5ef0cb7e0fac891f", "gsd-core/references/loop-hook-dispatch.md": "32e5dfb4dba76987", @@ -241,7 +243,7 @@ "gsd-core/templates/milestone.md": "74d2f750ae9f4a9c", "gsd-core/templates/phase-prompt.md": "b811bf951092df2f", "gsd-core/templates/planner-subagent-prompt.md": "ebf29dbb27042370", - "gsd-core/templates/project.md": "ab4af6becca2bb23", + "gsd-core/templates/project.md": "4f311fb1b05b823b", "gsd-core/templates/requirements.md": "a44de4c2f146e473", "gsd-core/templates/research-project/ARCHITECTURE.md": "746b9ef791d758b0", "gsd-core/templates/research-project/FEATURES.md": "f2b800de5df91b0f", @@ -294,7 +296,7 @@ "gsd-core/workflows/discuss-phase/templates/checkpoint.json": "e3bc3dca49db59eb", "gsd-core/workflows/discuss-phase/templates/context.md": "6cd929e989fe2b0f", "gsd-core/workflows/discuss-phase/templates/discussion-log.md": "1bbd7703f11128e1", - "gsd-core/workflows/do.md": "8f460af710c8f6a4", + "gsd-core/workflows/do.md": "7512dd1892f118a1", "gsd-core/workflows/docs-update.md": "f35922d15b7061c9", "gsd-core/workflows/edit-phase.md": "966a3eadd1bebc04", "gsd-core/workflows/eval-review.md": "f898936e2cfe4130", @@ -311,10 +313,10 @@ "gsd-core/workflows/graduation.md": "47f1594c88c08501", "gsd-core/workflows/health.md": "107e3c72e76d9535", "gsd-core/workflows/help.md": "5d040504b9ab35e3", - "gsd-core/workflows/help/modes/brief.md": "5fe077fbbdb5d9f7", - "gsd-core/workflows/help/modes/default.md": "cc8ef97de634c995", - "gsd-core/workflows/help/modes/full.md": "3ac1c1bb851da7a5", - "gsd-core/workflows/help/modes/topic.md": "6762e41e3291ae24", + "gsd-core/workflows/help/modes/brief.md": "924860e1f07defb0", + "gsd-core/workflows/help/modes/default.md": "08a02976c0c5cc50", + "gsd-core/workflows/help/modes/full.md": "fc307cb77544df1d", + "gsd-core/workflows/help/modes/topic.md": "5c160093f3cbf35d", "gsd-core/workflows/import.md": "3d3fa603ceb8bc9f", "gsd-core/workflows/inbox.md": "437f981ef9ae7b26", "gsd-core/workflows/ingest-docs.md": "c859921c811ac11b", @@ -332,6 +334,7 @@ "gsd-core/workflows/next.md": "13fb800f2472d970", "gsd-core/workflows/node-repair.md": "07a1628e5a1ff96b", "gsd-core/workflows/note.md": "5a99eb396c744619", + "gsd-core/workflows/onboard.md": "6f9e6c0b484271a9", "gsd-core/workflows/pause-work.md": "f2b33bba5593d422", "gsd-core/workflows/plan-milestone-gaps.md": "852f6d7c0c4299dc", "gsd-core/workflows/plan-phase.md": "8b1209958c31ca2f", @@ -413,7 +416,7 @@ "skills/gsd-ns-context/skills/docs-update/SKILL.md": "e7ab14a984f7462c", "skills/gsd-ns-context/skills/extract-learnings/SKILL.md": "48846bf26ccaf0e7", "skills/gsd-ns-context/skills/graphify/SKILL.md": "3d6341614add6ccd", - "skills/gsd-ns-context/skills/map-codebase/SKILL.md": "51d6b970dca3c28e", + "skills/gsd-ns-context/skills/map-codebase/SKILL.md": "2017007dcd69d153", "skills/gsd-ns-context/skills/mempalace-capture/SKILL.md": "a7261b5ead71cc58", "skills/gsd-ns-context/skills/mempalace-recall/SKILL.md": "646e59e76acd548f", "skills/gsd-ns-ideate/SKILL.md": "d70360a5f7e8ac90", @@ -441,7 +444,7 @@ "skills/gsd-ns-manage/skills/update/SKILL.md": "c8165b8085ba106a", "skills/gsd-ns-manage/skills/workspace/SKILL.md": "98cc03aa8c735e9d", "skills/gsd-ns-manage/skills/workstreams/SKILL.md": "94d00b5116523f36", - "skills/gsd-ns-project/SKILL.md": "4d7e3c3870536dc9", + "skills/gsd-ns-project/SKILL.md": "ae47130ec878de8c", "skills/gsd-ns-project/skills/audit-milestone/SKILL.md": "6d4c77390c549fc7", "skills/gsd-ns-project/skills/complete-milestone/SKILL.md": "0af489daf6fd3f16", "skills/gsd-ns-project/skills/import/SKILL.md": "a3cfa7abc5ddd26d", @@ -449,6 +452,7 @@ "skills/gsd-ns-project/skills/milestone-summary/SKILL.md": "18dc0c134cb62657", "skills/gsd-ns-project/skills/new-milestone/SKILL.md": "a94ff34b09e17a98", "skills/gsd-ns-project/skills/new-project/SKILL.md": "81f681f54ca61f90", + "skills/gsd-ns-project/skills/onboard/SKILL.md": "1f5b29c75a91be4f", "skills/gsd-ns-project/skills/profile-user/SKILL.md": "68b015a40d386bff", "skills/gsd-ns-project/skills/review-backlog/SKILL.md": "0f25310aa0cd48f6", "skills/gsd-ns-review/SKILL.md": "d7567fd9a75a5c21", diff --git a/tests/fixtures/golden-install-parity/claude.json b/tests/fixtures/golden-install-parity/claude.json index 7a285ad10..7c5c4a69b 100644 --- a/tests/fixtures/golden-install-parity/claude.json +++ b/tests/fixtures/golden-install-parity/claude.json @@ -85,6 +85,7 @@ "gsd-core/references/gates.md": "7dc9fd3a3d6217c6", "gsd-core/references/git-integration.md": "5c70ef3203b7c9ce", "gsd-core/references/git-planning-commit.md": "f897a15ebfc3f5a7", + "gsd-core/references/gsd-run-resolver.md": "e71eb728b84641b1", "gsd-core/references/honest-verifier.md": "8815c9fc18c35719", "gsd-core/references/ios-scaffold.md": "5ef0cb7e0fac891f", "gsd-core/references/loop-hook-dispatch.md": "32e5dfb4dba76987", @@ -170,7 +171,7 @@ "gsd-core/templates/milestone.md": "74d2f750ae9f4a9c", "gsd-core/templates/phase-prompt.md": "213ccd947451ff2b", "gsd-core/templates/planner-subagent-prompt.md": "6c9f1b23ee3dc05f", - "gsd-core/templates/project.md": "1f687c7a88381080", + "gsd-core/templates/project.md": "ae1f68db042c2522", "gsd-core/templates/requirements.md": "a44de4c2f146e473", "gsd-core/templates/research-project/ARCHITECTURE.md": "746b9ef791d758b0", "gsd-core/templates/research-project/FEATURES.md": "f2b800de5df91b0f", @@ -223,7 +224,7 @@ "gsd-core/workflows/discuss-phase/templates/checkpoint.json": "e3bc3dca49db59eb", "gsd-core/workflows/discuss-phase/templates/context.md": "6cd929e989fe2b0f", "gsd-core/workflows/discuss-phase/templates/discussion-log.md": "1bbd7703f11128e1", - "gsd-core/workflows/do.md": "56215b98e26448bc", + "gsd-core/workflows/do.md": "61b92fb4d0bf3975", "gsd-core/workflows/docs-update.md": "63082608d3ae92be", "gsd-core/workflows/edit-phase.md": "8323bfe10faa0c0a", "gsd-core/workflows/eval-review.md": "f59e8329dae1e528", @@ -240,10 +241,10 @@ "gsd-core/workflows/graduation.md": "47f1594c88c08501", "gsd-core/workflows/health.md": "f934b1f1e9f3ae72", "gsd-core/workflows/help.md": "5d040504b9ab35e3", - "gsd-core/workflows/help/modes/brief.md": "2e923b3ed635d495", - "gsd-core/workflows/help/modes/default.md": "b544113eb9aa54fa", - "gsd-core/workflows/help/modes/full.md": "93cbdf7e542115a1", - "gsd-core/workflows/help/modes/topic.md": "899d7168a485297f", + "gsd-core/workflows/help/modes/brief.md": "fa2675516b40e2e3", + "gsd-core/workflows/help/modes/default.md": "be05e56b2c5ee2c0", + "gsd-core/workflows/help/modes/full.md": "e2084c6766e32d6c", + "gsd-core/workflows/help/modes/topic.md": "6e42db16f1568be9", "gsd-core/workflows/import.md": "6e8acff8c3918795", "gsd-core/workflows/inbox.md": "91aac6360e1a8672", "gsd-core/workflows/ingest-docs.md": "25832c784e8812e6", @@ -261,6 +262,7 @@ "gsd-core/workflows/next.md": "ef30b829a6d5c5f6", "gsd-core/workflows/node-repair.md": "07a1628e5a1ff96b", "gsd-core/workflows/note.md": "42b66686b2c102cb", + "gsd-core/workflows/onboard.md": "3c50ed1f1fd07619", "gsd-core/workflows/pause-work.md": "5716362557f44ce4", "gsd-core/workflows/plan-milestone-gaps.md": "1b43d12812f7bc1e", "gsd-core/workflows/plan-phase.md": "6978a15b5232b310", @@ -365,7 +367,7 @@ "skills/gsd-inbox/SKILL.md": "d05a099c0be02c60", "skills/gsd-ingest-docs/SKILL.md": "eb85e654917a503a", "skills/gsd-manager/SKILL.md": "1370d93741e47828", - "skills/gsd-map-codebase/SKILL.md": "5009595dbde69739", + "skills/gsd-map-codebase/SKILL.md": "cf65e61890448285", "skills/gsd-mempalace-capture/SKILL.md": "40a31ad049374297", "skills/gsd-mempalace-recall/SKILL.md": "c3f412d5a64f3921", "skills/gsd-milestone-summary/SKILL.md": "33d51a325d314f3a", @@ -376,9 +378,10 @@ "skills/gsd-ns-context/SKILL.md": "3102e7ad9b60f182", "skills/gsd-ns-ideate/SKILL.md": "c2c129408a046d22", "skills/gsd-ns-manage/SKILL.md": "8d786e01fa28a7bb", - "skills/gsd-ns-project/SKILL.md": "cc0c4bd9feeab147", + "skills/gsd-ns-project/SKILL.md": "76c77b121ad68b6c", "skills/gsd-ns-review/SKILL.md": "4111ea56e820479f", "skills/gsd-ns-workflow/SKILL.md": "4282c40a5e6e8bbe", + "skills/gsd-onboard/SKILL.md": "46460b479b7524bf", "skills/gsd-pause-work/SKILL.md": "35e8a148e44f5361", "skills/gsd-phase/SKILL.md": "00be96e7ae36c6f0", "skills/gsd-plan-phase/SKILL.md": "0c9e87da048acfb7", diff --git a/tests/fixtures/golden-install-parity/cline.json b/tests/fixtures/golden-install-parity/cline.json index 734dc44ab..d22a1693c 100644 --- a/tests/fixtures/golden-install-parity/cline.json +++ b/tests/fixtures/golden-install-parity/cline.json @@ -89,6 +89,7 @@ "gsd-core/references/gates.md": "bd79c7f90c8cb8d7", "gsd-core/references/git-integration.md": "f5403e1470e46e69", "gsd-core/references/git-planning-commit.md": "f897a15ebfc3f5a7", + "gsd-core/references/gsd-run-resolver.md": "07544d9a957fc2ca", "gsd-core/references/honest-verifier.md": "8815c9fc18c35719", "gsd-core/references/ios-scaffold.md": "5ef0cb7e0fac891f", "gsd-core/references/loop-hook-dispatch.md": "32e5dfb4dba76987", @@ -174,7 +175,7 @@ "gsd-core/templates/milestone.md": "74d2f750ae9f4a9c", "gsd-core/templates/phase-prompt.md": "b811bf951092df2f", "gsd-core/templates/planner-subagent-prompt.md": "ebf29dbb27042370", - "gsd-core/templates/project.md": "ab4af6becca2bb23", + "gsd-core/templates/project.md": "4f311fb1b05b823b", "gsd-core/templates/requirements.md": "a44de4c2f146e473", "gsd-core/templates/research-project/ARCHITECTURE.md": "746b9ef791d758b0", "gsd-core/templates/research-project/FEATURES.md": "f2b800de5df91b0f", @@ -227,7 +228,7 @@ "gsd-core/workflows/discuss-phase/templates/checkpoint.json": "e3bc3dca49db59eb", "gsd-core/workflows/discuss-phase/templates/context.md": "6cd929e989fe2b0f", "gsd-core/workflows/discuss-phase/templates/discussion-log.md": "1bbd7703f11128e1", - "gsd-core/workflows/do.md": "a35bbd09f381d940", + "gsd-core/workflows/do.md": "045a18f30efb1202", "gsd-core/workflows/docs-update.md": "39f288623a8f6f32", "gsd-core/workflows/edit-phase.md": "9c9fadc047c61d74", "gsd-core/workflows/eval-review.md": "3e1d7829ed2ed494", @@ -244,10 +245,10 @@ "gsd-core/workflows/graduation.md": "16fedecda36769eb", "gsd-core/workflows/health.md": "788fad84fa42eb9f", "gsd-core/workflows/help.md": "5d040504b9ab35e3", - "gsd-core/workflows/help/modes/brief.md": "5fe077fbbdb5d9f7", - "gsd-core/workflows/help/modes/default.md": "77c34f4a77dec02c", - "gsd-core/workflows/help/modes/full.md": "1bf502890828ada8", - "gsd-core/workflows/help/modes/topic.md": "6762e41e3291ae24", + "gsd-core/workflows/help/modes/brief.md": "924860e1f07defb0", + "gsd-core/workflows/help/modes/default.md": "86f7a14ad06e2f6f", + "gsd-core/workflows/help/modes/full.md": "efb266b8dbe60f51", + "gsd-core/workflows/help/modes/topic.md": "5c160093f3cbf35d", "gsd-core/workflows/import.md": "96ec687c5cfe84ac", "gsd-core/workflows/inbox.md": "437f981ef9ae7b26", "gsd-core/workflows/ingest-docs.md": "7d0517356c9f2619", @@ -265,6 +266,7 @@ "gsd-core/workflows/next.md": "3f8b61a35587a021", "gsd-core/workflows/node-repair.md": "07a1628e5a1ff96b", "gsd-core/workflows/note.md": "5a99eb396c744619", + "gsd-core/workflows/onboard.md": "6f9e6c0b484271a9", "gsd-core/workflows/pause-work.md": "3530607514b0ac00", "gsd-core/workflows/plan-milestone-gaps.md": "bafdc6945cd2bd87", "gsd-core/workflows/plan-phase.md": "46db1a845f25a579", @@ -324,7 +326,7 @@ "skills/gsd-ns-context/skills/docs-update/SKILL.md": "d150afd41a25ec08", "skills/gsd-ns-context/skills/extract-learnings/SKILL.md": "d39269bea995fabc", "skills/gsd-ns-context/skills/graphify/SKILL.md": "030050fcd08d129d", - "skills/gsd-ns-context/skills/map-codebase/SKILL.md": "19aec854da15f77b", + "skills/gsd-ns-context/skills/map-codebase/SKILL.md": "fa6a37402430af7d", "skills/gsd-ns-context/skills/mempalace-capture/SKILL.md": "588ddf4fbf3ebe65", "skills/gsd-ns-context/skills/mempalace-recall/SKILL.md": "2d95e385fee26dee", "skills/gsd-ns-ideate/SKILL.md": "c10342345c01c91f", @@ -352,7 +354,7 @@ "skills/gsd-ns-manage/skills/update/SKILL.md": "2666ab7786b69017", "skills/gsd-ns-manage/skills/workspace/SKILL.md": "c2616b157ec2350b", "skills/gsd-ns-manage/skills/workstreams/SKILL.md": "737841783c7fdd4f", - "skills/gsd-ns-project/SKILL.md": "5668e3a5e1d8896d", + "skills/gsd-ns-project/SKILL.md": "fac77a9e770fd655", "skills/gsd-ns-project/skills/audit-milestone/SKILL.md": "739ed755ad84e58e", "skills/gsd-ns-project/skills/complete-milestone/SKILL.md": "a69d534b385d6aaf", "skills/gsd-ns-project/skills/import/SKILL.md": "bc9b615cb141d26f", @@ -360,6 +362,7 @@ "skills/gsd-ns-project/skills/milestone-summary/SKILL.md": "e3636a5e9bbaab1f", "skills/gsd-ns-project/skills/new-milestone/SKILL.md": "bc8989d97f3161ad", "skills/gsd-ns-project/skills/new-project/SKILL.md": "ff0d57491df30624", + "skills/gsd-ns-project/skills/onboard/SKILL.md": "56c34282575926d4", "skills/gsd-ns-project/skills/profile-user/SKILL.md": "0406eed4dbd9560c", "skills/gsd-ns-project/skills/review-backlog/SKILL.md": "d8a150558cc9326a", "skills/gsd-ns-review/SKILL.md": "c5afe33c212947dd", diff --git a/tests/fixtures/golden-install-parity/codebuddy.json b/tests/fixtures/golden-install-parity/codebuddy.json index 09416cee7..3596e2b09 100644 --- a/tests/fixtures/golden-install-parity/codebuddy.json +++ b/tests/fixtures/golden-install-parity/codebuddy.json @@ -62,7 +62,7 @@ "commands/gsd-inbox.md": "eecfcfff57f89975", "commands/gsd-ingest-docs.md": "ab3e58239c23d61d", "commands/gsd-manager.md": "bfe9e261fa918876", - "commands/gsd-map-codebase.md": "9ed09a9a9ce48ffd", + "commands/gsd-map-codebase.md": "5093093d42240325", "commands/gsd-mempalace-capture.md": "e9e00b0602e1d8b8", "commands/gsd-mempalace-recall.md": "6efef238d8c62569", "commands/gsd-milestone-summary.md": "e3a36fbd695a1833", @@ -73,9 +73,10 @@ "commands/gsd-ns-context.md": "cc8954f405ae7916", "commands/gsd-ns-ideate.md": "fd1dd80d705e6e36", "commands/gsd-ns-manage.md": "5cc012d0be1caabb", - "commands/gsd-ns-project.md": "52e30c8d84bb1ee5", + "commands/gsd-ns-project.md": "76672fae61723e55", "commands/gsd-ns-review.md": "a28dbfd4aba5f74b", "commands/gsd-ns-workflow.md": "a1b874be9cf16caf", + "commands/gsd-onboard.md": "63283b90aa671229", "commands/gsd-pause-work.md": "6caa75a7c2b4dd2d", "commands/gsd-phase.md": "e3ca4958ea20a935", "commands/gsd-plan-phase.md": "6de27d54ac191539", @@ -156,6 +157,7 @@ "gsd-core/references/gates.md": "bd79c7f90c8cb8d7", "gsd-core/references/git-integration.md": "77bf9dff38b2c9d4", "gsd-core/references/git-planning-commit.md": "f897a15ebfc3f5a7", + "gsd-core/references/gsd-run-resolver.md": "e71eb728b84641b1", "gsd-core/references/honest-verifier.md": "8815c9fc18c35719", "gsd-core/references/ios-scaffold.md": "5ef0cb7e0fac891f", "gsd-core/references/loop-hook-dispatch.md": "32e5dfb4dba76987", @@ -241,7 +243,7 @@ "gsd-core/templates/milestone.md": "74d2f750ae9f4a9c", "gsd-core/templates/phase-prompt.md": "b811bf951092df2f", "gsd-core/templates/planner-subagent-prompt.md": "ebf29dbb27042370", - "gsd-core/templates/project.md": "ab4af6becca2bb23", + "gsd-core/templates/project.md": "4f311fb1b05b823b", "gsd-core/templates/requirements.md": "a44de4c2f146e473", "gsd-core/templates/research-project/ARCHITECTURE.md": "746b9ef791d758b0", "gsd-core/templates/research-project/FEATURES.md": "f2b800de5df91b0f", @@ -294,7 +296,7 @@ "gsd-core/workflows/discuss-phase/templates/checkpoint.json": "e3bc3dca49db59eb", "gsd-core/workflows/discuss-phase/templates/context.md": "6cd929e989fe2b0f", "gsd-core/workflows/discuss-phase/templates/discussion-log.md": "1bbd7703f11128e1", - "gsd-core/workflows/do.md": "8f460af710c8f6a4", + "gsd-core/workflows/do.md": "7512dd1892f118a1", "gsd-core/workflows/docs-update.md": "f35922d15b7061c9", "gsd-core/workflows/edit-phase.md": "966a3eadd1bebc04", "gsd-core/workflows/eval-review.md": "f898936e2cfe4130", @@ -311,10 +313,10 @@ "gsd-core/workflows/graduation.md": "47f1594c88c08501", "gsd-core/workflows/health.md": "107e3c72e76d9535", "gsd-core/workflows/help.md": "5d040504b9ab35e3", - "gsd-core/workflows/help/modes/brief.md": "5fe077fbbdb5d9f7", - "gsd-core/workflows/help/modes/default.md": "cc8ef97de634c995", - "gsd-core/workflows/help/modes/full.md": "4c018bcc9ed4e55c", - "gsd-core/workflows/help/modes/topic.md": "6762e41e3291ae24", + "gsd-core/workflows/help/modes/brief.md": "924860e1f07defb0", + "gsd-core/workflows/help/modes/default.md": "08a02976c0c5cc50", + "gsd-core/workflows/help/modes/full.md": "3a19e96b69bcc33e", + "gsd-core/workflows/help/modes/topic.md": "5c160093f3cbf35d", "gsd-core/workflows/import.md": "3d3fa603ceb8bc9f", "gsd-core/workflows/inbox.md": "437f981ef9ae7b26", "gsd-core/workflows/ingest-docs.md": "c859921c811ac11b", @@ -332,6 +334,7 @@ "gsd-core/workflows/next.md": "13fb800f2472d970", "gsd-core/workflows/node-repair.md": "07a1628e5a1ff96b", "gsd-core/workflows/note.md": "5a99eb396c744619", + "gsd-core/workflows/onboard.md": "6f9e6c0b484271a9", "gsd-core/workflows/pause-work.md": "f2b33bba5593d422", "gsd-core/workflows/plan-milestone-gaps.md": "852f6d7c0c4299dc", "gsd-core/workflows/plan-phase.md": "3e4debac4579684f", @@ -436,7 +439,7 @@ "skills/gsd-inbox/SKILL.md": "0eb81a1b2e1835d3", "skills/gsd-ingest-docs/SKILL.md": "2df55e0ec95d57d9", "skills/gsd-manager/SKILL.md": "816db4d4ed618537", - "skills/gsd-map-codebase/SKILL.md": "00622b489483ba69", + "skills/gsd-map-codebase/SKILL.md": "b304ec25e9a95c93", "skills/gsd-mempalace-capture/SKILL.md": "5f10d368835e062c", "skills/gsd-mempalace-recall/SKILL.md": "70c8491f53f4161b", "skills/gsd-milestone-summary/SKILL.md": "9eb030a1ac307fa1", @@ -447,9 +450,10 @@ "skills/gsd-ns-context/SKILL.md": "305b9b6248e8cc95", "skills/gsd-ns-ideate/SKILL.md": "c63a1aed61888b35", "skills/gsd-ns-manage/SKILL.md": "6a5b711b5103c566", - "skills/gsd-ns-project/SKILL.md": "345ea11ccffd21b0", + "skills/gsd-ns-project/SKILL.md": "3711ce904d20ca66", "skills/gsd-ns-review/SKILL.md": "98f1f3b3caf1a279", "skills/gsd-ns-workflow/SKILL.md": "b77682820700300b", + "skills/gsd-onboard/SKILL.md": "6ad789a03124cd4f", "skills/gsd-pause-work/SKILL.md": "e2de20b7539e78d4", "skills/gsd-phase/SKILL.md": "f87211f779315ced", "skills/gsd-plan-phase/SKILL.md": "6134e837750034ab", diff --git a/tests/fixtures/golden-install-parity/codex.json b/tests/fixtures/golden-install-parity/codex.json index f150fac04..d673bae26 100644 --- a/tests/fixtures/golden-install-parity/codex.json +++ b/tests/fixtures/golden-install-parity/codex.json @@ -121,6 +121,7 @@ "gsd-core/references/gates.md": "11fd2bdf27df57a5", "gsd-core/references/git-integration.md": "94715b69448bb818", "gsd-core/references/git-planning-commit.md": "5aad099c51135a0f", + "gsd-core/references/gsd-run-resolver.md": "e71eb728b84641b1", "gsd-core/references/honest-verifier.md": "8815c9fc18c35719", "gsd-core/references/ios-scaffold.md": "5ef0cb7e0fac891f", "gsd-core/references/loop-hook-dispatch.md": "32e5dfb4dba76987", @@ -206,7 +207,7 @@ "gsd-core/templates/milestone.md": "74d2f750ae9f4a9c", "gsd-core/templates/phase-prompt.md": "56c67fdc5d31b556", "gsd-core/templates/planner-subagent-prompt.md": "a48a5a2ebd5a9f47", - "gsd-core/templates/project.md": "034a6501f348c5a5", + "gsd-core/templates/project.md": "c6005bd88a346a3e", "gsd-core/templates/requirements.md": "a44de4c2f146e473", "gsd-core/templates/research-project/ARCHITECTURE.md": "746b9ef791d758b0", "gsd-core/templates/research-project/FEATURES.md": "f2b800de5df91b0f", @@ -259,7 +260,7 @@ "gsd-core/workflows/discuss-phase/templates/checkpoint.json": "e3bc3dca49db59eb", "gsd-core/workflows/discuss-phase/templates/context.md": "9804674fccada405", "gsd-core/workflows/discuss-phase/templates/discussion-log.md": "2b56ec2868cbddb4", - "gsd-core/workflows/do.md": "8f3e77a9486bc57b", + "gsd-core/workflows/do.md": "feec00355f896a3d", "gsd-core/workflows/docs-update.md": "e255317df939e302", "gsd-core/workflows/edit-phase.md": "e592a4d85ce5380f", "gsd-core/workflows/eval-review.md": "63d0d0670b54c244", @@ -276,10 +277,10 @@ "gsd-core/workflows/graduation.md": "47f1594c88c08501", "gsd-core/workflows/health.md": "5b835fc606fd3e9b", "gsd-core/workflows/help.md": "08e1349950c5602a", - "gsd-core/workflows/help/modes/brief.md": "becceb85b25dca89", - "gsd-core/workflows/help/modes/default.md": "18c7dc50066f5cd6", - "gsd-core/workflows/help/modes/full.md": "8a7854a34df89bd8", - "gsd-core/workflows/help/modes/topic.md": "303613ba8b123b9f", + "gsd-core/workflows/help/modes/brief.md": "da44b130d1afe556", + "gsd-core/workflows/help/modes/default.md": "4bb3082d28026eea", + "gsd-core/workflows/help/modes/full.md": "01a1ec54df54da6e", + "gsd-core/workflows/help/modes/topic.md": "b7c7e4a8800bc3ea", "gsd-core/workflows/import.md": "cb3c8f9d09edb434", "gsd-core/workflows/inbox.md": "61b8b10e7a74b2e9", "gsd-core/workflows/ingest-docs.md": "3cb763e0687d7ffa", @@ -297,6 +298,7 @@ "gsd-core/workflows/next.md": "7097a9607a981086", "gsd-core/workflows/node-repair.md": "07a1628e5a1ff96b", "gsd-core/workflows/note.md": "664da466ab989f9d", + "gsd-core/workflows/onboard.md": "83c40ba7055b8b24", "gsd-core/workflows/pause-work.md": "a217770ecafcb2e0", "gsd-core/workflows/plan-milestone-gaps.md": "73d46f77c50a0690", "gsd-core/workflows/plan-phase.md": "89ee3233c1aee273", @@ -381,7 +383,7 @@ "skills/gsd-inbox/SKILL.md": "1315033595643485", "skills/gsd-ingest-docs/SKILL.md": "5bd2838bf0b6dc1b", "skills/gsd-manager/SKILL.md": "cb1cf56f5d3f66d6", - "skills/gsd-map-codebase/SKILL.md": "25d0b3adfc8b75dc", + "skills/gsd-map-codebase/SKILL.md": "cd27dc028718426b", "skills/gsd-mempalace-capture/SKILL.md": "1a7fac4d53f607ab", "skills/gsd-mempalace-recall/SKILL.md": "7205b02250e89f25", "skills/gsd-milestone-summary/SKILL.md": "af84ecb400f23556", @@ -392,9 +394,10 @@ "skills/gsd-ns-context/SKILL.md": "9b496da79789b3f9", "skills/gsd-ns-ideate/SKILL.md": "84ca1cde06110981", "skills/gsd-ns-manage/SKILL.md": "909dafa0cd19ba5a", - "skills/gsd-ns-project/SKILL.md": "fb8ad6c2223be3c3", + "skills/gsd-ns-project/SKILL.md": "936b6998d42520ac", "skills/gsd-ns-review/SKILL.md": "022253010db0e072", "skills/gsd-ns-workflow/SKILL.md": "cba075bc819b539e", + "skills/gsd-onboard/SKILL.md": "f42fc2edebeda671", "skills/gsd-pause-work/SKILL.md": "b379469eed78a196", "skills/gsd-phase/SKILL.md": "25477edc97a90c91", "skills/gsd-plan-phase/SKILL.md": "19ead1acb151a868", diff --git a/tests/fixtures/golden-install-parity/copilot.json b/tests/fixtures/golden-install-parity/copilot.json index c375753f6..66f6dabfc 100644 --- a/tests/fixtures/golden-install-parity/copilot.json +++ b/tests/fixtures/golden-install-parity/copilot.json @@ -87,6 +87,7 @@ "gsd-core/references/gates.md": "7dc9fd3a3d6217c6", "gsd-core/references/git-integration.md": "657a93c539c16cab", "gsd-core/references/git-planning-commit.md": "f897a15ebfc3f5a7", + "gsd-core/references/gsd-run-resolver.md": "fca7e30efb0afe3f", "gsd-core/references/honest-verifier.md": "08b1e82f59c18078", "gsd-core/references/ios-scaffold.md": "5ef0cb7e0fac891f", "gsd-core/references/loop-hook-dispatch.md": "32e5dfb4dba76987", @@ -172,7 +173,7 @@ "gsd-core/templates/milestone.md": "74d2f750ae9f4a9c", "gsd-core/templates/phase-prompt.md": "e2b07376944c84e8", "gsd-core/templates/planner-subagent-prompt.md": "6c9f1b23ee3dc05f", - "gsd-core/templates/project.md": "e4a3b331be081e62", + "gsd-core/templates/project.md": "fae14114f2b79b10", "gsd-core/templates/requirements.md": "a44de4c2f146e473", "gsd-core/templates/research-project/ARCHITECTURE.md": "746b9ef791d758b0", "gsd-core/templates/research-project/FEATURES.md": "f2b800de5df91b0f", @@ -225,7 +226,7 @@ "gsd-core/workflows/discuss-phase/templates/checkpoint.json": "e3bc3dca49db59eb", "gsd-core/workflows/discuss-phase/templates/context.md": "9804674fccada405", "gsd-core/workflows/discuss-phase/templates/discussion-log.md": "2b56ec2868cbddb4", - "gsd-core/workflows/do.md": "988a20dab90c60c5", + "gsd-core/workflows/do.md": "9b46119803df09a6", "gsd-core/workflows/docs-update.md": "9292cfa3c52c434e", "gsd-core/workflows/edit-phase.md": "8667c28b22b1599f", "gsd-core/workflows/eval-review.md": "81c8e72ba3862856", @@ -242,10 +243,10 @@ "gsd-core/workflows/graduation.md": "f013efc29096faf0", "gsd-core/workflows/health.md": "f343fd32a0e398e4", "gsd-core/workflows/help.md": "5d040504b9ab35e3", - "gsd-core/workflows/help/modes/brief.md": "2e923b3ed635d495", - "gsd-core/workflows/help/modes/default.md": "b544113eb9aa54fa", - "gsd-core/workflows/help/modes/full.md": "0e9381367d6257bd", - "gsd-core/workflows/help/modes/topic.md": "19a279fe91922d3b", + "gsd-core/workflows/help/modes/brief.md": "fa2675516b40e2e3", + "gsd-core/workflows/help/modes/default.md": "be05e56b2c5ee2c0", + "gsd-core/workflows/help/modes/full.md": "ce88d4eb6b301e09", + "gsd-core/workflows/help/modes/topic.md": "0bf9ab39d7044d69", "gsd-core/workflows/import.md": "f4fa65e332b00f7e", "gsd-core/workflows/inbox.md": "a448220c548f27bc", "gsd-core/workflows/ingest-docs.md": "52be14d1a0713731", @@ -263,6 +264,7 @@ "gsd-core/workflows/next.md": "81c08abb34b2da88", "gsd-core/workflows/node-repair.md": "07a1628e5a1ff96b", "gsd-core/workflows/note.md": "4a5ee74cf2fc1f54", + "gsd-core/workflows/onboard.md": "a62602c6f3fd538a", "gsd-core/workflows/pause-work.md": "9ce66367be6c40db", "gsd-core/workflows/plan-milestone-gaps.md": "5cf589802d08bdf3", "gsd-core/workflows/plan-phase.md": "da462f812d1d0e61", @@ -346,7 +348,7 @@ "skills/gsd-inbox/SKILL.md": "cb9ed3865b67c04f", "skills/gsd-ingest-docs/SKILL.md": "10500de29525f6cf", "skills/gsd-manager/SKILL.md": "9946975bec15e737", - "skills/gsd-map-codebase/SKILL.md": "75806f8189d8af49", + "skills/gsd-map-codebase/SKILL.md": "39e7fd6bcc561f9d", "skills/gsd-mempalace-capture/SKILL.md": "f4511f69c14befb7", "skills/gsd-mempalace-recall/SKILL.md": "89523db66f834b2f", "skills/gsd-milestone-summary/SKILL.md": "5ca1dabfe0cd85f0", @@ -357,9 +359,10 @@ "skills/gsd-ns-context/SKILL.md": "d61edde87ae53105", "skills/gsd-ns-ideate/SKILL.md": "ca62cdf78ebe3585", "skills/gsd-ns-manage/SKILL.md": "9b1b7f6d9b877fcd", - "skills/gsd-ns-project/SKILL.md": "f1a666fb76527e6b", + "skills/gsd-ns-project/SKILL.md": "597b8dde8702c22d", "skills/gsd-ns-review/SKILL.md": "6405d0b1cf3f245d", "skills/gsd-ns-workflow/SKILL.md": "243287d21663ba87", + "skills/gsd-onboard/SKILL.md": "4d325f3033df2d37", "skills/gsd-pause-work/SKILL.md": "4f0caa008a8001ff", "skills/gsd-phase/SKILL.md": "d38c7f9b1d0d2360", "skills/gsd-plan-phase/SKILL.md": "d257bb9b1786039d", diff --git a/tests/fixtures/golden-install-parity/cursor.json b/tests/fixtures/golden-install-parity/cursor.json index dc2e7f08f..956ca6c73 100644 --- a/tests/fixtures/golden-install-parity/cursor.json +++ b/tests/fixtures/golden-install-parity/cursor.json @@ -62,7 +62,7 @@ "commands/gsd-inbox.md": "e6bcee3f863d20db", "commands/gsd-ingest-docs.md": "9e7f8757b9408c01", "commands/gsd-manager.md": "f300b708a5487c76", - "commands/gsd-map-codebase.md": "cf50f4a600119c8a", + "commands/gsd-map-codebase.md": "12f705917eb202fb", "commands/gsd-mempalace-capture.md": "b30bce634ac3136c", "commands/gsd-mempalace-recall.md": "08c910285469a394", "commands/gsd-milestone-summary.md": "adfad2cf43fc5aad", @@ -73,9 +73,10 @@ "commands/gsd-ns-context.md": "b551dcc549c6a23f", "commands/gsd-ns-ideate.md": "32f561de74b1bc7b", "commands/gsd-ns-manage.md": "24445a84bd817c5b", - "commands/gsd-ns-project.md": "b39b509ac4161d28", + "commands/gsd-ns-project.md": "525f84d73f5c51e9", "commands/gsd-ns-review.md": "c8550463fbab5e76", "commands/gsd-ns-workflow.md": "2c1f1fde3c46bb40", + "commands/gsd-onboard.md": "d9e52f558fc2b90f", "commands/gsd-pause-work.md": "59630f05f95fff68", "commands/gsd-phase.md": "9a073dcd0f934f90", "commands/gsd-plan-phase.md": "57de92131fcb16b8", @@ -156,6 +157,7 @@ "gsd-core/references/gates.md": "7dc9fd3a3d6217c6", "gsd-core/references/git-integration.md": "9840f521ad6612b5", "gsd-core/references/git-planning-commit.md": "f897a15ebfc3f5a7", + "gsd-core/references/gsd-run-resolver.md": "e71eb728b84641b1", "gsd-core/references/honest-verifier.md": "8815c9fc18c35719", "gsd-core/references/ios-scaffold.md": "5ef0cb7e0fac891f", "gsd-core/references/loop-hook-dispatch.md": "32e5dfb4dba76987", @@ -241,7 +243,7 @@ "gsd-core/templates/milestone.md": "74d2f750ae9f4a9c", "gsd-core/templates/phase-prompt.md": "213ccd947451ff2b", "gsd-core/templates/planner-subagent-prompt.md": "6c9f1b23ee3dc05f", - "gsd-core/templates/project.md": "1f687c7a88381080", + "gsd-core/templates/project.md": "ae1f68db042c2522", "gsd-core/templates/requirements.md": "a44de4c2f146e473", "gsd-core/templates/research-project/ARCHITECTURE.md": "746b9ef791d758b0", "gsd-core/templates/research-project/FEATURES.md": "f2b800de5df91b0f", @@ -294,7 +296,7 @@ "gsd-core/workflows/discuss-phase/templates/checkpoint.json": "e3bc3dca49db59eb", "gsd-core/workflows/discuss-phase/templates/context.md": "6cd929e989fe2b0f", "gsd-core/workflows/discuss-phase/templates/discussion-log.md": "cd5d01c9ef84ab73", - "gsd-core/workflows/do.md": "dc0ddd1f8231d26b", + "gsd-core/workflows/do.md": "9da6a73980ef2a71", "gsd-core/workflows/docs-update.md": "e86d7d7e2e3dac6d", "gsd-core/workflows/edit-phase.md": "8323bfe10faa0c0a", "gsd-core/workflows/eval-review.md": "a86279dd98dd5c03", @@ -311,10 +313,10 @@ "gsd-core/workflows/graduation.md": "53a4a6fa3b4e6613", "gsd-core/workflows/health.md": "e4d770484b5e7496", "gsd-core/workflows/help.md": "08e1349950c5602a", - "gsd-core/workflows/help/modes/brief.md": "2e923b3ed635d495", - "gsd-core/workflows/help/modes/default.md": "37c5149aae232e61", - "gsd-core/workflows/help/modes/full.md": "ed31d1afcbd3591f", - "gsd-core/workflows/help/modes/topic.md": "177d351f7465787d", + "gsd-core/workflows/help/modes/brief.md": "fa2675516b40e2e3", + "gsd-core/workflows/help/modes/default.md": "b88ff431fffe40ae", + "gsd-core/workflows/help/modes/full.md": "a7a42d4340e8e00b", + "gsd-core/workflows/help/modes/topic.md": "cee80e0adfa3b06c", "gsd-core/workflows/import.md": "5d5fb8e51f6a243a", "gsd-core/workflows/inbox.md": "797c287852eb8957", "gsd-core/workflows/ingest-docs.md": "c6759dbf17e79293", @@ -332,6 +334,7 @@ "gsd-core/workflows/next.md": "174356dcfd7c6c32", "gsd-core/workflows/node-repair.md": "07a1628e5a1ff96b", "gsd-core/workflows/note.md": "1c1e466c764e3deb", + "gsd-core/workflows/onboard.md": "20c28136423d40ac", "gsd-core/workflows/pause-work.md": "5716362557f44ce4", "gsd-core/workflows/plan-milestone-gaps.md": "1b43d12812f7bc1e", "gsd-core/workflows/plan-phase.md": "c90c001a92fc8a47", @@ -416,7 +419,7 @@ "skills/gsd-inbox/SKILL.md": "f9b4ff17883ee7e4", "skills/gsd-ingest-docs/SKILL.md": "01ed9183a00252ee", "skills/gsd-manager/SKILL.md": "62cd9f671a39e8a4", - "skills/gsd-map-codebase/SKILL.md": "f529da27d3a30b09", + "skills/gsd-map-codebase/SKILL.md": "383559aca64201e8", "skills/gsd-mempalace-capture/SKILL.md": "b308823dee547c65", "skills/gsd-mempalace-recall/SKILL.md": "56f3037091a8bd9a", "skills/gsd-milestone-summary/SKILL.md": "c5dbbc8edb97a7f7", @@ -427,9 +430,10 @@ "skills/gsd-ns-context/SKILL.md": "dcf5711653d57354", "skills/gsd-ns-ideate/SKILL.md": "0114f0bc5501c1e3", "skills/gsd-ns-manage/SKILL.md": "f3232d05d5263f5b", - "skills/gsd-ns-project/SKILL.md": "9f737a544e8d3f31", + "skills/gsd-ns-project/SKILL.md": "81d802dd3ee2e1ff", "skills/gsd-ns-review/SKILL.md": "8c686e92f293bfdd", "skills/gsd-ns-workflow/SKILL.md": "c379192bd17d47d7", + "skills/gsd-onboard/SKILL.md": "cae1f9382469fa00", "skills/gsd-pause-work/SKILL.md": "10e7531a2cb392ad", "skills/gsd-phase/SKILL.md": "1a2c9b64c1af7ffc", "skills/gsd-plan-phase/SKILL.md": "0784da05d41dcfe7", diff --git a/tests/fixtures/golden-install-parity/hermes.json b/tests/fixtures/golden-install-parity/hermes.json index 2bb6ec260..cd44401f3 100644 --- a/tests/fixtures/golden-install-parity/hermes.json +++ b/tests/fixtures/golden-install-parity/hermes.json @@ -86,6 +86,7 @@ "gsd-core/references/gates.md": "7dc9fd3a3d6217c6", "gsd-core/references/git-integration.md": "12d23fcbaa7fcf06", "gsd-core/references/git-planning-commit.md": "f897a15ebfc3f5a7", + "gsd-core/references/gsd-run-resolver.md": "769d1472c989cd54", "gsd-core/references/honest-verifier.md": "8815c9fc18c35719", "gsd-core/references/ios-scaffold.md": "5ef0cb7e0fac891f", "gsd-core/references/loop-hook-dispatch.md": "32e5dfb4dba76987", @@ -171,7 +172,7 @@ "gsd-core/templates/milestone.md": "74d2f750ae9f4a9c", "gsd-core/templates/phase-prompt.md": "213ccd947451ff2b", "gsd-core/templates/planner-subagent-prompt.md": "6c9f1b23ee3dc05f", - "gsd-core/templates/project.md": "1f687c7a88381080", + "gsd-core/templates/project.md": "ae1f68db042c2522", "gsd-core/templates/requirements.md": "a44de4c2f146e473", "gsd-core/templates/research-project/ARCHITECTURE.md": "746b9ef791d758b0", "gsd-core/templates/research-project/FEATURES.md": "f2b800de5df91b0f", @@ -224,7 +225,7 @@ "gsd-core/workflows/discuss-phase/templates/checkpoint.json": "e3bc3dca49db59eb", "gsd-core/workflows/discuss-phase/templates/context.md": "6cd929e989fe2b0f", "gsd-core/workflows/discuss-phase/templates/discussion-log.md": "1bbd7703f11128e1", - "gsd-core/workflows/do.md": "045e70c238db6faf", + "gsd-core/workflows/do.md": "e37540cc874fb782", "gsd-core/workflows/docs-update.md": "4d6c06e611d83b6d", "gsd-core/workflows/edit-phase.md": "7f27003f20e88fb8", "gsd-core/workflows/eval-review.md": "f510e5762212dc6f", @@ -241,10 +242,10 @@ "gsd-core/workflows/graduation.md": "d1fd52bbe41dcf34", "gsd-core/workflows/health.md": "c622a5ad0d347d30", "gsd-core/workflows/help.md": "5d040504b9ab35e3", - "gsd-core/workflows/help/modes/brief.md": "2e923b3ed635d495", - "gsd-core/workflows/help/modes/default.md": "bb6876c976996dbd", - "gsd-core/workflows/help/modes/full.md": "fdab4b3690bdd11d", - "gsd-core/workflows/help/modes/topic.md": "899d7168a485297f", + "gsd-core/workflows/help/modes/brief.md": "fa2675516b40e2e3", + "gsd-core/workflows/help/modes/default.md": "8874dac94eb68ae6", + "gsd-core/workflows/help/modes/full.md": "62779da88565d65a", + "gsd-core/workflows/help/modes/topic.md": "6e42db16f1568be9", "gsd-core/workflows/import.md": "a441445515bc2dd5", "gsd-core/workflows/inbox.md": "91aac6360e1a8672", "gsd-core/workflows/ingest-docs.md": "ad496a4c423f1ab7", @@ -262,6 +263,7 @@ "gsd-core/workflows/next.md": "8e1fa29751d96564", "gsd-core/workflows/node-repair.md": "07a1628e5a1ff96b", "gsd-core/workflows/note.md": "42b66686b2c102cb", + "gsd-core/workflows/onboard.md": "3c50ed1f1fd07619", "gsd-core/workflows/pause-work.md": "ae2d5789a95f70fe", "gsd-core/workflows/plan-milestone-gaps.md": "c86cdc1964256b98", "gsd-core/workflows/plan-phase.md": "e995429805b69fdc", @@ -344,7 +346,7 @@ "skills/gsd/gsd-ns-context/skills/docs-update/SKILL.md": "b059b3045d5daf5c", "skills/gsd/gsd-ns-context/skills/extract-learnings/SKILL.md": "36e59d6e514dcaf0", "skills/gsd/gsd-ns-context/skills/graphify/SKILL.md": "169eefd42c444cde", - "skills/gsd/gsd-ns-context/skills/map-codebase/SKILL.md": "6062ccca1a14b827", + "skills/gsd/gsd-ns-context/skills/map-codebase/SKILL.md": "9d36eee52586bb34", "skills/gsd/gsd-ns-context/skills/mempalace-capture/SKILL.md": "3fa619f73834c436", "skills/gsd/gsd-ns-context/skills/mempalace-recall/SKILL.md": "5d06922e0d7ab7d9", "skills/gsd/gsd-ns-ideate/SKILL.md": "b36bb4700ed6723a", @@ -372,7 +374,7 @@ "skills/gsd/gsd-ns-manage/skills/update/SKILL.md": "433a236998c305b0", "skills/gsd/gsd-ns-manage/skills/workspace/SKILL.md": "d655afc6f16565ed", "skills/gsd/gsd-ns-manage/skills/workstreams/SKILL.md": "6893312eaf14dab0", - "skills/gsd/gsd-ns-project/SKILL.md": "3ff43fdc0e4a6d02", + "skills/gsd/gsd-ns-project/SKILL.md": "6b3af15e7c4441c9", "skills/gsd/gsd-ns-project/skills/audit-milestone/SKILL.md": "de0556f07d899e50", "skills/gsd/gsd-ns-project/skills/complete-milestone/SKILL.md": "180cccc09bf99444", "skills/gsd/gsd-ns-project/skills/import/SKILL.md": "bf781c7a0d83c2cd", @@ -380,6 +382,7 @@ "skills/gsd/gsd-ns-project/skills/milestone-summary/SKILL.md": "c4bda5737f1137f8", "skills/gsd/gsd-ns-project/skills/new-milestone/SKILL.md": "47586c1fc8aa0645", "skills/gsd/gsd-ns-project/skills/new-project/SKILL.md": "8f22ba75717b3c88", + "skills/gsd/gsd-ns-project/skills/onboard/SKILL.md": "1d8d06ac1f27dacd", "skills/gsd/gsd-ns-project/skills/profile-user/SKILL.md": "5a8e01bc7b873a20", "skills/gsd/gsd-ns-project/skills/review-backlog/SKILL.md": "f3ef97da4e9b1d4c", "skills/gsd/gsd-ns-review/SKILL.md": "23fbadeca640e2bd", diff --git a/tests/fixtures/golden-install-parity/kilo.json b/tests/fixtures/golden-install-parity/kilo.json index 4818d444d..0c52b8c0d 100644 --- a/tests/fixtures/golden-install-parity/kilo.json +++ b/tests/fixtures/golden-install-parity/kilo.json @@ -62,7 +62,7 @@ "command/gsd-inbox.md": "1429fc7f556337c3", "command/gsd-ingest-docs.md": "e655ecf1d4433ba9", "command/gsd-manager.md": "1cdc133079833552", - "command/gsd-map-codebase.md": "186c8f79319abc1c", + "command/gsd-map-codebase.md": "704cb63214f51523", "command/gsd-mempalace-capture.md": "a94ca275cbe7134c", "command/gsd-mempalace-recall.md": "d358cdd89c935877", "command/gsd-milestone-summary.md": "4ab29b777f62f0bb", @@ -73,9 +73,10 @@ "command/gsd-ns-context.md": "9a2b55b64f2e1e4b", "command/gsd-ns-ideate.md": "27e7fcdc69eeeb5f", "command/gsd-ns-manage.md": "eded59052ca4b240", - "command/gsd-ns-project.md": "91417cf7b76581dd", + "command/gsd-ns-project.md": "c56395edb9bc7467", "command/gsd-ns-review.md": "61fe33e28eb1b961", "command/gsd-ns-workflow.md": "13c1ab91080c0cc3", + "command/gsd-onboard.md": "3e87a21c9c04f0d7", "command/gsd-pause-work.md": "04e993b1c9f8322b", "command/gsd-phase.md": "8f0e98dc6c223229", "command/gsd-plan-phase.md": "b37e9a61f946c975", @@ -156,6 +157,7 @@ "gsd-core/references/gates.md": "7dc9fd3a3d6217c6", "gsd-core/references/git-integration.md": "fbdf814a3af9c051", "gsd-core/references/git-planning-commit.md": "f897a15ebfc3f5a7", + "gsd-core/references/gsd-run-resolver.md": "e71eb728b84641b1", "gsd-core/references/honest-verifier.md": "8815c9fc18c35719", "gsd-core/references/ios-scaffold.md": "5ef0cb7e0fac891f", "gsd-core/references/loop-hook-dispatch.md": "32e5dfb4dba76987", @@ -241,7 +243,7 @@ "gsd-core/templates/milestone.md": "74d2f750ae9f4a9c", "gsd-core/templates/phase-prompt.md": "2e6fd96c2cc26470", "gsd-core/templates/planner-subagent-prompt.md": "6c9f1b23ee3dc05f", - "gsd-core/templates/project.md": "e4a3b331be081e62", + "gsd-core/templates/project.md": "fae14114f2b79b10", "gsd-core/templates/requirements.md": "a44de4c2f146e473", "gsd-core/templates/research-project/ARCHITECTURE.md": "746b9ef791d758b0", "gsd-core/templates/research-project/FEATURES.md": "f2b800de5df91b0f", @@ -294,7 +296,7 @@ "gsd-core/workflows/discuss-phase/templates/checkpoint.json": "e3bc3dca49db59eb", "gsd-core/workflows/discuss-phase/templates/context.md": "9804674fccada405", "gsd-core/workflows/discuss-phase/templates/discussion-log.md": "04e4feee14772275", - "gsd-core/workflows/do.md": "1e6102574016b150", + "gsd-core/workflows/do.md": "d9a889717e390f8d", "gsd-core/workflows/docs-update.md": "79afaaf19fd527cc", "gsd-core/workflows/edit-phase.md": "8323bfe10faa0c0a", "gsd-core/workflows/eval-review.md": "926eda8bbee28b23", @@ -311,10 +313,10 @@ "gsd-core/workflows/graduation.md": "5cc8638dabcbfd40", "gsd-core/workflows/health.md": "064b3668d5d9569a", "gsd-core/workflows/help.md": "5d040504b9ab35e3", - "gsd-core/workflows/help/modes/brief.md": "2e923b3ed635d495", - "gsd-core/workflows/help/modes/default.md": "b544113eb9aa54fa", - "gsd-core/workflows/help/modes/full.md": "051f9633f45558b4", - "gsd-core/workflows/help/modes/topic.md": "19a279fe91922d3b", + "gsd-core/workflows/help/modes/brief.md": "fa2675516b40e2e3", + "gsd-core/workflows/help/modes/default.md": "be05e56b2c5ee2c0", + "gsd-core/workflows/help/modes/full.md": "775f766dfafb72f9", + "gsd-core/workflows/help/modes/topic.md": "0bf9ab39d7044d69", "gsd-core/workflows/import.md": "f8bbe6f2c0e08a78", "gsd-core/workflows/inbox.md": "a073396097c89c01", "gsd-core/workflows/ingest-docs.md": "29c1fe28bc93b345", @@ -332,6 +334,7 @@ "gsd-core/workflows/next.md": "888297a0b21888ea", "gsd-core/workflows/node-repair.md": "07a1628e5a1ff96b", "gsd-core/workflows/note.md": "f8c2842a2217f776", + "gsd-core/workflows/onboard.md": "78b288089305dc46", "gsd-core/workflows/pause-work.md": "a6e5336c409fdc8b", "gsd-core/workflows/plan-milestone-gaps.md": "1b43d12812f7bc1e", "gsd-core/workflows/plan-phase.md": "03e59f06885e200f", @@ -437,7 +440,7 @@ "skills/gsd-inbox/SKILL.md": "34370c6138415209", "skills/gsd-ingest-docs/SKILL.md": "f049f06a6ec7da43", "skills/gsd-manager/SKILL.md": "a37ecdbe32952262", - "skills/gsd-map-codebase/SKILL.md": "e8c01704e8ada1d2", + "skills/gsd-map-codebase/SKILL.md": "e06d6ac1b7632cbe", "skills/gsd-mempalace-capture/SKILL.md": "f960b7b1a8fdf89b", "skills/gsd-mempalace-recall/SKILL.md": "2091c48e6e986e28", "skills/gsd-milestone-summary/SKILL.md": "da645171ca2299d8", @@ -448,9 +451,10 @@ "skills/gsd-ns-context/SKILL.md": "110fb2227bcde535", "skills/gsd-ns-ideate/SKILL.md": "d093d59a8519decc", "skills/gsd-ns-manage/SKILL.md": "2756981de613022e", - "skills/gsd-ns-project/SKILL.md": "757976d48e8b7a26", + "skills/gsd-ns-project/SKILL.md": "56d3d8a321d267f8", "skills/gsd-ns-review/SKILL.md": "680bdd33c882b049", "skills/gsd-ns-workflow/SKILL.md": "579b7f0dac74e1fb", + "skills/gsd-onboard/SKILL.md": "0e3cc902f44b41b8", "skills/gsd-pause-work/SKILL.md": "34366b18a392a717", "skills/gsd-phase/SKILL.md": "64a241d4f8665aa2", "skills/gsd-plan-phase/SKILL.md": "c73cba04a26f0bfe", diff --git a/tests/fixtures/golden-install-parity/kimi.json b/tests/fixtures/golden-install-parity/kimi.json index fce5a3af1..e8bbe4c2f 100644 --- a/tests/fixtures/golden-install-parity/kimi.json +++ b/tests/fixtures/golden-install-parity/kimi.json @@ -122,6 +122,7 @@ "gsd-core/references/gates.md": "bd79c7f90c8cb8d7", "gsd-core/references/git-integration.md": "77bf9dff38b2c9d4", "gsd-core/references/git-planning-commit.md": "f897a15ebfc3f5a7", + "gsd-core/references/gsd-run-resolver.md": "e71eb728b84641b1", "gsd-core/references/honest-verifier.md": "8815c9fc18c35719", "gsd-core/references/ios-scaffold.md": "5ef0cb7e0fac891f", "gsd-core/references/loop-hook-dispatch.md": "32e5dfb4dba76987", @@ -207,7 +208,7 @@ "gsd-core/templates/milestone.md": "74d2f750ae9f4a9c", "gsd-core/templates/phase-prompt.md": "b811bf951092df2f", "gsd-core/templates/planner-subagent-prompt.md": "ebf29dbb27042370", - "gsd-core/templates/project.md": "ab4af6becca2bb23", + "gsd-core/templates/project.md": "4f311fb1b05b823b", "gsd-core/templates/requirements.md": "a44de4c2f146e473", "gsd-core/templates/research-project/ARCHITECTURE.md": "746b9ef791d758b0", "gsd-core/templates/research-project/FEATURES.md": "f2b800de5df91b0f", @@ -260,7 +261,7 @@ "gsd-core/workflows/discuss-phase/templates/checkpoint.json": "e3bc3dca49db59eb", "gsd-core/workflows/discuss-phase/templates/context.md": "6cd929e989fe2b0f", "gsd-core/workflows/discuss-phase/templates/discussion-log.md": "1bbd7703f11128e1", - "gsd-core/workflows/do.md": "8f460af710c8f6a4", + "gsd-core/workflows/do.md": "7512dd1892f118a1", "gsd-core/workflows/docs-update.md": "f35922d15b7061c9", "gsd-core/workflows/edit-phase.md": "966a3eadd1bebc04", "gsd-core/workflows/eval-review.md": "f898936e2cfe4130", @@ -277,10 +278,10 @@ "gsd-core/workflows/graduation.md": "47f1594c88c08501", "gsd-core/workflows/health.md": "107e3c72e76d9535", "gsd-core/workflows/help.md": "5d040504b9ab35e3", - "gsd-core/workflows/help/modes/brief.md": "5fe077fbbdb5d9f7", - "gsd-core/workflows/help/modes/default.md": "cc8ef97de634c995", - "gsd-core/workflows/help/modes/full.md": "94c18706768e5a41", - "gsd-core/workflows/help/modes/topic.md": "6762e41e3291ae24", + "gsd-core/workflows/help/modes/brief.md": "924860e1f07defb0", + "gsd-core/workflows/help/modes/default.md": "08a02976c0c5cc50", + "gsd-core/workflows/help/modes/full.md": "ee47582c5d8d94a7", + "gsd-core/workflows/help/modes/topic.md": "5c160093f3cbf35d", "gsd-core/workflows/import.md": "3d3fa603ceb8bc9f", "gsd-core/workflows/inbox.md": "437f981ef9ae7b26", "gsd-core/workflows/ingest-docs.md": "c859921c811ac11b", @@ -298,6 +299,7 @@ "gsd-core/workflows/next.md": "13fb800f2472d970", "gsd-core/workflows/node-repair.md": "07a1628e5a1ff96b", "gsd-core/workflows/note.md": "5a99eb396c744619", + "gsd-core/workflows/onboard.md": "6f9e6c0b484271a9", "gsd-core/workflows/pause-work.md": "f2b33bba5593d422", "gsd-core/workflows/plan-milestone-gaps.md": "852f6d7c0c4299dc", "gsd-core/workflows/plan-phase.md": "2f16f3cc05fc59f1", @@ -380,7 +382,7 @@ "skills/gsd-inbox/SKILL.md": "955779a4b1df1c33", "skills/gsd-ingest-docs/SKILL.md": "6366644e623ae9e4", "skills/gsd-manager/SKILL.md": "8a11a1beb8e35a9c", - "skills/gsd-map-codebase/SKILL.md": "55dade835b0f4954", + "skills/gsd-map-codebase/SKILL.md": "73ab0afb2398de2c", "skills/gsd-mempalace-capture/SKILL.md": "64a2ec493092d26e", "skills/gsd-mempalace-recall/SKILL.md": "c6e0195e55cd934c", "skills/gsd-milestone-summary/SKILL.md": "3ea93ccaa0d4d967", @@ -391,9 +393,10 @@ "skills/gsd-ns-context/SKILL.md": "89f5bffe6702c0c5", "skills/gsd-ns-ideate/SKILL.md": "e0c0420f6878906a", "skills/gsd-ns-manage/SKILL.md": "b7fbe29e45e75f54", - "skills/gsd-ns-project/SKILL.md": "1292d4a6a4280ce9", + "skills/gsd-ns-project/SKILL.md": "fcb8a93ade9ecc72", "skills/gsd-ns-review/SKILL.md": "2ff62330379f947f", "skills/gsd-ns-workflow/SKILL.md": "86272fd655c206bc", + "skills/gsd-onboard/SKILL.md": "fd66b3c5b9c6a871", "skills/gsd-pause-work/SKILL.md": "95017c70ae9dca0d", "skills/gsd-phase/SKILL.md": "31578c329cc2583e", "skills/gsd-plan-phase/SKILL.md": "54798eddf30056b5", diff --git a/tests/fixtures/golden-install-parity/opencode.json b/tests/fixtures/golden-install-parity/opencode.json index dacda292c..0eacc03a6 100644 --- a/tests/fixtures/golden-install-parity/opencode.json +++ b/tests/fixtures/golden-install-parity/opencode.json @@ -62,7 +62,7 @@ "command/gsd-inbox.md": "cc850bab897aed1f", "command/gsd-ingest-docs.md": "b47c812c247e58a4", "command/gsd-manager.md": "86ece154b34b6d1b", - "command/gsd-map-codebase.md": "1fb678f8a17a380e", + "command/gsd-map-codebase.md": "9aba6b4eed565912", "command/gsd-mempalace-capture.md": "a94ca275cbe7134c", "command/gsd-mempalace-recall.md": "d358cdd89c935877", "command/gsd-milestone-summary.md": "86a827271bc647c5", @@ -73,9 +73,10 @@ "command/gsd-ns-context.md": "9a2b55b64f2e1e4b", "command/gsd-ns-ideate.md": "27e7fcdc69eeeb5f", "command/gsd-ns-manage.md": "eded59052ca4b240", - "command/gsd-ns-project.md": "91417cf7b76581dd", + "command/gsd-ns-project.md": "c56395edb9bc7467", "command/gsd-ns-review.md": "61fe33e28eb1b961", "command/gsd-ns-workflow.md": "13c1ab91080c0cc3", + "command/gsd-onboard.md": "3aafaeb5d3941efe", "command/gsd-pause-work.md": "bb5bf91a2e3e480e", "command/gsd-phase.md": "6bcda1539f949d5a", "command/gsd-plan-phase.md": "7ee44086b59862b9", @@ -156,6 +157,7 @@ "gsd-core/references/gates.md": "7dc9fd3a3d6217c6", "gsd-core/references/git-integration.md": "fbdf814a3af9c051", "gsd-core/references/git-planning-commit.md": "f897a15ebfc3f5a7", + "gsd-core/references/gsd-run-resolver.md": "4e5af9905e4276e4", "gsd-core/references/honest-verifier.md": "b67482409f896a10", "gsd-core/references/ios-scaffold.md": "5ef0cb7e0fac891f", "gsd-core/references/loop-hook-dispatch.md": "32e5dfb4dba76987", @@ -241,7 +243,7 @@ "gsd-core/templates/milestone.md": "74d2f750ae9f4a9c", "gsd-core/templates/phase-prompt.md": "ee8880432b4d1566", "gsd-core/templates/planner-subagent-prompt.md": "6c9f1b23ee3dc05f", - "gsd-core/templates/project.md": "e4a3b331be081e62", + "gsd-core/templates/project.md": "fae14114f2b79b10", "gsd-core/templates/requirements.md": "a44de4c2f146e473", "gsd-core/templates/research-project/ARCHITECTURE.md": "746b9ef791d758b0", "gsd-core/templates/research-project/FEATURES.md": "f2b800de5df91b0f", @@ -294,7 +296,7 @@ "gsd-core/workflows/discuss-phase/templates/checkpoint.json": "e3bc3dca49db59eb", "gsd-core/workflows/discuss-phase/templates/context.md": "9804674fccada405", "gsd-core/workflows/discuss-phase/templates/discussion-log.md": "04e4feee14772275", - "gsd-core/workflows/do.md": "d72e76d9050b53f3", + "gsd-core/workflows/do.md": "85c4c8cb7aa8af87", "gsd-core/workflows/docs-update.md": "850366c2ef8fb780", "gsd-core/workflows/edit-phase.md": "1876c855fb0a0a39", "gsd-core/workflows/eval-review.md": "5394694d29ad7543", @@ -311,10 +313,10 @@ "gsd-core/workflows/graduation.md": "13080b5c24eec27d", "gsd-core/workflows/health.md": "a91e0a8e5d20b2e9", "gsd-core/workflows/help.md": "5d040504b9ab35e3", - "gsd-core/workflows/help/modes/brief.md": "2e923b3ed635d495", - "gsd-core/workflows/help/modes/default.md": "b544113eb9aa54fa", - "gsd-core/workflows/help/modes/full.md": "604993c20f4e4b20", - "gsd-core/workflows/help/modes/topic.md": "19a279fe91922d3b", + "gsd-core/workflows/help/modes/brief.md": "fa2675516b40e2e3", + "gsd-core/workflows/help/modes/default.md": "be05e56b2c5ee2c0", + "gsd-core/workflows/help/modes/full.md": "35598c0ed5f7356f", + "gsd-core/workflows/help/modes/topic.md": "0bf9ab39d7044d69", "gsd-core/workflows/import.md": "67fbf389ab8e57b4", "gsd-core/workflows/inbox.md": "a073396097c89c01", "gsd-core/workflows/ingest-docs.md": "82370f93c45c8015", @@ -332,6 +334,7 @@ "gsd-core/workflows/next.md": "6719a37b8ce2ac4f", "gsd-core/workflows/node-repair.md": "07a1628e5a1ff96b", "gsd-core/workflows/note.md": "0d1374f2a2257858", + "gsd-core/workflows/onboard.md": "102556e1715c01b9", "gsd-core/workflows/pause-work.md": "70c72beca55c080a", "gsd-core/workflows/plan-milestone-gaps.md": "0a9dacd422cd9533", "gsd-core/workflows/plan-phase.md": "3c49d9f4061b2388", @@ -438,7 +441,7 @@ "skills/gsd-inbox/SKILL.md": "3b2dd319d91dbab4", "skills/gsd-ingest-docs/SKILL.md": "8f294b4894f782a5", "skills/gsd-manager/SKILL.md": "cf40f237b4f20aa7", - "skills/gsd-map-codebase/SKILL.md": "6d74ea41e29ff035", + "skills/gsd-map-codebase/SKILL.md": "73f714297815f74c", "skills/gsd-mempalace-capture/SKILL.md": "f960b7b1a8fdf89b", "skills/gsd-mempalace-recall/SKILL.md": "2091c48e6e986e28", "skills/gsd-milestone-summary/SKILL.md": "175366bb500b5e64", @@ -449,9 +452,10 @@ "skills/gsd-ns-context/SKILL.md": "110fb2227bcde535", "skills/gsd-ns-ideate/SKILL.md": "d093d59a8519decc", "skills/gsd-ns-manage/SKILL.md": "2756981de613022e", - "skills/gsd-ns-project/SKILL.md": "757976d48e8b7a26", + "skills/gsd-ns-project/SKILL.md": "56d3d8a321d267f8", "skills/gsd-ns-review/SKILL.md": "680bdd33c882b049", "skills/gsd-ns-workflow/SKILL.md": "579b7f0dac74e1fb", + "skills/gsd-onboard/SKILL.md": "ea0b1217e5ecae23", "skills/gsd-pause-work/SKILL.md": "c7e9ba4f242c4648", "skills/gsd-phase/SKILL.md": "ee78c0c56c814d84", "skills/gsd-plan-phase/SKILL.md": "6abcc3a1568a6bb9", diff --git a/tests/fixtures/golden-install-parity/qwen.json b/tests/fixtures/golden-install-parity/qwen.json index bec6afbe0..67e5f5980 100644 --- a/tests/fixtures/golden-install-parity/qwen.json +++ b/tests/fixtures/golden-install-parity/qwen.json @@ -86,6 +86,7 @@ "gsd-core/references/gates.md": "7dc9fd3a3d6217c6", "gsd-core/references/git-integration.md": "bd249d9024c39c0d", "gsd-core/references/git-planning-commit.md": "f897a15ebfc3f5a7", + "gsd-core/references/gsd-run-resolver.md": "10575c928ff9230d", "gsd-core/references/honest-verifier.md": "8815c9fc18c35719", "gsd-core/references/ios-scaffold.md": "5ef0cb7e0fac891f", "gsd-core/references/loop-hook-dispatch.md": "32e5dfb4dba76987", @@ -171,7 +172,7 @@ "gsd-core/templates/milestone.md": "74d2f750ae9f4a9c", "gsd-core/templates/phase-prompt.md": "213ccd947451ff2b", "gsd-core/templates/planner-subagent-prompt.md": "6c9f1b23ee3dc05f", - "gsd-core/templates/project.md": "1f687c7a88381080", + "gsd-core/templates/project.md": "ae1f68db042c2522", "gsd-core/templates/requirements.md": "a44de4c2f146e473", "gsd-core/templates/research-project/ARCHITECTURE.md": "746b9ef791d758b0", "gsd-core/templates/research-project/FEATURES.md": "f2b800de5df91b0f", @@ -224,7 +225,7 @@ "gsd-core/workflows/discuss-phase/templates/checkpoint.json": "e3bc3dca49db59eb", "gsd-core/workflows/discuss-phase/templates/context.md": "6cd929e989fe2b0f", "gsd-core/workflows/discuss-phase/templates/discussion-log.md": "1bbd7703f11128e1", - "gsd-core/workflows/do.md": "35862ba1f7230247", + "gsd-core/workflows/do.md": "68f2607de614157d", "gsd-core/workflows/docs-update.md": "45d2f0d173c84e07", "gsd-core/workflows/edit-phase.md": "0fb5e0123cfc6f36", "gsd-core/workflows/eval-review.md": "6dee8a1e40ececd4", @@ -241,10 +242,10 @@ "gsd-core/workflows/graduation.md": "40401655435beee3", "gsd-core/workflows/health.md": "043de14edb6a9723", "gsd-core/workflows/help.md": "5d040504b9ab35e3", - "gsd-core/workflows/help/modes/brief.md": "2e923b3ed635d495", - "gsd-core/workflows/help/modes/default.md": "cef457f954a9991e", - "gsd-core/workflows/help/modes/full.md": "1e1e826ba1da0bc5", - "gsd-core/workflows/help/modes/topic.md": "899d7168a485297f", + "gsd-core/workflows/help/modes/brief.md": "fa2675516b40e2e3", + "gsd-core/workflows/help/modes/default.md": "7ca77077085452f5", + "gsd-core/workflows/help/modes/full.md": "00c1433a639f6ed8", + "gsd-core/workflows/help/modes/topic.md": "6e42db16f1568be9", "gsd-core/workflows/import.md": "e56c18a984396066", "gsd-core/workflows/inbox.md": "91aac6360e1a8672", "gsd-core/workflows/ingest-docs.md": "f291310a8a89dbd8", @@ -262,6 +263,7 @@ "gsd-core/workflows/next.md": "c13515a80c20d37d", "gsd-core/workflows/node-repair.md": "07a1628e5a1ff96b", "gsd-core/workflows/note.md": "42b66686b2c102cb", + "gsd-core/workflows/onboard.md": "3c50ed1f1fd07619", "gsd-core/workflows/pause-work.md": "be33f84dc1d4822f", "gsd-core/workflows/plan-milestone-gaps.md": "d98e98486123eb97", "gsd-core/workflows/plan-phase.md": "1cac08591d361397", @@ -343,7 +345,7 @@ "skills/gsd-ns-context/skills/docs-update/SKILL.md": "3d41e81ec571de60", "skills/gsd-ns-context/skills/extract-learnings/SKILL.md": "8d38e55e5f8b774b", "skills/gsd-ns-context/skills/graphify/SKILL.md": "ac3661e6e576188b", - "skills/gsd-ns-context/skills/map-codebase/SKILL.md": "5009595dbde69739", + "skills/gsd-ns-context/skills/map-codebase/SKILL.md": "cf65e61890448285", "skills/gsd-ns-context/skills/mempalace-capture/SKILL.md": "40a31ad049374297", "skills/gsd-ns-context/skills/mempalace-recall/SKILL.md": "c3f412d5a64f3921", "skills/gsd-ns-ideate/SKILL.md": "4a0d2691054b23e5", @@ -371,7 +373,7 @@ "skills/gsd-ns-manage/skills/update/SKILL.md": "530b4206d729b56d", "skills/gsd-ns-manage/skills/workspace/SKILL.md": "047c3f4247bc869e", "skills/gsd-ns-manage/skills/workstreams/SKILL.md": "f4e54cb9b1ca0442", - "skills/gsd-ns-project/SKILL.md": "a58b3170197968be", + "skills/gsd-ns-project/SKILL.md": "5d7ec93b195555e7", "skills/gsd-ns-project/skills/audit-milestone/SKILL.md": "edb6a0cc6305d724", "skills/gsd-ns-project/skills/complete-milestone/SKILL.md": "f6799a5a713be7bb", "skills/gsd-ns-project/skills/import/SKILL.md": "88f83921a85e536b", @@ -379,6 +381,7 @@ "skills/gsd-ns-project/skills/milestone-summary/SKILL.md": "33d51a325d314f3a", "skills/gsd-ns-project/skills/new-milestone/SKILL.md": "ac99ffb8a966fe9d", "skills/gsd-ns-project/skills/new-project/SKILL.md": "9d5c27ebfa2c4746", + "skills/gsd-ns-project/skills/onboard/SKILL.md": "46460b479b7524bf", "skills/gsd-ns-project/skills/profile-user/SKILL.md": "78ca46045e85223f", "skills/gsd-ns-project/skills/review-backlog/SKILL.md": "1708aab6cb919223", "skills/gsd-ns-review/SKILL.md": "7badceb8627d8154", diff --git a/tests/fixtures/golden-install-parity/trae.json b/tests/fixtures/golden-install-parity/trae.json index a045862ef..6f78043f4 100644 --- a/tests/fixtures/golden-install-parity/trae.json +++ b/tests/fixtures/golden-install-parity/trae.json @@ -86,6 +86,7 @@ "gsd-core/references/gates.md": "7dc9fd3a3d6217c6", "gsd-core/references/git-integration.md": "1bd40c3f94d712b1", "gsd-core/references/git-planning-commit.md": "f897a15ebfc3f5a7", + "gsd-core/references/gsd-run-resolver.md": "0534754c2758352a", "gsd-core/references/honest-verifier.md": "8815c9fc18c35719", "gsd-core/references/ios-scaffold.md": "5ef0cb7e0fac891f", "gsd-core/references/loop-hook-dispatch.md": "32e5dfb4dba76987", @@ -171,7 +172,7 @@ "gsd-core/templates/milestone.md": "74d2f750ae9f4a9c", "gsd-core/templates/phase-prompt.md": "213ccd947451ff2b", "gsd-core/templates/planner-subagent-prompt.md": "6c9f1b23ee3dc05f", - "gsd-core/templates/project.md": "1f687c7a88381080", + "gsd-core/templates/project.md": "ae1f68db042c2522", "gsd-core/templates/requirements.md": "a44de4c2f146e473", "gsd-core/templates/research-project/ARCHITECTURE.md": "746b9ef791d758b0", "gsd-core/templates/research-project/FEATURES.md": "f2b800de5df91b0f", @@ -224,7 +225,7 @@ "gsd-core/workflows/discuss-phase/templates/checkpoint.json": "e3bc3dca49db59eb", "gsd-core/workflows/discuss-phase/templates/context.md": "6cd929e989fe2b0f", "gsd-core/workflows/discuss-phase/templates/discussion-log.md": "1bbd7703f11128e1", - "gsd-core/workflows/do.md": "f3328dbd4416f11a", + "gsd-core/workflows/do.md": "5131e8796ba9d99b", "gsd-core/workflows/docs-update.md": "f13571f08e083356", "gsd-core/workflows/edit-phase.md": "7facd0faa33c8cad", "gsd-core/workflows/eval-review.md": "37d545d4f0db4927", @@ -241,10 +242,10 @@ "gsd-core/workflows/graduation.md": "1ca877cda258a5de", "gsd-core/workflows/health.md": "1f9fd2deea45896f", "gsd-core/workflows/help.md": "08e1349950c5602a", - "gsd-core/workflows/help/modes/brief.md": "2e923b3ed635d495", - "gsd-core/workflows/help/modes/default.md": "1b3c315342701265", - "gsd-core/workflows/help/modes/full.md": "62c71f57f047999b", - "gsd-core/workflows/help/modes/topic.md": "229e3f3d85bda04b", + "gsd-core/workflows/help/modes/brief.md": "fa2675516b40e2e3", + "gsd-core/workflows/help/modes/default.md": "ed7368e0d1b8644a", + "gsd-core/workflows/help/modes/full.md": "b3287aa383806758", + "gsd-core/workflows/help/modes/topic.md": "8a5344e56fa64ab9", "gsd-core/workflows/import.md": "31af58468db15daf", "gsd-core/workflows/inbox.md": "e9ea37b2d46dc5b4", "gsd-core/workflows/ingest-docs.md": "fba176ad3cc22f5f", @@ -262,6 +263,7 @@ "gsd-core/workflows/next.md": "2163195861877de5", "gsd-core/workflows/node-repair.md": "07a1628e5a1ff96b", "gsd-core/workflows/note.md": "acc9130fb1e94f0b", + "gsd-core/workflows/onboard.md": "61f111302af0f404", "gsd-core/workflows/pause-work.md": "c20d267e28ce92f0", "gsd-core/workflows/plan-milestone-gaps.md": "26db7b9329b7ddc8", "gsd-core/workflows/plan-phase.md": "fc7d25c0649e2fdf", @@ -321,7 +323,7 @@ "skills/gsd-ns-context/skills/docs-update/SKILL.md": "52755343585b987b", "skills/gsd-ns-context/skills/extract-learnings/SKILL.md": "d39269bea995fabc", "skills/gsd-ns-context/skills/graphify/SKILL.md": "e0253aef14693a7e", - "skills/gsd-ns-context/skills/map-codebase/SKILL.md": "0910348701b1fc65", + "skills/gsd-ns-context/skills/map-codebase/SKILL.md": "2982436d8652f172", "skills/gsd-ns-context/skills/mempalace-capture/SKILL.md": "36c486f14abe869a", "skills/gsd-ns-context/skills/mempalace-recall/SKILL.md": "2d95e385fee26dee", "skills/gsd-ns-ideate/SKILL.md": "c10342345c01c91f", @@ -349,7 +351,7 @@ "skills/gsd-ns-manage/skills/update/SKILL.md": "2fc47bf059aa7b38", "skills/gsd-ns-manage/skills/workspace/SKILL.md": "257d17b9d20274d8", "skills/gsd-ns-manage/skills/workstreams/SKILL.md": "737841783c7fdd4f", - "skills/gsd-ns-project/SKILL.md": "5668e3a5e1d8896d", + "skills/gsd-ns-project/SKILL.md": "fac77a9e770fd655", "skills/gsd-ns-project/skills/audit-milestone/SKILL.md": "0ccabc5556d65d56", "skills/gsd-ns-project/skills/complete-milestone/SKILL.md": "a69d534b385d6aaf", "skills/gsd-ns-project/skills/import/SKILL.md": "a11e630bfd8ae4de", @@ -357,6 +359,7 @@ "skills/gsd-ns-project/skills/milestone-summary/SKILL.md": "9d408f56712ba948", "skills/gsd-ns-project/skills/new-milestone/SKILL.md": "7cbc011130e8590c", "skills/gsd-ns-project/skills/new-project/SKILL.md": "ff0d57491df30624", + "skills/gsd-ns-project/skills/onboard/SKILL.md": "ae4c7b799d9ffb09", "skills/gsd-ns-project/skills/profile-user/SKILL.md": "4f526120cda2f6cc", "skills/gsd-ns-project/skills/review-backlog/SKILL.md": "d8a150558cc9326a", "skills/gsd-ns-review/SKILL.md": "c5afe33c212947dd", diff --git a/tests/fixtures/golden-install-parity/windsurf.json b/tests/fixtures/golden-install-parity/windsurf.json index ae20090c1..ed1f715ea 100644 --- a/tests/fixtures/golden-install-parity/windsurf.json +++ b/tests/fixtures/golden-install-parity/windsurf.json @@ -86,6 +86,7 @@ "gsd-core/references/gates.md": "7dc9fd3a3d6217c6", "gsd-core/references/git-integration.md": "6ec36ea6b868655f", "gsd-core/references/git-planning-commit.md": "f897a15ebfc3f5a7", + "gsd-core/references/gsd-run-resolver.md": "1bb6a410d6ebfb33", "gsd-core/references/honest-verifier.md": "8815c9fc18c35719", "gsd-core/references/ios-scaffold.md": "5ef0cb7e0fac891f", "gsd-core/references/loop-hook-dispatch.md": "32e5dfb4dba76987", @@ -171,7 +172,7 @@ "gsd-core/templates/milestone.md": "74d2f750ae9f4a9c", "gsd-core/templates/phase-prompt.md": "213ccd947451ff2b", "gsd-core/templates/planner-subagent-prompt.md": "6c9f1b23ee3dc05f", - "gsd-core/templates/project.md": "1f687c7a88381080", + "gsd-core/templates/project.md": "ae1f68db042c2522", "gsd-core/templates/requirements.md": "a44de4c2f146e473", "gsd-core/templates/research-project/ARCHITECTURE.md": "746b9ef791d758b0", "gsd-core/templates/research-project/FEATURES.md": "f2b800de5df91b0f", @@ -224,7 +225,7 @@ "gsd-core/workflows/discuss-phase/templates/checkpoint.json": "e3bc3dca49db59eb", "gsd-core/workflows/discuss-phase/templates/context.md": "6cd929e989fe2b0f", "gsd-core/workflows/discuss-phase/templates/discussion-log.md": "cd5d01c9ef84ab73", - "gsd-core/workflows/do.md": "a7ff800fdab468c7", + "gsd-core/workflows/do.md": "e2b848547e43c7a5", "gsd-core/workflows/docs-update.md": "70f73cc8c27e0ca0", "gsd-core/workflows/edit-phase.md": "c0ae7d0063f3e789", "gsd-core/workflows/eval-review.md": "b28be79ef29f16fd", @@ -241,10 +242,10 @@ "gsd-core/workflows/graduation.md": "a766039ff6ca653f", "gsd-core/workflows/health.md": "7b19d6e2c0357c3e", "gsd-core/workflows/help.md": "08e1349950c5602a", - "gsd-core/workflows/help/modes/brief.md": "2e923b3ed635d495", - "gsd-core/workflows/help/modes/default.md": "91509fe03bad9795", - "gsd-core/workflows/help/modes/full.md": "4c1a43f7095647e1", - "gsd-core/workflows/help/modes/topic.md": "177d351f7465787d", + "gsd-core/workflows/help/modes/brief.md": "fa2675516b40e2e3", + "gsd-core/workflows/help/modes/default.md": "6a253f1756f74e95", + "gsd-core/workflows/help/modes/full.md": "0cd464dcd077bbfc", + "gsd-core/workflows/help/modes/topic.md": "cee80e0adfa3b06c", "gsd-core/workflows/import.md": "029cacf530aca86b", "gsd-core/workflows/inbox.md": "797c287852eb8957", "gsd-core/workflows/ingest-docs.md": "78ba04ca39f28e8d", @@ -262,6 +263,7 @@ "gsd-core/workflows/next.md": "d48cea140a5153cb", "gsd-core/workflows/node-repair.md": "07a1628e5a1ff96b", "gsd-core/workflows/note.md": "1c1e466c764e3deb", + "gsd-core/workflows/onboard.md": "20c28136423d40ac", "gsd-core/workflows/pause-work.md": "93fcc1c845da6396", "gsd-core/workflows/plan-milestone-gaps.md": "7880866ee1caf923", "gsd-core/workflows/plan-phase.md": "3e143f39514f8192", diff --git a/tests/workflow-size-baseline.json b/tests/workflow-size-baseline.json index bf1ba001e..8477fa97e 100644 --- a/tests/workflow-size-baseline.json +++ b/tests/workflow-size-baseline.json @@ -20,7 +20,7 @@ "discuss-phase-assumptions.md": 27028, "discuss-phase-power.md": 11273, "discuss-phase.md": 31986, - "do.md": 10112, + "do.md": 10353, "docs-update.md": 55706, "edit-phase.md": 12927, "eval-review.md": 9967, @@ -50,6 +50,7 @@ "next.md": 20138, "node-repair.md": 4173, "note.md": 6563, + "onboard.md": 8590, "pause-work.md": 14441, "plan-milestone-gaps.md": 11809, "plan-phase.md": 90455, From 192764f0c36a4a097ded6caedf76a165d0a88108 Mon Sep 17 00:00:00 2001 From: Codesmith Date: Tue, 7 Jul 2026 02:55:18 +0000 Subject: [PATCH 43/48] chore(#1990): recapture zcode golden install fixture with onboard artifacts Co-authored-by: Codesmith --- .../fixtures/golden-install-parity/zcode.json | 24 +++++++++++-------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/tests/fixtures/golden-install-parity/zcode.json b/tests/fixtures/golden-install-parity/zcode.json index 2f09d5f90..aca29fca4 100644 --- a/tests/fixtures/golden-install-parity/zcode.json +++ b/tests/fixtures/golden-install-parity/zcode.json @@ -62,7 +62,7 @@ "commands/gsd-inbox.md": "da55c1408a6ee6cc", "commands/gsd-ingest-docs.md": "7a3c21ae5d5d133a", "commands/gsd-manager.md": "9f54653a7c589b00", - "commands/gsd-map-codebase.md": "8b605921868c03a3", + "commands/gsd-map-codebase.md": "709e9572953accc6", "commands/gsd-mempalace-capture.md": "5d4556e444acbb90", "commands/gsd-mempalace-recall.md": "5ac67fa4b7f2b03b", "commands/gsd-milestone-summary.md": "f8fa9c357c08b74b", @@ -73,9 +73,10 @@ "commands/gsd-ns-context.md": "011c44e7aa46e64a", "commands/gsd-ns-ideate.md": "edc5e543512dd48a", "commands/gsd-ns-manage.md": "0409d810e499357f", - "commands/gsd-ns-project.md": "8dfd1b9a2ffe86ac", + "commands/gsd-ns-project.md": "ff67e85bc6f7fc5a", "commands/gsd-ns-review.md": "3766ed10827882a0", "commands/gsd-ns-workflow.md": "c3b3c046a74ec0ee", + "commands/gsd-onboard.md": "a35340ce39334fc7", "commands/gsd-pause-work.md": "40a953fcddbedb5d", "commands/gsd-phase.md": "5dd3d40e3461a973", "commands/gsd-plan-phase.md": "2fb6cc9c4caa6a36", @@ -157,6 +158,7 @@ "gsd-core/references/gates.md": "bd79c7f90c8cb8d7", "gsd-core/references/git-integration.md": "77bf9dff38b2c9d4", "gsd-core/references/git-planning-commit.md": "f897a15ebfc3f5a7", + "gsd-core/references/gsd-run-resolver.md": "e71eb728b84641b1", "gsd-core/references/honest-verifier.md": "8815c9fc18c35719", "gsd-core/references/ios-scaffold.md": "5ef0cb7e0fac891f", "gsd-core/references/loop-hook-dispatch.md": "32e5dfb4dba76987", @@ -242,7 +244,7 @@ "gsd-core/templates/milestone.md": "74d2f750ae9f4a9c", "gsd-core/templates/phase-prompt.md": "b811bf951092df2f", "gsd-core/templates/planner-subagent-prompt.md": "ebf29dbb27042370", - "gsd-core/templates/project.md": "ab4af6becca2bb23", + "gsd-core/templates/project.md": "4f311fb1b05b823b", "gsd-core/templates/requirements.md": "a44de4c2f146e473", "gsd-core/templates/research-project/ARCHITECTURE.md": "746b9ef791d758b0", "gsd-core/templates/research-project/FEATURES.md": "f2b800de5df91b0f", @@ -295,7 +297,7 @@ "gsd-core/workflows/discuss-phase/templates/checkpoint.json": "e3bc3dca49db59eb", "gsd-core/workflows/discuss-phase/templates/context.md": "6cd929e989fe2b0f", "gsd-core/workflows/discuss-phase/templates/discussion-log.md": "1bbd7703f11128e1", - "gsd-core/workflows/do.md": "8f460af710c8f6a4", + "gsd-core/workflows/do.md": "7512dd1892f118a1", "gsd-core/workflows/docs-update.md": "f35922d15b7061c9", "gsd-core/workflows/edit-phase.md": "966a3eadd1bebc04", "gsd-core/workflows/eval-review.md": "f898936e2cfe4130", @@ -312,10 +314,10 @@ "gsd-core/workflows/graduation.md": "47f1594c88c08501", "gsd-core/workflows/health.md": "107e3c72e76d9535", "gsd-core/workflows/help.md": "5d040504b9ab35e3", - "gsd-core/workflows/help/modes/brief.md": "5fe077fbbdb5d9f7", - "gsd-core/workflows/help/modes/default.md": "cc8ef97de634c995", - "gsd-core/workflows/help/modes/full.md": "96abbac7f3f10e32", - "gsd-core/workflows/help/modes/topic.md": "6762e41e3291ae24", + "gsd-core/workflows/help/modes/brief.md": "924860e1f07defb0", + "gsd-core/workflows/help/modes/default.md": "08a02976c0c5cc50", + "gsd-core/workflows/help/modes/full.md": "895b35f264530d24", + "gsd-core/workflows/help/modes/topic.md": "5c160093f3cbf35d", "gsd-core/workflows/import.md": "3d3fa603ceb8bc9f", "gsd-core/workflows/inbox.md": "437f981ef9ae7b26", "gsd-core/workflows/ingest-docs.md": "c859921c811ac11b", @@ -333,6 +335,7 @@ "gsd-core/workflows/next.md": "13fb800f2472d970", "gsd-core/workflows/node-repair.md": "07a1628e5a1ff96b", "gsd-core/workflows/note.md": "5a99eb396c744619", + "gsd-core/workflows/onboard.md": "6f9e6c0b484271a9", "gsd-core/workflows/pause-work.md": "f2b33bba5593d422", "gsd-core/workflows/plan-milestone-gaps.md": "852f6d7c0c4299dc", "gsd-core/workflows/plan-phase.md": "a886ba9bdf4d0baf", @@ -414,7 +417,7 @@ "skills/gsd-ns-context/skills/docs-update/SKILL.md": "8fb602920a333d73", "skills/gsd-ns-context/skills/extract-learnings/SKILL.md": "6de7eeaaf4939e5d", "skills/gsd-ns-context/skills/graphify/SKILL.md": "d54c2b44e8059299", - "skills/gsd-ns-context/skills/map-codebase/SKILL.md": "ce7f2382e4086b68", + "skills/gsd-ns-context/skills/map-codebase/SKILL.md": "f48d48b43e2cc4bd", "skills/gsd-ns-context/skills/mempalace-capture/SKILL.md": "40a31ad049374297", "skills/gsd-ns-context/skills/mempalace-recall/SKILL.md": "c3f412d5a64f3921", "skills/gsd-ns-ideate/SKILL.md": "4a0d2691054b23e5", @@ -442,7 +445,7 @@ "skills/gsd-ns-manage/skills/update/SKILL.md": "01ca0efbdb8f6efa", "skills/gsd-ns-manage/skills/workspace/SKILL.md": "c6c07625a373e6a3", "skills/gsd-ns-manage/skills/workstreams/SKILL.md": "f4e54cb9b1ca0442", - "skills/gsd-ns-project/SKILL.md": "a58b3170197968be", + "skills/gsd-ns-project/SKILL.md": "5d7ec93b195555e7", "skills/gsd-ns-project/skills/audit-milestone/SKILL.md": "a6eb7edcfd23c7e4", "skills/gsd-ns-project/skills/complete-milestone/SKILL.md": "d7f6202222d1b26e", "skills/gsd-ns-project/skills/import/SKILL.md": "0a734021e0b86481", @@ -450,6 +453,7 @@ "skills/gsd-ns-project/skills/milestone-summary/SKILL.md": "c77f6c8ce7c57db9", "skills/gsd-ns-project/skills/new-milestone/SKILL.md": "3aad804c48d77474", "skills/gsd-ns-project/skills/new-project/SKILL.md": "e3cfd1fdbc2c3406", + "skills/gsd-ns-project/skills/onboard/SKILL.md": "84519552f7396347", "skills/gsd-ns-project/skills/profile-user/SKILL.md": "f57ad5e5c5899100", "skills/gsd-ns-project/skills/review-backlog/SKILL.md": "1708aab6cb919223", "skills/gsd-ns-review/SKILL.md": "7badceb8627d8154", From 3c7d722ed9ef2421115914e6537bc3c405bd7bf3 Mon Sep 17 00:00:00 2001 From: Tom Boucher Date: Mon, 6 Jul 2026 23:58:27 -0400 Subject: [PATCH 44/48] docs(#1990): add ADR-1990 onboard projection module --- docs/adr/1990-onboard-projection-module.md | 69 ++++++++++++++++++++++ 1 file changed, 69 insertions(+) create mode 100644 docs/adr/1990-onboard-projection-module.md diff --git a/docs/adr/1990-onboard-projection-module.md b/docs/adr/1990-onboard-projection-module.md new file mode 100644 index 000000000..8e67eb5a9 --- /dev/null +++ b/docs/adr/1990-onboard-projection-module.md @@ -0,0 +1,69 @@ +# Onboard Projection Module owns deterministic brownfield repo-state detection and onboarding route selection + +- **Status:** Proposed +- **Date:** 2026-07-06 +- **Issue:** #1990 +- **Implementation:** PR #1994 + +## Context + +GSD already ships strong individual primitives for adopting an existing codebase: `/gsd:map-codebase` (parallel codebase analysis), `/gsd:ingest-docs` (classify and consolidate existing ADR/PRD/SPEC/RFC docs), and `/gsd:new-project` (planning initialization). What it lacked was a single guided entry point that inspects a brownfield repository and tells the user *which primitive runs first*. + +Left to prose alone, that ordering is ambiguous and unsafe: a user can initialize planning before a codebase map exists, skip relevant design docs, or overwrite/duplicate `.planning/` context instead of reusing it. The ordering is not a matter of taste — it is a **dependency graph** (a map should exist before planning; existing design docs should be ingested before a fresh `/gsd:new-project`; nothing should clobber an in-progress `.planning/`). A dependency graph that decides the next safe action from filesystem state is a *projection*, not something a workflow's natural-language instructions can evaluate reliably or test. + +GSD already has the seam for this. The **Init Command Module** (`src/init.cts` → `gsd-core/bin/lib/init.cjs`) owns the `init.*` family of query handlers that compose atomic queries into the flat JSON bundles that init workflows consume, alongside the projection-module precedent set by the **Planning Path Projection Module** (ADR-0006) and the **Shell Command Projection Module** (ADR-0009). Adding `/gsd:onboard` as free-form workflow prose that scans the tree inline would put untested, non-deterministic filesystem logic in markdown — precisely the anti-pattern those projection modules exist to prevent. + +## Decision + +Introduce the **Onboard Projection Module** (`src/onboard-projection.cts` → `gsd-core/bin/lib/onboard-projection.cjs`) as the Seam that owns **deterministic detection of brownfield repository state and the selection of the next onboarding action**. It is a pure, side-effect-free projection consumed by the Init Command Module's `initOnboard` handler and rendered by the `/gsd:onboard` workflow. It never writes; detection and route selection are a function of repository state only. + +**Detected state (inputs):** + +| Signal | Rule / invariant | +|---|---| +| Brownfield code present | Depth-capped recursive scan for source files (`hasCodeFilesInternal`) OR a recognized package manifest (`hasPackageFileInternal`). | +| Generated / vendor exclusion | Scan skips `CODE_SCAN_SKIP_DIRS` (`node_modules`, `dist`, `build`, `.next`, `.nuxt`, `.svelte-kit`, `coverage`, `vendor`, `.venv`, `venv`) so vendored trees never produce a false brownfield positive. | +| Codebase-map completeness | Whether `.planning/codebase/` holds the canonical map artifacts. | +| Existing design docs | Presence of ADR/PRD/SPEC/RFC-style candidates (root, nested, and segment-based). | +| Partial planning state | Whether some but not all of `PROJECT.md` / `REQUIREMENTS.md` / `ROADMAP.md` / `STATE.md` exist. | + +**Route selection (output), ordered by dependency, not by convenience:** + +1. Brownfield code without a complete `.planning/codebase/` map → hand off to `/gsd:map-codebase` (or `/gsd:map-codebase --fast` in fast mode). +2. Design-doc candidates present and no project yet → offer `/gsd:ingest-docs` **before** `/gsd:new-project`. +3. Otherwise → `/gsd:new-project`. + +The gate order is load-bearing: **partial-planning and fast-map-completeness are evaluated before the docs-ingest branch**, so a half-mapped or half-initialized repo is never routed past the step it still owes. Handoff commands are runtime-formatted (`buildHandoffCommands` / `formatGsdSlash`) so the projected next command is correct for the installed runtime's slash syntax. + +**Safety invariants (the reason this is a Module, not a helper):** + +- **Idempotent / no silent overwrite.** Onboarding never mutates existing tracked `.planning/` artifacts; re-running leaves them byte-unchanged. +- **`SUMMARY.md` is a trailing artifact.** `.planning/onboarding/SUMMARY.md` is written only *after* project setup exists, and only if absent. +- **"Complete" is a conjunction.** Onboarding does not report complete until `PROJECT.md`, `REQUIREMENTS.md`, `ROADMAP.md`, and `STATE.md` all exist — no single-file short-circuit. +- **Text-mode parity.** `--text` renders the same gate decisions as numbered plain-text prompts, so runtimes without an interactive picker get identical routing. + +## What stays OUTSIDE this Module + +- **The primitives themselves.** `/gsd:map-codebase`, `/gsd:ingest-docs`, and `/gsd:new-project` retain their own behavior; the Module only *chooses and orders* them. It projects the route; it does not re-implement the destinations. +- **Writing planning artifacts.** All `.planning/` writes remain owned by the destination commands and the Installer/planning modules. The projection is read-only. +- **The workflow's rendering.** `gsd-core/workflows/onboard.md` owns menu/gate presentation; the command `commands/gsd/onboard.md` (and its skill mirror) owns delegation. The Module owns only the state→route decision they consume. + +## Consequences + +- Brownfield onboarding becomes a single, testable entry point with deterministic routing, rather than order-of-operations folklore in prose. The projection is unit-tested (`tests/onboard-command.test.cjs`) for brownfield/greenfield detection, vendor-dir exclusion, gate ordering (partial-planning before docs-ingest), idempotency/no-mutation, and runtime-formatted handoffs. +- The Init Command Module gains one more heavyweight handler (`initOnboard`) with the same `{ data: }` contract as its siblings — no new dispatch shape. +- **New maintenance coupling, now explicit.** The Module's completeness checks must track the canonical `.planning/codebase/` artifact list and the routing targets' identities; if `/gsd:map-codebase` / `/gsd:ingest-docs` / `/gsd:new-project` change their entry contracts, this projection must follow. This ADR records that coupling as the known cost of centralizing the routing decision (the alternative — duplicating the decision across each primitive — is worse). +- No new runtime dependencies; no change to existing command semantics (additive). + +## Open questions + +- Should codebase-map completeness be sourced from a single shared predicate (owned by the map module) rather than re-encoded here, so the two cannot drift? +- The `/gsd:onboard` workflow sources its `gsd_run` bootstrap from a shared `references/gsd-run-resolver.md` snippet rather than inlining it. If that delegation pattern is adopted by other workflows, it likely deserves its own short ADR — noting it here so the precedent is visible rather than silently established. + +## References + +- ADR-0006 — Planning Path Projection Module (projection-module precedent for `.planning` path resolution). +- ADR-0009 — Shell Command Projection Module (runtime-aware projection precedent). +- Init Command Module (`src/init.cts` → `gsd-core/bin/lib/init.cjs`) — owner of the `init.*` handler family that consumes this projection via `initOnboard`. +- `CONTEXT.md` § Init Command Module — where the onboarding projection is registered. +- Issue #1990 — feature spec and acceptance criteria. From e8fb05e9655f2d1a87fa1a6b8d1b5687e368f6eb Mon Sep 17 00:00:00 2001 From: Tom Boucher Date: Mon, 6 Jul 2026 23:58:50 -0400 Subject: [PATCH 45/48] docs(#1990): index ADR-1990 in adr README --- docs/adr/README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/adr/README.md b/docs/adr/README.md index 5922a7422..945e088cc 100644 --- a/docs/adr/README.md +++ b/docs/adr/README.md @@ -64,6 +64,7 @@ See **[CONTRIBUTING.md — "Proposing an ADR or PRD"](../../CONTRIBUTING.md#prop | [1769-state-md-transition-module.md](1769-state-md-transition-module.md) | STATE.md Transition Module — intent-based transitions over scattered RMW callbacks | Proposed | | [1817-state-md-rebuild-derivability-contract.md](1817-state-md-rebuild-derivability-contract.md) | STATE.md rebuild — derivability contract (capstone 11th transition) | Accepted | | [2008-command-exit-zero-gate.md](2008-command-exit-zero-gate.md) | Generic gate-predicate evaluator with a `command-exit-zero` kind (#2008) | Accepted | +| [1990-onboard-projection-module.md](1990-onboard-projection-module.md) | Onboard Projection Module owns deterministic brownfield repo-state detection and onboarding route selection | Proposed | ## Seam map From d0b8eacd3ce404fe02b3fa6f57c48bb59f7306b5 Mon Sep 17 00:00:00 2001 From: Tom Boucher Date: Tue, 7 Jul 2026 00:01:55 -0400 Subject: [PATCH 46/48] docs(#1990): rename ADR to Existing Code Onboarding --- docs/adr/1990-existing-code-onboarding.md | 69 +++++++++++++++++++++++ 1 file changed, 69 insertions(+) create mode 100644 docs/adr/1990-existing-code-onboarding.md diff --git a/docs/adr/1990-existing-code-onboarding.md b/docs/adr/1990-existing-code-onboarding.md new file mode 100644 index 000000000..aa9b47c3f --- /dev/null +++ b/docs/adr/1990-existing-code-onboarding.md @@ -0,0 +1,69 @@ +# Existing Code Onboarding Module owns deterministic repo-state detection and onboarding route selection + +- **Status:** Proposed +- **Date:** 2026-07-06 +- **Issue:** #1990 +- **Implementation:** PR #1994 + +## Context + +GSD already ships strong individual primitives for adopting an existing codebase: `/gsd:map-codebase` (parallel codebase analysis), `/gsd:ingest-docs` (classify and consolidate existing ADR/PRD/SPEC/RFC docs), and `/gsd:new-project` (planning initialization). What it lacked was a single guided entry point that inspects a brownfield repository and tells the user *which primitive runs first*. + +Left to prose alone, that ordering is ambiguous and unsafe: a user can initialize planning before a codebase map exists, skip relevant design docs, or overwrite/duplicate `.planning/` context instead of reusing it. The ordering is not a matter of taste — it is a **dependency graph** (a map should exist before planning; existing design docs should be ingested before a fresh `/gsd:new-project`; nothing should clobber an in-progress `.planning/`). A dependency graph that decides the next safe action from filesystem state is a *projection*, not something a workflow's natural-language instructions can evaluate reliably or test. + +GSD already has the seam for this. The **Init Command Module** (`src/init.cts` → `gsd-core/bin/lib/init.cjs`) owns the `init.*` family of query handlers that compose atomic queries into the flat JSON bundles that init workflows consume, alongside the projection-module precedent set by the **Planning Path Projection Module** (ADR-0006) and the **Shell Command Projection Module** (ADR-0009). Adding `/gsd:onboard` as free-form workflow prose that scans the tree inline would put untested, non-deterministic filesystem logic in markdown — precisely the anti-pattern those projection modules exist to prevent. + +## Decision + +Introduce the **Existing Code Onboarding Module** (implemented as the `src/onboard-projection.cts` → `gsd-core/bin/lib/onboard-projection.cjs` projection) as the Seam that owns **deterministic detection of brownfield repository state and the selection of the next onboarding action**. It is a pure, side-effect-free projection consumed by the Init Command Module's `initOnboard` handler and rendered by the `/gsd:onboard` workflow. It never writes; detection and route selection are a function of repository state only. + +**Detected state (inputs):** + +| Signal | Rule / invariant | +|---|---| +| Brownfield code present | Depth-capped recursive scan for source files (`hasCodeFilesInternal`) OR a recognized package manifest (`hasPackageFileInternal`). | +| Generated / vendor exclusion | Scan skips `CODE_SCAN_SKIP_DIRS` (`node_modules`, `dist`, `build`, `.next`, `.nuxt`, `.svelte-kit`, `coverage`, `vendor`, `.venv`, `venv`) so vendored trees never produce a false brownfield positive. | +| Codebase-map completeness | Whether `.planning/codebase/` holds the canonical map artifacts. | +| Existing design docs | Presence of ADR/PRD/SPEC/RFC-style candidates (root, nested, and segment-based). | +| Partial planning state | Whether some but not all of `PROJECT.md` / `REQUIREMENTS.md` / `ROADMAP.md` / `STATE.md` exist. | + +**Route selection (output), ordered by dependency, not by convenience:** + +1. Brownfield code without a complete `.planning/codebase/` map → hand off to `/gsd:map-codebase` (or `/gsd:map-codebase --fast` in fast mode). +2. Design-doc candidates present and no project yet → offer `/gsd:ingest-docs` **before** `/gsd:new-project`. +3. Otherwise → `/gsd:new-project`. + +The gate order is load-bearing: **partial-planning and fast-map-completeness are evaluated before the docs-ingest branch**, so a half-mapped or half-initialized repo is never routed past the step it still owes. Handoff commands are runtime-formatted (`buildHandoffCommands` / `formatGsdSlash`) so the projected next command is correct for the installed runtime's slash syntax. + +**Safety invariants (the reason this is a Module, not a helper):** + +- **Idempotent / no silent overwrite.** Onboarding never mutates existing tracked `.planning/` artifacts; re-running leaves them byte-unchanged. +- **`SUMMARY.md` is a trailing artifact.** `.planning/onboarding/SUMMARY.md` is written only *after* project setup exists, and only if absent. +- **"Complete" is a conjunction.** Onboarding does not report complete until `PROJECT.md`, `REQUIREMENTS.md`, `ROADMAP.md`, and `STATE.md` all exist — no single-file short-circuit. +- **Text-mode parity.** `--text` renders the same gate decisions as numbered plain-text prompts, so runtimes without an interactive picker get identical routing. + +## What stays OUTSIDE this Module + +- **The primitives themselves.** `/gsd:map-codebase`, `/gsd:ingest-docs`, and `/gsd:new-project` retain their own behavior; the Module only *chooses and orders* them. It projects the route; it does not re-implement the destinations. +- **Writing planning artifacts.** All `.planning/` writes remain owned by the destination commands and the Installer/planning modules. The projection is read-only. +- **The workflow's rendering.** `gsd-core/workflows/onboard.md` owns menu/gate presentation; the command `commands/gsd/onboard.md` (and its skill mirror) owns delegation. The Module owns only the state→route decision they consume. + +## Consequences + +- Brownfield onboarding becomes a single, testable entry point with deterministic routing, rather than order-of-operations folklore in prose. The projection is unit-tested (`tests/onboard-command.test.cjs`) for brownfield/greenfield detection, vendor-dir exclusion, gate ordering (partial-planning before docs-ingest), idempotency/no-mutation, and runtime-formatted handoffs. +- The Init Command Module gains one more heavyweight handler (`initOnboard`) with the same `{ data: }` contract as its siblings — no new dispatch shape. +- **New maintenance coupling, now explicit.** The Module's completeness checks must track the canonical `.planning/codebase/` artifact list and the routing targets' identities; if `/gsd:map-codebase` / `/gsd:ingest-docs` / `/gsd:new-project` change their entry contracts, this projection must follow. This ADR records that coupling as the known cost of centralizing the routing decision (the alternative — duplicating the decision across each primitive — is worse). +- No new runtime dependencies; no change to existing command semantics (additive). + +## Open questions + +- Should codebase-map completeness be sourced from a single shared predicate (owned by the map module) rather than re-encoded here, so the two cannot drift? +- The `/gsd:onboard` workflow sources its `gsd_run` bootstrap from a shared `references/gsd-run-resolver.md` snippet rather than inlining it. If that delegation pattern is adopted by other workflows, it likely deserves its own short ADR — noting it here so the precedent is visible rather than silently established. + +## References + +- ADR-0006 — Planning Path Projection Module (projection-module precedent for `.planning` path resolution). +- ADR-0009 — Shell Command Projection Module (runtime-aware projection precedent). +- Init Command Module (`src/init.cts` → `gsd-core/bin/lib/init.cjs`) — owner of the `init.*` handler family that consumes this projection via `initOnboard`. +- `CONTEXT.md` § Init Command Module — where the onboarding projection is registered. +- Issue #1990 — feature spec and acceptance criteria. From 1171499f3842b77864e39be9a351f48f7c4c8257 Mon Sep 17 00:00:00 2001 From: Tom Boucher Date: Tue, 7 Jul 2026 00:01:56 -0400 Subject: [PATCH 47/48] docs(#1990): remove pre-rename ADR filename --- docs/adr/1990-onboard-projection-module.md | 69 ---------------------- 1 file changed, 69 deletions(-) delete mode 100644 docs/adr/1990-onboard-projection-module.md diff --git a/docs/adr/1990-onboard-projection-module.md b/docs/adr/1990-onboard-projection-module.md deleted file mode 100644 index 8e67eb5a9..000000000 --- a/docs/adr/1990-onboard-projection-module.md +++ /dev/null @@ -1,69 +0,0 @@ -# Onboard Projection Module owns deterministic brownfield repo-state detection and onboarding route selection - -- **Status:** Proposed -- **Date:** 2026-07-06 -- **Issue:** #1990 -- **Implementation:** PR #1994 - -## Context - -GSD already ships strong individual primitives for adopting an existing codebase: `/gsd:map-codebase` (parallel codebase analysis), `/gsd:ingest-docs` (classify and consolidate existing ADR/PRD/SPEC/RFC docs), and `/gsd:new-project` (planning initialization). What it lacked was a single guided entry point that inspects a brownfield repository and tells the user *which primitive runs first*. - -Left to prose alone, that ordering is ambiguous and unsafe: a user can initialize planning before a codebase map exists, skip relevant design docs, or overwrite/duplicate `.planning/` context instead of reusing it. The ordering is not a matter of taste — it is a **dependency graph** (a map should exist before planning; existing design docs should be ingested before a fresh `/gsd:new-project`; nothing should clobber an in-progress `.planning/`). A dependency graph that decides the next safe action from filesystem state is a *projection*, not something a workflow's natural-language instructions can evaluate reliably or test. - -GSD already has the seam for this. The **Init Command Module** (`src/init.cts` → `gsd-core/bin/lib/init.cjs`) owns the `init.*` family of query handlers that compose atomic queries into the flat JSON bundles that init workflows consume, alongside the projection-module precedent set by the **Planning Path Projection Module** (ADR-0006) and the **Shell Command Projection Module** (ADR-0009). Adding `/gsd:onboard` as free-form workflow prose that scans the tree inline would put untested, non-deterministic filesystem logic in markdown — precisely the anti-pattern those projection modules exist to prevent. - -## Decision - -Introduce the **Onboard Projection Module** (`src/onboard-projection.cts` → `gsd-core/bin/lib/onboard-projection.cjs`) as the Seam that owns **deterministic detection of brownfield repository state and the selection of the next onboarding action**. It is a pure, side-effect-free projection consumed by the Init Command Module's `initOnboard` handler and rendered by the `/gsd:onboard` workflow. It never writes; detection and route selection are a function of repository state only. - -**Detected state (inputs):** - -| Signal | Rule / invariant | -|---|---| -| Brownfield code present | Depth-capped recursive scan for source files (`hasCodeFilesInternal`) OR a recognized package manifest (`hasPackageFileInternal`). | -| Generated / vendor exclusion | Scan skips `CODE_SCAN_SKIP_DIRS` (`node_modules`, `dist`, `build`, `.next`, `.nuxt`, `.svelte-kit`, `coverage`, `vendor`, `.venv`, `venv`) so vendored trees never produce a false brownfield positive. | -| Codebase-map completeness | Whether `.planning/codebase/` holds the canonical map artifacts. | -| Existing design docs | Presence of ADR/PRD/SPEC/RFC-style candidates (root, nested, and segment-based). | -| Partial planning state | Whether some but not all of `PROJECT.md` / `REQUIREMENTS.md` / `ROADMAP.md` / `STATE.md` exist. | - -**Route selection (output), ordered by dependency, not by convenience:** - -1. Brownfield code without a complete `.planning/codebase/` map → hand off to `/gsd:map-codebase` (or `/gsd:map-codebase --fast` in fast mode). -2. Design-doc candidates present and no project yet → offer `/gsd:ingest-docs` **before** `/gsd:new-project`. -3. Otherwise → `/gsd:new-project`. - -The gate order is load-bearing: **partial-planning and fast-map-completeness are evaluated before the docs-ingest branch**, so a half-mapped or half-initialized repo is never routed past the step it still owes. Handoff commands are runtime-formatted (`buildHandoffCommands` / `formatGsdSlash`) so the projected next command is correct for the installed runtime's slash syntax. - -**Safety invariants (the reason this is a Module, not a helper):** - -- **Idempotent / no silent overwrite.** Onboarding never mutates existing tracked `.planning/` artifacts; re-running leaves them byte-unchanged. -- **`SUMMARY.md` is a trailing artifact.** `.planning/onboarding/SUMMARY.md` is written only *after* project setup exists, and only if absent. -- **"Complete" is a conjunction.** Onboarding does not report complete until `PROJECT.md`, `REQUIREMENTS.md`, `ROADMAP.md`, and `STATE.md` all exist — no single-file short-circuit. -- **Text-mode parity.** `--text` renders the same gate decisions as numbered plain-text prompts, so runtimes without an interactive picker get identical routing. - -## What stays OUTSIDE this Module - -- **The primitives themselves.** `/gsd:map-codebase`, `/gsd:ingest-docs`, and `/gsd:new-project` retain their own behavior; the Module only *chooses and orders* them. It projects the route; it does not re-implement the destinations. -- **Writing planning artifacts.** All `.planning/` writes remain owned by the destination commands and the Installer/planning modules. The projection is read-only. -- **The workflow's rendering.** `gsd-core/workflows/onboard.md` owns menu/gate presentation; the command `commands/gsd/onboard.md` (and its skill mirror) owns delegation. The Module owns only the state→route decision they consume. - -## Consequences - -- Brownfield onboarding becomes a single, testable entry point with deterministic routing, rather than order-of-operations folklore in prose. The projection is unit-tested (`tests/onboard-command.test.cjs`) for brownfield/greenfield detection, vendor-dir exclusion, gate ordering (partial-planning before docs-ingest), idempotency/no-mutation, and runtime-formatted handoffs. -- The Init Command Module gains one more heavyweight handler (`initOnboard`) with the same `{ data: }` contract as its siblings — no new dispatch shape. -- **New maintenance coupling, now explicit.** The Module's completeness checks must track the canonical `.planning/codebase/` artifact list and the routing targets' identities; if `/gsd:map-codebase` / `/gsd:ingest-docs` / `/gsd:new-project` change their entry contracts, this projection must follow. This ADR records that coupling as the known cost of centralizing the routing decision (the alternative — duplicating the decision across each primitive — is worse). -- No new runtime dependencies; no change to existing command semantics (additive). - -## Open questions - -- Should codebase-map completeness be sourced from a single shared predicate (owned by the map module) rather than re-encoded here, so the two cannot drift? -- The `/gsd:onboard` workflow sources its `gsd_run` bootstrap from a shared `references/gsd-run-resolver.md` snippet rather than inlining it. If that delegation pattern is adopted by other workflows, it likely deserves its own short ADR — noting it here so the precedent is visible rather than silently established. - -## References - -- ADR-0006 — Planning Path Projection Module (projection-module precedent for `.planning` path resolution). -- ADR-0009 — Shell Command Projection Module (runtime-aware projection precedent). -- Init Command Module (`src/init.cts` → `gsd-core/bin/lib/init.cjs`) — owner of the `init.*` handler family that consumes this projection via `initOnboard`. -- `CONTEXT.md` § Init Command Module — where the onboarding projection is registered. -- Issue #1990 — feature spec and acceptance criteria. From bc751a64ecde27071673b2e183f7d418c1ad9fe6 Mon Sep 17 00:00:00 2001 From: Tom Boucher Date: Tue, 7 Jul 2026 00:01:57 -0400 Subject: [PATCH 48/48] docs(#1990): point adr index at renamed file --- docs/adr/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/adr/README.md b/docs/adr/README.md index 945e088cc..03038a5c9 100644 --- a/docs/adr/README.md +++ b/docs/adr/README.md @@ -64,7 +64,7 @@ See **[CONTRIBUTING.md — "Proposing an ADR or PRD"](../../CONTRIBUTING.md#prop | [1769-state-md-transition-module.md](1769-state-md-transition-module.md) | STATE.md Transition Module — intent-based transitions over scattered RMW callbacks | Proposed | | [1817-state-md-rebuild-derivability-contract.md](1817-state-md-rebuild-derivability-contract.md) | STATE.md rebuild — derivability contract (capstone 11th transition) | Accepted | | [2008-command-exit-zero-gate.md](2008-command-exit-zero-gate.md) | Generic gate-predicate evaluator with a `command-exit-zero` kind (#2008) | Accepted | -| [1990-onboard-projection-module.md](1990-onboard-projection-module.md) | Onboard Projection Module owns deterministic brownfield repo-state detection and onboarding route selection | Proposed | +| [1990-existing-code-onboarding.md](1990-existing-code-onboarding.md) | Existing Code Onboarding Module owns deterministic repo-state detection and onboarding route selection | Proposed | ## Seam map