You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
docs(plan): split metamodel batch into parallel metadata-codegen + migrate-ts workstreams
The unified implementation plan from commit a8bb997 was written for a single
session to pick up. The shape of the actual work splits cleanly along package
boundaries — metadata + codegen in one stream, migrate-ts in the other — so two
sessions on two machines can run in parallel after the metadata foundation lands
per FR.
- Rename existing plan to metamodel-batch-metadata-codegen-plan.md and re-scope
to metadata + codegen only. Adds a Coordination-with-migrate-ts-session
section spelling out the metadata-lands-first contract, per-FR push beacons,
and shared-resource boundaries.
- New sibling: metamodel-batch-migrate-ts-plan.md. Scoped to the three migrate-ts
slices (FR-016 resolution rewrite, FR-015 pg_proc introspect + skeleton emit,
FR-014 TPH DDL + drift). FR-013 has no migrate-ts work — noted explicitly.
Per-task preflight checks gate on the sister-session's metadata commit being
on main.
Each plan now reads as a self-contained execution doc for its session. Sister-plan
pointers at the top of both. ADR-0015 (TS-only schema migration) keeps the
migrate-ts work TS-only — no per-port fan-out on that workstream.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
> **For agentic workers:** REQUIRED SUB-SKILLS: `superpowers:brainstorming` (before each FR's implementation, brainstorm with the user if scope is unclear), `superpowers:test-driven-development` (every loader / codegen / migrate change is TDD-first against the conformance corpus), `superpowers:subagent-driven-development` (the per-port fan-outs in FR-013/015/016 are parallel-friendly subagent work once TS lands).
3
+
> **For agentic workers:** REQUIRED SUB-SKILLS: `superpowers:brainstorming` (before each FR's implementation, brainstorm with the user if scope is unclear), `superpowers:test-driven-development` (every loader / codegen change is TDD-first against the conformance corpus), `superpowers:subagent-driven-development` (the per-port fan-outs are parallel-friendly subagent work once TS lands).
4
4
>
5
5
> **Gate:** the cross-port conformance corpus is the contract. A change is done when (a) its TS reference is green against the conformance fixtures it adds, AND (b) every other port — Java / Kotlin / C# / Python — runs the same fixtures byte-identically. No exceptions.
6
6
7
-
**Status:** Plan (ready for execution on a fresh Claude session).
7
+
**Status:** Plan (in execution).
8
8
**Created:** 2026-05-31.
9
-
**Scope:**four new metamodel design FRs + the ADR that frames one of them. Closes the metamodel gaps surfaced by adopter pressure ahead of 1.0:
9
+
**Sister plan:**[migrate-ts workstream](2026-05-31-metamodel-batch-migrate-ts-plan.md) — runs in parallel on a separate session/machine. **Coordination contract is "metadata-lands-first per FR";** see [Coordination with migrate-ts session](#coordination-with-migrate-ts-session).
10
10
11
+
**Scope of this plan:****metadata + codegen** across the four FRs. The four `migrate-ts` slices (FR-014 TPH DDL, FR-015 `pg_proc` introspect, FR-016 physical-name resolution rewrite, FR-013 optional `verify` warn) are **out of scope here** — the sister plan owns them.
12
+
13
+
Source designs:
11
14
-[ADR-0018 — Per-kind physical-name attributes within source paradigms](../../../spec/decisions/ADR-0018-per-kind-physical-name-attrs.md)
The four FRs are **design-complete** at the metamodel / loader / ORM-emission layer. This plan adds the missing pieces:
20
+
This plan adds the three pieces missing from the per-FR design docs:
18
21
1.**Execution order + dependency map** so two of these FRs don't crash into each other.
19
-
2.**Generator-stack gap list per FR.** The FRs' per-port codegen tables describe the entity/ORM layer; this plan enumerates the additional generator surfaces — routes, hooks, forms, grids, filter allowlists, Spring controllers/DTOs/repos — each FR must touch and which currently aren't specified in the FRs themselves.
22
+
2.**Generator-stack gap list per FR.** The FRs' per-port codegen tables describe the entity/ORM layer; this plan enumerates the additional generator surfaces — routes, hooks, forms, grids, filter allowlists, Spring controllers/DTOs/repos — each FR must touch and which aren't specified in the FRs themselves.
20
23
3.**A directive for FR-014 specifically:** write FR-017 as the first execution step of TPH work, before implementation. The TPH polymorphic-codegen design is its own beast and deserves a focused spec.
21
24
22
25
---
@@ -35,45 +38,57 @@ The four FRs are **design-complete** at the metamodel / loader / ORM-emission la
**Why FR-016 first.** FR-015's example metadata writes`@proc: "fn_x"` (not `@table: "fn_x"`), and FR-014 doesn't depend on alias spelling at all, but the canonical-serializer rewrite from ADR-0018 changes the corpus's wire format. Landing FR-016 before adding new conformance fixtures for the other FRs means new fixtures use canonical per-kind spellings from the start — no churn.
49
+
**Why FR-016 first.** FR-015's example metadata uses`@proc: "fn_x"` (not `@table: "fn_x"`), and the canonical-serializer rewrite from ADR-0018 changes the corpus's wire format. Landing FR-016 before adding new conformance fixtures for the other FRs means new fixtures use canonical per-kind spellings from the start — no churn.
47
50
48
51
**Why FR-013/015 are independent.** Different layers (FR-013 is field-attr; FR-015 is source-attr) with no shared loader code path.
49
52
50
53
**Why FR-014 needs FR-017 written first.** The metamodel piece of TPH (`@discriminator` + `@discriminatorValue` on `object.entity`) is well-specified in FR-014. The generator-stack design (polymorphic REST routes, per-subtype forms, discriminated-union hooks, per-subtype filter allowlists, Spring `@Inheritance` controllers / DTOs / repos / payload generators) is **not** specified. Implementing TPH without that design produces inconsistent per-port output. Write FR-017 first, then implement.
51
54
52
55
---
53
56
54
-
## Recommended workflow for the next session
57
+
## Coordination with migrate-ts session
58
+
59
+
The sibling [migrate-ts plan](2026-05-31-metamodel-batch-migrate-ts-plan.md) runs in parallel. Coordination rules:
60
+
61
+
1.**Metadata-lands-first per FR.** This session pushes the metadata (constants, schemas, loader validation, canonical-serializer, conformance fixtures) for FR-N to `main` BEFORE the migrate-ts session starts FR-N migrate-ts work. The migrate-ts session reads the loaded model — without the new attrs registered, the migrate-ts work has nothing to consume.
62
+
2.**Per-FR push beacon.** When the metadata commit for an FR lands on `main`, leave a single-line comment in the sister plan's "FR-N preflight" row marking it green (or just message the user; the user is the human courier between the two sessions).
63
+
3.**Disjoint package directories.** This session touches `packages/metadata`, `packages/codegen-ts*`, `packages/runtime-ts`, `server/java/codegen-spring`, `server/kotlin/codegen-kotlin`, C# / Python codegen. The migrate-ts session touches `packages/migrate-ts` only. No code-file overlap.
-`fixtures/persistence-conformance/` — both sessions add fixtures: this session adds query scenarios for new attrs (e.g., TPH polymorphic queries); the migrate-ts session adds migration scenarios for new DDL emission.
67
+
- Conformance corpus regeneration after FR-016 (canonical rewrite of `@table` → `@view`/`@proc`/etc. for non-table kinds) is a **this session task** since it's the canonical-serializer output that changes; the migrate-ts session pulls and continues.
68
+
69
+
---
55
70
56
-
When a fresh Claude session picks this up:
71
+
## Recommended workflow for this session
57
72
58
-
1.**Pull latest.**`git fetch && git status` — ensure on `main` and clean. The five spec docs + ADR-0018 + this plan are already on `origin/main`.
59
-
2.**Read the four spec docs + ADR-0018** in this order: ADR-0018, FR-016, FR-013, FR-015, FR-014. (You're reading high-context first, then easier-to-harder.)
60
-
3.**Pick a task.** Start with FR-016 (smallest, unblocks everything). When that lands, fan out FR-013 + FR-015 in parallel, and start FR-014 by writing FR-017.
61
-
4.**Per-FR rhythm:** brainstorm (only if the FR's design has gaps you discover) → write TDD-style task plan as a new file under `docs/superpowers/plans/` named `2026-MM-DD-fr-NNN-implementation.md` → execute red/green/refactor → fan out to ports via subagents → conformance corpus stays green throughout.
62
-
5.**Push cadence:** each FR is its own PR-sized chunk. Land TS reference + corpus fixtures first, then per-port fan-out commits, then close.
73
+
1.**Pull latest**every time you start. The migrate-ts session pushes to `main` too.
74
+
2.**Read the four spec docs + ADR-0018** in this order: ADR-0018, FR-016, FR-013, FR-015, FR-014.
75
+
3.**Pick a task.** Start with FR-016 (smallest, unblocks everything). When FR-016 metadata lands, signal the migrate-ts session, then fan out FR-013 + FR-015 in parallel here, and start FR-014 by writing FR-017.
76
+
4.**Per-FR rhythm:** brainstorm (only if the FR's design has gaps you discover) → write TDD-style task list with TodoWrite → execute red/green/refactor → fan out to ports via subagents → conformance corpus stays green throughout.
77
+
5.**Push cadence:** each FR is its own PR-sized chunk. Land TS reference + metadata fixtures first (signal migrate-ts session), then codegen, then per-port fan-out commits.
63
78
64
79
---
65
80
66
81
## Task: FR-016 (lands first)
67
82
68
-
### Metamodel / loader work (specified in FR-016)
83
+
### Metadata / loader work
69
84
- 5 new `AttrSchema` entries on `sourceRdbAttrs` (`@table`, `@view`, `@materializedView`, `@proc`, `@function`), 1 new `SOURCE_ATTR_NAME` schema entry.
70
85
- Constants in `server/typescript/packages/metadata/src/persistence/source/source-constants.ts` per FR-016 §Decision Part 2.
71
86
-`PHYSICAL_NAME_ATTR_BY_KIND` map.
72
87
- Four-step physical-name resolution in the loader (`server/typescript/packages/metadata/src/loader/`).
-`server/typescript/packages/migrate-ts/src/expected-schema.ts` — already in scope per FR-016 §migrate-ts impact.
101
+
102
+
> The corresponding `migrate-ts/src/expected-schema.ts` rewrite is **on the sister plan**, not here.
87
103
88
104
**Sweep recipe:**`grep -rn 'SOURCE_ATTR_TABLE\|"@table"\|source\.table\b' server/typescript/packages/ --include='*.ts'` → migrate each call site to the helper.
89
105
90
106
### Per-port fan-out
91
107
Java / Kotlin / C# / Python: register the same 5 attr aliases; mirror canonical-serializer output; sweep their generators for `@table`-hardcoding equivalent to the TS sweep. Per FR-016, ~half day per port.
92
108
93
-
### Done when
109
+
### Done when (this session)
94
110
- TS reference green against the 9 new fixtures.
95
111
-`WARN_LEGACY_PHYSICAL_NAME_ALIAS` fires on legacy `@table` for non-table kind.
96
112
- Every existing rdb-source conformance fixture canonical-output uses the per-kind attr key matching `@kind`.
97
113
- All four other ports run the 9 fixtures byte-identically.
114
+
-**Signal the migrate-ts session that FR-016 metadata is on `main` so they can start their slice.**
98
115
99
116
---
100
117
101
118
## Task: FR-013 (fan out after FR-016)
102
119
103
-
### Metamodel / loader work (specified in FR-013)
120
+
### Metadata / loader work (specified in FR-013)
104
121
-`FIELD_ATTR_READ_ONLY = "readOnly"` constant + schema entry on `commonFieldAttrs` in `server/typescript/packages/metadata/src/core/field/`.
TS Drizzle, Java JPA, Kotlin Exposed, C# EF Core, Python SQLAlchemy. See FR-013 §Per-port codegen mapping for the per-port emission rules.
130
+
TS Drizzle, Java JPA, Kotlin Exposed, C# EF Core, Python SQLAlchemy. See FR-013 §Per-port codegen mapping.
114
131
115
132
### Generator-stack gaps (NOT in FR-013 — open work)
116
133
The FR's per-port table covers the entity/ORM emission. These generators also need updating:
@@ -123,10 +140,12 @@ The FR's per-port table covers the entity/ORM emission. These generators also ne
123
140
-**`server/java/codegen-spring/`** — filter-allowlist generator no change (filter is a read concern).
124
141
-**`fixtures/api-contract-conformance/`** — add a scenario: POST with a readOnly field in the body returns 400. Cross-port byte-equivalent.
125
142
143
+
> FR-013 has **no migrate-ts work** (the FR explicitly states "no DDL emission"). The optional `WARN_READONLY_NO_GENERATOR` in `migrate-ts verify` is listed on the sister plan as "defer/skip."
144
+
126
145
### Per-port fan-out
127
146
After TS reference + ORM-emission per port, run the conformance corpus on each port. ~1 day per port per FR-013's estimate, parallel.
128
147
129
-
### Done when
148
+
### Done when (this session)
130
149
- TS reference green against 6 fixtures.
131
150
- API-contract conformance scenario (POST with readOnly field) green across all 5 ports.
132
151
- Generated forms in `client/web/packages/react` skip / disable readOnly fields (snapshot test).
@@ -135,7 +154,7 @@ After TS reference + ORM-emission per port, run the conformance corpus on each p
135
154
136
155
## Task: FR-015 (fan out after FR-016)
137
156
138
-
### Metamodel / loader work (specified in FR-015)
157
+
### Metadata / loader work (specified in FR-015)
139
158
-`SOURCE_ATTR_PARAMETER_REF = "parameterRef"` constant + schema entry on `sourceRdbAttrs`.
- Resolution: bare name OR FQN; reuses standard reference-resolution.
@@ -146,10 +165,7 @@ After TS reference + ORM-emission per port, run the conformance corpus on each p
146
165
### Per-port repo emission (specified in FR-015)
147
166
TS Drizzle wrapper, Java Spring `@Query`, Kotlin Exposed transaction, C# EF Core `FromSqlInterpolated`, Python SQLAlchemy `text(...)`. See FR-015 §Per-port codegen mapping.
148
167
149
-
### `migrate-ts` work (specified in FR-015)
150
-
-`pg_proc` introspection in `migrate-ts/src/expected-schema.ts`.
151
-
- Signature validation against live DB.
152
-
-`CREATE OR REPLACE FUNCTION` skeleton emit for new procs (body = `RAISE NOTICE 'unimplemented'`).
168
+
> The `pg_proc` introspection + signature drift + `CREATE OR REPLACE FUNCTION` skeleton emit are on the sister plan, not here.
153
169
154
170
### Generator-stack gaps (NOT in FR-015 — open work)
155
171
The FR specifies how the **calling code** emits. It does NOT specify whether stored procs are exposed as REST endpoints. **Decision required before implementation:**
@@ -171,9 +187,8 @@ Procs typically don't accept arbitrary filter/sort. **Default:** no filter / sor
171
187
### Per-port fan-out
172
188
After TS reference + REST decision, port the attr-registration + repo-emission per port. ~1 day per port per FR-015's estimate, parallel.
173
189
174
-
### Done when
190
+
### Done when (this session)
175
191
- TS reference green against 10 fixtures.
176
-
-`pg_proc` signature drift test green (in `server/typescript/packages/migrate-ts/test/`).
177
192
-`@exposeAsRoute` decision documented in the implementation-plan PR.
178
193
- All 5 ports' generated repo helpers callable in the persistence-conformance corpus.
> FR-014's migrate-ts piece (TPH DDL emit + drift detection) is on the sister plan. **This session and the migrate-ts session both depend on the FR-014 metadata commit landing first.** Once it does, they execute in parallel — disjoint package directories.
206
222
207
223
### Step 2: Implementation order
208
224
209
225
Per FR-014:
210
-
1. TS reference: metamodel + 9 conformance fixtures + `migrate-ts` TPH emit and diff (~1 week per FR-014 estimate).
2. TS reference: FR-017 generator-stack work (~1+ week — the polymorphic generator surface is large).
212
228
3. Per-port fan-out: TS metamodel + generator-stack per port (Java largest because of Spring controller / DTO / repo / payload generator interplay).
213
229
214
-
### Done when
230
+
### Done when (this session)
215
231
- FR-017 spec doc landed.
216
232
- FR-014's 9 metamodel fixtures green.
217
233
- FR-017's API-contract conformance scenarios green across 5 ports.
218
-
- Persistence-conformance TPH scenarios green across 5 ports (`fixtures/persistence-conformance/`).
219
234
- An adopter project (the C# CareMetx P3 CRM is the driver) can model their workflow-task / authorization / payment polymorphism in metadata and codegen produces working CRUD.
220
235
221
236
---
@@ -242,14 +257,15 @@ Before every commit: scan the diff for absolute home paths and other-project nam
242
257
243
258
---
244
259
245
-
## Done criteria for the whole batch
260
+
## Done criteria for this workstream
261
+
262
+
- All 4 FRs' metadata layers implemented across all 5 ports.
- Cross-port conformance corpus (metamodel + render + api-contract) green.
266
+
- Each FR's status updated from *Design* → *Implemented* (the migrate-ts portion may still be in flight on the sister plan; mark the codegen-side as done independently).
0 commit comments