Skip to content

Commit c407886

Browse files
dmealingclaude
andcommitted
fix(docs): the auto-loading codegen rule taught metadata that no longer loads
`.claude/rules/codegen-architecture.md` loads itself into a Claude Code session on any codegen path match, unprompted. Its "Source-aware entities + projections" section was written before the v2 source paradigm and never revisited, so the file an agent doing codegen reads FIRST taught three spellings that are now illegal: - `source.dbTable` / `source.dbView` — retired subtypes (ADR-0007). There is one subtype, `source.rdb`, and read-only-ness comes from `@kind`. - `@name` for the physical name — it is the kind-matching alias, `@table` / `@view` (ADR-0018). - a projection as an `object.entity extends Program` with a view source — which is now `ERR_ENTITY_PRIMARY_SOURCE_READONLY` outright (ADR-0028 B4b). A read-only derived representation is `object.projection`. Every example in that block had stopped loading. Corrected, and the dispatch list now states the projection route contract (GET list + GET by id; write verbs answer 405) and points at the two corpora that gate it. `AGENTS.md` carried the same retired `source.dbView` in its file-organization section. Closes the gap that let it rot. `scripts/check-doc-examples.ts` exists to fail the build when shipped metadata examples stop loading, and its SCAN_ROOTS are described as "trees whose fenced metadata examples ship to a reader or to an agent" — but it read only `docs` and `agent-context`. `.claude/rules` is the most agent-facing prose in the repo and was the one such tree it did not read. This is exactly what #337 cost in agent-context, in the one place still unguarded. Adding the root takes the gate from 100 examples over 72 blocks to 103 over 75, all green. Found while building the F22 projection corpus — the stale block is the projection-authoring guidance. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015NrWUxA6euwvnFcwKxcK6A
1 parent d88fc95 commit c407886

3 files changed

Lines changed: 41 additions & 11 deletions

File tree

‎.claude/rules/codegen-architecture.md‎

