Repository navigation
Commit 7b8bcfe
docs(adr): ADR-0141 says the build refuses a lookup into another artifact and only the save door honours a declared dependency (#27812)
<!-- claude-projects-attribution: {"github_login":"os-elon-musk"} -->
_Requested by **Elon** · [project
thread](https://claude.ai/code/project/chan_01WedDzV26nniwxv7jC88B9D?thread=cmsg_01WedDzV26nniwxv7jC88B9DHpDhX1q4f9FeSSfiSgMm4F)_
Fixes #27616
Clause-②: no
Metadata-protocol: none
## 维护者速读
- **改了什么:** 只改 ADR-0141 的文字。D1、Consequences 和执行计划第 4 条原来说 `os validate`
/ `os build` / `os
lint`「对跨包绑定两边都不判」;现在写成代码的实际做法:构建时看不到制品之外的依赖包的对象,lookup
指向这种对象会被报错拒绝,流程的触发对象指向它只给警告;声明的依赖只在运行时保存门生效(流程触发对象、数据集主对象、列表视图对象),保存门不判
lookup。
- **为什么改:** ADR-0141 是跨应用依赖的依据文本。旧句让读者(人或 AI)以为指向依赖包对象的 lookup 能过 `os
validate`,实际会被拒;#25805 的分析就在这句上错过一次。按 #25805 的裁决(字母 D,暂缓)只改文字,不改行为。
- **风险与回滚:** 零代码、零行为变化,不发版;回滚就是 revert 这一个 commit。
- **先看:**
`docs/adr/0141-inter-app-dependency-declared-checked-before-install.md`
的 D1 末段(主改动),其次 Consequences 的 Unchanged 一行和执行计划第 4 条。
- **两分钟验证:** 先 `pnpm exec turbo run build --filter=@objectstack/lint`,再跑
`pnpm --filter @objectstack/lint exec vitest run
src/validate-object-references.test.ts
src/runtime-gate.package-closure.test.ts`,预期全绿:「NON-DEGENERACY — a name
NO package in the artifact provides still errors」钉住 lookup 报错,「the CLI
reading is unchanged: no scope stated, the advisory the rule always
gave」钉住流程触发对象只警告。
- **需要你做的:** 暂无。contract review owed:席位的契约复审还没做,复审 PASS 之前不求批。
## What changes
One file, text only:
`docs/adr/0141-inter-app-dependency-declared-checked-before-install.md`,
+10 / -6 (net +4 lines).
- **D1, last sentence.** Was: "`os validate`, `os build` and `os lint`
keep judging neither side of a cross-package binding: a stack there is
one app and cannot see its dependencies' objects." Now: the three
commands cannot see the objects of a dependency the artifact does not
carry; a stack there resolves against its own objects, its artifact's
`packages[]` and the platform's names, so a lookup to such an object is
refused (`object-reference-unknown`) and a flow triggered on one warns
(`flow-trigger-unknown-object`). Only the save door honours the
declaration, for a flow's trigger, a dataset's base and a list view's
object; it does not judge a lookup. Closing that gap at build is
deferred by the ruling on #25805.
- **Consequences, Unchanged.** "the compile-time boundary (`os validate`
judges neither side of a cross-artifact binding)" becomes "the
compile-time boundary (`os validate` refuses a lookup into another
artifact, D1)".
- **Execution plan item 4.** The docs state that `os validate` cannot
see the objects of a dependency the artifact does not carry, "so it
refuses a lookup to one and warns on a flow triggered on one (D1)".
- **Evidence header.** One dated sentence: the three build-time
sentences were re-read at `f5dd057587` and corrected on 2026-10-30
(#27616). The `**Status**:` line is unchanged (`Proposed`).
No decision moves, no behaviour changes, no changeset: `docs/adr/**`
publishes nothing (`skip-changeset`).
### What the tree does (read at `origin/main` `f5dd057587`)
- **Build, lookup target.**
`packages/lint/src/validate-object-references.ts`:
`validateObjectReferences` resolves a name against the stack's own
objects plus `artifactProvidedObjectNames` (the bodies in `packages[]`;
its docblock: "Nothing else is read off the entry: not its id, not its
dependencies"), then `isPlatformProvidedObjectName`. An unresolved name
without a platform prefix (`PLATFORM_OBJECT_PREFIXES` = `sys_`,
`cloud_`, `ai_`, which a stack's own objects may not use) is rung 2 of
the header's severity ladder: `severity: 'error'`,
`object-reference-unknown`. The field site walks `lookup`,
`master_detail` and `user` (`RELATIONSHIP_TARGET_FIELD_TYPES`). The rule
is a member of `REFERENCE_INTEGRITY_RULES`, which runs on `validate`,
`lint` and `build`.
- **Build, flow trigger object.**
`packages/lint/src/validate-flow-trigger-readiness.ts`:
`validateFlowTriggerReadiness` returns `flow-trigger-unknown-object` at
`severity: 'warning'` when no `options.packageScope` is stated, with the
hint "ignore this if another installed package declares it"; the CLI
never states one. Its registry entry in `authoring-rules.ts` carries
`commands: ALL`.
- **Save door, closure.**
`packages/metadata-protocol/src/protocol-authoring-gate.ts` resolves
`this.resolveWritePackageScope(evt.packageId)` (the transitive
`manifest.dependencies` walk over the live registry,
`protocol-write-package-scope.ts`), and
`packages/lint/src/runtime-gate.ts` `buildRuntimeWriteSnapshotSet`
narrows `objects` with `narrowObjectsToPackageClosure`. Under that
closure a flow's trigger object outside it is
`flow-trigger-unknown-object` at `error`, a dataset's base object is
`object-reference-unknown`, and a list view's object is
`list-view-object-outside-closure`; a declared dependency's objects
survive the narrowing.
- **Save door, lookup.** `validateReferenceIntegrity` skips a member
whose `runtimeTypes` does not list the written type, and
`validateObjectReferences` declares `runtimeTypes: ['flow', 'dataset']`
(`reference-integrity-suite.ts`). So a field `reference` written through
an `object` save is not judged there. Read from source, not exercised
through a door; it matches the dev report and the director's re-reading
on #25805.
## Tests
No test changed. The readings above are pinned by existing tests, run at
`d1c404fc` after `pnpm exec turbo run build
--filter=@objectstack/formula --filter=@objectstack/lint`:
- `validate-object-references.test.ts`: "NON-DEGENERACY — a name NO
package in the artifact provides still errors" (`crm_contract`, the
card's cross-repo spelling, is `error` / `object-reference-unknown`).
- `runtime-gate.package-closure.test.ts`: "the CLI reading is unchanged:
no scope stated, the advisory the rule always gave" (`warning` with no
closure, `error` under one), and the flow door's "admits the own
package, a declared dependency, platform objects and overlay rows".
<details><summary>vitest, 3 files</summary>
```
pnpm --filter @objectstack/lint exec vitest run --maxWorkers=2 src/validate-object-references.test.ts src/runtime-gate.package-closure.test.ts src/validate-flow-trigger-readiness.test.ts
Test Files 3 passed (3)
Tests 210 passed (210)
os-verify-lock: VERDICT command-exit 0
```
</details>
## Acceptance notes
- **Not edited, outside the three sentences the card names.** TL;DR item
2, Context §1 ("Reference is already judged against the declared closure
— at the runtime save door, nowhere else"), D1's sentence just before
the corrected one ("An undeclared cross-app reference is refused where
it is refused today — at the save door, `422`") and Consequences /
Positive bullet 2 speak of the save door's closure for every cross-app
reference. At `f5dd057587` that door judges a flow's trigger object, a
dataset's base object and a list view's object, and not a field lookup
(read from source, as above). The corrected D1 says so for its own
paragraph; narrowing the other sentences is the seat's and the
maintainer's call. carrier: none.
- **Context §1's quotation stays.** Its `os validate`, `os build` and
`os lint` "judge neither: …" is byte-identical to
`LIST_VIEW_OBJECT_OUTSIDE_CLOSURE_EXPLANATION` in
`packages/lint/src/rule-explanations.ts`, and it is true there: it names
the two list-view verdicts, which the CLI does not run.
- **The card's wording, measured.** The card's Expected says the build
refuses a cross-package lookup / `record_change` trigger target. The
lookup is refused (`error`); the trigger object only warns at build,
because no closure is stated there. The text says what the tree does.
## Verification
<details><summary>dispatch-gates --commands at d1c404f: 21 families,
all exit 0</summary>
- `node scripts/check-adr-links.mjs` → exit 0
- `node scripts/check-adr-links.mjs --self-test` → exit 0
- `node scripts/check-closing-keyword-parity.mjs` → exit 0
- `node scripts/check-closing-keyword-parity.mjs --self-test` → exit 0
- `node scripts/check-comment-mask-corpus.mjs` → exit 0
- `node scripts/ci/plan-test-core-shards.mjs --self-test` → exit 0
- `pnpm --filter @objectstack/lint run check:doc-formula-expressions` →
exit 0
- `pnpm check:adr-anchors` → exit 0
- `pnpm check:adr-index` → exit 0
- `pnpm check:adr-symbol-anchors` → exit 0
- `pnpm check:ci-filter-parity` → exit 0
- `pnpm check:closed-ceremony-text` → exit 0
- `pnpm check:cross-package-test-inputs` → exit 0
- `pnpm check:doc-authoring` → exit 0
- `pnpm check:driver-memory-census` → exit 0
- `pnpm check:gitlink-declared` → exit 0
- `pnpm check:nul-bytes` → exit 0
- `pnpm check:pm-governed-merges` → exit 0
- `pnpm check:pm-prior-rulings` → exit 0
- `pnpm check:refd-timer-probe` → exit 0
- `pnpm check:watch-hint-literal` → exit 0
The first run of `check:doc-formula-expressions` exited 3 (PREREQUISITE
NOT MET: `@objectstack/formula` and `@objectstack/lint` not built); it
was re-run after the build and exited 0.
```
✓ dispatch-gates --ran: 21 derived famil(ies) accounted for — 21 run, 0 NOT-MEASURED (a DERIVED zero — all 21 recorded an exit code and none of them is 3).
✓ check:commit-card-trailers: 1 commit message(s) on origin/main..HEAD carry no card relation and no model identifier in the trailer pair.
```
</details>
Every other family CI runs on this PR is read from its check-runs, not
re-run here.
---
_Generated by [Claude
Code](https://claude.ai/code/session_016WV4cyxnej16LG3YiCoKe6)_
---------
Co-authored-by: Claude <noreply@anthropic.com>1 parent 6226e7c commit 7b8bcfe
1 file changed
Lines changed: 25 additions & 14 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
65 | 65 | | |
66 | 66 | | |
67 | 67 | | |
68 | | - | |
| 68 | + | |
| 69 | + | |
69 | 70 | | |
70 | 71 | | |
71 | 72 | | |
| |||
77 | 78 | | |
78 | 79 | | |
79 | 80 | | |
80 | | - | |
| 81 | + | |
| 82 | + | |
| 83 | + | |
81 | 84 | | |
82 | 85 | | |
83 | 86 | | |
| |||
195 | 198 | | |
196 | 199 | | |
197 | 200 | | |
198 | | - | |
| 201 | + | |
199 | 202 | | |
200 | 203 | | |
201 | | - | |
202 | | - | |
203 | | - | |
204 | | - | |
| 204 | + | |
| 205 | + | |
| 206 | + | |
| 207 | + | |
| 208 | + | |
| 209 | + | |
| 210 | + | |
205 | 211 | | |
206 | 212 | | |
207 | 213 | | |
| |||
487 | 493 | | |
488 | 494 | | |
489 | 495 | | |
| 496 | + | |
| 497 | + | |
490 | 498 | | |
491 | 499 | | |
492 | 500 | | |
| |||
532 | 540 | | |
533 | 541 | | |
534 | 542 | | |
535 | | - | |
536 | | - | |
537 | | - | |
| 543 | + | |
| 544 | + | |
| 545 | + | |
| 546 | + | |
| 547 | + | |
538 | 548 | | |
539 | 549 | | |
540 | 550 | | |
| |||
561 | 571 | | |
562 | 572 | | |
563 | 573 | | |
564 | | - | |
| 574 | + | |
565 | 575 | | |
566 | 576 | | |
567 | 577 | | |
| |||
727 | 737 | | |
728 | 738 | | |
729 | 739 | | |
730 | | - | |
731 | | - | |
| 740 | + | |
| 741 | + | |
732 | 742 | | |
733 | 743 | | |
734 | | - | |
| 744 | + | |
| 745 | + | |
735 | 746 | | |
736 | 747 | | |
737 | 748 | | |
| |||
0 commit comments