Skip to content

fix(cli): select runtime during setup#420

Merged
moncher-dev merged 2 commits into
mainfrom
feat/390-setup-runtime-selection
Jun 25, 2026
Merged

fix(cli): select runtime during setup#420
moncher-dev merged 2 commits into
mainfrom
feat/390-setup-runtime-selection

Conversation

@moncher-dev

@moncher-dev moncher-dev commented Jun 25, 2026

Copy link
Copy Markdown
Collaborator

Issues

TL;DR

gh-symphony setup now uses the selected runtime throughout onboarding instead of hardcoding Codex, and the review rework keeps that flow clean for real CLI users: auth runs before runtime selection, interactive step labels are consistent, missing-runtime warnings do not corrupt --json stdout, and setup no longer imports the large doctor command module for a small PATH check.

변경 지점 다이어그램

setup --runtime / runtime prompt
  -> normalize preset aliases
  -> plan WORKFLOW.md + ecosystem files with selected runtime
  -> initialize repo runtime
  -> PATH check via shared commandExistsOnPath utility
  -> text warning on terminal UI OR stderr warning in --json mode
  -> summary / repo start hint

여기부터 보세요

  • packages/cli/src/commands/setup.ts — runtime flag parsing, auth-before-runtime prompt ordering, artifact wiring, JSON-safe install warning, 5-step labels.
  • packages/cli/src/utils/command-exists-on-path.ts — lightweight shared PATH lookup used by setup and doctor.
  • packages/cli/src/commands/setup.test.ts — non-interactive Claude runtime generation, unsupported runtime rejection, JSON parseability, auth-before-prompt, and step-label regression coverage.
  • packages/cli/src/commands/doctor.ts — reuses the shared PATH lookup utility.

위험 & 롤백

  • Risk: first-run setup gains one additional runtime selection step and now surfaces missing runtime binaries immediately.
  • Rollback: revert this PR to restore the previous Codex-only setup behavior.

변경 파일

  • .changeset/setup-runtime-selection.md
  • packages/cli/src/commands/setup.ts
  • packages/cli/src/commands/setup.test.ts
  • packages/cli/src/commands/doctor.ts
  • packages/cli/src/utils/command-exists-on-path.ts
  • packages/cli/src/index.ts
  • packages/cli/src/completion.ts

Evidence

  • pnpm --filter @gh-symphony/cli test -- setup.test.ts — pass
  • pnpm lint — pass
  • pnpm test — pass
  • pnpm typecheck — pass
  • pnpm build — pass

머지 후/사람 확인

  • Optionally run gh-symphony setup manually and confirm the runtime prompt and missing-runtime warning read well in a real terminal.

@github-actions

github-actions Bot commented Jun 25, 2026

Copy link
Copy Markdown
Contributor

Coverage Report

Status Category Percentage Covered / Total
🔵 Lines 39.19% 28689 / 73192
🔵 Statements 39.19% 28689 / 73192
🔵 Functions 71.69% 1406 / 1961
🔵 Branches 76.56% 5898 / 7703
File Coverage
File Stmts Branches Functions Lines Uncovered Lines
Changed Files
packages/cli/src/completion.ts 100% 87.09% 100% 100%
packages/cli/src/index.ts 80.49% 82.25% 72% 80.49% 123-124, 138-140, 148-150, 152-153, 176-177, 192-193, 254-259, 280-292, 302-306, 321-329, 346-354, 378-386, 395-396, 455-456, 500-504, 515-520, 647-651, 659-660, 666-671, 682-687, 693-698, 717-722, 743-744, 758-759, 762-764, 770-778
packages/cli/src/commands/doctor.ts 78.5% 73.42% 97.87% 78.5% 295-297, 304-310, 385-386, 396-397, 492-499, 510-511, 560-562, 613-614, 641-644, 694, 715, 735-745, 748-758, 785-797, 811-824, 840-844, 851-852, 859-860, 877, 887, 918-921, 932-938, 947-948, 994, 1010-1030, 1077-1086, 1138-1140, 1173, 1239, 1244, 1292-1302, 1305-1315, 1318-1328, 1362-1374, 1377-1385, 1404-1414, 1417-1427, 1475-1487, 1494-1502, 1718, 1746, 1763, 1779-1787, 1809-1817, 1852, 1857, 1893-1894, 1913-1932, 2135-2136, 2142-2143, 2184-2193, 2214-2223, 2235, 2239-2247, 2250-2259, 2266-2275, 2287-2302, 2325-2335, 2338-2348, 2378-2394, 2397-2409, 2435, 2437-2438, 2440-2459, 2487, 2491, 2525, 2528, 2537-2548, 2550-2562, 2575, 2594, 2605, 2611-2628, 2645-2648, 2659-2660, 2689-2690
packages/cli/src/commands/setup.ts 76.62% 71.08% 93.33% 76.62% 78-83, 86-87, 92-93, 95-96, 145-146, 172-190, 207-210, 216-219, 226-229, 283-284, 312-317, 325-328, 332-337, 343-348, 352-355, 366-372, 376-381, 463-464, 479-487, 497-501, 505-510, 530-531, 581-584, 613-617
packages/cli/src/utils/command-exists-on-path.ts 74.07% 76.19% 100% 74.07% 27-28, 38-39, 43-53
Generated in workflow #313 for commit fdc4aa2 by the Vitest Coverage Report Action

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 8ab0ab2b96

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread packages/cli/src/commands/setup.ts Outdated
workflowFile: workflowPath,
});

