Replace M.PRIMITIVES with daw_field_type/v1 registry validation #11

Closed
opened 2026-08-11 14:57:48 +02:00 by michael · 1 comment
Owner

Goal

Remove M.PRIMITIVES (the hardcoded field type list: text, textarea,
number, boolean, select, date) from types.lua and re-implement
types.resolve() as pure registry validation against the
daw_field_type/v1 contract proposed in DAW/daw-contracts#3.

Background

Identified as a blocker during the 2.1 daw_error/v1 migration
(feature/daw-error-v1-migration branch). M.PRIMITIVES embeds
field type vocabulary directly in program code -- exactly the
anti-pattern described in "Festgelegt heißt nicht einprogrammiert".
berhtjan-cli was verified (prompt.lua, render.lua) to already be
fully field-type-name-agnostic today -- it treats every field as an
opaque, generically presented value and never branches on
field.type or reads field.primitive. types.lua's hardcoded list
is therefore the only place in the current ecosystem that would
block a new field type (e.g. a hypothetical LATTENZAUN) from
working without a code change.

Scope

  • types.resolve(field_type, registry) validates purely against
    registry[field_type] and the daw_field_type/v1 structural
    rules (required value/acquisition, collection required
    iff an acquisition entry has kind=selection, resource
    required iff an acquisition entry has kind=resource) -- no
    built-in primitive names anywhere in code
  • M.PRIMITIVES removed from types.lua
  • M.is_primitive() / M.primitives() re-evaluated -- may no
    longer make sense once "primitive" is a data property
    (value.kind without composition) rather than a fixed set Core
    owns; re-check call sites before removing
  • composer.lua's resolved.primitive = def.primitive /
    type_def fields re-evaluated against the new contract shape
    -- currently unread by berhtjan-cli (verified), but check
    other consumers before changing
  • Tests rewritten against daw_field_type/v1 fixtures instead of
    the current hardcoded-primitive fixtures
  • The six former primitives re-expressed as daw_field_type/v1
    data (see open question below for where they are shipped from)

Depends on

DAW/daw-contracts#3 (daw_field_type/v1 contract) -- this issue should
not start implementation before that contract is settled enough that
its shape (value/acquisition/collection/resource keys) is not
expected to change further.

Open question, not blocking contract work but blocking this issue's completion

Where do the six base primitives ship from at runtime once they are
data instead of code? Discussed, not decided:

  1. berhtjan-core ships its own types.json contribution, scanned
    like any module's contribution
  2. every host program must supply them itself, Core assumes nothing
  3. a separate, ecosystem-wide base-vocabulary module/repo

Acceptance test

Define a new field type (e.g. LATTENZAUN, an atomic value with its
own domain, senkrecht/waagerecht/kreuz) as daw_field_type/v1
data only. No commit to daw-modul-berhtjan-core or
daw-modul-berhtjan-cli required for it to work end to end.

Refs: DAW/daw-contracts#3

## Goal Remove `M.PRIMITIVES` (the hardcoded field type list: text, textarea, number, boolean, select, date) from `types.lua` and re-implement `types.resolve()` as pure registry validation against the `daw_field_type/v1` contract proposed in `DAW/daw-contracts#3`. ## Background Identified as a blocker during the 2.1 `daw_error/v1` migration (`feature/daw-error-v1-migration` branch). `M.PRIMITIVES` embeds field type *vocabulary* directly in program code -- exactly the anti-pattern described in "Festgelegt heißt nicht einprogrammiert". `berhtjan-cli` was verified (prompt.lua, render.lua) to already be fully field-type-name-agnostic today -- it treats every field as an opaque, generically presented value and never branches on `field.type` or reads `field.primitive`. `types.lua`'s hardcoded list is therefore the only place in the current ecosystem that would block a new field type (e.g. a hypothetical `LATTENZAUN`) from working without a code change. ## Scope - [ ] `types.resolve(field_type, registry)` validates purely against `registry[field_type]` and the `daw_field_type/v1` structural rules (required `value`/`acquisition`, `collection` required iff an acquisition entry has `kind=selection`, `resource` required iff an acquisition entry has `kind=resource`) -- no built-in primitive names anywhere in code - [ ] `M.PRIMITIVES` removed from `types.lua` - [ ] `M.is_primitive()` / `M.primitives()` re-evaluated -- may no longer make sense once "primitive" is a data property (`value.kind` without composition) rather than a fixed set Core owns; re-check call sites before removing - [ ] `composer.lua`'s `resolved.primitive = def.primitive` / `type_def` fields re-evaluated against the new contract shape -- currently unread by `berhtjan-cli` (verified), but check other consumers before changing - [ ] Tests rewritten against `daw_field_type/v1` fixtures instead of the current hardcoded-primitive fixtures - [ ] The six former primitives re-expressed as `daw_field_type/v1` data (see open question below for where they are shipped from) ## Depends on DAW/daw-contracts#3 (daw_field_type/v1 contract) -- this issue should not start implementation before that contract is settled enough that its shape (`value`/`acquisition`/`collection`/`resource` keys) is not expected to change further. ## Open question, not blocking contract work but blocking this issue's completion Where do the six base primitives ship from at runtime once they are data instead of code? Discussed, not decided: 1. `berhtjan-core` ships its own `types.json` contribution, scanned like any module's contribution 2. every host program must supply them itself, Core assumes nothing 3. a separate, ecosystem-wide base-vocabulary module/repo ## Acceptance test Define a new field type (e.g. `LATTENZAUN`, an atomic value with its own domain, `senkrecht`/`waagerecht`/`kreuz`) as `daw_field_type/v1` data only. No commit to `daw-modul-berhtjan-core` or `daw-modul-berhtjan-cli` required for it to work end to end. Refs: DAW/daw-contracts#3
Author
Owner

Resolved (v2.1.0).

types.resolve() reduced to pure registry lookup -- M.PRIMITIVES,
is_primitive(), primitives() removed entirely. Field types are now
validated structurally against daw_field_type/v1 (DAW/daw-contracts#3)
once, at the boundary where they enter the system
(loader.parse_types()), not hardcoded anywhere in Core.

Acceptance test passed: a new field type (lattenzaun, with its own
value.kind = lattenzaun_orientation) resolves and composes correctly
as pure data, with no change to types.lua, composer.lua, or
daw-modul-berhtjan-cli.

Open follow-up, not blocking this issue: where the ecosystem's six
former primitives are shipped from at runtime (own contribution vs.
host-required vs. shared vocabulary module) -- still undecided,
tracked separately.

Resolved (v2.1.0). types.resolve() reduced to pure registry lookup -- M.PRIMITIVES, is_primitive(), primitives() removed entirely. Field types are now validated structurally against daw_field_type/v1 (DAW/daw-contracts#3) once, at the boundary where they enter the system (loader.parse_types()), not hardcoded anywhere in Core. Acceptance test passed: a new field type (lattenzaun, with its own value.kind = lattenzaun_orientation) resolves and composes correctly as pure data, with no change to types.lua, composer.lua, or daw-modul-berhtjan-cli. Open follow-up, not blocking this issue: where the ecosystem's six former primitives are shipped from at runtime (own contribution vs. host-required vs. shared vocabulary module) -- still undecided, tracked separately.
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
DAW/daw-modul-berhtjan-core#11
No description provided.