engine: multiselect field type (multi-value curated options) #128

Closed
opened 2026-07-19 10:13:33 +02:00 by dominik.polakovics · 1 comment

This was generated by AI during triage.

Split out of #77 (News v2 categories). First slice of the stack: the engine-level multi-value field type that the news categories field will use. No news-bundle changes here.

Decision record from triage on #77: full Hugo-taxonomy scope, categories only, vocabulary curated in sidecar options (not free-form), work split into stacked issues.

Agent brief follows in the comments.

> *This was generated by AI during triage.* Split out of #77 (News v2 categories). First slice of the stack: the engine-level multi-value field type that the news categories field will use. No news-bundle changes here. Decision record from triage on #77: full Hugo-taxonomy scope, **categories only**, vocabulary **curated in sidecar options** (not free-form), work split into stacked issues. Agent brief follows in the comments.
Author
Owner

This was generated by AI during triage.

Agent Brief

Category: enhancement
Summary: Add a multiselect field type — multiple values chosen from a curated options list — usable in page-type fields.

Current behavior:
The engine has nine field types (text, textarea, link, image, select, bool, number, datetime, page), all scalar-valued. select is single-valued with an options list declared in the sidecar. No field type can hold a list of values, and the editor has no multi-value widget. Front-matter writing already supports string lists (page-type defaults accept them), but no field type produces a list value.

Desired behavior:
A tenth field type, multiselect:

  • Declared in a sidecar like select: options is required and follows the same rules (non-empty list of unique, non-empty strings). An optional default is a list whose members must each be an option, with no duplicates.
  • Valid in page-type fields: only. A multiselect param declared on an element must be rejected at sidecar-load time with a clear error — element params serialize to shortcode params, which are single typed scalars and cannot hold lists.
  • Value shape is a list of strings. Server-side validation: every member must be one of the options, no duplicates; a required multiselect must be a non-empty list; an optional one may be empty. Coercion preserves the list-of-strings shape.
  • The value is stored in page front matter as a native YAML string list under the field key.
  • Editor widget: a multi-value picker over the fixed options (checkbox list or chips — follow the visual pattern of the existing chip-style pickers), dispatched from the shared field-widget switch. The client-side value plumbing (initial values, validation, payload building) currently assumes string | boolean values and must be widened to carry string lists.
  • The scaffolded site manual (AGENTS.md) documents the new type, its sidecar shape, and the page-type-fields-only restriction; the "nine field types" count in code comments and docs is updated. The AGENTS.md drift test mechanically requires the new type to be named there.

Key interfaces:

  • The field-type registry / valid-types set in the element schema package — new multiselect type constant
  • Shared sidecar param parsing/validation (used by both elements and page types) — options scoping, list-valued default handling, and rejection in element context
  • The schema's value validation and coercion entry points — currently scalar-only (string | bool | number), must accept a string list for multiselect
  • Front-matter application — writes the list value (string-list support already exists for page-type defaults)
  • The web editor's field-widget dispatcher and its values store / payload builder, currently typed string | boolean
  • The web API's schema-param type (already carries options)

Acceptance criteria:

  • A page-type sidecar can declare a multiselect field with options; sidecar load fails with clear errors on missing/empty/duplicate options, on a default containing a non-option or duplicates, and on a multiselect declared in an element's params
  • Saving a page with a multiselect value writes a YAML string list to front matter; values outside options, duplicates, and wrong shapes are rejected server-side
  • A required multiselect rejects an empty list; an optional one accepts it
  • The editor renders a multi-value picker for the field, pre-populates it from existing front matter, and round-trips edits
  • The AGENTS.md drift test passes with the new type documented, and the field-type count references are updated
  • Go tests cover load validation and value validation/coercion; web tests cover the widget alongside the existing field-widget tests

Out of scope:

  • Free-form, editor-created terms (vocabulary is curated in the sidecar by decision on #77)
  • Multiselect on element params / any list serialization for shortcode params
  • Any news-bundle usage or Hugo taxonomy configuration (separate stacked issues)
> *This was generated by AI during triage.* ## Agent Brief **Category:** enhancement **Summary:** Add a `multiselect` field type — multiple values chosen from a curated `options` list — usable in page-type fields. **Current behavior:** The engine has nine field types (`text`, `textarea`, `link`, `image`, `select`, `bool`, `number`, `datetime`, `page`), all scalar-valued. `select` is single-valued with an `options` list declared in the sidecar. No field type can hold a list of values, and the editor has no multi-value widget. Front-matter writing already supports string lists (page-type `defaults` accept them), but no field type produces a list value. **Desired behavior:** A tenth field type, `multiselect`: - Declared in a sidecar like `select`: `options` is required and follows the same rules (non-empty list of unique, non-empty strings). An optional `default` is a list whose members must each be an option, with no duplicates. - **Valid in page-type `fields:` only.** A `multiselect` param declared on an *element* must be rejected at sidecar-load time with a clear error — element params serialize to shortcode params, which are single typed scalars and cannot hold lists. - Value shape is a list of strings. Server-side validation: every member must be one of the options, no duplicates; a `required` multiselect must be a non-empty list; an optional one may be empty. Coercion preserves the list-of-strings shape. - The value is stored in page front matter as a native YAML string list under the field key. - Editor widget: a multi-value picker over the fixed options (checkbox list or chips — follow the visual pattern of the existing chip-style pickers), dispatched from the shared field-widget switch. The client-side value plumbing (initial values, validation, payload building) currently assumes `string | boolean` values and must be widened to carry string lists. - The scaffolded site manual (AGENTS.md) documents the new type, its sidecar shape, and the page-type-fields-only restriction; the "nine field types" count in code comments and docs is updated. The AGENTS.md drift test mechanically requires the new type to be named there. **Key interfaces:** - The field-type registry / valid-types set in the element schema package — new `multiselect` type constant - Shared sidecar param parsing/validation (used by both elements and page types) — `options` scoping, list-valued `default` handling, and rejection in element context - The schema's value validation and coercion entry points — currently scalar-only (`string | bool | number`), must accept a string list for multiselect - Front-matter application — writes the list value (string-list support already exists for page-type defaults) - The web editor's field-widget dispatcher and its values store / payload builder, currently typed `string | boolean` - The web API's schema-param type (already carries `options`) **Acceptance criteria:** - [ ] A page-type sidecar can declare a `multiselect` field with `options`; sidecar load fails with clear errors on missing/empty/duplicate options, on a `default` containing a non-option or duplicates, and on a `multiselect` declared in an element's params - [ ] Saving a page with a multiselect value writes a YAML string list to front matter; values outside `options`, duplicates, and wrong shapes are rejected server-side - [ ] A `required` multiselect rejects an empty list; an optional one accepts it - [ ] The editor renders a multi-value picker for the field, pre-populates it from existing front matter, and round-trips edits - [ ] The AGENTS.md drift test passes with the new type documented, and the field-type count references are updated - [ ] Go tests cover load validation and value validation/coercion; web tests cover the widget alongside the existing field-widget tests **Out of scope:** - Free-form, editor-created terms (vocabulary is curated in the sidecar by decision on #77) - Multiselect on element params / any list serialization for shortcode params - Any news-bundle usage or Hugo taxonomy configuration (separate stacked issues)
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
Cloonar/deckle#128
No description provided.