Skip to content

docs(dialogs): specify text input and select composition - #40

Merged
fx merged 4 commits into
mainfrom
docs/0017-dialog-input-fields
Aug 29, 2026
Merged

docs(dialogs): specify text input and select composition#40
fx merged 4 commits into
mainfrom
docs/0017-dialog-input-fields

Conversation

@fx

@fx fx commented Aug 29, 2026

Copy link
Copy Markdown
Owner

Documentation only. No file under src/, plugins/, test/, or site/ is touched; the behavior described here is planned and implemented by the two PRs enumerated in the change document.

What the spec now requires

docs/specs/dialogs/index.md grows from a select-only capability to select plus a text input dialog, and the two compose:

  • Text input. input renders a message and the current value, starts from an optional initial value, appends printable characters, removes the last character on Backspace (a no-op when empty), ignores everything else, and resolves on Enter with the value exactly as entered — including the empty string. Escape and Ctrl-C resolve undefined, so a caller can tell cancellation from an intentional empty value. Whether empty is acceptable is the caller's decision; the dialog does not trim, validate, or transform.
  • Shared terminal contract. The existing stream, TTY-rejection, and cleanup-before-settlement requirements are generalized from select to any dialog, so input inherits them rather than restating them.
  • Field model. A field carries a discriminating type, a name unique within its option, and a message. text is the only type available to callers; the type discriminator exists so a later field kind is an addition rather than a redesign.

The composition model

An option is marked user-provided by declaring a non-empty ordered list of fields. Choosing it collects those fields one at a time, in declared order, in the same render session — no teardown or re-render between the selection and field stages. After the last field is submitted, select resolves.

  • Resolved value: select now resolves { value, values } for every completed selection — the chosen option's exact opaque value, plus a record of collected strings keyed by field name. A plain option carries an empty record; a user-provided option carries exactly the field names it declared, which is how a caller tells them apart. A uniform envelope is used because an opaque T cannot be safely discriminated against a bare-value/envelope union.
  • Cancellation: Escape or Ctrl-C at any stage cancels the whole dialog, resolves undefined, and discards already collected values. There is no return to the option list. Escape keeps one meaning regardless of invisible stage state, Ctrl-C must never mean "go back", and back-navigation would require a stage stack, retained partials, and a re-entry rule with no consumer.
  • Validation: an empty field list or a field name repeated within one option is rejected before rendering, alongside the existing empty-options and non-interactive rejections.

Two-PR plan

docs/changes/0017-add-dialog-text-input-and-composition.md decomposes into exactly two implementation PRs:

  1. The standalone text input dialog, reusing the existing stream adapters, failure tracking, and render session.
  2. Select/input composition — the field declaration, the new select result, sequential collection, cancellation, the manual update for composition, and the status flip.

Each PR documents in docs/manual/plugins.md the capability it ships, so the manual never describes a surface that does not exist.

Deliberate non-goals

  • Multi-select is out. The composition model does not preclude it — a multi-choice dialog reuses the same option and field declarations — but nothing about it is specified here.
  • A full form contract is out. One field type ships, fields are collected one at a time, and there is no focus movement, simultaneous presentation, validation framework, required-field policy, or dropdown/checkbox/numeric field.
  • Caret movement, entry history, masking, back-navigation, partial results, a confirm dialog, and a public/external dialogs package all remain out of scope.

CI runs the documentation-only path for this branch, so the quality commands are skipped by design (docs/specs/architecture/index.md); Biome does not process markdown.

Copilot AI lite review requested due to automatic review settings August 29, 2026 15:10

Copilot AI 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.

🟡 Changes recommended

The dialogs spec has a documented TextField.initialValue without corresponding normative behavior, and a new requirement sentence that should be reworded for clarity.

Once you've addressed the issues Copilot identified, you can request another Copilot review.

Pull request overview

