spec: schema-camelcase-fix — expand scope to data-model.md + rustdoc layer (refs #30)

Spec amendment after plan-recon flagged four missed touch-points
in the brainstorm grounding-check loop:

1. `design/contracts/data-model.md:142-147` — fenced JSON-block in
   the canonical data-model contract. The data-model contract IS
   the canonical-schema doc (INDEX.md row, ratifying test
   `tests/design_schema_drift.rs`); leaving it on camelCase after
   `ast.rs` ships kebab is a direct Honesty-Rule violation.

2. Three rustdoc strings in production source that describe the
   present-state schema vocabulary: `ast.rs:8`, `parse.rs:81`,
   `check/lib.rs:1707`. Each enumerates the rename targets in
   prose; left unchanged they would describe a state that no
   longer exists.

3. Better home for the new schema-shape pin: `design_schema_drift.rs`
   (not `schema_coverage.rs`). That file already operates as the
   data-model-contract ratifying test, already builds Term::Lam
   exemplars at L121-129, and uses `anchor_in_jsonc_block` to walk
   data-model.md fenced blocks — the proposed extension slots
   directly into the existing pin family.

4. Experiment-tree files (`experiments/2026-05-12-.../master/spec.md`,
   `rendered/*.md`, `runs/**`) carry old tags. Per Honesty-Rule
   analogy with docs/plans/* — these are frozen historical
   artefacts of the 2026-05-12 cross-model-authoring experiment
   and are NOT migrated. The experiment's `master/examples/*.ail.json`
   fixture IS migrated (live JSON the workspace loader can
   deserialise); surrounding prose is not.

Plus an editorial fix: the fixture-occurrence count parenthetical
corrected from "3" to "2" — each fixture has one `paramTypes` +
one `retType`, one per line.

Spec re-dispatched through `ailang-grounding-check` (Step 7.5
re-PASS). All 9 load-bearing claims ratified, with 2 negative-grep
"no test pins this" ratifications openly flagged in the agent
report as a Boss-override-eligible shape. Acceptance criteria
renumbered to 7 (was 6).

Touch-point count now: 2 serde-renames + 1 workspace.rs literal +
2 .ail.json fixtures + 1 data-model.md fenced block + 3 rustdoc
strings = 9 files, all small edits. No hash-pin refresh required.
This commit is contained in:
2026-05-21 12:45:51 +02:00
parent 7d086e69ce
commit 55ce6d0d70
+81 -27
View File
@@ -17,7 +17,7 @@ the canonical JSON layer.
## Architecture
This is a schema-only milestone. Three layers are affected:
This is a schema-only milestone. Four layers are affected:
1. **Canonical JSON tag layer.** Two `#[serde(rename = "...")]`
attributes on `Term::Lam` in `crates/ailang-core/src/ast.rs:492,494`
@@ -41,7 +41,42 @@ This is a schema-only milestone. Three layers are affected:
- `experiments/2026-05-12-cross-model-authoring/master/examples/fn_with_lambda.ail.json`
- `crates/ailang-core/src/workspace.rs:1925-1926`
(Verified via `grep -rn '"paramTypes"\|"retType"' --include="*.rs"
--include="*.json"` — exhaustive list.)
--include="*.json"` — exhaustive list. Each fixture carries
exactly two occurrences of the two tags combined, one per line.)
4. **Canonical-schema contract + rustdoc layer.** Three rustdoc
strings in production source describe the present-state schema
(rather than implementation history); per the Honesty Rule
(`design/contracts/honesty-rule.md`) they must read truthfully
after the rename:
- `crates/ailang-core/src/ast.rs:8` — module-level `//!` enumerating
example field renames.
- `crates/ailang-surface/src/parse.rs:81` — module-level `//!`
mentioning `lam`'s `paramTypes` carry.
- `crates/ailang-check/src/lib.rs:1707` — rustdoc on the InstanceMethod
routing helper.
Plus the canonical data-model contract document itself, which
ships fenced JSON blocks describing the schema verbatim:
- `design/contracts/data-model.md:142-147` — the `Term::Lam`
fenced-JSON schema block.
The data-model contract IS the canonical schema documentation
(linked from `design/INDEX.md` row `data-model`, with ratifying
test `crates/ailang-core/tests/design_schema_drift.rs`). Leaving
it on the old tags after `ast.rs` ships kebab would be a direct
Honesty-Rule violation.
The experiment-tree under
`experiments/2026-05-12-cross-model-authoring/` (master spec,
renderings, run transcripts) carries the old tags in multiple
places. These are frozen historical artefacts of the 2026-05-12
cross-model-authoring experiment — analogous to `docs/plans/*.md`
under the Honesty Rule — and are NOT migrated by this milestone.
The experiment's `master/examples/fn_with_lambda.ail.json` IS
migrated (it is a checked-in JSON fixture the workspace loader
could deserialise); the surrounding prose documents and run
transcripts are not.
**Hash blast radius is zero on pinned modules.** None of the
`.ail` modules pinned in `crates/ailang-core/tests/hash_pin.rs`
@@ -180,20 +215,27 @@ the surrounding fixture content is untouched.
| Component | Change |
|-----------|--------|
| `crates/ailang-core/src/ast.rs:492,494` | Two `#[serde(rename)]` strings: `"paramTypes" → "param-types"`, `"retType" → "ret-type"`. |
| `crates/ailang-core/src/workspace.rs:1925-1926` | In-source JSON-literal in a test: same two key renames. |
| `examples/test_loop_binder_captured_by_lambda.ail.json` | Same two key renames (verified 3 occurrences combined of the two tags via `grep -c`). |
| `experiments/2026-05-12-cross-model-authoring/master/examples/fn_with_lambda.ail.json` | Same two key renames (verified 3 occurrences combined). |
| `crates/ailang-surface/src/{print,parse}.rs` | **No change.** Form-A never used these tag names. |
| `crates/ailang-core/src/ast.rs:8` | Module-level `//!` rustdoc — substitute the new tag spellings in the example list. |
| `crates/ailang-surface/src/parse.rs:81` | Module-level `//!` rustdoc — substitute the new tag spelling. |
| `crates/ailang-check/src/lib.rs:1707` | `///` rustdoc — substitute the new tag spellings. |
| `crates/ailang-core/src/workspace.rs:1925-1926` | In-source JSON-literal in `ct1_validator_walks_lam_embedded_types` (function at L1911): same two key renames. |
| `design/contracts/data-model.md:142-147` | Fenced JSON-block in the canonical data-model contract: same two key renames. |
| `examples/test_loop_binder_captured_by_lambda.ail.json` | Same two key renames (2 occurrences total of the two tags, one per line). |
| `experiments/2026-05-12-cross-model-authoring/master/examples/fn_with_lambda.ail.json` | Same two key renames (2 occurrences total). |
| `crates/ailang-surface/src/{print,parse}.rs` (code) | **No change.** Form-A never used these tag names — only `parse.rs:81` rustdoc above. |
| `crates/ailang-core/tests/hash_pin.rs` | **No change.** No pinned `.ail` module contains `(lam ...)` (verified per-file). |
Historic documents (`docs/plans/2026-05-10-23.3-...`,
`docs/plans/2026-05-09-22b3-monomorphisation.md`,
`docs/plans/2026-05-09-22c-user-class-e2e.md`,
`docs/plans/24.2.md`) embed the old tag names inside example JSON
blocks. Per the Honesty Rule
(`design/contracts/honesty-rule.md`), historic plan documents
describe the state at the time of writing — not the present state —
and are NOT migrated.
Historic / frozen documents NOT migrated (per Honesty Rule
analogue: these describe state at the time of writing, not the
present state):
- `docs/plans/2026-05-10-23.3-...md`,
`docs/plans/2026-05-09-22b3-monomorphisation.md`,
`docs/plans/2026-05-09-22c-user-class-e2e.md`, `docs/plans/24.2.md`
— embed old tag names in example JSON blocks.
- `experiments/2026-05-12-cross-model-authoring/master/spec.md`,
`experiments/2026-05-12-cross-model-authoring/rendered/*.md`,
and any `experiments/2026-05-12-cross-model-authoring/runs/**`
transcripts — frozen artefacts of the 2026-05-12 experiment.
## Data flow
@@ -257,12 +299,20 @@ The milestone is GREEN if:
- `cargo test -p ailang-surface --test round_trip` passes — confirms
Form-A is untouched.
- A single targeted assertion is added: a fresh test in
`crates/ailang-core/tests/schema_coverage.rs` (or equivalent
existing schema-shape test) verifies that
`crates/ailang-core/tests/design_schema_drift.rs` verifies that
`serde_json::to_value(&Term::Lam{...})` emits the keys
`"param-types"` and `"ret-type"` (and NOT the old camelCase). The
test pins the new schema layer concretely so a future regression
cannot silently flip the rename string back.
`"param-types"` and `"ret-type"` (and NOT the old camelCase),
AND extends the existing fenced-block anchor sweep to assert
that `design/contracts/data-model.md` contains the new tag
spellings inside the `Term::Lam` fenced JSON block. The home
is `design_schema_drift.rs` (not `schema_coverage.rs`, which is
a corpus-coverage walker) because that file already operates as
the data-model contract's ratifying test, already builds
`Term::Lam` exemplars (L121-129), and already pins the
`data-model.md` ↔ schema pairing via the
`anchor_in_jsonc_block` helper. The two assertions pin the
schema layer and the contract document together so a future
regression cannot silently flip the rename string back.
- `cargo build --workspace` produces no new clippy warnings.
No bench-regression check is required: the rename is a string
@@ -272,15 +322,19 @@ literal swap at compile time with no runtime cost path.
1. Tag-rename change in `crates/ailang-core/src/ast.rs:492,494` is
landed and observable in serialisation output.
2. Three call-sites (`workspace.rs` + two `.ail.json` fixtures)
carry the new tag names verbatim.
3. `cargo test --workspace` is GREEN.
4. `cargo test -p ailang-surface --test round_trip` is GREEN
2. All four code call-sites (`workspace.rs` JSON-literal + two
`.ail.json` fixtures + `design/contracts/data-model.md` fenced
JSON block) carry the new tag names verbatim.
3. All three rustdoc strings (`ast.rs:8`, `parse.rs:81`,
`check/lib.rs:1707`) describe the new tag spellings.
4. `cargo test --workspace` is GREEN.
5. `cargo test -p ailang-surface --test round_trip` is GREEN
(Form-A unchanged invariant).
5. A new schema-shape assertion test fires GREEN with the new tag
names and would fire RED with the old ones.
6. The commit body references `closes #30`. No `docs/plans/*.md`
files are mutated.
6. The new `design_schema_drift.rs` assertion(s) fire GREEN with
the new tag names and would fire RED with the old ones.
7. The commit body references `closes #30`. No `docs/plans/*.md`,
`experiments/.../master/spec.md`, `experiments/.../rendered/*`,
or `experiments/.../runs/*` files are mutated.
## Feature-acceptance gate