Files
scarf/scarf
Alan Wizemann b34f432f00 feat(config): configure-step UI + post-install Configuration editor
Adds the user-facing side of v2.3 template configuration. Install-time
flow: templates with a non-empty config.schema get a Configure step
between the parent-directory pick and the preview sheet. Post-install
flow: a Configuration button on the dashboard header + a context-menu
entry on the project list opens the same form pre-filled with current
values.

New files:
- Features/Templates/ViewModels/TemplateConfigViewModel.swift — drives
  the form. Keeps freshly-entered secret bytes in `pendingSecrets`
  in-memory until commit() succeeds, then calls
  ProjectConfigService.storeSecret for each one. Cancelling never
  leaves orphan Keychain entries — the form is transactional.
  Validates via ProjectConfigService.validateValues on commit and
  populates per-field `errors` the sheet surfaces inline. Two modes:
  .install (needs a project passed at commit time) and
  .edit(project:) (VM already holds the target).
- Features/Templates/Views/TemplateConfigSheet.swift — the form. One
  row per field with a control dispatched by type: TextField (string),
  TextEditor (text), number input, Toggle (bool), segmented/dropdown
  Picker (enum, picks form by option count), add/remove list editor,
  SecureField with show/hide toggle (secret). Required-field asterisk
  + per-field error display. Optional modelRecommendation panel at
  the bottom — informational badge; no auto-switch.
- Features/Templates/ViewModels/TemplateConfigEditorViewModel.swift —
  loads <project>/.scarf/manifest.json + config.json, hands a
  TemplateConfigViewModel to the sheet, writes edited values back on
  commit. Has a .notConfigurable stage for projects without a
  manifest cache (hand-added projects, schema-less templates).
- Features/Templates/Views/ConfigEditorSheet.swift — thin wrapper
  that owns the editor VM and routes its stages to loading / form /
  saving / success / error / not-configurable views.

Wiring:
- TemplateInstallerViewModel gains an .awaitingConfig stage between
  .awaitingParentDirectory and .planned. pickParentDirectory() now
  inspects plan.configSchema and either routes to .awaitingConfig
  (non-empty schema) or straight to .planned (schema-less). New
  submitConfig(values:) stashes finalized values in plan.configValues
  and advances; cancelConfig() returns to .awaitingParentDirectory.
- TemplateInstallSheet renders a new `configureView` that inlines
  TemplateConfigSheet into the install flow for .awaitingConfig.
  The existing preview (.planned) gains a new "Configuration" section
  listing each field + its display value (secrets shown as "••••••
  (Keychain)", lists shown as "first + N more", "(not set)" for
  missing values).
- ProjectsView adds an isConfigurable(_:) check (transport.fileExists
  on .scarf/manifest.json), a new @State configEditorProject for
  sheet presentation, a new "Configuration…" context-menu entry on
  project list rows (for configurable projects), and a new
  slider.horizontal.3 button on the dashboard header next to the
  existing Uninstall button.

50/50 tests still pass. This commit is UI-only — no new Phase C tests
(sheet behaviour is hard to unit-test without UI automation and the
underlying VM logic is exercised by Phase A/B's config-round-trip
tests).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-23 01:46:21 +02:00
..
2026-04-23 01:42:25 +02:00
2026-04-23 01:42:25 +02:00
2026-04-23 01:42:25 +02:00
2026-04-23 01:42:25 +02:00