await warnIfRuntimeMissing(selectedRuntime);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Keep JSON setup output machine-readable

When gh-symphony setup --non-interactive --json runs on a host where the selected runtime binary is not on PATH, this call logs the install warning via p.log.warn before writing the JSON result. @clack/prompts log helpers write to stdout, so the command emits a warning block followed by JSON on stdout, which breaks callers that parse --json output; route this warning to stderr or suppress it in JSON mode.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Addressed in fdc4aa2: missing-runtime warnings now go to stderr when setup runs with --json, so stdout remains a single parseable JSON object. Added a regression test that parses the captured JSON output while asserting the warning is emitted on stderr.

@hojinzs hojinzs left a comment

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ Approve — #390 fully addressed

요구사항 대비 검증 (issue #390 수용 조건):

수용 조건 상태
Interactive setup에 런타임 선택 단계 추가 (Codex / Claude Code) ✅ Step 1/5 prompt 추가, 나머지 단계 /5로 재번호
비대화형 --runtime 플래그 ✅ 파싱·검증·completion·help 모두 반영
선택 런타임 PATH 체크 + 설치 힌트 (doctor commandExistsOnPath 재사용) warnIfRuntimeMissing 로 비대화형/대화형 양쪽에서 경고
하드코딩된 runtime: "codex" 4곳 제거 ✅ 4곳 모두 selectedRuntime 로 교체

Smoke Test (built CLI, node dist/index.js):

  • setup --help--runtime <kind> 노출 ✅
  • setup --non-interactive --runtime claud-printError: Unsupported runtime 'claud-print'. Choose one of: codex-app-server, claude-print. (exit 1, auth 이전에 거부) ✅
  • setup --non-interactive --runtime (값 누락) → option '--runtime <kind>' argument missing
  • completion bash--runtime 포함 ✅
  • --runtime claude-code 별칭 → claude-print 정규화 + WORKFLOW.md 에 kind: claude-print / command: claude 작성 (단위 테스트로 확인) ✅

Build / Test: pnpm --filter @gh-symphony/cli build 성공, setup.test.ts 15 tests 통과.

코드 품질도 양호합니다 — doctor 헬퍼 재사용, 별칭 정규화, 누락 인자 가드 등 기존 컨벤션을 잘 따랐습니다. 인라인의 prompt 순서 nit은 비차단 사항입니다. LGTM 🎉


Generated by Claude Code

Comment thread packages/cli/src/commands/setup.ts Outdated
): Promise<void> {
p.intro("gh-symphony — One-command Setup");

const selectedRuntime = await promptRuntimeSelection();

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit (non-blocking, UX ordering): the runtime prompt runs before the gh auth check below. If auth fails, the user has already answered the runtime step and re-runs from scratch. workflow init resolves auth first; consider moving this prompt after the auth spinner succeeds for symmetry. Minor — not worth blocking the merge.


Generated by Claude Code

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Addressed in fdc4aa2: interactive setup now completes the gh auth check before prompting for runtime selection, matching the workflow init ordering. The auth-remediation test now asserts no runtime/project prompt is shown when auth fails.

@hojinzs hojinzs left a comment

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ Completeness verification — Approve

PR #420 fully satisfies issue #390. Verified end-to-end below.

Acceptance criteria (issue #390)

Requirement Status
Runtime-selection prompt in interactive setup (Codex / Claude Code) promptRuntimeSelection() added as the first interactive step
--runtime flag in non-interactive setup ✅ parsed in parseSetupFlags, validated + normalized, wired through index.ts and completion.ts
PATH check reusing doctor's commandExistsOnPath with install hint commandExistsOnPath exported; warnIfRuntimeMissing warns in both interactive and non-interactive paths with runtime-specific hints

Smoke test (black-box, built CLI)

  • setup --help exposes --runtime <kind>
  • setup --non-interactive --runtime bogus → exits 1 with Unsupported runtime 'bogus'. Choose one of: codex-app-server, claude-print.
  • --runtime claude-print and the alias --runtime claude-code both pass validation and proceed (normalization works) ✅
  • Non-interactive summary now reports Agent runtime

Quality gates (run locally)

  • vitest run setup.test.ts15/15 pass (incl. new Claude non-interactive, unsupported-runtime rejection, interactive prompt-ordering tests)
  • pnpm --filter @gh-symphony/cli typecheck → pass
  • pnpm --filter @gh-symphony/cli lint → pass
  • pnpm build → pass

Findings

1 non-blocking nit (inline): the interactive step counter wasn't fully renumbered after inserting the runtime step — the flow shows two "Step 1" prompts and never reaches "Step 5/5". Cosmetic; workflow init already has the correct pattern to mirror. Recommend a quick follow-up but it does not block merge.

Verdict: Approve. Functionality is complete and correct against the issue; the only outstanding item is a cosmetic step-label fix.


Generated by Claude Code

Comment thread packages/cli/src/commands/setup.ts Outdated
);
const mappings = await promptStateMappings(statusField, {
stepLabel: "Step 2/4",
stepLabel: "Step 2/5",

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Step counter regression (non-blocking nit). Adding the runtime prompt as Step 1/5 shifted every later step, but the project-board prompt at selectProjectSummary (line 225) was left at Step 1/4, and the labels here weren't fully renumbered. The interactive flow now reads:

  • runtime → Step 1/5
  • project board (line 225) → Step 1/4 ← should be Step 2/5
  • state mappings (here) → Step 2/5 ← should be Step 3/5
  • blocker check → Step 3/5 ← should be Step 4/5
  • priority → Step 4/5 ← should be Step 5/5

So the wizard shows two consecutive "Step 1" prompts and never reaches "Step 5/5". The sibling workflow init flow gets this right (workflow-init.ts:304 runtime = Step 1/5, :1878 project = Step 2/5) — worth mirroring. Onboarding clarity is the point of #390, so a quick renumber is warranted, but it doesn't block merge.


Generated by Claude Code

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Addressed in fdc4aa2: the setup wizard now uses Step 1/5 through Step 5/5 consistently: runtime, project board, state mappings, blocker check, then priority. Added regression assertions over the prompt labels.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Updates the CLI onboarding flow (Configuration layer) so gh-symphony setup can configure a repo for a user-selected agent runtime rather than always wiring Codex, aligning setup behavior with the runtime presets already supported by the workflow runtime model.

Changes:

  • Add --runtime <kind> support to gh-symphony setup, propagate it through CLI invocation, and include it in shell completion.
  • Extend interactive setup with a runtime selection prompt and add a runtime binary PATH preflight warning.
  • Export commandExistsOnPath from doctor for reuse and add setup tests covering runtime selection/validation.

Reviewed changes

Copilot reviewed 6 out of 6 changed files in this pull request and generated 5 comments.

Show a summary per file
File Description
.changeset/setup-runtime-selection.md Adds a patch changeset documenting runtime selection during setup.
packages/cli/src/commands/setup.ts Implements runtime selection/flag parsing and runtime PATH warning during setup.
packages/cli/src/commands/setup.test.ts Adds/updates tests for runtime selection and non-interactive --runtime behavior.
packages/cli/src/commands/doctor.ts Exports commandExistsOnPath so setup can reuse the PATH-check logic.
packages/cli/src/index.ts Wires the new --runtime option through the top-level CLI command definition and argument forwarding.
packages/cli/src/completion.ts Adds --runtime to completion options for the setup command.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines 509 to 511
const mappings = await promptStateMappings(statusField, {
stepLabel: "Step 2/4",
stepLabel: "Step 2/5",
});

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Addressed in fdc4aa2: state mapping now receives Step 3/5, with project selection as Step 2/5 and the later prompts shifted accordingly. Covered by the interactive setup prompt-label regression test.

Comment on lines 525 to 528
const lifecycleBase = toWorkflowLifecycleConfig(statusField.name, mappings);
const blockerCheckStates = await promptBlockerCheck(lifecycleBase, {
stepLabel: "Step 3/4",
stepLabel: "Step 3/5",
});

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Addressed in fdc4aa2: blocker check now receives Step 4/5. The interactive setup test asserts the blocker-check confirmation message includes that label.

Comment on lines 534 to 538
const { priority, priorityField } = await promptPriorityConfig({
priorityResolution,
labelNames: priorityLabelNames,
stepLabel: "Step 4/4",
stepLabel: "Step 4/5",
});

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Addressed in fdc4aa2: priority configuration now receives Step 5/5, and the test asserts the priority selection prompt uses that label.

Comment thread packages/cli/src/commands/setup.test.ts Outdated
Comment on lines +316 to +320
const gitPath = execFileSync("which", ["git"], {
encoding: "utf8",
}).trim();
const binDir = await mkdtemp(join(tmpdir(), "setup-runtime-bin-"));
await symlink(gitPath, join(binDir, "git"));

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Addressed in fdc4aa2: the setup test no longer shells out to which or creates symlinks. It mocks the shared commandExistsOnPath utility directly, so the missing-runtime path is covered without platform-specific PATH setup.

Comment on lines 35 to 40
promptBlockerCheck,
promptLegacyGhSymphonyCleanup,
warnDeprecatedSkipContext,
} from "./workflow-init.js";
import { commandExistsOnPath } from "./doctor.js";
import {

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Addressed in fdc4aa2: commandExistsOnPath now lives in packages/cli/src/utils/command-exists-on-path.ts, and both setup.ts and doctor.ts import that lightweight utility instead of setup importing the full doctor command module.

@moncher-dev moncher-dev merged commit 022c158 into main Jun 25, 2026
2 checks passed
@moncher-dev moncher-dev deleted the feat/390-setup-runtime-selection branch June 25, 2026 01:25
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

gh-symphony setup hardcodes the Codex runtime — no prompt, no --runtime flag, no install check

3 participants