Skip to content

Commit 905b327

Browse files
dmealingclaude
andcommitted
docs(roadmap): track the projection/view-materialization epic (#206-212)
Fold the triage of the 7 view/projection follow-on issues into the roadmap as durable tracking. Grouped by effort × 1.0-timing: - Group A (concrete, 1.0-shippable, TS meta-migrate-owned → single-port): #206 docs on-ramp for legacy views, #209 INNER/OUTER join derivation, #207 view-level @filter (row-scope WHERE) reusing the shipped attr.filter AST, #208 @sqlview escape valve + managed-elsewhere marker (design with Fable; formalizes the #195 follow-up (a) escape valve). - Group B (1.0-freeze vocab ruling): #210 retire origin.* on object.value. - Group C (post-1.0 backend generalization): #212 events emit projections (ADR-0007 vs ADR-0028 resolution), #211 backend-agnostic materialization. Also marks #204 SHIPPED in the #195 follow-ups bullet (projection-decl now carries isArray/storage through extends) and points its escape-valve item at the new #208 entry. Refresh date updated. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NGQ7oSuNcjhsMHWwZzhBwr
1 parent 15a023e commit 905b327

1 file changed

Lines changed: 13 additions & 2 deletions

File tree

spec/roadmap.md

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# MetaObjects Roadmap
22

3-
_Last refreshed 2026-06-13._
3+
_Last refreshed 2026-07-16._
44

55
> **This file is the single source of truth for the roadmap.** GitHub Milestones + Issues +
66
> the Project board mirror it. Keeping them in sync: `docs/ROADMAP-PROCESS.md`.
@@ -124,7 +124,18 @@ _(FR-032 was developed under the working number "FR-026" — see commit history;
124124

125125
## Planned
126126

127-
- **#195 follow-ups — projection read-model origins.** The four capabilities (`origin.aggregate @agg:any|all|collect`, `origin.computed @expr`, `origin.first`) shipped (validate + type in all 5 ports; TS `meta migrate` view synthesis; see `CHANGELOG.md` [Unreleased] + `docs/superpowers/specs/2026-07-15-issue-195-projection-readmodel-origins-design.md`). Remaining as fast-follows: (a) the **"not-migrate-managed" escape valve** — a **separate FR to design with Fable**: an `@sqlView`-style attribute carrying hand-written view DDL PLUS a distinct "managed elsewhere" marker, generalizing to **any** DB object (entities included), so a genuinely-irreducible view no longer aborts the whole `meta migrate` run (the four capabilities cover the known monitoring shapes but do not remove the all-or-nothing abort); (b) a **`collect` native-array persistence roundtrip** gate (Postgres `text[]` vs SQLite `json_group_array` → same wire) in `fixtures/persistence-conformance/`; (c) **#204** — the `codegen-ts` projection array-typing fix (a projection array field's `isArray`/`storage:jsonb` is dropped in `projection-decl`, so `collect → T[]` currently types as scalar). `origin.computed`'s expression grammar is designed so **#159**'s arithmetic / `case` / `@via`-joined refs slot in as additive node kinds.
127+
- **#195 follow-ups — projection read-model origins.** The four capabilities (`origin.aggregate @agg:any|all|collect`, `origin.computed @expr`, `origin.first`) shipped (validate + type in all 5 ports; TS `meta migrate` view synthesis; see `CHANGELOG.md` [Unreleased] + `docs/superpowers/specs/2026-07-15-issue-195-projection-readmodel-origins-design.md`). Remaining as fast-follows: (a) the **"not-migrate-managed" escape valve** — now tracked as **#208** in the projection/view-materialization epic below (an `@sqlView`-style attribute carrying hand-written view DDL PLUS a distinct "managed elsewhere" marker, generalizing to **any** DB object, so a genuinely-irreducible view no longer aborts the whole `meta migrate` run); (b) a **`collect` native-array persistence roundtrip** gate (Postgres `text[]` vs SQLite `json_group_array` → same wire) in `fixtures/persistence-conformance/`; (c) **#204 — SHIPPED** (`codegen-ts` `projection-decl` now carries a projection field's `isArray`/`storage:jsonb` through `extends` into both the Drizzle view column and the Zod read schema, so `collect → T[]` types correctly; TS-only, pending the next npm release). `origin.computed`'s expression grammar is designed so **#159**'s arithmetic / `case` / `@via`-joined refs slot in as additive node kinds.
128+
- **Projection / view-materialization epic (#206–212).** Follow-ons from #195 + adopter feedback on migrating legacy SQL-view-heavy schemas. Grouped by effort × 1.0-timing; **Group A is TS-`meta migrate`-owned (schema is TS-only per ADR-0015 → single-port, no 5-port fan-out).**
129+
- **Group A — concrete, 1.0-shippable (TS migrate/codegen):**
130+
- **#206** — Docs on-ramp: surface **entity read-views** (FR-024 §7, already shipped) as the first answer for legacy `SELECT A.*, extras` views + an entity-vs-projection decision table. Docs-only, no metamodel change. Ship immediately.
131+
- **#209** — Derive **INNER vs LEFT OUTER** join from reference optionality (`renderJoin` hardcodes `LEFT OUTER` → silent extra rows / wrong data on a required FK). Small, self-contained correctness fix (`view-ddl-emit.ts`); optional `@join: inner|left` override.
132+
- **#207****View-level `@filter`** (row-scope WHERE) reusing the shipped 5-port `attr.filter` AST, lowered to an outer `WHERE` in `emitViewDdl`. The single largest functional gap blocking full `meta migrate` adoption for filtered views (soft-delete / status / type views). Semantic (field + op), never raw SQL. Touches `view-spec.ts` + `emitViewDdl` + validation.
133+
- **#208****`@sqlView` escape valve** (a metadata-carried hand-written view body migrate registers + fingerprints but does not author) **+ a distinct "managed-elsewhere" marker** (skip create/drop/drift). Removes the all-or-nothing `meta migrate` abort; **design with Fable** per the #195 owner ruling (2026-07-15). Chartered above as #195 follow-up (a).
134+
- **Group B — 1.0-freeze-window vocab decision (needs an owner ruling before the freeze):**
135+
- **#210** — Retire `origin.*` on `object.value` (total value purity: no identity, no source, **no origins**). Pre-1.0 per ADR-0035's window; cross-port payload-VO churn but "mostly node-type relabeling" since the payload path already shares the projection codegen path. Ruling: do the churn now vs. accept the fallback rule-of-thumb and leave the two-spellings seam.
136+
- **Group C — post-1.0 backend generalization (design-now, build-later):**
137+
- **#212** — Events emit projections: resolve the **ADR-0007 vs ADR-0028 contradiction** (a stream is a channel, not a source). The ADR amendment (drop `source.event`; model emission at the surface as `api.eventing`/`operation.event`/`binding.messaging` with a payload→projection ref) is cheap to decide now; the eventing surface builds post-1.0. Lands the CQRS+events symmetry: queries return projections, commands take values, events emit projections.
138+
- **#211****Backend-agnostic projection materialization** (one derivation spec, N lowerings): generalize `SelectSpec` from RDB-only to document/search/… with an origin × (paradigm, `@kind`) capability matrix + load-time errors. Large FR; its foundation is Group A landing with the "semantic, not RDB-specific" lens (#207/#208/#209 become the first lowerings). Post-1.0; composes with FR-034 (ecosystem tier).
128139
- **FR-019 — Shared + externally-provided enums.** Stop redeclaring a `field.enum` inline in every consuming entity: a package-level abstract `field.enum` materializes ONE standalone enum type per port (the existing D6 `extends` reuse vocabulary), and **`@provided: true`** — a provenance flag on the named-type *declaration* (not the field), shared cross-type with value objects — references an existing hand-written type instead of emitting one (per-port namespace via codegen config, never a metadata FQN — retires the C#-only `@csEnumType`). Decision in [ADR-0026](decisions/ADR-0026-shared-and-provided-named-types.md); implementation spec `docs/superpowers/specs/2026-06-06-fr-019-shared-and-provided-enums-design.md`. (Generators are now subclass-extensible across all 5 ports, so this lands on open seams.)
129140
- **FR-020 — `@inheritance` persistence strategy (single-table vs joined).** TPH (one physical table, nullable subtype columns) is the single implicit strategy today (FR-014/FR-017). FR-020 adds an `@inheritance` attr to choose **joined** (a base table + per-subtype tables, joined on read) as an alternative — **additive, default stays TPH** (no breaking change). Status: design (proposed, sequenced after FR-017, which shipped). Design: `docs/superpowers/specs/2026-06-07-fr-020-inheritance-strategy-design.md`. *(Was not previously surfaced in this roadmap.)*
130141
- **FR-025 — Cross-port package-binding codegen config.** Config for how a metadata FQN/package maps to each port's native namespace/package at codegen time (the ADR-0001 build-time binding), so cross-package references (and metadata shared across projects, FR-023) emit correct imports per language. Status: design (ready for implementation). Design: `docs/superpowers/specs/2026-06-08-fr-025-cross-port-package-binding-config-design.md`. *(Was not previously surfaced in this roadmap.)*

0 commit comments

Comments
 (0)