Skip to content

feat(cli): /scaffold command — discoverable at the prompt, wizard-safe in the browser#128

Merged
agjs merged 1 commit into
mainfrom
feat/scaffold-command
Jul 18, 2026
Merged

feat(cli): /scaffold command — discoverable at the prompt, wizard-safe in the browser#128
agjs merged 1 commit into
mainfrom
feat/scaffold-command

Conversation

@agjs

@agjs agjs commented Jul 17, 2026

Copy link
Copy Markdown
Owner

What

Adds /scaffold as a first-class slash command so the scaffolder is reachable at the prompt — the #1 onboarding gap (users opened tsforge and saw no obvious "start here"). It now appears in /help text, the / palette, and typed dispatch.

Why the browser path is special

The /help capability browser must NOT get a generated command row for /scaffold. That row would dispatch via fire-and-forget void runLine, and handleHelp's finally immediately resumes the editor — racing the wizard for stdin (the double-typed-text failure). Instead, /scaffold's browser home is the existing awaited "Build something new" wizard row.

  • capabilities.ts: new COMMAND_WIZARD_HOME maps /scaffold → the scaffold wizard opener; commandCapabilities() skips wizard-homed commands.
  • capabilities.test.ts: anti-drift now accepts a wizard home, and asserts /scaffold never gets a run/prefill command row.
  • repl.ts: case "scaffold" awaits openScaffoldInRepl, extracted to an openScaffold helper to keep the command dispatcher's cognitive complexity down.
  • scripts/e2e-scaffold-command-pty.py: real pty test — /scaffold opens the wizard, keystrokes (Enter → Review → Project directory) flow to the wizard (proves it owns stdin), Esc cancels cleanly, and the prompt is usable afterward (suspend/resume, no double-stdin).
  • e2e-help-menu-pty.py: /scaffold is no longer a browser command row, so the capability order reverts.

Reviewer panel

Passed the local harness-review panel. Addressed its advisory findings: extracted the case to lower complexity, and strengthened the pty test to type while the wizard is active.

Known pre-existing limitation (follow-up, not a regression): in basic-input / very-small-terminal (non-editor) mode, openScaffoldInRepl's suspend only controls editorControl, so readline is not suspended during the wizard — identical to the existing /help wizard path that calls the same function.

…e in the browser

Adds /scaffold as a first-class slash command so the scaffolder is reachable at
the prompt (the #1 onboarding gap: users saw no obvious "start here"). It appears
in /help text, the / palette, and typed dispatch.

The /help capability browser does NOT get a generated command row for /scaffold:
that path dispatches via fire-and-forget void runLine and handleHelp's finally
immediately resumes the editor, racing the wizard for stdin (double-typed text).
Instead /scaffold's browser home is the existing awaited "Build something new"
wizard row. New COMMAND_WIZARD_HOME maps the command to that wizard opener; the
anti-drift test now accepts a wizard home, and asserts /scaffold never gets a
run/prefill row. The typed/palette paths await openScaffoldInRepl, so the wizard's
own suspend/resume owns the screen for its lifetime.

- capabilities.ts: COMMAND_WIZARD_HOME; skip wizard-homed commands in commandCapabilities
- capabilities.test.ts: anti-drift accepts wizard home + asserts no /scaffold command row
- repl.ts: case scaffold awaits openScaffoldInRepl (comment clarifies the browser path)
- scripts/e2e-scaffold-command-pty.py: real pty test — /scaffold opens the wizard,
  Esc cancels cleanly, prompt is usable afterwards (proves suspend/resume, no double-stdin)
- e2e-help-menu-pty.py: /scaffold no longer a browser row, capability order reverts
@agjs
agjs merged commit bceb1f0 into main Jul 18, 2026
8 checks passed
@agjs
agjs deleted the feat/scaffold-command branch July 18, 2026 07:51
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.

1 participant