Updates the Dialogs specification and documentation index to define the planned text input dialog and its composition with select via user-provided options, and introduces Change 0017 to track the two-PR implementation plan.

Changes:

  • Expanded docs/specs/dialogs/index.md to specify input, field declarations on select options, composed collection flow, and the new select result envelope.
  • Added docs/changes/0017-add-dialog-text-input-and-composition.md (draft) describing requirements, design decisions, and task breakdown.
  • Updated docs/index.yml and docs/index.md to include Change 0017 and refresh the dialogs spec description.
File summaries
File Description
docs/specs/dialogs/index.md Specifies input, field model, user-provided options, composed behavior, and updated cleanup/stream contract.
docs/index.yml Updates dialogs spec description and registers Change 0017 metadata.
docs/index.md Updates dialogs spec description and adds Change 0017 to the changes table.
docs/changes/0017-add-dialog-text-input-and-composition.md New change document defining scope, requirements, design, and tasks for input + composition.
Review details
  • Files reviewed: 4/4 changed files
  • Comments generated: 2
  • Review effort level: Lite

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread docs/specs/dialogs/index.md
Comment thread docs/specs/dialogs/index.md Outdated
@fx
fx requested a lite review from Copilot August 29, 2026 15:12

Copilot AI 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.

🔵 Needs a closer look

The updated dialogs spec has a few internal ambiguities (notably around user-provided option marking, field initial values, and “printable character” input) that should be clarified to keep the acceptance criteria unambiguous.

Review details

Suppressed comments (3)

Previously missed (2) — in code that hasn't changed since the last review.

docs/specs/dialogs/index.md:5

  • The overview says options are "marked as user-provided" but the spec’s contract later defines user-provided options specifically as options that declare fields. Making the mechanism explicit here avoids ambiguity about whether a separate flag/property is required.
`tx` provides a bundled dialogs plugin for terminal interactions shared by its own plugins. The plugin MUST expose dialogs through the generic registry rather than through core vocabulary, and its contract MUST contain only a single-choice `select` dialog and a single-field text `input` dialog, which compose when a select option is marked as user-provided.

docs/specs/dialogs/index.md:148

  • The term "printable character" is currently undefined, which makes the acceptance criteria ambiguous (e.g., how to treat multi-codepoint input, Alt-modified keys, or paste events). Tightening the wording here will help ensure consistent implementation and tests.
- Printable character input MUST append to the current value in typed order.
- Backspace MUST remove the last character of the current value and MUST do nothing when the value is empty.
- Input that is none of a printable character, Backspace, Enter, Escape, or Ctrl-C MUST leave the value unchanged.

docs/specs/dialogs/index.md:134

  • TextField includes an optional initialValue, and Change 0017 explicitly calls out an initial value for fields, but the "Field Model" section doesn’t specify how initialValue affects collection. Without this, an implementation could ignore field initial values while still satisfying the written bullets.
- A field MUST describe exactly one value the user supplies and MUST carry a type that discriminates it, a name that is unique within the option declaring it, and a message to display while it is collected.
- `text` MUST be the only field type available to callers.
- A field name MUST be an opaque key that identifies the collected value to the caller and MUST NOT be rendered in place of the field's message.
- The fields of an option MUST form an ordered list whose order is the order they are collected in.
  • Files reviewed: 4/4 changed files
  • Comments generated: 0 new
  • Review effort level: Lite

@fx
fx requested a lite review from Copilot August 29, 2026 15:17

Copilot AI 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.

🟢 Approval recommended

The changes are documentation-only and appear internally consistent, with indexes updated to include the new change document and no incomplete cross-referenced task completions requiring checkbox updates.

Review details
  • Files reviewed: 4/4 changed files
  • Comments generated: 0 new
  • Review effort level: Lite

@fx
fx merged commit d1c8498 into main Aug 29, 2026
2 checks passed
@fx
fx deleted the docs/0017-dialog-input-fields branch August 29, 2026 15:19
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.

2 participants