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
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ const OWNER = '@objectstack/runtime';
const asDetails = (d: ActionConfirmationRequiredDetails) => d;
const asConfirmation = (c: AIActionConfirmation) => c;

describe('action-confirmation contract (#16293)', () => {
describe('action-confirmation contract — an unconfirmed gated action is refused', () => {
it('the refusal code is ADMITTED by the closed `ErrorCode` union', () => {
expect(ErrorCode.parse(CODE)).toBe(CODE);
// Control: the union is closed, so a one-character near-miss is refused.
Expand Down
6 changes: 3 additions & 3 deletions packages/spec/src/contracts/approval-service.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ import type {
IApprovalService,
} from './approval-service';

describe('approval row organization_id declaration (#10331)', () => {
describe('approval rows declare the organization_id they are stamped with', () => {
it('is readable off ApprovalRequestRow without a cast, at the stamped shape', () => {
// Reading the property off the declared type — no `as`, no indexing
// through `any`. This line failing to compile is the regression.
Expand Down Expand Up @@ -87,7 +87,7 @@ export type ActedAsIsOptional = Assert<{} extends Pick<ApprovalActionRow, 'acted
/** A string slot address — not a boolean flag, not an object, not nullable. */
export type ActedAsIsAString = Assert<Eq<ApprovalActionRow['acted_as'], string | undefined>>;

describe('[#21458] ApprovalActionRow.acted_as — the slot an approval action was taken as', () => {
describe('ApprovalActionRow.acted_as — the slot an approval action was taken as', () => {
it('is optional and string-typed: a row without it still conforms, and one with it reads back', () => {
const read = (row: ApprovalActionRow): string | undefined => row.acted_as;

Expand Down Expand Up @@ -187,7 +187,7 @@ const minimalService = (): IApprovalService => ({
listActions: async () => [],
});

describe('[#15389] continueRestoredRun — the approvals operator repair verb, declared', () => {
describe('continueRestoredRun — the approvals operator repair verb, declared', () => {
it('is optional: the minimal implementation still conforms and has no operator door', () => {
const service = minimalService();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ export const contextSupplyingSubject: AutomationContext = {
// @ts-expect-error — a per-key boolean map is not the shape: the key lists names.
export const contextWithAMap: AutomationContext = { params: { subject: 'x' }, callerParamKeys: { subject: true } };

describe('[#19846] AutomationContext.callerParamKeys', () => {
describe('AutomationContext.callerParamKeys — the keys the caller supplied', () => {
it('reads back absent, empty and populated as three different values', () => {
expect('callerParamKeys' in contextWithoutTheKey).toBe(false);
expect(contextSupplyingNothing.callerParamKeys).toEqual([]);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ export const contextWithTheKey: AutomationContext = { record: { id: 'rec-1' }, o
// @ts-expect-error — `false` is not a member: the key is ABSENT, never `false` (handler-face convention, mirrored).
export const contextWithFalse: AutomationContext = { record: { id: 'rec-1' }, object: 'crm_deal', recordLoadDenied: false };

describe('[#14244] AutomationContext.recordLoadDenied mirrors the producer signal', () => {
describe('AutomationContext.recordLoadDenied mirrors the producer signal', () => {
it('reads the key back as exactly `true`, and its absence as `undefined` (anti-vacuity)', () => {
expect(contextWithTheKey.recordLoadDenied).toBe(true);
expect(contextWithoutTheKey.recordLoadDenied).toBeUndefined();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ export type WireStatusMatchesContract = Assert< Eq< WireStatus, ContractStatus >
/** The wire enum, unwrapped from `.optional()` through the `lazySchema` Proxy. */
const wireStatusEnum = TriggerFlowResponseSchema.shape.data.shape.status.unwrap();

describe('[#14384] AutomationResult.status names the stranded run', () => {
describe('AutomationResult.status names the stranded run', () => {
it('reads a non-empty membership (anti-vacuity)', () => {
expect(AUTOMATION_RESULT_STATUSES.length).toBe(5);
expect(wireStatusEnum.options.length).toBeGreaterThan(0);
Expand All @@ -93,7 +93,7 @@ describe('[#14384] AutomationResult.status names the stranded run', () => {
expect([...wireStatusEnum.options]).toEqual([...AUTOMATION_RESULT_STATUSES]);
});

it("names the terminally-failed-but-repairable run 'stranded' (#13937 shape 4)", () => {
it("names the terminally-failed-but-repairable run 'stranded'", () => {
expect(AUTOMATION_RESULT_STATUSES).toContain('stranded');
expect(wireStatusEnum.options).toContain('stranded');
});
Expand All @@ -115,7 +115,7 @@ describe('[#14384] AutomationResult.status names the stranded run', () => {
expect(parsed.data.runId).toBe('run_stranded_001');
});

it("names the refused run 'refused' (#14945) — beside `'failed'`, never folded into it", () => {
it("names the refused run 'refused' — beside `'failed'`, never folded into it", () => {
expect(AUTOMATION_RESULT_STATUSES).toContain('refused');
expect(wireStatusEnum.options).toContain('refused');
expect(wireStatusEnum.options).toContain('failed');
Expand Down
4 changes: 2 additions & 2 deletions packages/spec/src/contracts/automation-service.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -302,7 +302,7 @@ describe('Automation Service Contract', () => {
// `verb(runId)` shorthand), and their docblocks carry the ruling's
// persistent-face statement. The type-level identities are the exported
// aliases above the suite; the compile of the literals below is the rest.
describe('[#16495] cancelRun / restoreConsumedSuspension — the operator verbs, declared', () => {
describe('cancelRun / restoreConsumedSuspension — the operator verbs, declared', () => {
it('are optional: the minimal implementation still conforms and has no operator door', () => {
const service: IAutomationService = {
execute: async () => ({ success: true }),
Expand Down Expand Up @@ -419,7 +419,7 @@ describe('Automation Service Contract', () => {
* passes these rows to Studio verbatim, so a shape with no reason field made a
* policy-disabled flow indistinguishable from a broken binding on the wire.
*/
describe('FlowRuntimeState — the unbound reason (#18235)', () => {
describe('FlowRuntimeState — carries the reason a flow is unbound', () => {
it('a row that explains itself and one that does not both satisfy the contract', () => {
// PROBE: the reason-carrying row, in the shape the engine emits for a flow
// the deployment switch refused.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ const asOptions = (o: ChatWithToolsOptions) => o;
/** A plausible digest — the shape cloud stamps, opaque to this contract. */
const DIGEST = 'sha256:3f6a1c0e9b2d4a7f8c5e1b0d9a2f4c6e8b0d3a5f7c9e1b3d5a7f9c1e3b5d7a9f';

describe('confirmedBlueprintIdentity contract (#15937)', () => {
describe('confirmedBlueprintIdentity — declared on the protocol ToolExecutionContext', () => {
it('is declared on `ToolExecutionContext` and round-trips the digest', () => {
const ctx = asCtx({
actor: { id: 'usr_1' },
Expand Down
6 changes: 3 additions & 3 deletions packages/spec/src/contracts/core-service-contracts.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ import type { IShareLinkService } from './share-link-service';
type Expect<T extends true> = T;
type Equals<A, B> = (<G>() => G extends A ? 1 : 2) extends (<G>() => G extends B ? 1 : 2) ? true : false;

describe('CoreServiceName → contract map (#4127)', () => {
describe('CoreServiceName → contract map', () => {
it('maps every key to a declared CoreServiceName slot', () => {
// The map's keys are checked against the enum at compile time below;
// this asserts the same thing at runtime so a rename shows up as a
Expand Down Expand Up @@ -70,7 +70,7 @@ describe('CoreServiceName → contract map (#4127)', () => {
});
});

describe('slot → contract ledger beyond the enum (#4127 batch 3)', () => {
describe('slot → contract ledger beyond the enum', () => {
it('keeps every core binding', () => {
// The extension must not shadow or drop a core entry — `data` staying
// `IDataEngine` is what makes the `objectql` alias below meaningful.
Expand All @@ -96,7 +96,7 @@ describe('slot → contract ledger beyond the enum (#4127 batch 3)', () => {
expect(true).toBe(true);
});

it('resolves objectql to the FULL engine contract, a strict widening of data (#4251 B3)', () => {
it('resolves objectql to the FULL engine contract, a strict widening of data', () => {
// Same instance, two views: `data` is the engine as IDataEngine (the
// data plane), `objectql` is the whole engine. The subtype relation is
// the claim that they cannot drift apart — every IObjectQLEngine IS an
Expand Down
2 changes: 1 addition & 1 deletion packages/spec/src/contracts/data-driver.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -287,7 +287,7 @@ describe('IDataDriver', () => {
// unused directive is itself an error, so `pnpm --filter @objectstack/spec
// typecheck` goes red on regression in either direction.

describe('introspectSchema (#11493)', () => {
describe('introspectSchema — an optional driver member at the spec shape', () => {
/** The declared return type, read off the CONTRACT rather than re-spelled. */
type DriverIntrospection = Awaited<ReturnType<NonNullable<IDataDriver['introspectSchema']>>>;

Expand Down
12 changes: 6 additions & 6 deletions packages/spec/src/contracts/data-engine.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -213,7 +213,7 @@ describe('Data Engine Contract', () => {
* `IDataEngine[…]`, so nothing here can drift from the contract by being
* modelled beside it.
*/
describe('the narrowed verb declarations are pinned, not just guarded (#16231)', () => {
describe('the narrowed verb declarations are pinned, not just guarded', () => {
type FindOneAnswer = Awaited<ReturnType<IDataEngine['findOne']>>;
type UpdateAnswer = Awaited<ReturnType<IDataEngine['update']>>;
type DeleteAnswer = Awaited<ReturnType<IDataEngine['delete']>>;
Expand Down Expand Up @@ -266,7 +266,7 @@ describe('Data Engine Contract', () => {
* re-opening Option A or has moved the member, and either way it is a
* maintainer decision, not a merge conflict to resolve by hand.
*/
describe('strictReadonlyWrites stays OFF the serializable options bags (#5126)', () => {
describe('strictReadonlyWrites stays OFF the serializable options bags', () => {
const shapeKeys = (schema: unknown): string[] =>
Object.keys((schema as { shape: Record<string, unknown> }).shape);

Expand Down Expand Up @@ -452,7 +452,7 @@ describe('Data Engine Contract', () => {
// it). The value-level optionality evidence already exists above: every
// pre-existing minimal `IDataEngine` literal in this file omits
// `introspectDatasource` and compiles.
describe('introspectDatasource (#11493)', () => {
describe('introspectDatasource — answers the spec introspection shape', () => {
type Member = IDataEngine['introspectDatasource'];
type EngineIntrospection = Awaited<ReturnType<NonNullable<Member>>>;

Expand Down Expand Up @@ -511,7 +511,7 @@ describe('Data Engine Contract', () => {
// file, which omit all five and compile); every directive below is resolved
// by tsc, so reverting a member makes its `@ts-expect-error` unused, and an
// unused directive is itself an error.
describe('datasource resolution members (#12248, #11833 fork 1)', () => {
describe('datasource resolution members — declared, and optional', () => {
type ResolveMember = IDataEngine['resolveEffectiveDatasource'];
type DriverMember = IDataEngine['getDriverForObject'];

Expand Down Expand Up @@ -572,7 +572,7 @@ describe('Data Engine Contract', () => {
});
});

describe('datasource lifecycle members (#12248, #12010, #12805 via the #11833 ruling item 4)', () => {
describe('datasource lifecycle members — declared at the shape the engine keeps', () => {
type RegisterMember = IDataEngine['registerDatasourceDef'];
type ListMember = IDataEngine['listDatasourceDefs'];
type MarkMember = IDataEngine['markDatasourceUnavailable'];
Expand Down Expand Up @@ -676,7 +676,7 @@ describe('Data Engine Contract', () => {
});
});

describe('syncObjectSchema (#12482 — the #12010 "not verified" member, via the #11833 ruling item-4 precedent)', () => {
describe('syncObjectSchema — declared, since two services already call it', () => {
type SyncMember = IDataEngine['syncObjectSchema'];

it('is optional — only engines owning drivers and DDL answer', () => {
Expand Down
4 changes: 2 additions & 2 deletions packages/spec/src/contracts/email-service.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ import type { SendEmailInput, SendTemplateInput } from './email-service';
* BOTH `SendEmailInput` and `SendTemplateInput` (the template entry point
* forwards it into the send it performs).
*/
describe('Email Service Contract — organization widening (#11741)', () => {
describe('Email Service Contract — organization widening', () => {
it('accepts the pre-widening SendEmailInput shape unchanged (organizationId optional, absent legal)', () => {
const legacy: SendEmailInput = { to: 'a@b.com', subject: 'Hi', text: 'x' };
expect(legacy).not.toHaveProperty('organizationId');
Expand Down Expand Up @@ -60,7 +60,7 @@ describe('Email Service Contract — organization widening (#11741)', () => {
* itself a compile error (TS2578) under `check:test-typecheck` — the pin fails
* loudly in both directions.
*/
describe('Email Service Contract — SendTemplateInput.org retired (#11832)', () => {
describe('Email Service Contract — SendTemplateInput.org retired', () => {
it('refuses `org` at compile time (excess property; organizationId is NOT an overlay opt-in)', () => {
const input: SendTemplateInput = {
template: 'auth.password_reset',
Expand Down
6 changes: 3 additions & 3 deletions packages/spec/src/contracts/http-server.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -180,7 +180,7 @@ describe('HTTP Server Contract', () => {
await expect(server.close!()).resolves.toBeUndefined();
});

describe('optional setFallbackHandler (#5040 E1)', () => {
describe('optional setFallbackHandler — a not-found hook, not a wildcard route', () => {
/** A server with only the REQUIRED members. */
const baseServer = (): IHttpServer => ({
get: () => {},
Expand Down Expand Up @@ -313,7 +313,7 @@ describe('HTTP Server Contract', () => {
});
});

describe('optional afterResponse (#9835)', () => {
describe('optional afterResponse — a transport-agnostic response observer', () => {
/** A server with only the REQUIRED members. */
const baseServer = (): IHttpServer => ({
get: () => {},
Expand Down Expand Up @@ -344,7 +344,7 @@ describe('HTTP Server Contract', () => {
expect(typeof server.afterResponse).toBe('function');
});

it('a delegating wrapper that forwards only required members ERASES detection (#5122 shape)', () => {
it('a delegating wrapper that forwards only required members ERASES detection', () => {
const underlying: IHttpServer = {
...baseServer(),
afterResponse: (_observer) => {},
Expand Down
4 changes: 2 additions & 2 deletions packages/spec/src/contracts/job-service.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,7 @@ describe('Job Service Contract', () => {
* which reddens the `degraded` direction only, and leaves every legacy pin
* green. That asymmetry IS additivity.
*/
describe('[#6617] JobHandler degraded-outcome channel', () => {
describe('JobHandler degraded-outcome channel — optional and additive', () => {
/**
* The handler type EXACTLY as it stood before #6617. Pinning it as a
* standalone declaration is what makes the additivity claim falsifiable:
Expand Down Expand Up @@ -260,7 +260,7 @@ describe('[#6617] JobHandler degraded-outcome channel', () => {
* signature back to `(name, data?)` — (b), (c) and the identity pin go red,
* (a) stays green. That asymmetry IS additivity.
*/
describe('[#14766] IJobService.replay force option — contract half of the #14501 A+a2 ruling', () => {
describe('IJobService.replay force option — a succeeded window replays only when forced', () => {
type Eq<A, B> = (<T>() => T extends A ? 1 : 2) extends (<T>() => T extends B ? 1 : 2) ? true : false;
type ReplayParams = Parameters<NonNullable<IJobService['replay']>>;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,14 +65,14 @@ function assertRegisterContract(type: string, name: string, data: unknown): void
const shape = data === null ? 'null' : Array.isArray(data) ? 'an array' : `a ${typeof data}`;
throw registerRefusal(
`IMetadataService.register('${type}', '${name}'): data is ${shape}, not a metadata document — ` +
`refused, never accepted-and-dropped or coerced into storability (#7378 row 3).`,
`refused, never accepted-and-dropped or coerced into storability.`,
);
}
const documentName = (data as { name?: unknown }).name;
if (documentName !== undefined && documentName !== name) {
throw registerRefusal(
`IMetadataService.register('${type}', '${name}'): data.name is '${String(documentName)}', which disagrees ` +
`with the name argument '${name}' — refused, since silent resolution in either direction can misplace the item (#7378 row 1).`,
`with the name argument '${name}' — refused, since silent resolution in either direction can misplace the item.`,
);
}
}
Expand Down Expand Up @@ -139,7 +139,7 @@ async function assertRefused(service: IMetadataService, testCase: MetadataRoundT
() => undefined,
(thrown: unknown) => thrown as Error & { code?: string; status?: number },
);
expect(error, `register must REFUSE this write (#7378): ${testCase.id}`).toBeDefined();
expect(error, `register must REFUSE this write: ${testCase.id}`).toBeDefined();
expect(error).toMatchObject({
code: StandardErrorCode.enum.VALIDATION_ERROR,
status: 400,
Expand Down
2 changes: 1 addition & 1 deletion packages/spec/src/contracts/notification-service.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,7 @@ describe('Notification Service Contract', () => {
* Optional, and the first test is the reason: a send-only provider (SMTP,
* Twilio, a Slack webhook) fills the slot legitimately with no inbox at all.
*/
describe('inbox (#4127)', () => {
describe('inbox — declared on the contract, and optional', () => {
it('keeps a send-only provider valid — the inbox trio is optional', () => {
const sendOnly: INotificationService = {
send: async () => ({ success: true }),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ type Equals<A, B> = (<G>() => G extends A ? 1 : 2) extends (<G>() => G extends B

type RegisterHookOptions = NonNullable<Parameters<IObjectQLEngine['registerHook']>[2]>;

describe('[#5928] IObjectQLEngine.registerHook scope faces', () => {
describe('IObjectQLEngine.registerHook scope faces — global minus excluded objects', () => {
it('declares `excludeObjects` in both accepted spellings', () => {
// Fails to COMPILE if the declared type is anything else — `true` is not
// assignable to `false`.
Expand Down
6 changes: 3 additions & 3 deletions packages/spec/src/contracts/objectql-engine.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ import type { ExecutionContext } from '../kernel/execution-context.zod';
* contract (`check:engine-double-contract` counts this file's doubles against
* a shrink-only baseline, and a pin block is not a reason to grow it).
*/
describe('getObject return contract (#12248, #11833 fork 3)', () => {
describe('getObject return contract — a structured answer, not `unknown`', () => {
type EngineAnswer = ReturnType<IObjectQLEngine['getObject']>;
type RegistryAnswer = ReturnType<EngineSchemaRegistryView['getObject']>;

Expand Down Expand Up @@ -103,7 +103,7 @@ describe('getObject return contract (#12248, #11833 fork 3)', () => {
* the contract, no engine double is stood up, and on a revert to `unknown` the
* consumer reads below stop compiling with no `@ts-expect-error` needed.
*/
describe('getSchema return contract (#12481 — #12248 one member over, #11833 fork 3 by inheritance)', () => {
describe('getSchema return contract — the same answer as its alias getObject', () => {
type SchemaAnswer = ReturnType<IObjectQLEngine['getSchema']>;

it('answers exactly the spec registered-object type', () => {
Expand Down Expand Up @@ -160,7 +160,7 @@ describe('getSchema return contract (#12481 — #12248 one member over, #11833 f
* Same discipline as the blocks above: member types read off the contract, no
* engine double.
*/
describe('judgeFilter contract (#20157, #19995 ruling C)', () => {
describe('judgeFilter contract — the engine judges a filter without running it', () => {
type Member = IObjectQLEngine['judgeFilter'];

it('is OPTIONAL: a caller must work with an engine that lacks it', () => {
Expand Down
Loading
Loading