Lines changed: 30 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -113,34 +113,54 @@ const { data } = useSubscribers({
113113

114114
**Architecture:** `parseFilterParams` (in `@metaobjectsdev/runtime-ts/drizzle-fastify`) translates parsed qs into a Drizzle expression tree. `buildFilterQs` (in `@metaobjectsdev/runtime-web` and `@metaobjectsdev/tanstack`) serializes a typed filter object back to a bracketed qs URL.
115115

116-
### Source-aware entities + projections (Project E)
116+
### Source-aware objects + projections (Project E)
117117

118-
`source` is a top-level metadata type describing where an object's data lives. Subtypes: `dbTable` (writable, default) and `dbView` (read-only).
118+
`source` is a top-level metadata type describing where an object's data lives.
119+
There is ONE subtype — **`source.rdb`** (the v2 paradigm, ADR-0007) — and
120+
read-only-ness comes from **`@kind`**: `table` (writable, the default) vs
121+
`view` / `materializedView` / `storedProc` / `tableFunction` (read-only).
122+
The physical name is the **kind-matching alias** (`@table` / `@view` / …,
123+
ADR-0018), never `@name`.
119124

120-
**Authoring a projection:**
125+
> The pre-v2 `source.dbTable` / `source.dbView` subtypes are **RETIRED** and no
126+
> longer load. Multi-source objects use `@role` (exactly one `primary`).
127+
128+
**Authoring a projection.** A read-only derived representation is
129+
**`object.projection`**, not an entity: an `object.entity`'s primary source must
130+
be a writable `@kind`, so an entity whose only source is a view is
131+
`ERR_ENTITY_PRIMARY_SOURCE_READONLY` (ADR-0028 B4b). Its fields are
132+
`extends`-bound or `origin`-derived, and its identity extends the base entity's.
121133

122134
```jsonc
123-
{ "object.entity": {
135+
{ "object.projection": {
124136
"name": "ProgramSummary",
125-
"extends": "Program",
126137
"children": [
127-
{ "source.dbView": { "@name": "v_program_summary" }},
138+
{ "source.rdb": { "@kind": "view", "@view": "v_program_summary" }},
139+
{ "field.string": { "name": "title", "extends": "Program.title" }},
128140
{ "field.int": { "name": "weekCount", "children": [
129141
{ "origin.aggregate": {
130142
"@agg": "count", "@of": "Week.id", "@via": "Program.weeks" }}
131143
]}},
132-
{ "identity.primary": { "@fields": ["id"] }}
144+
{ "identity.primary": { "name": "pk", "extends": "Program.pk" }}
133145
]
134146
}}
135147
```
136148

137-
**`origin`** subtypes: `passthrough` (cross-entity field reference) and `aggregate` (count/sum/avg/min/max). Origins drive view DDL.
149+
**`origin`** subtypes: `passthrough`, `aggregate`, `collection`, `computed`,
150+
`first` (`base` is the abstract root). Origins drive view DDL. The four assembly
151+
origins live on `object.projection` only.
138152

139153
**Source-aware codegen dispatch:**
140-
- Projection (dbView only) → read-only Zod, read-only routes, read-only hooks.
141-
- Write-through (dbTable + dbView) → mutations target table, queries target view.
154+
- Projection (read-only `@kind` only) → read-only Zod, read-only routes (GET list
155+
+ GET by id; every write verb answers `405 {"error":"method_not_allowed"}`),
156+
read-only hooks.
157+
- Write-through (`@role:primary` table + `@role:replica` view) → mutations target
158+
the table, reads route through the view.
142159
- Vanilla entity → standard behavior.
143160

161+
Gated end-to-end by `fixtures/api-contract-conformance/projection/` (view-only)
162+
and `.../write-through/` (table + replica view).
163+
144164
**`columnNamingStrategy`** in `metaobjects.config.ts`: `snake_case` (default) | `literal` | `kebab-case`.
145165

146166
### Currency (Project F)

‎AGENTS.md‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -284,7 +284,7 @@ import { EntityFetcherProvider, EntityGrid } from "@metaobjectsdev/tanstack";
284284

285285
## File organization
286286

287-
**Default convention**: one file per domain concept under `metaobjects/`. Multiple objects per file when they share a domain. Projections (`source.dbView`) live inline with their base entity.
287+
**Default convention**: one file per domain concept under `metaobjects/`. Multiple objects per file when they share a domain. Projections (`object.projection` with a read-only `source.rdb @kind`) live inline with their base entity.
288288

289289
`metaobjects/` is the **default value** of `sources` in `.metaobjects/config.json` — never a requirement. A project declaring `sources` explicitly can point anywhere (and need not have such a directory at all); `"sources": []`, which is what `meta init` scaffolds, takes the default.
290290

‎scripts/check-doc-examples.ts‎

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,16 @@ const SCAN_ROOTS = [
8585
// the entire corpus it was BUILT for — #337 was about the agent-context docs teaching
8686
// retired vocabulary, which is exactly what stops being checked.
8787
"agent-context",
88+
// The auto-loading Claude Code rules. These are the MOST agent-facing prose in
89+
// the repo — `.claude/rules/*.md` loads itself into a session on a path match,
90+
// unprompted — and they were the one such tree this gate did not read. It cost
91+
// exactly what #337 cost in agent-context: `codegen-architecture.md` taught
92+
// `source.dbView` / `@name` / a view-sourced `object.entity` long after the v2
93+
// paradigm (ADR-0007) retired the first two and B4b (ADR-0028) made the third
94+
// `ERR_ENTITY_PRIMARY_SOURCE_READONLY`. Every example it shipped had stopped
95+
// loading, and the file that teaches codegen is the file an agent doing codegen
96+
// reads first.
97+
".claude/rules",
8898
];
8999

90100
/**

0 commit comments

Comments
 (0)