Unblocked 2026-09-02 (R+105). PR #14665 has landed: packages/objectql/src/engine.ts:192 now reads import { deriveViewContainerObject } from '@objectstack/metadata'; at origin/main75adf11. The site the card describes exists, and this is actionable now. (The earlier Blocked-by: #14399 is discharged and removed.)
Raised by the isolated contract reviewer on PR #14665 (card #14399) as an advisory finding. ⛔ It did not downgrade that PR's PASS and was deliberately not fixed there: the import direction was ruled by triage, and root-vs-subpath was left open, so this is the open half rather than a defect in the landed change.
The site — re-measured at origin/main75adf11
packages/objectql/src/engine.ts:192 imports deriveViewContainerObject from the root entry of @objectstack/metadata. core.ts — the ADR-0076 lean entry — re-exports engine.ts, so that closure inherits the import.
Before PR #14665, objectql's non-test sources had no edge into @objectstack/metadata's root at all: the only edge was @objectstack/metadata/errors, about 3.6 KB. After it, the lean closure loads dist/index.js at module-init, which pulls MetadataPlugin → NodeMetadataManager → chokidar, plus glob and js-yaml — roughly 450 KB — to reach a six-line pure function.
⭐ The same file already carries a written rule against this exact root entry
Added by triage. ~80 lines above the new import:
// [#5979] The ONE shared "which read failure is benign?" predicate (#4825
// family). Imported from the leaf `/errors` subpath — which exists precisely
// so a cross-package consumer gets the 40-line predicate without the manager,
// the loaders or the YAML/filesystem machinery behind `@objectstack/metadata`'s
// root entry.
import { isMissingTableError } from '@objectstack/metadata/errors';
This package has met the problem before, decided the answer, had the leaf subpath created for it, and recorded why. That makes shape 1 below the established pattern rather than one of two open options.
Why this is a finding and not a bug
Nothing enforced is crossed, and the reviewer checked each one rather than asserting it:
So this is a footprint cost, not a correctness or layering violation. It is worth recording because the cost is invisible: no gate measures the weight of the lean entry's closure, and the PR body's own "Confinement" section does not mention the delta.
Two shapes worth considering — ⛔ neither prescribed
- A lean subpath on
@objectstack/metadata (e.g. @objectstack/metadata/view-container) exporting just this helper. Still minor, still one import, and it keeps the root entry out of the lean closure. This is the /errors precedent, in this same file. - Move the helper down to
@objectstack/spec, beside expandViewContainer and isAggregatedViewContainer, which are the two functions it is conceptually paired with and which objectql already depends on. ⚠️ That is the spec lane's call, not this one — packages/spec belongs to the domain:spec seat. If this route is taken it must be filed there, ⛔ never fixed from this lane.
⛔ The closure figure above is the reviewer's reading, not a built-artifact measurement. Re-measure it before choosing between the shapes.
Re-check
git grep -n "@objectstack/metadata" origin/main -- packages/objectql/src/engine.ts
git show origin/main:packages/metadata/package.json | sed -n '/"exports"/,/^ }/p'
Dedup
Distinguished from #14666 (the boot-loop vs artifact-door data.name reconciliation asymmetry) and from #14678 (residual bare 'global' literals in action-execution.ts). Different subject, different files.
Unassigned, recording only.
Unblocked 2026-09-02 (R+105). PR #14665 has landed:
packages/objectql/src/engine.ts:192now readsimport { deriveViewContainerObject } from '@objectstack/metadata';atorigin/main75adf11. The site the card describes exists, and this is actionable now. (The earlierBlocked-by: #14399is discharged and removed.)Raised by the isolated contract reviewer on PR #14665 (card #14399) as an advisory finding. ⛔ It did not downgrade that PR's PASS and was deliberately not fixed there: the import direction was ruled by triage, and root-vs-subpath was left open, so this is the open half rather than a defect in the landed change.
The site — re-measured at
origin/main75adf11packages/objectql/src/engine.ts:192importsderiveViewContainerObjectfrom the root entry of@objectstack/metadata.core.ts— the ADR-0076 lean entry — re-exportsengine.ts, so that closure inherits the import.Before PR #14665, objectql's non-test sources had no edge into
@objectstack/metadata's root at all: the only edge was@objectstack/metadata/errors, about 3.6 KB. After it, the lean closure loadsdist/index.jsat module-init, which pullsMetadataPlugin→NodeMetadataManager→chokidar, plusglobandjs-yaml— roughly 450 KB — to reach a six-line pure function.⭐ The same file already carries a written rule against this exact root entry
Added by triage. ~80 lines above the new import:
This package has met the problem before, decided the answer, had the leaf subpath created for it, and recorded why. That makes shape 1 below the established pattern rather than one of two open options.
Why this is a
findingand not a bugNothing enforced is crossed, and the reviewer checked each one rather than asserting it:
core-boundary.ratchet.test.ts:59) forbids only@objectstack/metadata-protocol, and metadata's closure has no runtime import of it;engine.tsis already node-only (it importsnode:async_hooks), so no portability class changes;namesits in the object-derivation chain #14399 — re-spelling is what that card existed to remove.So this is a footprint cost, not a correctness or layering violation. It is worth recording because the cost is invisible: no gate measures the weight of the lean entry's closure, and the PR body's own "Confinement" section does not mention the delta.
Two shapes worth considering — ⛔ neither prescribed
@objectstack/metadata(e.g.@objectstack/metadata/view-container) exporting just this helper. Stillminor, still one import, and it keeps the root entry out of the lean closure. This is the/errorsprecedent, in this same file.@objectstack/spec, besideexpandViewContainerandisAggregatedViewContainer, which are the two functions it is conceptually paired with and which objectql already depends on.packages/specbelongs to thedomain:specseat. If this route is taken it must be filed there, ⛔ never fixed from this lane.⛔ The closure figure above is the reviewer's reading, not a built-artifact measurement. Re-measure it before choosing between the shapes.
Re-check
Dedup
Distinguished from #14666 (the boot-loop vs artifact-door
data.namereconciliation asymmetry) and from #14678 (residual bare'global'literals inaction-execution.ts). Different subject, different files.Unassigned, recording only.