Skip to content

Multi-line dialog prompts (0.2.0-rc.2)#4

Merged
ThatRendle merged 17 commits into
mainfrom
change/multi-line-dialog-prompts
May 28, 2026
Merged

Multi-line dialog prompts (0.2.0-rc.2)#4
ThatRendle merged 17 commits into
mainfrom
change/multi-line-dialog-prompts

Conversation

@ThatRendle
Copy link
Copy Markdown
Contributor

Summary

Widens the preamble field on all four dcli dialog request types from Line? to IReadOnlyList<Line>? so consumers can render multi-line preambles inside the overlay. Closes the API gap surfaced by the dmon-migration Phase 2 ToolConfirmPrompt port (which had been working around the constraint by appending lines to scrollback before opening the dialog).

  • Public API: SelectRequest.Title, MultiSelectRequest.Title, ChoiceRequest.Prompt, InputRequest.Prompt widen to IReadOnlyList<Line>?. Full convenience-ctor matrix preserved (single-Line, single-string, params Line[], params string[], IReadOnlyList<Line>, IReadOnlyList<string>). No source-level breaking changes.
  • Renderer: Dialog.cs and InputDialog.cs iterate the preamble list; truncation when preamble exceeds the overlay budget rides on the existing arithmetic.
  • Tests: +21 (714 → 735) covering multi-line render, round-trip ctor BC, null/empty, and truncation regression.
  • Sample: Dcli.Demo.DmonWizard secret-input step now demonstrates a 3-line preamble (bold prompt + two dim context lines). Set DCLI_DEMO_DMONWIZARD_INTERACTIVE=1 to disable the sample's 10-second auto-cancel for interactive walks.
  • Version: dcli and Dcli.Testing bumped 0.2.0-rc.10.2.0-rc.2. nupkg + snupkg packed cleanly.

OpenSpec change: 2026-05-28-multi-line-dialog-prompts/ (archived in this PR). Delta synced into the main fixed-region spec — Awaitable modal dialogs now carries 13 scenarios (8 original + 5 new).

Test plan

  • dotnet build -c Release — 0 warnings, 0 errors
  • dotnet test -c Release — 735/735 passed
  • dotnet format --verify-no-changes — clean
  • openspec validate multi-line-dialog-prompts --strict — valid (pre-archive)
  • dotnet pack -c Releasedcli.0.2.0-rc.2.{nupkg,snupkg} + dcli.testing.0.2.0-rc.2.{nupkg,snupkg}
  • HITL: DCLI_DEMO_DMONWIZARD_INTERACTIVE=1 dotnet run --project samples/Dcli.Demo.DmonWizard — three preamble rows render above the API-key input; Enter advances the wizard.
  • dmon-migration Phase 2 resumed against rc.2 (user-confirmed) — ToolConfirmPrompt scrollback workaround dropped.

🤖 Generated with Claude Code

ThatRendle and others added 17 commits May 28, 2026 16:47
Widen `Title` / `Prompt` on all four dialog request types from
`Line?` to `IReadOnlyList<Line>?` so consumers can render multi-line
preambles inside the overlay. Closes the gap surfaced by the
dmon-migration Phase 2 `ToolConfirmPrompt` port.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
- 1.1 SelectRequest.Title widened from Line? to IReadOnlyList<Line>?
- 1.2 SelectRequest gains (IReadOnlyList<Line>?, bool), params Line[],
      IReadOnlyList<string>?, params string[] preamble ctors
- 1.3 MultiSelectRequest mirrors 1.1 + 1.2 (no AllowBack)
- 1.4 ChoiceRequest mirrors 1.1 + 1.2 (with AllowBack)
- 1.5 InputRequest mirrors 1.1 + 1.2 (preserve Default/IsSecret;
      params overloads drop Default/IsSecret per language rules)
- 1.6 XML docs describe multi-line semantics + one-element-list equivalence
- 1.7 Explicit-only contract noted on each new multi-line ctor

Single-Line/string secondaries use PascalCase parameter names so
existing named-arg call sites (Title:, Prompt:, AllowBack:) continue
to bind. Terminal.cs collapses req.Title/Prompt to .Count>0 ? t[0] : null
as a four-line bridge until §2 widens Dialog/ChoiceDialog/InputDialog
internal ctors.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
- 2.1 Dialog.cs ctor + Title property widened to IReadOnlyList<Line>?;
      Render truncates preamble to Math.Min(count, _maxRows) then list
      fills the remainder
- 2.2 (no ChoiceDialog.cs exists) — ChoiceRequest renders via Dialog.cs;
      covered by 2.1
- 2.3 InputDialog.cs ctor + Prompt property widened; _lastCaret offset
      inherits via the existing promptRows formula
