Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
8 changes: 4 additions & 4 deletions packages/spec/src/assembled-package-body.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,7 @@ const ordersStack = () => defineStack({ manifest: ordersManifest, objects: [orde

// ─── 1. The key set is derived ──────────────────────────────────────

describe('#14242 B — the assembled body carries the stack schema\'s collections, derived', () => {
describe('the assembled body, declared apart from the authoring manifest, carries the stack schema\'s collections, derived', () => {
it('lacks exactly the artifact-envelope keys, and nothing else', () => {
const stackKeys = shapeKeys(ObjectStackDefinitionSchema);
const bodyKeys = shapeKeys(AssembledPackageBodySchema);
Expand Down Expand Up @@ -156,7 +156,7 @@ describe('#14242 B — the assembled body carries the stack schema\'s collection

// ─── 2. Each stage refuses the other's spelling ─────────────────────

describe('#14242 B — two stages, two declarations, neither tolerant of the other', () => {
describe('two stages, two declarations, neither tolerant of the other', () => {
const assembledBody = { ...coreManifest, objects: [accountObject] };
const globBody = { ...coreManifest, objects: ['./src/objects/*.object.ts'] };

Expand All @@ -165,7 +165,7 @@ describe('#14242 B — two stages, two declarations, neither tolerant of the oth
expect(verdict.success).toBe(true);
});

it('the AUTHORING entry still refuses that same body — the mismatch #14242 measured', () => {
it('the AUTHORING entry still refuses that same body — the mismatch that is the reason two declarations exist', () => {
// Kept as a live measurement rather than prose: it is the reason two
// declarations exist, and a widened authoring schema (road C) would turn
// this green without anyone noticing the stages had merged.
Expand Down Expand Up @@ -281,7 +281,7 @@ describe("ADR-0130 D4 — `manifest: 'preserve'` assembles each input stack", ()

// ─── 4. `plugins` / `devPlugins` are envelope keys (#15219) ──────────

describe('#15219 A — `plugins` / `devPlugins` are envelope keys: top level only, never inside `packages[]`', () => {
describe('`plugins` / `devPlugins` are envelope keys: top level only, never inside `packages[]`', () => {
/** What a host hands to `kernel.use()` — a live instance, not metadata. */
const livePlugin = { name: 'plugin.example', init: () => undefined };

Expand Down
10 changes: 5 additions & 5 deletions packages/spec/src/compose-key-dispositions-export.pin.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ afterEach(() => {

// ─── 1. Key-set parity with the schema, both directions ─────────────

describe('#14877 pin 1 — the exported key set equals the schema\'s declared top-level key set', () => {
describe('compose-key dispositions export, pin 1 — the exported key set equals the schema\'s declared top-level key set', () => {
it('COMPOSE_KEY_DISPOSITIONS names every key the schema declares, and no other', () => {
const schemaKeys = schemaTopLevelKeys();
// Non-vacuity: the schema really is the 40+-key envelope, not an empty shape agreeing with anything.
Expand Down Expand Up @@ -135,7 +135,7 @@ describe('#14877 pin 1 — the exported key set equals the schema\'s declared to

// ─── 2. Frozen ──────────────────────────────────────────────────────

describe('#14877 pin 2 — the view is frozen', () => {
describe('compose-key dispositions export, pin 2 — the view is frozen', () => {
it('COMPOSE_KEY_DISPOSITIONS is frozen and refuses assignment to an existing key', () => {
expect(Object.isFrozen(COMPOSE_KEY_DISPOSITIONS)).toBe(true);
const mutable = COMPOSE_KEY_DISPOSITIONS as unknown as Record<string, string>;
Expand Down Expand Up @@ -163,7 +163,7 @@ describe('#14877 pin 2 — the view is frozen', () => {

// ─── 3. Every value is a declared disposition ───────────────────────

describe('#14877 pin 3 — every value is one of the declared dispositions', () => {
describe('compose-key dispositions export, pin 3 — every value is one of the declared dispositions', () => {
it('no key carries a disposition outside the ComposeDisposition vocabulary', () => {
const vocabulary = new Set(Object.keys(DECLARED_DISPOSITIONS));
for (const [key, disposition] of Object.entries(COMPOSE_KEY_DISPOSITIONS)) {
Expand All @@ -189,7 +189,7 @@ describe('#14877 pin 3 — every value is one of the declared dispositions', ()

// ─── 4. The dispositions are the composer's rules ───────────────────

describe('#14877 pin 4 — each disposition is what composeStacks actually does', () => {
describe('compose-key dispositions export, pin 4 — each disposition is what composeStacks actually does', () => {
it("every 'concat' key concatenates in stack order — the export's concat subset IS the composer's", () => {
const concatKeys = keysWith('concat');
// Non-vacuity: the concat family is the bulk of the table.
Expand Down Expand Up @@ -264,7 +264,7 @@ describe('#14877 pin 4 — each disposition is what composeStacks actually does'

// ─── 5. Derived, and reaching the surface as the same objects ───────

describe('#14877 pin 5 — STACK_DEFINITION_KEYS is derived, and both symbols reach the package surface', () => {
describe('compose-key dispositions export, pin 5 — STACK_DEFINITION_KEYS is derived, and both symbols reach the package surface', () => {
it('STACK_DEFINITION_KEYS is Object.keys of the table — same members, same order, no second literal', () => {
expect([...STACK_DEFINITION_KEYS]).toEqual(Object.keys(COMPOSE_KEY_DISPOSITIONS));
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ const topEntries: Array<{ label: string; value: unknown }> = [
{ label: 'an array', value: [] },
];

describe('#19816 — a non-object top-level `actions` entry is refused with the envelope, not a TypeError', () => {
describe('a non-object top-level `actions` entry is refused with the envelope, not a TypeError', () => {
for (const row of topEntries) {
it(`entry ${row.label} is refused at ['actions', 1]`, () => {
const refused = refusal(() => compose([valid(), withTop([row.value])]));
Expand All @@ -123,7 +123,7 @@ describe('#19816 — a non-object top-level `actions` entry is refused with the
});
});

describe("#19816 — a malformed object's own `actions` is refused with the envelope, not a TypeError", () => {
describe("a malformed object's own `actions` is refused with the envelope, not a TypeError", () => {
const nonArrays: Array<{ label: string; value: unknown }> = [
{ label: 'a number', value: 5 },
{ label: 'a string', value: 'abc' },
Expand Down Expand Up @@ -165,7 +165,7 @@ describe("#19816 — a malformed object's own `actions` is refused with the enve
});
});

describe('#19816 — the controls: well-formed stacks compose, and a real collision is still refused', () => {
describe('the controls: well-formed stacks compose, and a real collision is still refused', () => {
it('a valid pair composes, every action carried', () => {
const composed = compose([valid(), withTop([act('b_home')])]);
expect(composed.actions?.map((a) => a.name)).toEqual(['a_home', 'b_home']);
Expand Down
8 changes: 4 additions & 4 deletions packages/spec/src/compose-stacks-action-echo.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ const boundA = () =>
const boundB = () =>
defineStack({ manifest: mf('com.example.b'), objects: [obj('b_item')], actions: [act('dup_y', { objectName: 'b_item' })] });

describe('composeStacks - a bound standalone action appears once in the composed object (#14847)', () => {
describe('composeStacks - a bound standalone action appears once in the composed object', () => {
it("carries each input's own bound action once under the default strategy, and the standalone once at the top", () => {
const a = boundA();
const b = boundB();
Expand Down Expand Up @@ -137,7 +137,7 @@ describe('composeStacks - a bound standalone action appears once in the composed
expect(keysOf(out).embedded).toEqual({ shared: ['emb3/EMB', 'b3/BOUND', 'b1/BOUND', 'b2/BOUND'] });
});

it("with three stacks under objectConflict: 'merge', the composition is refused at the object merge — each built object carries a different `actions` array (#14848)", () => {
it("with three stacks under objectConflict: 'merge', the composition is refused at the object merge — each built object carries a different `actions` array", () => {
// s1's `shared` carries [emb1, b1/BOUND], s2's [emb2, b2/BOUND]: two
// declarations `'merge'` used to resolve by replacement, dropping `emb1`.
let msg: string | null = null;
Expand Down Expand Up @@ -173,7 +173,7 @@ describe('composeStacks - a bound standalone action appears once in the composed
});

describe('composeStacks - what the identity skip does NOT fold', () => {
it("refuses a hand-written twin — the same action authored standalone AND on its object — through #14686's rule, unchanged", () => {
it("refuses a hand-written twin — the same action authored standalone AND on its object — through defineStack's scope-qualified action-key refusal, unchanged", () => {
const msg = refusal(() =>
defineStack({
manifest: mf('com.example.t'),
Expand Down Expand Up @@ -221,7 +221,7 @@ describe('composeStacks - round trip through defineStack', () => {
expect(keysOf(defineStack(out))).toEqual(keysOf(out));
});

it("with bound actions, is refused exactly as far as a lone built input is — 'declared twice' by #14686's landed pin, never '3 times'", () => {
it("with bound actions, is refused exactly as far as a lone built input is — 'declared twice' by defineStack's scope-qualified action-key refusal, never '3 times'", () => {
const a = boundA();
const LINE =
" ✗ Action key 'a_item:dup_x' is declared twice: stack.actions[0] (objectName 'a_item') and " +
Expand Down
4 changes: 2 additions & 2 deletions packages/spec/src/compose-stacks-action-key-collision.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -219,7 +219,7 @@ describe('composeStacks - object-scoped keys across stacks, judged on what the c
['embedding stack last', () => [boundToSharedB(), embeddedA()], "'com.example.b' (stack #0)", "'com.example.a' (stack #1)"],
['embedding stack first', () => [embeddedA(), boundToSharedB()], "'com.example.a' (stack #0)", "'com.example.b' (stack #1)"],
] as const)(
"under 'merge' the same pair is refused one step earlier, at the object merge: both objects declare a DIFFERENT `actions` (%s) — #14848, not a collision",
"under 'merge' the same pair is refused one step earlier, at the object merge: both objects declare a DIFFERENT `actions` (%s) — the 'merge' collection refusal, not an action-key collision",
(_order, stacks, holder, later) => {
// B's built object carries its bound copy (`dup_m/BOUND`), A's carries
// the embedded declaration (`dup_m/EMB`): two different arrays on one
Expand Down Expand Up @@ -259,7 +259,7 @@ describe('composeStacks - object-scoped keys across stacks, judged on what the c
expect((out.objects ?? []).find((o) => o.name === 'shared')?.actions?.[0]?.label).toBe('Dup E (b)');
});

it("refuses the same pair under 'merge' — two different `actions` arrays on one object are no longer resolved by replacement (#14848; formerly the P3 acceptance pin)", () => {
it("refuses the same pair under 'merge' — two different `actions` arrays on one object are no longer resolved by replacement (formerly the P3 acceptance pin)", () => {
const msg = refusal(() => composeStacks([embedA(), embedB()], { objectConflict: 'merge' }));
expect(msg).toContain(
"composeStacks conflict: object 'shared' is defined in multiple stacks and its 'actions' is declared " +
Expand Down
10 changes: 5 additions & 5 deletions packages/spec/src/compose-stacks-collection-pipe-arm.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -189,7 +189,7 @@ const composedShared = (left: Record<string, unknown>, right: Record<string, unk
const refuse = (key: string, left: unknown, right: unknown) =>
refusal(() => composedShared({ [key]: left }, { [key]: right }));

describe('#19150 — the probe keys are the shapes this pin is about (anti-vacuity)', () => {
describe('the probe keys are the shapes this pin is about (anti-vacuity)', () => {
it('the preprocess probe is a pipe whose IN is a transform and whose OUT is the array', () => {
const def = defOf(defOf(probe(NAMES.preprocess))?.innerType);
expect(def?.type).toBe('pipe');
Expand All @@ -208,7 +208,7 @@ describe('#19150 — the probe keys are the shapes this pin is about (anti-vacui
});
});

describe('#19150 BRIGHT CONTROL — the pre-fix reading of the preprocess probe', () => {
describe('BRIGHT CONTROL — the preprocess probe as read before the `pipe` arm took the authored side', () => {
it('reading IN alone answers "not a collection" — the silent direction', () => {
expect(inOnlyWalk(probe(NAMES.preprocess))).toBe(false);
});
Expand All @@ -230,7 +230,7 @@ describe('#19150 BRIGHT CONTROL — the pre-fix reading of the preprocess probe'
});
});

describe('#19150 MAIN — the preprocess-wrapped collection key is IN the refusal set', () => {
describe('MAIN — the preprocess-wrapped collection key is IN the refusal set', () => {
it('refuses two differing declarations, naming the object, the key and both stacks', () => {
const msg = refuse(NAMES.preprocess, ['a'], ['b']);
expect(msg).toContain(
Expand Down Expand Up @@ -264,7 +264,7 @@ describe('#19150 MAIN — the preprocess-wrapped collection key is IN the refusa
});
});

describe('#19150 DARK CONTROL — keys whose verdict must not move', () => {
describe('DARK CONTROL — keys whose verdict must not move', () => {
it('a genuine `.pipe()` authored as a scalar composes by later-wins, and is NOT refused', () => {
expect(refuse(NAMES.pipeScalar, 'a', 'b')).toBeNull();
expect(composedShared({ [NAMES.pipeScalar]: 'a' }, { [NAMES.pipeScalar]: 'b' })?.[NAMES.pipeScalar]).toBe('b');
Expand All @@ -287,7 +287,7 @@ describe('#19150 DARK CONTROL — keys whose verdict must not move', () => {
});
});

describe("#19150 TODAY-INVARIANCE — the fix moves no key on today's ObjectSchema", () => {
describe("TODAY-INVARIANCE — the fix moves no key on today's ObjectSchema", () => {
const realShape = async (): Promise<Record<string, unknown>> => {
const actual = await vi.importActual<typeof import('./data/object.zod')>('./data/object.zod');
return shapeOf(actual.ObjectSchema);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ afterEach(() => {
vi.restoreAllMocks();
});

describe('#19784 — composeStacks refuses a non-array concatenated collection', () => {
describe('composeStacks refuses a non-array concatenated collection', () => {
it('covers every concat key the composer declares (the table is the census, not a transcription)', () => {
expect(CONCAT_KEYS).toContain('permissions');
expect(CONCAT_KEYS).toContain('data');
Expand Down
4 changes: 2 additions & 2 deletions packages/spec/src/compose-stacks-i18n-merge.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ afterEach(() => {

// ─── Conflicts — the behaviour #5051 changed ────────────────────────

describe('#5051 — conflicting `i18n` declarations are a composition error', () => {
describe('conflicting `i18n` declarations are a composition error', () => {
it('throws instead of letting the later stack win (the issue\'s own repro)', () => {
const a = raw({ manifest: manifestA, i18n: { defaultLocale: 'en' } });
const b = raw({ manifest: manifestB, i18n: { defaultLocale: 'zh-CN' } });
Expand Down Expand Up @@ -172,7 +172,7 @@ describe('#5051 — conflicting `i18n` declarations are a composition error', ()

// ─── Pass-through — CONTROL (green before and after #5051) ──────────

describe('#5051 control — an `i18n` nobody disagrees about still composes', () => {
describe('control — an `i18n` nobody disagrees about still composes', () => {
it('keeps the only declaration, from either position', () => {
const withI18n = { manifest: manifestA, i18n: { defaultLocale: 'en', supportedLocales: ['en'] } };
const without = { manifest: manifestB };
Expand Down
16 changes: 8 additions & 8 deletions packages/spec/src/compose-stacks-key-loss.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ afterEach(() => {

// ─── Rule 1 — same value passes through ─────────────────────────────

describe('#5005 rule 1 — non-array top-level keys survive composition', () => {
describe('composition rule 1 — non-array top-level keys survive composition', () => {
it('keeps `api` when only one stack declares it (the issue\'s own repro)', () => {
const a = raw({ manifest: manifestA, api: { enforceProjectMembership: true } });
const b = raw({ manifest: manifestB });
Expand All @@ -61,7 +61,7 @@ describe('#5005 rule 1 — non-array top-level keys survive composition', () =>
expect(composeStacks([b, a]).api).toEqual({ enforceProjectMembership: true });
});

it('keeps `server` when only one stack declares it (#4910 rate limiting)', () => {
it('keeps `server` (the inbound rate limiting config) when only one stack declares it', () => {
const a = raw({
manifest: manifestA,
server: { security: { rateLimit: { enabled: true, maxRequests: 5 } } },
Expand Down Expand Up @@ -101,7 +101,7 @@ describe('#5005 rule 1 — non-array top-level keys survive composition', () =>

// ─── Rule 2 — conflict is an error with a prescription ──────────────

describe('#5005 rule 2 — conflicting values throw a prescriptive error', () => {
describe('composition rule 2 — conflicting values throw a prescriptive error', () => {
it('throws naming the key, both source stacks and the fix', () => {
const a = raw({ manifest: manifestA, api: { enforceProjectMembership: true } });
const b = raw({ manifest: manifestB, api: { enforceProjectMembership: false } });
Expand Down Expand Up @@ -157,7 +157,7 @@ describe('#5005 rule 2 — conflicting values throw a prescriptive error', () =>

// ─── Rule 3 — unhandled keys warn ───────────────────────────────────

describe('#5005 rule 3 — a key with no declared rule warns', () => {
describe('composition rule 3 — a key with no declared rule warns', () => {
it('warns once, names the key and carries the declare-a-rule prescription', () => {
// A key the schema does not declare: reaches composeStacks only via
// `strict: false`, which is exactly how a NEW key looks before someone
Expand Down Expand Up @@ -188,7 +188,7 @@ describe('#5005 rule 3 — a key with no declared rule warns', () => {
expect(warnSpy.mock.calls.map((c) => String(c[0])).some((w) => w.includes("'futureList'"))).toBe(true);
});

it('refuses — never skips — a collection key that holds a non-array value (#19784)', () => {
it('refuses — never skips — a collection key that holds a non-array value', () => {
// Skipping it (the #5005 warn-and-drop) composed an artifact that silently
// lacked stack B's views; the full per-key census lives in
// `compose-stacks-concat-shape-refusal.test.ts`.
Expand Down Expand Up @@ -217,7 +217,7 @@ describe('#5005 rule 3 — a key with no declared rule warns', () => {

// ─── Control — array keys keep today's concat semantics ─────────────

describe('#5005 control — array keys still concatenate', () => {
describe('control — array keys still concatenate', () => {
it('concatenates in stack order, unchanged', () => {
const a = raw({
manifest: manifestA,
Expand Down Expand Up @@ -294,7 +294,7 @@ describe('#5005 control — array keys still concatenate', () => {

// ─── Control — the pre-existing bespoke strategies are untouched ────

describe('#5005 control — manifest / objects strategies unchanged', () => {
describe('control — manifest / objects strategies unchanged', () => {
it('manifest still follows the `manifest` option', () => {
const a = raw({ manifest: manifestA });
const b = raw({ manifest: manifestB });
Expand All @@ -319,7 +319,7 @@ describe('#5005 control — manifest / objects strategies unchanged', () => {

// ─── Structural pin — every declared key has a rule ─────────────────

describe('#5005 structural pin — the schema and the composer cannot drift', () => {
describe('structural pin — the schema and the composer cannot drift', () => {
/**
* The disposition table is typed `Record< keyof ObjectStackDefinition, … >`,
* so a key added to the schema without a composition rule is already a
Expand Down
Loading
Loading