Skip to content

Commit 14d93ad

Browse files
dmealingclaude
andcommitted
docs(#206): mark the entity-read-view schema pipeline as pending #213 (was overstated)
Follow-up to ce98902 / 905b327. Those described the FR-024 §7 entity-read-view path in present-tense ("writes route to the table … reads route to the view … the CREATE VIEW DDL is emitted by meta migrate … one emitter, two hosts") and tagged it "already shipped" in the roadmap. That conflates loader-licensing with implementation: the shape LOADS + is validated, but the schema pipeline (#213) is NOT built — meta migrate emits the derived field as a spurious column on the write table (colliding with a hand-written SELECT o.*, extra view's alias) and never emits the replica view. Amends (not reverts — the on-ramp is the right modeling story, and the decision table / boundaries are stable): the three overstated sentences move to contract tense ("The FR-024 §7 contract: …") + a status callout pointing at #213 with the concrete interim guidance (keep derived join columns off the entity / model that read as a projection until #213 lands; @readonly guards the write codecs but not the table DDL). Roadmap #206 entry corrected to "doctrine-complete + loader-validated; schema/codegen pipeline tracked by #213", with #213's two holes + cross-port codegen-half blast radius recorded. Docs-only. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NGQ7oSuNcjhsMHWwZzhBwr
1 parent 05d0f60 commit 14d93ad

2 files changed

Lines changed: 16 additions & 4 deletions

File tree

docs/features/source-kinds.md

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -59,9 +59,21 @@ This is **not** a projection — it is the `Order` entity *with a read route*. R
5959
**entity read-view** first: an `object.entity` that keeps its writable `table` source and
6060
adds a **non-primary** read-only `view` source, declaring only the *extra* as a derived
6161
(`origin.*`) field. The entity's own field set **is** the `o.*`, so you re-state nothing
62-
but the extra. Writes route to the table (derived fields don't exist there and are excluded
63-
from the write codecs); reads route to the view; the `CREATE VIEW` DDL is emitted by
64-
`meta migrate` from the **same assembly logic** as a projection view — one emitter, two hosts.
62+
but the extra. The FR-024 §7 contract: writes route to the table (derived fields don't exist
63+
there and are excluded from the write codecs); reads route to the view; the `CREATE VIEW` DDL
64+
is emitted by `meta migrate` from the **same assembly logic** as a projection view — one
65+
emitter, two hosts.
66+
67+
> **Status — authoring is validated; the schema/codegen pipeline is pending
68+
> [#213](https://github.com/metaobjectsdev/metaobjects/issues/213).** The shape above
69+
> loads and is loader-validated (the `origin.*` providability guardrail below), but the
70+
> schema half of the contract is **not yet implemented**: today `meta migrate` emits the
71+
> derived field as a spurious column on the *write* table (which then collides with a
72+
> hand-written `SELECT o.*, extra` view's alias), and the replica-view DDL is **not** emitted.
73+
> Until #213 lands, either keep derived join columns off the entity (model that read as a
74+
> separate `object.projection`), or expect to hand-manage the view. (`@readOnly: true` on a
75+
> derived field guards the generated write codecs but not the table DDL.) The decision table
76+
> and boundaries below are stable regardless.
6577
6678
```json
6779
{

spec/roadmap.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -127,7 +127,7 @@ _(FR-032 was developed under the working number "FR-026" — see commit history;
127127
- **#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.
128128
- **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).**
129129
- **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.
130+
- **#206** — Docs on-ramp: surface **entity read-views** (FR-024 §7 — doctrine-complete + loader-validated; the schema/codegen pipeline is tracked by **#213**, see below) as the first answer for legacy `SELECT A.*, extras` views + an entity-vs-projection decision table. Docs-only, no metamodel change. The docs carry a "#213 pending" status note; drop it once #213 lands. **#213** — `meta migrate` does not implement FR-024 §7 on the schema path: derived entity fields leak into the write table DDL (`expected-schema.ts` builds a column for every field, no origin exclusion) AND the replica read-view is never emitted (`isWriteThrough` has zero call sites; `buildProjectionViews` walks `isProjection` only). A real correctness bug (silent wrong-table + missing view) that gates the entity-read-view on-ramp; do it first. Blast radius couples to the TS-codegen half (the same unfiltered `fields()` leak also hits the Drizzle table def + Insert/Update Zod schemas, and reads never route to the replica view — the §7 write-codec-exclusion + read-routing half is unimplemented cross-port and needs its own issue).
131131
- **#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.
132132
- **#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.
133133
- **#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).

0 commit comments

Comments
 (0)