- 2.4 Budget arithmetic unchanged in shape — titleRows = Count ?? 0
      replaces the old 0/1 constant; MaxRows setter forwards
      Math.Max(1, value - titleRows)
- 2.5 null/empty/single/multi all paint consistently — early-return
      on Count == 0; loop runs N times otherwise
- Terminal.cs: four §1 bridge sites reverted to title:/prompt:
      passthrough; bridge comments removed
- Tests: signature fallout only — DialogSelectionTests helper +
      5 direct ctor sites, InputDialogTests helper + 3 direct ctor
      sites wrap single Line via [line] collection expression

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
…tion 3)

- 3.1 SelectRequest multi-line Title via HeadlessTerminal/FrameSnapshot
- 3.2 MultiSelectRequest multi-line Title (placed in DialogSelectionTests.cs
      — no dedicated MultiSelect test file exists)
- 3.3 ChoiceRequest multi-line Prompt
- 3.4 InputRequest multi-line Prompt
- 3.5 Round-trip ctor tests in new DialogRequestsTests.cs covering
      single-Line and single-string forms for all four request types,
      including the verbatim spec call `new ChoiceRequest(options,
      prompt: "Permission:")`
- 3.6 Null/empty preamble: property tests + end-to-end snapshot
- 3.7 Truncation regression (Select + Input) — assert overlay active +
      row count bounded; NO caret-in-frame coupling (per §2 review)

Option A on the §1 reviewer flag: added
`(IReadOnlyList<Line>, string?, bool)` ctor overloads on Select,
MultiSelect, and Choice so the spec's literal call shape compiles.
InputRequest already carried the equivalent.

Test count: 714 → 735 (+21). All four gates pass.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
- 4.1 WizardRenderer.RenderTextInputAsync — when step.Secret == true,
      the prompt becomes a 3-line preamble: Bold(step.Prompt) +
      Dim("Used only for this session. Not persisted to disk.") +
      Dim("Press Esc to cancel; Enter to confirm."). Non-secret
      inputs keep today's single-line shape. Validates the API
      end-to-end through the dmon-wizard sample. Box stays unticked
      pending HITL verification by the user.
- 4.2 Dcli.Demo Program.cs Phase 5d "Run the tour again?" — two-line
      ChoiceRequest prompt (bold question + dim navigation hint).
      Existing 1500ms auto-cancel timeout keeps the demo unattended.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
…active mode (§4 follow-up)

Pre-existing 10s auto-cancel timeout in the DmonWizard sample blocked
the §4.1 HITL verification — the wizard self-cancelled before keyboard
input was possible. Add a small env-var toggle: when
DCLI_DEMO_DMONWIZARD_INTERACTIVE=1 the cancellation source has no
timeout; otherwise the 10s CI default is preserved.

Sample-only change; no production-code impact.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
User confirmed via DCLI_DEMO_DMONWIZARD_INTERACTIVE=1 walk-through:
the multi-line preamble renders three rows above the input caret
and Enter advances the wizard correctly.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
…, pack (section 5)

- 5.1 dotnet build -c Release — 0 warnings
- 5.2 dotnet test -c Release — 735/735 passed (baseline 714 + 21 new)
- 5.3 dotnet format --verify-no-changes — clean
- 5.4 openspec validate multi-line-dialog-prompts --strict — valid
- 5.5 Bump Dcli.csproj + Dcli.Testing.csproj 0.2.0-rc.1 → 0.2.0-rc.2
- 5.6 dotnet pack produced dcli.0.2.0-rc.2 + dcli.testing.0.2.0-rc.2
      (nupkg + snupkg) cleanly
- 5.7 DEVLOG updated with all section status rows + open follow-ups
- 5.8 dmon Phase 2 resume recipe handed off to user (recorded in
      DEVLOG Open follow-ups); ticks on user confirmation that
      dmon Phase 2 has resumed.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
User confirmed dmon Phase 2 has resumed: ToolConfirmPrompt now passes
the preamble lines directly into ChoiceRequest.Prompt instead of the
scrollback workaround.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Status flipped to shipped. Final commit 56de80d. Released as
dcli + dcli.testing 0.2.0-rc.2. dmon-migration Phase 2 resumed
against rc.2 on the same day (user-confirmed).

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Apply the change's `fixed-region` delta to the main spec:
- Widen each dialog request's preamble field to IReadOnlyList<Line>?
- Document the backwards-compat convenience constructor matrix
- Add 5 new scenarios (multi-line render, single-Line ctor, single-
  string ctor, null/empty preamble, over-budget truncation)

8 original + 5 new = 13 scenarios under `Awaitable modal dialogs`.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
…ialog-prompts

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
@ThatRendle ThatRendle merged commit ddbd356 into main May 28, 2026
3 checks passed
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