Repository navigation
Commit 600b1e2
docs(deployment): the four-doors matrix names rule families and doors, so the input each door hands them is written as its own axis (#18872)
Fixes #18815
Clause-②: no
Docs-only. One file, +69 / -0:
`content/docs/deployment/validating-metadata.mdx`.
## The gap, restated at the scope it is actually at
The "one gate, four doors" table has exactly two axes: its **rows** are
rule
**families**, its **columns** are the four doors. A check mark says that
door runs
that family. It cannot say what that door **hands** the family to judge
— and that
input is where the three CLI doors have drifted three separate times. So
the
two-pass shape they run (the union fold over the artifact's collections,
then the
same table once per `packages[]` entry) was documented nowhere, for any
door,
across the three landings that wired it.
This PR adds a third axis to the page as its own `###` section, plus two
short
scoping paragraphs: one above the table naming what the table's two axes
are, one
under the `one-directional` parenthetical saying which scope that
sentence is
written at.
## The card's gating claim, re-derived rather than relayed
The card rests on "all three doors now run the per-package pass".
Verified on the
branch base `fb2bccfc96` by reading the call sites, not by trusting the
card:
| door | call site | wired by |
|---|---|---|
| `os build` | `packages/cli/src/commands/compile.ts:482` | #16611 |
| `os validate` | `packages/cli/src/commands/validate.ts:421` | #18677
(PR #18769, merged 2026-09-17T21:18:28Z) |
| `os lint` | `packages/cli/src/commands/lint.ts:722` | #18778 (PR
#18813, merged 2026-09-17T23:32:18Z) |
All three reach the one loop, `runPerPackageAuthoringRules` at
`packages/cli/src/utils/artifact-packages.ts:189`. Both PRs are merged
and are
ancestors of this branch's base. **The successor condition holds.**
Measured end to end as well, not only read:
`validate-per-package-authoring-parity`,
`lint-per-package-authoring-parity` and `union-fold-command-parity`
(spawned, real
binaries) — 3 files, 15 tests, exit 0.
## The seat's premise probe, re-run structurally
The dispatch handed one grep (`per-package | union fold | union-folded |
stack tier`
=> 0 hits, lit control `os build|os validate|os lint` => 25). Re-run as
a structural
read rather than a keyword miss, and widened to the whole docs tree:
- on the page, every occurrence of "tier" is a **rule** tier —
`pre-parse tier`
(:519), `react tier` (:335), `tier findings` (:63), the ADR-0049 `tier
programme`
(:241). None is a stack shape.
- across `content/docs/**`: zero hits for the per-package pass or the
union fold in
that sense (the 13 `per-package` hits are changelogs, doc-book grouping,
capability
prefixes, one-app-per-package ADRs), against a lit control of **64**
files naming
the three commands. Same probe over the published `skills/` catalog:
zero, lit
control 14.
So the gap is real and is repo-wide, not just table-shaped.
## Falsification — the card's own word for the axis is already taken,
and for a DIFFERENT axis
The card and the dispatch both name the second axis the **stack TIER**.
That phrase is
already spent in this repo, on something else:
- `packages/lint/src/authoring-rules.ts:1671` — *"The stack tiers a
command has in
hand when it runs the registry"*, documenting `AuthoringRuleRun`, whose
members are
`normalized` and `parsed`;
- `:215` — *"Which tier of the stack a rule reads"*, for the same two;
- `:213` — and `AuthoringRuleTier` is a third sense again, `'gating' |
'advisory'`.
Those are not near-synonyms of the axis this card is about; they are
**orthogonal to
it**. `runPerPackageAuthoringRules` hands BOTH stack tiers the same
per-package stack
(`artifact-packages.ts:230-231`, `normalized: asStack, parsed:
asStack`), and
`lint.ts:653` says the mirror thing for the other pass — *"Both tiers
are handed the
UNION-FOLDED stack"*. A page that wrote "stack tier" for the
union-vs-per-package axis
would therefore have created a **new** collision, in the very module the
table cites as
its source, of exactly the class this card exists to close.
⇒ the page names the axis for what it is — the **input** each door hands
the rule
table — and names the two passes what the code already calls them: **the
union fold**
and **the per-package walk**. The card's *requirement* is met (family
and input are
kept apart, explicitly, at the one paragraph where they were conflated);
its *wording*
is deliberately not adopted. Flagging it rather than quietly diverging.
## Also written out, because it is a third thing again
The fourth door is on **neither** pass. A runtime write is one item, so
the publish
gate evaluates differentially (context alone, then with the item grafted
in, #4463)
and narrows its resolution context to the written item's **package
closure** (#9612) —
which changes what a rule can *resolve*, never what it judges, and
iterates no
`packages[]`. "Runs per package" therefore names one thing at the three
CLI doors and
another at this one, and the `runtime publish` column says neither.
Sourced from
`packages/lint/src/runtime-gate.ts:208-259`, not from the card, which
explicitly did
not assert what that row should say.
## Evidence
- **Derived gate families** — `node scripts/pm/dispatch-gates.mjs
--commands --repo objectstack-ai/objectstack`
derived **39**; all 39 run, exit codes recorded and reconciled:
`--ran` => *"39 derived famil(ies) accounted for — 39 run, 0
NOT-MEASURED (a DERIVED
zero — all 39 recorded an exit code and none of them is 3)"*. Five first
reported
`PREREQUISITE NOT MET` (exit 3 / exit 1, nothing measured) and were
re-run to exit 0
after building `@objectstack/spec`, `@objectstack/formula`,
`@objectstack/lint` and
`@objectstack/client-react`: `check:doc-formula-expressions`,
`check:doc-security-posture`, `spec check:docs`, `spec
check:skill-examples`,
`check:docs-transcript-drift`.
- **`pnpm lint`** — the family `dispatch-gates.mjs` does not name. Run
**whole**, not
narrowed: `eslint . --no-inline-config`, **exit 0**, 82s, at
`777cd9aeca`.
- **MDX compiles** — `@mdx-js/mdx` 3.1.1 `compile()` on the edited page,
exit 0.
- **Anchors** — `pnpm check:doc-anchors` exit 0; the new heading adds
`#what-each-door-hands-the-rule-table` and renames nothing, so the
existing inbound
links to `#the-one-gate-four-doors` (`cli.mdx:650`,
`deployment/index.mdx:153`) are
untouched.
- **Control bytes** — `grep -naP` over the edited file: no hits; `pnpm
check:nul-bytes` exit 0.
- **Publishing surface, measured with controls both ways** — 83
manifests, 70
non-private. Manifests whose `files[]` mentions `content`: **0**.
Positive control,
`dist`: **70 of 70**. Manifests with no `files[]` at all (whole dir
ships): **0**.
`content/docs` is at the repo root, outside every package directory, and
the one
manifest that names a `content/docs` path at all does so in its
`description` string
(`plugin-webhooks`), not in `files[]`. ⇒ nothing published moves ⇒
`skip-changeset`,
applied to this PR.
## Acceptance notes
*Out of scope, noted and not filed:*
- `content/docs/getting-started/examples.mdx` §"A project is a
multi-package artifact"
is the page that teaches `packages[]` to authors and would be the
natural second home
for a one-line pointer at the per-package pass. It does **not**
enumerate the doors
and contradicts nothing here, so triage's escalation condition ("a
second page that
cannot express the axis ⇒ p1 plus a structural card") is **not** met —
measured, not
assumed. Successor: none; noted for whoever next edits that section.
- `content/docs/deployment/cli.mdx` carries the doors in two places
(`:649`, `:668`,
`:1485`) and defers to this page's matrix by link for the detail. Those
three
statements are true at both passes now, so nothing there is falsified by
this PR and
nothing was edited there. Successor: none.
---
_Generated by [Claude
Code](https://claude.ai/code/session_01DvvamiacK328idtBYJBxV3)_
Co-authored-by: Claude <noreply@anthropic.com>1 parent 36f13bb commit 600b1e2
1 file changed
Lines changed: 69 additions & 0 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
382 | 382 | | |
383 | 383 | | |
384 | 384 | | |
| 385 | + | |
| 386 | + | |
| 387 | + | |
| 388 | + | |
| 389 | + | |
| 390 | + | |
385 | 391 | | |
386 | 392 | | |
387 | 393 | | |
| |||
522 | 528 | | |
523 | 529 | | |
524 | 530 | | |
| 531 | + | |
| 532 | + | |
| 533 | + | |
| 534 | + | |
| 535 | + | |
| 536 | + | |
| 537 | + | |
| 538 | + | |
525 | 539 | | |
526 | 540 | | |
527 | 541 | | |
| |||
546 | 560 | | |
547 | 561 | | |
548 | 562 | | |
| 563 | + | |
| 564 | + | |
| 565 | + | |
| 566 | + | |
| 567 | + | |
| 568 | + | |
| 569 | + | |
| 570 | + | |
| 571 | + | |
| 572 | + | |
| 573 | + | |
| 574 | + | |
| 575 | + | |
| 576 | + | |
| 577 | + | |
| 578 | + | |
| 579 | + | |
| 580 | + | |
| 581 | + | |
| 582 | + | |
| 583 | + | |
| 584 | + | |
| 585 | + | |
| 586 | + | |
| 587 | + | |
| 588 | + | |
| 589 | + | |
| 590 | + | |
| 591 | + | |
| 592 | + | |
| 593 | + | |
| 594 | + | |
| 595 | + | |
| 596 | + | |
| 597 | + | |
| 598 | + | |
| 599 | + | |
| 600 | + | |
| 601 | + | |
| 602 | + | |
| 603 | + | |
| 604 | + | |
| 605 | + | |
| 606 | + | |
| 607 | + | |
| 608 | + | |
| 609 | + | |
| 610 | + | |
| 611 | + | |
| 612 | + | |
| 613 | + | |
| 614 | + | |
| 615 | + | |
| 616 | + | |
| 617 | + | |
549 | 618 | | |
550 | 619 | | |
551 | 620 | | |
| |||
0 commit comments