Commit ae8e3ca
fix(lint)!: refuse a view container whose
Fixes #20216
Clause-②: no (narrowing)
**Landing order: PR #20228 → PR #20229 → this PR.** #20228 has merged.
#20229 (the `packages[]` read in `artifactProvidedObjectNames`, still in
a rework round) edits the same file. This PR does not touch that hunk,
its import line, or `packages/lint/src/object-graph.ts`, and a local
`git merge-tree` of this branch against #20229's head `a4b05d6` writes a
clean tree. The seat enqueues this PR after #20229 merges, and this
branch merges `origin/main` then.
## CI fix round: `Test Core (6/6)`, and a file-surface amendment
- **What went red:**
`packages/cli/test/generate-scaffold-validates.test.ts`, "`os g 'view'`
writes a stack `os validate` accepts", got `object-reference-unknown at
views[0].object: view container object "probe_thing" …`.
- **Why:** the harness judged each scaffold in a host stack holding only
the collection under test. The view scaffold binds `probe_thing`, the
object `os g object probe_thing` writes, but no object was in the stack.
The new leg refused it correctly: the omission was the harness's, not
the template's. Reproduced red locally before the fix (1 failed, 17
passed).
- **Fix (test fixture only):** every `namesObject` generator other than
`object` itself (view, action, flow, app) is now judged beside the
object scaffold for the same name, materialized through the same
`bundle-require` loader. A new pin asserts the view's binding and the
seeded object's `name` are the same spelling, and that a non-binding
generator (`dashboard`) and `object` itself carry no seeded object. ⛔
The rule is not weakened, `probe_thing` is not special-cased, and no
test is skipped.
- **File-surface amendment:**
`packages/cli/test/generate-scaffold-validates.test.ts`, test fixture
only. No other CLI fixture needed a change (see the runs below).
- **Other generators:** action, flow and app also bind `probe_thing`.
They passed before the seeding and still pass with it.
## What changed
A view container's own `object` (`ViewSchema.object`) is the key the
runtime indexes views by (`getViewsByObject()` / `GET
/meta/view?object=`). Nothing resolved it at authoring time:
`defineStack`'s `validateCrossReferences` reads a container's
`list.data` / `form.data` bindings, never the container's own key.
- `packages/lint/src/validate-object-references.ts` gains a
view-container leg beside the relationship-target leg. It uses the same
`check` ladder and the same `resolvable` set: the stack's objects plus
what its `packages[]` provide.
- An unresolved unprefixed name is an **error**,
`object-reference-unknown` at `views[N].object`.
- A known platform object passes.
- A platform-shaped name that nothing registers gets the existing
`object-reference-unregistered-platform` advisory.
- The refusal is located and carries a prescription:
- it lists the objects the stack declares (`Defined objects: ...`);
- when the bound name is exactly a declared object minus the stack's
`manifest.namespace` prefix, the hint names that object: `write
"my_app_order_line", not "order_line"`.
- It gates like its sibling. It is the same member of the same
reference-integrity suite entry, so `os validate`, `os build` and `os
lint` all run it at the same tier.
- Not judged, on purpose:
- a container with no `object` (its binding falls back to
`list.data.object` / `form.data.object` / `name`, which is a different
reference);
- a runtime-authored container (#13407 is out of scope). This member
does not run on a `view` write at the runtime publish gate, and the
runtime is untouched.
- ⛔ No second copy in `packages/spec/src/stack.zod.ts`.
## Measured at the public door (CLI built at this branch)
The scratch project has `manifest.namespace: 'my_app'`, an object
`my_app_order_line`, and a view container with `object: 'order_line'`.
| run | `os validate` | `os build` |
|:--|:--|:--|
| leg disabled (ablation, lint rebuilt, marker proven in `dist/`) | exit
0, "Validation passed", nothing about the view | not run |
| this branch, `object: 'order_line'` | exit 1,
`object-reference-unknown at views[0].object`, hint names
`my_app_order_line` | exit 1, same rule and path |
| this branch, `object: 'my_app_order_line'` (control) | exit 0 | exit 0
|
`os generate view order_line` in the same namespaced project (after PR
#20214) writes `object: 'my_app_order_line'`, which passes.
## Census of producers (H2)
The instrument is one TypeScript-AST scan at `0d60f88760`. It reads
`examples/**`, `packages/**` (tests and fixtures included), `skills/**`,
and the ts/js code fences in `content/docs/**` md/mdx (generated
`references/` excluded). It covers 7242 files and counts object literals
that carry a view-container slot
(`list`/`form`/`listViews`/`formViews`). A name resolves when it is
declared by an object literal (`name` + `fields`) anywhere in the
corpus, or when it is a platform-provided object.
| tree | containers | carrying `object` | unresolved |
|:--|--:|--:|--:|
| examples | 10 | 0 | 0 |
| packages | 367 | 105 | 11 |
| skills | 3 | 0 | 0 |
| content/docs | 21 | 0 | 0 |
- **Control from the same instrument:** 94 of the 105 containers
carrying `object` resolve.
- **No example or platform package ships a dangling container.** No
example container carries `object` at all; they bind through
`list.data.object`.
- **The 11 unresolved:**
- 10 are non-literal `object` expressions in code, not stored views:
schema/`strictObject` definitions in `view.zod.ts`, walkers in
`validate-translation-references.ts` /
`validate-translatable-sections.ts` / `protocol.ts`, a helper in a rest
measurement test, and the parameterised helper in this PR's own test.
- 1 literal: `packages/cli/test/format-zod-union.test.ts`
(`union_probe_obj`). That specimen fails schema parse first, which that
file asserts as exactly one `invalid_union` issue. `os validate` exits
at the schema step, so author-time rules never run on it. No pin flips.
- **Pin sweep ①:** grepping `object-reference-unknown` and the rule's
message across the repo found no pin on a view container. The pins in
`packages/cli` (`artifact-packages.test.ts`,
`build-multi-package-artifact.e2e.test.ts`,
`union-fold-command-parity.test.ts`) have fixtures with no container
`object`, so none flips. **②:** nothing flipped, so no load-bearing
re-pin was owed.
## Tests (at `60808317dc` unless marked)
- `pnpm --filter @objectstack/lint exec vitest run --maxWorkers=2`:
**109 files / 4242 tests passed**.
- `pnpm --filter @objectstack/lint typecheck`: exit 0 (`tsc --noEmit`
plus `check:test-typecheck: OK`).
- `pnpm --filter @objectstack/cli exec vitest run --project unit
--maxWorkers=2`: **227 files / 3219 tests passed**. This includes the
fixed `generate-scaffold-validates.test.ts` (19 of 19).
- CLI integration tier, the 21 files that reference views or scaffolds
(`--project integration`): **21 files / 196 tests passed**.
- `pnpm --filter @objectstack/cli typecheck`: exit 0
(`check:test-typecheck: OK`).
- Nightly tier (`OS_TEST_TIERS=nightly`), 7 e2e files on views or
scaffolds: 6 files passed. One test failed in
`generate-agent-retired.e2e.test.ts` ("`os g object … --dry-run` still
previews a typed object file"). It expects `import * as Data from
'@objectstack/spec/data'`, but the object template writes `import {
ObjectSchema }` since #20195. That failure is independent of this PR:
neither file differs from the merge base (0 diff lines).
- New pins in `validate-object-references.test.ts` (two new `describe`
blocks, appended so they stay clear of #20229's hunk):
- `object: 'order_line'` in a `my_app` stack is refused, naming
`my_app_order_line`; the prefixed container is the control;
- the map form of `views` is read;
- a non-prefix miss is refused without the namespace prescription;
- a container over a `packages[]` sibling's object passes, and the same
package alone is refused (control);
- `sys_user` passes and `sys_approval_process` advises;
- no views, `views: []`, and a container with no `object` stay silent;
- the finding reaches the gating tier of `runAuthoringRules` for
`validate`, `build` and `lint`.
- **Unit ablation** (`scripts/ablation-replace.mjs`, anchor `const bound
= strName(view.object);`, anchor count 1 to 0, blob `27699c9` to
`03f6f47`): **8 refusal pins red; 48 green, including both controls
(prefixed container, silence).** Restored with blob equal to HEAD and
`git diff HEAD` empty. Taken at `9fa1ff4c61`. Since then only comment
lines changed in `src`.
- **Door ablation:** marker planted, `@objectstack/lint` rebuilt,
`ablation-dist-preflight` found the marker in 4 built files, and `os
validate` exited 0. Then the restore leg: blob equal to HEAD, lint
rebuilt, preflight `--absent` confirmed the marker gone from all 14
built files with a clean tree, and `os validate` exited 1 again.
## Gates (derived by `node scripts/pm/dispatch-gates.mjs --repo
objectstack-ai/objectstack --commands` at `60808317dc`)
- 60 families derived (one new: `check:cli-test-child-env`, green) and
all run at `60808317dc`. `--ran` reconciliation with exit codes: 59 run,
1 NOT MEASURED, 0 unrun.
- The ones this diff actually moves are green:
`check-adr-0087-registration` (disposition `not-required
(no-migration-prescription)` accepted), `check-changeset-no-major`,
`check-empty-changeset`, `check:doc-authoring`, `check:nul-bytes`,
`check-closing-keyword-parity`, `check:published-files`,
`check:type-check-coverage`, `check:test-source-alias`.
- `check:type-check-debt` now measures green (`none above its recorded
number`).
- NOT MEASURED: `check:dual-build-cjs-loads` (exit 3, PREREQUISITE NOT
MET: it needs every package's `dist/`, and this box built the lint and
CLI closures only). Declared to CI.
- Correction to the first round: I declared the `packages/cli` suites to
CI without running them, and the census missed `os g view` because its
container sits inside a template string the AST scan cannot see. That is
the red this round fixes. The CLI unit project now runs in full here.
## Changeset
`.changeset/20216-view-container-object-refused.md`:
- `@objectstack/lint: minor`, carrying a **BREAKING** banner and
`Clause-②: no (narrowing)`;
- a before/after accept-set table;
- ADR-0087 `not-required (no-migration-prescription)`: nothing
authorable moves in spec, and which object an author meant is a fact
about their stack, not a mechanical conversion.
The table is a behaviour table (door: FROM exit 0, TO exit 1). My first
draft headed it "FROM → TO", and the ADR-0087 gate read that heading as
a rewrite prescription and refused the exemption. The heading now says
"before and after", and the table carries no rewrite row.
## Acceptance notes (not filed)
- The namespace prescription is on this leg only. The other sites on the
same rule (a field `reference`, action params, dataset base object)
could give the same hint for the same missing-prefix miss. I noted it
and did not widen it here. Carrier: none.
- A container whose `object` and `list.data.object` name different
objects is not judged by any rule. It is out of this card's scope, and I
found no instance in the census.
---
_Generated by [Claude
Code](https://claude.ai/code/session_01QcAS3qiYYZNezaxZxaUdMV)_
---------
Co-authored-by: Claude <noreply@anthropic.com>object names no object (#20253)1 parent 5f9d7d7 commit ae8e3ca
4 files changed
Lines changed: 293 additions & 8 deletions
File tree
- .changeset
- packages
- cli/test
- lint/src
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
| 41 | + | |
| 42 | + | |
| 43 | + | |
| 44 | + | |
| 45 | + | |
| 46 | + | |
| 47 | + | |
| 48 | + | |
| 49 | + | |
| 50 | + | |
| 51 | + | |
| 52 | + | |
| 53 | + | |
| 54 | + | |
| 55 | + | |
| 56 | + | |
| 57 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
132 | 132 | | |
133 | 133 | | |
134 | 134 | | |
135 | | - | |
136 | | - | |
| 135 | + | |
| 136 | + | |
| 137 | + | |
| 138 | + | |
| 139 | + | |
137 | 140 | | |
138 | 141 | | |
139 | 142 | | |
140 | 143 | | |
141 | 144 | | |
142 | 145 | | |
143 | 146 | | |
| 147 | + | |
144 | 148 | | |
145 | 149 | | |
146 | 150 | | |
| 151 | + | |
| 152 | + | |
| 153 | + | |
| 154 | + | |
| 155 | + | |
| 156 | + | |
| 157 | + | |
| 158 | + | |
| 159 | + | |
| 160 | + | |
| 161 | + | |
| 162 | + | |
| 163 | + | |
| 164 | + | |
| 165 | + | |
| 166 | + | |
| 167 | + | |
| 168 | + | |
| 169 | + | |
| 170 | + | |
| 171 | + | |
| 172 | + | |
| 173 | + | |
| 174 | + | |
| 175 | + | |
| 176 | + | |
| 177 | + | |
| 178 | + | |
| 179 | + | |
| 180 | + | |
| 181 | + | |
| 182 | + | |
| 183 | + | |
147 | 184 | | |
148 | 185 | | |
149 | 186 | | |
150 | 187 | | |
151 | 188 | | |
152 | | - | |
153 | | - | |
154 | | - | |
155 | | - | |
156 | | - | |
| 189 | + | |
157 | 190 | | |
158 | 191 | | |
159 | | - | |
| 192 | + | |
160 | 193 | | |
161 | 194 | | |
162 | 195 | | |
| |||
203 | 236 | | |
204 | 237 | | |
205 | 238 | | |
| 239 | + | |
| 240 | + | |
| 241 | + | |
| 242 | + | |
| 243 | + | |
| 244 | + | |
| 245 | + | |
| 246 | + | |
| 247 | + | |
| 248 | + | |
| 249 | + | |
| 250 | + | |
| 251 | + | |
| 252 | + | |
| 253 | + | |
| 254 | + | |
206 | 255 | | |
207 | 256 | | |
208 | 257 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
6 | 6 | | |
7 | 7 | | |
8 | 8 | | |
| 9 | + | |
9 | 10 | | |
10 | 11 | | |
11 | 12 | | |
| |||
685 | 686 | | |
686 | 687 | | |
687 | 688 | | |
| 689 | + | |
| 690 | + | |
| 691 | + | |
| 692 | + | |
| 693 | + | |
| 694 | + | |
| 695 | + | |
| 696 | + | |
| 697 | + | |
| 698 | + | |
| 699 | + | |
| 700 | + | |
| 701 | + | |
| 702 | + | |
| 703 | + | |
| 704 | + | |
| 705 | + | |
| 706 | + | |
| 707 | + | |
| 708 | + | |
| 709 | + | |
| 710 | + | |
| 711 | + | |
| 712 | + | |
| 713 | + | |
| 714 | + | |
| 715 | + | |
| 716 | + | |
| 717 | + | |
| 718 | + | |
| 719 | + | |
| 720 | + | |
| 721 | + | |
| 722 | + | |
| 723 | + | |
| 724 | + | |
| 725 | + | |
| 726 | + | |
| 727 | + | |
| 728 | + | |
| 729 | + | |
| 730 | + | |
| 731 | + | |
| 732 | + | |
| 733 | + | |
| 734 | + | |
| 735 | + | |
| 736 | + | |
| 737 | + | |
| 738 | + | |
| 739 | + | |
| 740 | + | |
| 741 | + | |
| 742 | + | |
| 743 | + | |
| 744 | + | |
| 745 | + | |
| 746 | + | |
| 747 | + | |
| 748 | + | |
| 749 | + | |
| 750 | + | |
| 751 | + | |
| 752 | + | |
| 753 | + | |
| 754 | + | |
| 755 | + | |
| 756 | + | |
| 757 | + | |
| 758 | + | |
| 759 | + | |
| 760 | + | |
| 761 | + | |
| 762 | + | |
| 763 | + | |
| 764 | + | |
| 765 | + | |
| 766 | + | |
| 767 | + | |
| 768 | + | |
| 769 | + | |
| 770 | + | |
| 771 | + | |
| 772 | + | |
| 773 | + | |
| 774 | + | |
| 775 | + | |
| 776 | + | |
| 777 | + | |
| 778 | + | |
| 779 | + | |
| 780 | + | |
| 781 | + | |
| 782 | + | |
| 783 | + | |
| 784 | + | |
| 785 | + | |
| 786 | + | |
| 787 | + | |
| 788 | + | |
| 789 | + | |
| 790 | + | |
| 791 | + | |
| 792 | + | |
| 793 | + | |
| 794 | + | |
| 795 | + | |
| 796 | + | |
| 797 | + | |
| 798 | + | |
| 799 | + | |
| 800 | + | |
| 801 | + | |
| 802 | + | |
| 803 | + | |
| 804 | + | |
| 805 | + | |
| 806 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
46 | 46 | | |
47 | 47 | | |
48 | 48 | | |
| 49 | + | |
| 50 | + | |
| 51 | + | |
| 52 | + | |
| 53 | + | |
49 | 54 | | |
50 | 55 | | |
51 | 56 | | |
| |||
328 | 333 | | |
329 | 334 | | |
330 | 335 | | |
| 336 | + | |
| 337 | + | |
| 338 | + | |
| 339 | + | |
| 340 | + | |
| 341 | + | |
| 342 | + | |
| 343 | + | |
| 344 | + | |
| 345 | + | |
| 346 | + | |
| 347 | + | |
| 348 | + | |
| 349 | + | |
| 350 | + | |
| 351 | + | |
| 352 | + | |
| 353 | + | |
| 354 | + | |
| 355 | + | |
| 356 | + | |
| 357 | + | |
| 358 | + | |
| 359 | + | |
| 360 | + | |
| 361 | + | |
| 362 | + | |
| 363 | + | |
| 364 | + | |
| 365 | + | |
| 366 | + | |
| 367 | + | |
| 368 | + | |
| 369 | + | |
| 370 | + | |
| 371 | + | |
| 372 | + | |
| 373 | + | |
| 374 | + | |
| 375 | + | |
| 376 | + | |
| 377 | + | |
| 378 | + | |
| 379 | + | |
| 380 | + | |
| 381 | + | |
| 382 | + | |
| 383 | + | |
| 384 | + | |
| 385 | + | |
| 386 | + | |
| 387 | + | |
| 388 | + | |
| 389 | + | |
| 390 | + | |
331 | 391 | | |
332 | 392 | | |
333 | 393 | | |
| |||
0 commit comments