Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
94 commits
Select commit Hold shift + click to select a range
8de88ee
feat(objectql, plugin-email): email template names held per namespace…
claude Nov 10, 2026
cef0ef9
test(objectql, plugin-email): pin the email template narrowing, the p…
claude Nov 10, 2026
c88476f
test(dogfood): the flow-family boot pins read the email template's na…
claude Nov 10, 2026
4312637
fix(metadata-protocol): the exact qualifier reads a bundle addition a…
claude Nov 10, 2026
8bbcc56
test(core, cli): the resolver and the stored-references report read t…
claude Nov 10, 2026
e37cebe
docs(changeset): a code package's bundle addition is still judged aga…
claude Nov 10, 2026
f1189c7
test(plugin-email): the platform-requested list pin loads core at mod…
claude Nov 10, 2026
3ccfb7a
Merge remote-tracking branch 'origin/main' into claude/project-thread…
claude Nov 10, 2026
3465aaa
fix(metadata-protocol): the exact qualifier keeps a pair's item on it…
claude Nov 10, 2026
a52f89e
docs(changeset): the email template change declares the ?package= nar…
claude Nov 10, 2026
a4326c9
Merge remote-tracking branch 'origin/main' into claude/project-thread…
claude Nov 10, 2026
50e1ef9
fix(plugin-email, service-automation, service-messaging): an email te…
claude Nov 10, 2026
a4ca293
fix(metadata-protocol, cli): a pair member row two holders could own …
claude Nov 10, 2026
1484ab5
test(plugin-email): read the last protocol request without Array.prot…
claude Nov 10, 2026
1fabc5d
feat(metadata): the in-memory store keeps one slot per (package, name…
claude Nov 10, 2026
f6bbafc
Merge remote-tracking branch 'origin/main' into claude/project-thread…
claude Nov 10, 2026
4c176c5
Merge remote-tracking branch 'origin/main' into claude/project-thread…
claude Nov 10, 2026
249a6a4
fix(metadata-protocol, cli)!: a package-less row of a name two packag…
claude Nov 10, 2026
9102aca
Merge remote-tracking branch 'origin/main' into claude/project-thread…
claude Nov 10, 2026
14bbef3
fix(service-automation, metadata-protocol, objectql, cli): contract r…
claude Nov 10, 2026
376b80e
Merge remote-tracking branch 'origin/main' into claude/project-thread…
claude Nov 10, 2026
9ea252e
Merge remote-tracking branch 'origin/main' into claude/project-thread…
claude Nov 10, 2026
c79a4e6
test(metadata-protocol, rest, runtime): the getItem-reading doubles r…
claude Nov 10, 2026
c5d0e37
Merge remote-tracking branch 'origin/main' into claude/project-thread…
claude Nov 10, 2026
d808486
fix(cli): the stored-references hint names no tracker id in its print…
claude Nov 11, 2026
ee4bcab
Merge remote-tracking branch 'origin/main' into claude/project-thread…
claude Nov 11, 2026
7136e33
fix(metadata-protocol): a row hydrated into the registry with no pack…
claude Nov 11, 2026
4668d9e
Merge origin/main into claude/project-thread-3giljf
claude Nov 11, 2026
460df4a
test(objectql): the package-less row is written as the store writes i…
claude Nov 11, 2026
248d471
fix(metadata): a bundled type's unscoped loader reads keep every memb…
claude Nov 11, 2026
26e2548
Merge origin/main into claude/project-thread-3giljf
claude Nov 11, 2026
61dfabf
docs(changeset): declare the loader half — rollback and delete by nam…
claude Nov 11, 2026
f9f589d
fix(metadata): MetadataManager's plural reads keep a bundled type's m…
claude Nov 11, 2026
f779531
fix(metadata): a bundled type's save writes its own member's row, and…
claude Nov 11, 2026
12ee9e5
docs(changeset): the manager's plural reads per member, and the membe…
claude Nov 11, 2026
cfb8f30
Merge origin/main into claude/project-thread-3giljf
claude Nov 11, 2026
0f93f8f
fix(metadata): the boot priming pass never writes an item back into t…
claude Nov 11, 2026
74a7e4c
Merge origin/main into claude/project-thread-3giljf
claude Nov 11, 2026
e8c7447
docs(metadata): MetadataUnregisterOptions keeps its own doc comment (…
claude Nov 11, 2026
fefaa51
test(metadata): the R5-A control seeds the database loader from a rea…
claude Nov 11, 2026
2990c4c
docs(metadata): the boot write-back note is its own changeset line; o…
claude Nov 11, 2026
74d2e76
Merge origin/main into claude/project-thread-3giljf
claude Nov 11, 2026
7594637
test(metadata): database-loader.test.ts pays the metadata-fs load at …
claude Nov 11, 2026
6ed3bea
docs(metadata): keep database-loader.ts out of round 7's diff
claude Nov 11, 2026
17cfbf8
fix(metadata): the boot pass binds a legacy row's empty package colum…
claude Nov 11, 2026
e2ab2d3
wip(automation): flow names per namespace — slot-served /automation a…
claude Nov 12, 2026
cea1e0f
wip(test): teach the doubles and the family pins that a flow reads by…
claude Nov 12, 2026
58586bf
wip(runtime): read the registry only for a packaged flow caller, fail…
claude Nov 12, 2026
e4725f6
wip(dogfood): pin the package-less save of a shared flow name as the …
claude Nov 12, 2026
b32464f
wip: changeset for flow names per namespace; pin the co-owner refusal…
claude Nov 12, 2026
0e5eb45
Merge remote-tracking branch 'origin/main' into claude/project-thread…
claude Nov 12, 2026
290d918
test: the core narrowed-set pin reads the flow as narrowed; pay the m…
claude Nov 12, 2026
27abd45
Merge branch 'main' into claude/project-thread-3giljf
objectstack-fleet[bot] Nov 12, 2026
0ecd1ff
Merge remote-tracking branch 'origin/claude/project-thread-3giljf' in…
claude Nov 12, 2026
14132f0
wip(objectql): a pair row binds to the holder the exact read's owner …
claude Nov 12, 2026
97eff78
wip(objectql): pins for the pair row's binding on every overlay-slot …
claude Nov 12, 2026
4fc0ba8
wip(objectql): narrowing pin, declared non-holder pin and changeset (…
claude Nov 12, 2026
2dbc914
test: the published-door double reads the flow by package; the instal…
claude Nov 12, 2026
ee13867
wip(changeset): no FROM-TO heading in a no-migration changeset (#32408)
claude Nov 12, 2026
49dd454
wip(objectql): CONTROL pin, two independent holders still refuse the …
claude Nov 12, 2026
c768862
Merge remote-tracking branch 'origin/main' into claude/project-thread…
claude Nov 12, 2026
f845bef
Merge remote-tracking branch 'origin/main' into claude/project-thread…
claude Nov 12, 2026
ed0f2ba
Merge remote-tracking branch 'origin/main' into claude/project-thread…
claude Nov 12, 2026
d9d3621
fix(objectql): a pair row's owners are counted as the exact read coun…
claude Nov 12, 2026
a187fb1
fix(runtime): a flow name two namespaces hold is resolved per package…
claude Nov 12, 2026
a8b63c2
fix(objectql): a pair row's owners are counted over every holder with…
claude Nov 12, 2026
7b74268
fix(objectql): an undeclared row of another App's pair counts where i…
claude Nov 12, 2026
075fb31
fix(objectql): a pair row whose count would read another App's undecl…
claude Nov 12, 2026
2c65035
test(runtime): pay the metadata load at collection in the list_action…
claude Nov 12, 2026
731ac15
fix(service-automation,runtime): a run's records follow its slot key …
claude Nov 12, 2026
1e89878
Merge remote-tracking branch 'origin/main' into claude/project-thread…
claude Nov 12, 2026
6bc8374
fix(service-automation): the boot binds every run row that names no p…
claude Nov 12, 2026
097cb8f
fix(plugin-approvals): an approval request reads its flow from its ow…
claude Nov 12, 2026
616ebb1
fix(metadata-protocol): a pair's row of a name two namespaces hold is…
claude Nov 12, 2026
590e2c3
Merge branch 'claude/project-thread-wqgmuu' of https://github.com/obj…
claude Nov 12, 2026
9af5916
test(objectql): pin the list after a second holder's override is remo…
claude Nov 12, 2026
73391d5
Merge remote-tracking branch 'origin/main' into claude/project-thread…
claude Nov 12, 2026
7bea2a2
Merge remote-tracking branch 'origin/main' into claude/project-thread…
claude Nov 12, 2026
6d317e6
docs(spec, changeset): register the pair-row locale narrowing as an A…
claude Nov 12, 2026
4fd9eeb
test(objectql): a pair row's binding over every holder meets the serv…
claude Nov 12, 2026
47c03c3
docs(objectql, changeset): the pair-row binding counts every holder, …
claude Nov 12, 2026
e94a8de
docs(changeset): the Clause-② line names the reads a disabled holder'…
claude Nov 12, 2026
669d498
docs(spec): the pair-row upgrade entry names only the remedies the sa…
claude Nov 12, 2026
4776430
fix(objectql): a door reads a holder's bundle members as if the arriv…
claude Nov 12, 2026
7509d92
test(objectql): pin a pair row's locale at both doors and at the cold…
claude Nov 12, 2026
bc22c1a
test(objectql): name the undeclared-row door pins for what they hold:…
claude Nov 12, 2026
c3cc324
docs(changeset): declare the pair row's mirror admission at the gate …
claude Nov 12, 2026
bd04e20
Merge remote-tracking branch 'origin/main' into claude/project-thread…
claude Nov 12, 2026
0ad8d15
Merge branch 'claude/project-thread-iv3vz6' (PR #32815 head c3cc324b1…
claude Nov 12, 2026
f841777
test(objectql): pin each holder's pair removal, revert and census wit…
claude Nov 12, 2026
d4d3241
docs(changeset): the three moved answers hold with one of the two hol…
claude Nov 12, 2026
c35a911
Merge remote-tracking branch 'origin/main' into claude/project-thread…
claude Nov 13, 2026
ae11537
Merge remote-tracking branch 'origin/main' into claude/project-thread…
claude Nov 13, 2026
d311b66
fix(metadata-protocol): the boot census judges a second holder's over…
claude Nov 13, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 24 additions & 0 deletions .changeset/32552-pair-row-removal-every-shipper.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
---
'@objectstack/metadata-protocol': patch
---

fix(metadata-protocol): a customization pair's row of a name two namespaces hold is judged against its own base, whichever package registered first — its removal, its commit revert and the boot census (ADR-0150 D4)

Clause-②: yes (widening) — answers that refused or misreported the second-registered holder's declared override now admit or leave it, as they already did for the first. For a name two packages of two namespaces ship, each with its paired `.custom` holding a declared override (ADR-0146 D2), three answers depended on which package registered first, because each judged the pair's row against the one package the bare-name artifact lookup answers. Each is now judged against every package that ships the name. First-party callers in any of these positions: 0.
Metadata-protocol: none

Every row below is the `widening` arm, is pinned in both registration orders in `@objectstack/objectql`'s `protocol-flow-custom-override.test.ts`, and keeps its one-holder answer (the one-holder CONTROL there):

| Door | Second-registered holder B, before | Now | One holder (CONTROL) |
|:--|:--|:--|:--|
| `DELETE /meta/TYPE/NAME?package=<B>.custom` (`deleteMetaItem`); pinned for a flow, and for an action in the list probe below | `403 NOT_OVERRIDABLE` "sealed against removal"; B's override stays | `200`: B's override row removed (runtime-only), A's untouched; afterwards every listed and execution-view entry of the name is its own package's | unchanged: `200`, removed |
| `revertCommit` of a commit into `<B>.custom` (the restore limb; the per-item rollback shares the derivation); pinned for a flow | the item in `failed[]`, `NOT_OVERRIDABLE` "sealed against in-place edits"; nothing restored | restored, judged by the override write gate as the pair's declared override | unchanged: restored |
| boot census `[metadata_sealed_overlay_unserved]` (`loadMetaFromDb`), a flow or an action only | named B's live declared override as an unserved row to delete | not named | unchanged: the override not named |

With one of the two holders disabled (ADR-0150 D3), the bare-name answer is still the first-registered holder, disabled or not, so the same three answers moved the same way whichever holder is disabled: each holder's pair removal and commit revert are admitted now, the disabled holder's pair included, and the census names neither override. A binding never moves with a reversible disable. Pinned in both registration orders with each holder disabled in turn, beside a one-holder disabled CONTROL (its removal and revert admitted, as before).

Unchanged in both: a row of a package that is no shipper's pair keeps its removal `403` and is still named by the census.

The census judges a row as the reads serve it (`declinesStoredRow`). The reads serve a second holder's declared override per shipper for a flow and an action only (#32613), so only those two types move here. A page, app, dataset, doc, book or mapping keeps the name's first-registered shipper in the census, as in the reads, until #33131 moves them: the second holder's override of such a name is still named, pinned for a mapping in both registration orders.

No shipper is picked: the row judged is always the one its own `package_id` names, and the judgement asks only whether that package is a pair of SOME package that ships the name. A name one package ships answers exactly as before (the bare-name answer is read first and alone while it holds).
11 changes: 8 additions & 3 deletions packages/metadata-protocol/src/protocol-class-head.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ import { PLURAL_TO_SINGULAR } from '@objectstack/spec/shared';
import type { IObjectQLEngine, IPubSub } from '@objectstack/spec/contracts';
import { isPairOf } from '@objectstack/metadata-core';
import { installedManifestsOfEngine } from './installed-manifests.js';
import { someShipperOf } from './protocol-environment-rows.js';
import { overrideWriteRefusalError } from './protocol-packaged-base-refusal.js';
import { OBJECT_EXTENSION_TYPE, registrableObjectExtension } from './protocol-object-extension-item.js';
import type { ObjectExtensionRegistry } from './protocol-object-extension-item.js';
Expand Down Expand Up @@ -201,13 +202,17 @@ export class ProtocolClassHeadFacet {
* caller's `artifactBacked` decides the intent, and the body writer is
* {@link restoredBodyWriter}'s alone.
*/
static restoreWriteFor(host: Pick<ProtocolHost, 'engine' | 'overrideWriteVerdict' | 'packagedArtifactOwner' | 'restoredBodyWriter'>, singularType: string,
static restoreWriteFor(host: Pick<ProtocolHost, 'engine' | 'overrideWriteVerdict' | 'packagedArtifactOwner' | 'restoredBodyWriter' | 'shippedArtifactsOf'>, singularType: string,
name: string,
binding: string | null,
artifactBacked: boolean,
source: string,): { intent: 'override-artifact' | 'runtime-only'; deriveRestoredBody: (historyBody: unknown) => Promise<unknown> } {
const owner = artifactBacked ? host.packagedArtifactOwner({ type: singularType, name }) : undefined;
const pairRow = owner !== undefined && isPairOf(binding, owner, installedManifestsOfEngine(host.engine));
// [ADR-0150 D4, #32552] The binding is judged against every package
// that ships the name ({@link someShipperOf}): each namespace's holder
// has its own pair, never only the shipper registered first.
const installed = installedManifestsOfEngine(host.engine);
const pairRow = artifactBacked && someShipperOf(host, singularType, name,
(owner) => owner !== undefined && isPairOf(binding, owner, installed));
const intent: 'override-artifact' | 'runtime-only' = artifactBacked && !pairRow ? 'override-artifact' : 'runtime-only';
const writeRestored = host.restoredBodyWriter(singularType, name, binding, source);
const deriveRestoredBody = pairRow
Expand Down
42 changes: 29 additions & 13 deletions packages/metadata-protocol/src/protocol-diff-delete-load.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,12 +39,13 @@ import { isMissingTableError } from '@objectstack/metadata/errors';
import { PLURAL_TO_SINGULAR } from '@objectstack/spec/shared';
import { isServedOverrideRowOf } from './served-override.js';
import { installedManifestsOfEngine } from './installed-manifests.js';
import { someShipperOf } from './protocol-environment-rows.js';
import type { ServedOverrideRow } from './served-override.js';
import { REFERENCE_SITES } from './reference-sites.js';
import { computeMetadataDiagnostics } from './metadata-diagnostics.js';
import { hasMetadataRedactor, redactMetadataItem } from './metadata-redaction.js';
import { isPairRowRemoval } from './protocol-packaged-base-refusal.js';
import { canonicalizeMetaRequestType } from './protocol-meta-type-schema.js';
import { canonicalMetaType, canonicalizeMetaRequestType } from './protocol-meta-type-schema.js';
import { boundPackageOf } from './protocol-package-bindings.js';
import { remainingRowsPhrase } from './protocol-authoring-refusals.js';
import { memberOption, mutationEventMember, resolveBundleMemberSelector } from './protocol-bundle-members.js';
Expand Down Expand Up @@ -391,7 +392,7 @@ export class ProtocolDiffDeleteLoadFacet {
}

/** [#28355] The body of {@link deleteMetaItem} before its refusal audit; that method's docblock is the contract. */
static async deleteMetaItemUnaudited(host: Pick<ProtocolHost, 'assertLockAllowsDelete' | 'dropObjectStorage' | 'dropStorageRemainingRowsRefusal' | 'emitMetadataMutation' | 'engine' | 'environmentId' | 'findEnvironmentRow' | 'getOverlayRepo' | 'isArtifactBacked' | 'isOverlayAllowed' | 'isRuntimeCreateAllowed' | 'metadataConflictRefusal' | 'originGatedRemovalRefusal' | 'packagedArtifactOwner' | 'packagedBaseRefusal' | 'packagelessAddress' | 'packagelessDraftAddress' | 'packagelessOverlayWriteRefusal' | 'recordMetadataAudit' | 'recordOptimisticConflictAudit' | 'refuseOrganizationScopedWrite' | 'refusePackagedBaseRemoval' | 'registryAllowsOverlay' | 'restoreArtifactRegistryView' | 'runMutationProjector' | 'shouldDropStorage' | 'storedParentForToken'>, request: DeleteMetaItemRequest): Promise<{
static async deleteMetaItemUnaudited(host: Pick<ProtocolHost, 'assertLockAllowsDelete' | 'dropObjectStorage' | 'dropStorageRemainingRowsRefusal' | 'emitMetadataMutation' | 'engine' | 'environmentId' | 'findEnvironmentRow' | 'getOverlayRepo' | 'isArtifactBacked' | 'isOverlayAllowed' | 'isRuntimeCreateAllowed' | 'metadataConflictRefusal' | 'originGatedRemovalRefusal' | 'packagedArtifactOwner' | 'packagedBaseRefusal' | 'packagelessAddress' | 'packagelessDraftAddress' | 'packagelessOverlayWriteRefusal' | 'recordMetadataAudit' | 'recordOptimisticConflictAudit' | 'refuseOrganizationScopedWrite' | 'refusePackagedBaseRemoval' | 'registryAllowsOverlay' | 'restoreArtifactRegistryView' | 'runMutationProjector' | 'shippedArtifactsOf' | 'shouldDropStorage' | 'storedParentForToken'>, request: DeleteMetaItemRequest): Promise<{
success: boolean;
message?: string;
reset?: boolean;
Expand Down Expand Up @@ -427,10 +428,13 @@ export class ProtocolDiffDeleteLoadFacet {
// flow's armed) again. Admitted past the sealed-removal refusal and
// told to the store as a runtime-only removal, as the declared save
// is ({@link isPairRowRemoval}).
const pairRowRemoval = isPairRowRemoval(
request.type, host.packagedArtifactOwner({ type: request.type, name: request.name }), request.packageId,
installedManifestsOfEngine(host.engine),
);
// [ADR-0150 D4, #32552] Judged against every package that ships the
// name ({@link someShipperOf}): two namespaces' items of one name each
// carry their own pair, so the pair named here is judged against its
// own base, never against whichever shipper registered first.
const installed = installedManifestsOfEngine(host.engine);
const pairRowRemoval = someShipperOf(host, request.type, request.name,
(base) => isPairRowRemoval(request.type, base, request.packageId, installed));
// Two-tier authorization for delete (mirrors saveMetaItem).
// • Artifact-backed item → delete becomes a tombstone overlay,
// requires `allowEnvironmentOverlay`…
Expand Down Expand Up @@ -1105,7 +1109,7 @@ export class ProtocolDiffDeleteLoadFacet {
}

/** The body of `ObjectStackProtocolImplementation#loadMetaFromDb`; the method's docblock there is its contract. */
static async loadMetaFromDb(host: Pick<ProtocolHost, 'classifyObjectContribution' | 'convertStoredItem' | 'engine' | 'ensureOverlayMembersBackfilled' | 'findEnvironmentRows' | 'hydrateOverlayIntoRegistry' | 'isHostCodeDatasource' | 'isUnservedSealedOverlay' | 'overlayPackageMismatchError' | 'packagedArtifactOwner' | 'packagelessAddress' | 'reportPageRequiresAbsentAtLoad' | 'reportSealedOverlayRows' | 'resolveSduiManifest' | 'storeHydratedIntoRegistry'>): Promise<{ loaded: number; errors: number; invalid: number; storeUnavailable: boolean }> {
static async loadMetaFromDb(host: Pick<ProtocolHost, 'classifyObjectContribution' | 'convertStoredItem' | 'engine' | 'ensureOverlayMembersBackfilled' | 'findEnvironmentRows' | 'hydrateOverlayIntoRegistry' | 'isHostCodeDatasource' | 'isUnservedSealedOverlay' | 'overlayPackageMismatchError' | 'packagedArtifactOwner' | 'packagelessAddress' | 'reportPageRequiresAbsentAtLoad' | 'reportSealedOverlayRows' | 'resolveSduiManifest' | 'shippedArtifactsOf' | 'storeHydratedIntoRegistry'>): Promise<{ loaded: number; errors: number; invalid: number; storeUnavailable: boolean }> {
let loaded = 0;
let errors = 0;
let invalid = 0;
Expand Down Expand Up @@ -1173,13 +1177,25 @@ export class ProtocolDiffDeleteLoadFacet {
// would prescribe deleting the live customization. The
// one predicate, on the row's `package_id` column. The
// census only: what this loop loads is unchanged.
//
// [ADR-0150 D4, #32552] …judged as the reads judge it
// (`declinesStoredRow`): for a flow and an action
// against every package that ships the name
// ({@link someShipperOf}), so a second holder's
// served override is not named for deletion; for the
// six sealed types against the name's first-registered
// shipper alone, which is the only override the reads
// serve for them until #33131 moves them.
const servedOverrideOf = (base: string | undefined) => isServedOverrideRowOf(
record as ServedOverrideRow, base, installedManifestsOfEngine(host.engine),
);
const recordName = String(record.name);
const perShipperType = ['flow', 'action'].includes(canonicalMetaType(normalizedType));
if (
!host.isHostCodeDatasource(normalizedType, String(record.name))
&& !isServedOverrideRowOf(
record as ServedOverrideRow,
host.packagedArtifactOwner({ type: normalizedType, name: String(record.name) }),
installedManifestsOfEngine(host.engine),
)
!host.isHostCodeDatasource(normalizedType, recordName)
&& !(perShipperType
? someShipperOf(host, normalizedType, recordName, servedOverrideOf)
: servedOverrideOf(host.packagedArtifactOwner({ type: normalizedType, name: recordName })))
) {
sealedOverlays.push({ type: normalizedType, name: String(record.name) });
}
Expand Down
27 changes: 27 additions & 0 deletions packages/metadata-protocol/src/protocol-environment-rows.ts
Original file line number Diff line number Diff line change
Expand Up @@ -264,6 +264,33 @@ export function shippingPackageIds(shipped: readonly unknown[]): ReadonlySet<str
return shippers;
}

/**
* [ADR-0150 D4, #32552] Whether `judge` holds for SOME code package that ships
* `(type, name)`: the package the bare-name artifact lookup answers first (the
* one-holder answer, read alone while it holds), then every shipper
* ({@link shippingPackageIds} over `shippedArtifactsOf`).
*
* The question a pair's row asks of its base — is this row a declared
* override of the item, may this removal or restore treat it as one — when two
* namespaces' packages each ship the name (ADR-0150 D9): each holder has its
* own pair, so a row is judged against its own base, never against whichever
* shipper registered first. No shipper is picked: the row judged is the one
* its own `package_id` names. A name one package ships answers exactly as the
* bare lookup alone did.
*/
export function someShipperOf(
host: {
packagedArtifactOwner(request: { type: string; name: string }): string | undefined;
shippedArtifactsOf(type: string, name: string): unknown[];
},
type: string,
name: string,
judge: (basePackageId: string | undefined) => boolean,
): boolean {
if (judge(host.packagedArtifactOwner({ type, name }))) return true;
return [...shippingPackageIds(host.shippedArtifactsOf(type, name))].some((shipper) => judge(shipper));
}

/**
* [ADR-0146 D11] The READ-ONLY code packages that ship a name, sorted: the
* {@link shippingPackageIds} of `shipped` less every package
Expand Down
Loading
Loading