Skip to content

Commit 8256a4b

Browse files
test(spec): contracts and conversions test titles state each cited decision in words instead of a tracker number (stage 13) (#21763)
Part of #20749 Clause-②: no Stage 13 of this card, and the fourth area of class (e): the test strings shipped under `packages/spec/src`, as ruled in `5902360492` on #20513. This stage takes two whole directories, `contracts/` and `conversions/`. Their 97 test-title and test-string literals carried 108 tracker ids citing 78 records. 107 ids in 96 literals now either state what their record decided, in words (form D), or are dropped where the title already says it. One id stays, for the reason given below. Text only: no assertion, identifier, test count or code comment changes. ## Census at the base (`866b4393d0`, the claim's base) Instruments: `census10.cjs` (md5 `9d08602ab972b4b8643c90d64d40fa41`), `census.cjs` (md5 `6e42a45a926d375013c32d62f16a296e`) and `census-wide.cjs` (md5 `c98410a19529c439adb0afbfb00026a2`), byte-identical to the copies stages 10 to 12 used. A literal counts as a test title when its folded message is argument 0 of a `describe` / `it` / `test` call, `.each` / `.skip` / `.only` chains included. Everything else is an "other" string. Both instruments read **1509 messages / 1606 ids in 348 files at the base**, which is stage 12's head reading exactly. `contracts/` reads 63 / 74 and `conversions/` 34 / 34, also stage 12's figures. | directory | files | messages / ids | titles | other | |:--|--:|--:|--:|--:| | `data/` | 95 | 468 / 501 | 445 / 475 | 23 / 26 | | `ui/` | 81 | 392 / 415 | 374 / 397 | 18 / 18 | | `api/` | 40 | 189 / 201 | 181 / 193 | 8 / 8 | | `system/` | 34 | 154 / 165 | 128 / 138 | 26 / 27 | | (files directly in `src/`) | 30 | 118 / 120 | 117 / 119 | 1 / 1 | | **`contracts/`** (this PR) | 25 | **63 / 74** | 59 / 70 | 4 / 4 | | **`conversions/`** (this PR) | 9 | **34 / 34** | 34 / 34 | 0 | | `security/` | 8 | 28 / 28 | 28 / 28 | 0 | | `ai/` | 9 | 18 / 20 | 13 / 15 | 5 / 5 | | `identity/` | 6 | 15 / 15 | 14 / 14 | 1 / 1 | | `integration/` | 4 | 14 / 14 | 13 / 13 | 1 / 1 | | `migrations/` | 2 | 9 / 12 | 9 / 12 | 0 | | `marketplace/`, `meta-spelling/`, `studio/` | 5 | 7 / 7 | 7 / 7 | 0 | | **total** | **348** | **1509 / 1606** | **1422 / 1515** | **87 / 91** | - **Controls.** Lit, a title: `contracts/data-engine.test.ts:575` reads one message with four ids. Lit, an `expect` message: `contracts/metadata-service-roundtrip-conformance.test.ts:142` reads one message. Dark: the comment at `contracts/core-service-contracts.test.ts:3` ("[#4127] The map claims a binding per slot") reads 0. Planted in a scratch copy: an id put back into a title reads 1 / 1, and an id in an added comment reads 0. - **A wider pattern** (any `#` plus digits) reads 63 / 75 under `contracts/` and 35 / 36 under `conversions/` test files at the base. The extras are `(batch #76)` in the `resume-failure-report.pin.test.ts:137` title, and `PD #12` (Prime Directive 12, contract-first) in two `conversions.test.ts` titles, `:180` and `:785`. None matches the gate's 3-to-5-digit pattern. - **At the head:** 1413 messages / 1499 ids in 315 files. `contracts/` reads 1 / 1 (the needle below), `conversions/` 0 / 0. Nothing else moved. The wider pattern reads that needle and the two `PD #12` titles, and nothing else. ## How the area was chosen Stage 10's rule: rank whole first-level directories by ids, and take the busiest within about 10% of the ~100-id bound. `data/` (501), `ui/` (415), `api/` (201) and `system/` (165) each exceed it alone, and the files directly in `src/` (120) are 20% over. No single remaining directory fits except smaller ones, and `contracts/` with `conversions/` reads exactly 108, within 10% of the bound. That is the pairing the stage-10 ACCEPT named, so the rule needed no second pass. **Named for the next stages:** `data/` (about five stages, by subdirectory or file group; `data/driver/` alone is 52), `ui/` (about four), `api/` (two), `system/` (two), the files directly in `src/` (one, 120), and `security/`, `ai/`, `identity/`, `integration/`, `migrations/`, `marketplace/`, `meta-spelling/` and `studio/` together (one, 96). ## What each id became 32 ids in 21 literals now state a decision in words. 75 ids in 75 literals are dropped where the title already says what the record decided. Every cited record was read with its comments through REST: 71 answer 200, and 7 answer 404 (#6345, #6523, #11741, #12010, #12248, #16559, #16786). For those seven the decision was read from what landed: the landing commit and the CHANGELOG entry. | record(s) | literal | now reads | |:--|:--|:--| | #16293 | `action-confirmation-contract.pin.test.ts:63` | "action-confirmation contract — an unconfirmed gated action is refused". The ruling: a gated action without an explicit confirmation is refused loudly, with the way to confirm. | | #10331 | `approval-service.test.ts:23` | "approval rows declare the organization_id they are stamped with". The finding's first reading landed: both row types declare it, optional and nullable. | | #19846 | `automation-context-caller-param-keys.pin.test.ts:49` | "AutomationContext.callerParamKeys — the keys the caller supplied". The ruling replaced the headless-screen inference with this explicit signal. | | #18235 | `automation-service.test.ts:422` | "FlowRuntimeState — carries the reason a flow is unbound", so a policy-disabled flow reads differently from a broken binding. | | #15937 | `confirmed-blueprint-identity-contract.pin.test.ts:52` | "confirmedBlueprintIdentity — declared on the protocol ToolExecutionContext". The maintainer chose option 1: declare it in the protocol, not only on cloud's augmentation. | | #11493 (2) | `data-driver.test.ts:290`, `data-engine.test.ts:455` | "introspectSchema — an optional driver member at the spec shape" and "introspectDatasource — answers the spec introspection shape". Both ruled steps. | | #12248, #11833 | `data-engine.test.ts:514` | "datasource resolution members — declared, and optional". Fork 1 of the #11833 ruling, option A, landed as `8425c17cc`. | | #12248, #12010, #12805, #11833 | `data-engine.test.ts:575` | "datasource lifecycle members — declared at the shape the engine keeps". Item 4 of the #11833 ruling put `ConnectionEngineLike`'s members on the contract (`8425c17cc`, `77b91bd`), and #12805 caught the declared def up to what the engine retains. | | #12482, #12010, #11833 | `data-engine.test.ts:679` | "syncObjectSchema — declared, since two services already call it". | | #5040 | `http-server.test.ts:183` | "optional setFallbackHandler — a not-found hook, not a wildcard route". The design's option C, so a declared endpoint never shadows a registered route. | | #9835 | `http-server.test.ts:316` | "optional afterResponse — a transport-agnostic response observer". | | #6617 | `job-service.test.ts:126` | "JobHandler degraded-outcome channel — optional and additive". | | #14766, #14501 | `job-service.test.ts:263` | "IJobService.replay force option — a succeeded window replays only when forced". The A + a2 ruling. | | #4127 | `notification-service.test.ts:153` | "inbox — declared on the contract, and optional". | | #5928 | `objectql-engine-hook-scope.test.ts:41` | "IObjectQLEngine.registerHook scope faces — global minus excluded objects". The ruled A shape, `excludeObjects`. | | #12248, #11833 | `objectql-engine.test.ts:29` | "getObject return contract — a structured answer, not `unknown`". Fork 3. | | #12481, #12248, #11833 | `objectql-engine.test.ts:106` | "getSchema return contract — the same answer as its alias getObject". Fork 3, one member over. | | #20157, #19995 | `objectql-engine.test.ts:163` | "judgeFilter contract — the engine judges a filter without running it". Ruling C. | | #4539 | `sharing-service.test.ts:35` | "recipient vocabularies, each under its own name". The same-name, different-form exports were split by renaming. | | #5858 | `sharing-service.test.ts:194` | "HierarchyScopeContext tenancy authority — organizationId is authoritative". | **Dropped only (75 ids):** #3903, #4045, #4127 (2), #4158, #4251, #4343, #4347 (2), #4401, #4456 (2), #4538 (2), #4827, #4829, #4923 (5), #5011, #5122, #5125, #5126, #5493 (3), #5777, #5817, #5945 (4), #6345 (2), #6428, #6430, #6523, #6775 (2), #6776, #7378 (3), #7616 (2), #8321, #11122 (2), #11741, #11832, #13700, #13937, #14103, #14244, #14384, #14945, #14969, #15389, #15429, #16231, #16495, #16559, #16693, #16786, #19620, #20323, #20390, #20740, #20935, #20940, #21005, #21220, #21458. - Each title already states the pinned decision. In `conversions/` most titles are the conversion entry's own id ("action-aria-removed", "app-hidden-to-unpublished"), which is the decision that landed. - **Qualified references** were read before dropping: "#13937 shape 4" (keep the consume order and add an operator exit verb; the title already names the repairable run), "#4923 house rule" (equal values dedupe, different values keep both; the title already says "keeps BOTH"), "#4127 batch 3" (the ledger extends past the enum; the title says "beyond the enum"), "#4251 B3" (`IObjectQLEngine` widens `IDataEngine`; the title says it), "#5122 shape" (a wrapper that forwards only required members; the title says it), and "#7378 row 1" / "row 3" (both refusal messages already state their row's ruling). - **The 404 records:** #6345 (`e2798fa`: one driver vocabulary, `mongo` converged to `mongodb`), #6523 (`aa4b90d`: enforcement takes the full `ExecutionContext`), #11741 (`b706af9`: an optional `organizationId` on both email inputs), #16559 (`c7aca0dce`: the resume failure declared once, carried by a success answer), #16786 (`6059b29`: `updateById` declares the record or `null`). Each title already carries what landed. - **`(batch #76)`** in `resume-failure-report.pin.test.ts:137` goes with `#16559` in the same literal. It names the decision batch whose ruling the title already states ("the resume failure a success answer carries"). It is outside the gate's pattern, and it is declared here. - **`PD #12`** stays in `conversions.test.ts:785`. It is a Prime Directive reference in AGENTS.md, not a tracker number, and the untouched sibling title at `:180` spells it the same way. ## The one id that stays `contracts/approval-service.test.ts:274` is `expect(doc).toContain('#16495')`. It is not a title: it is the expected value of an assertion that reads the `continueRestoredRun` docblock in `contracts/approval-service.ts` and pins that the docblock names the sibling it was ruled to copy. Changing it needs a code comment and assertion logic, which this claim excludes. It moves with that docblock when the comment lane rewrites `approval-service.ts:999`. ## Readers - **Test-name filters:** none. A tracked-tree search for `-t` and `--testNamePattern` finds only `packages/qa/dogfood/README.md:142` (`-t "owner-scoped"`), which is unrelated. - **Snapshots:** none. Neither directory has `__snapshots__`, and no `.snap` file is tracked under `packages/spec`. - **Projects:** none of the 34 files is listed in `packages/spec/vitest.repo-tests.json`, so all run in the `local` project. - **By substring:** every old literal, plus a window around each id (241 needles), was searched across the tracked tree outside its own file. No gate, doc, filter, snapshot or `scripts/check-*.mjs` self-test reads one. The 17 needle hits land on 11 lines: - Sibling test strings in other lanes' packages: `packages/objectql/src/metadata-service-roundtrip-conformance.test.ts:232` (the objectql driver of the same table, `register must REFUSE this write (#7378)`); `packages/plugins/plugin-security/src/get-queryable-fields.test.ts:136` and `:165` (`[#20935]`), `resolve-permission-sets-for-context.pin.test.ts:103` (`[#7616]`), `authored-row-write-verdict.test.ts:350` (`[#5493]`); and `packages/metadata-core/src/artifact-forward-conversion.test.ts:277` (`(ADR-0113, #16693)`). - Code comments: `packages/spec/src/contracts/automation-service.ts:1061` (`#13937 shape 4`), `packages/spec/src/contracts/index.ts:44` (`(#4127)`), `packages/cli/src/utils/view-container-names.ts:11` and `packages/objectql/src/view-container-name-refusal.ts:13` (`#7378 row 1`). ## Text-only proof Stage 10's scratch tool (`textonly10.cjs`, md5 `d5e4801dbb4329ab1984da91e92fc47c`) compares base and head file by file on three legs: 1. **Skeleton:** the full AST, with string pieces masked. It must be identical. 2. **Comments:** every comment, byte-equal. 3. **Strings:** each changed string leaf must sit in a test-call title position or on a declared line, must carry a tracker id before, and must carry no `#` plus digits after. The declared lines are the three in `metadata-service-roundtrip-conformance.test.ts`: the reference double's two refusal messages (`:68`, `:75`) and the `expect` message at `:142`. No test asserts on the dropped text: the refusal checks assert `code`, `status` and the write's coordinates. - **Result:** 33 of 34 files SAME on all three legs. `conversions.test.ts` passes the skeleton and comment legs and is flagged on one string, `:785`, because its rewritten title keeps `PD #12`. That was predicted in writing before the run. With `PD #12` spelled `PD-12` in both the base and head copies of that one line, the file reads SAME with 19 changed titles. - **Totals:** 96 changed literals, 93 titles and 3 declared. The diff's `+` lines are exactly the 96 planned lines, and every file keeps its line count. - **Controls (10 of 10 as predicted, on scratch copies, each anchor hit once):** identifier rename DIFF; numeric literal DIFF; comment edit COMMENT DIFF; a non-title string given an id VIOLATION; a rewritten title given a new id VIOLATION; a title that was id-free at base edited VIOLATION; one title reverted to base SAME; a declared string keeping an id VIOLATION; an undeclared `expect` message changed VIOLATION; a title re-split into a `+` chain DIFF. **Test counts:** the 34 files were run at the base (in a separate base worktree at `866b4393d0`) and at the head, in the `local` project. Both sides read 595 / 595 passed, with the same count and status sequence per file in 34 of 34. 354 full test names change, and each equals the base name with the planned replacements applied. One full name repeats on both sides: two `sqlite` rows of the `stored.test.ts` `it.each` table share the `%s` name. That predates this PR. ## Changeset: `skip-changeset` Measured, not assumed: - `npm pack --dry-run` of `@objectstack/spec` lists 2068 files. 0 of the 34 touched files are in it, and no `*.test.ts` at all. The controls `src/shared/expression.zod.ts` and `dist/contracts/index.js` are in it. - In `dist/`, four new phrases and three old ones each read in 0 files. The control `Unrecognized key(s) on` reads in 42. So this PR publishes nothing, and no changeset is added. ## Verification (at `72513933ee`) - `pnpm turbo run build` over all packages: 71 / 71. - `@objectstack/spec`: - `vitest run --project local`: 614 files, 18285 passed, 1 todo. - `typecheck` exit 0, including `check:test-typecheck`. Its program holds all 34 touched files, counted with `tsc --listFilesOnly`. - **Gates:** `dispatch-gates --commands` derived 79 families (stage 12's 80 without `check:future-spec-major`, which no touched file feeds), and all 79 exit 0. `--ran` reconciles: 79 derived, 79 run, 0 NOT-MEASURED, 0 UNRUN. - The five roster families whose rosters sit under a touched directory were also run, and each exits 0: `check:meta-url-spelling`, `check:spec-changes`, `check:authz-resolver`, `check:error-code-casing` and `check:filter-alias-parity`. - **ESLint, a proven narrowing:** `--no-inline-config` over the 34 files, 0 errors and 0 warnings. The population comes from ESLint's own config: 34 configured, 0 ignored. No `parserOptions.project` or `projectService`, so no untouched file's verdict can move. - `check-governed-merges --test`: NOT governed, 192 changed lines. ## Acceptance notes - **The `#16495` needle** at `approval-service.test.ts:274` stays, with the `approval-service.ts:999` docblock it pins. The comment lane owns both. - **Code comments still carry ids** in these 34 files and in the two directories' sources. Comments are not this card's share and are untouched here. - **Sibling test strings in other packages** repeat ids this PR dropped: the objectql driver of the round-trip table, three `plugin-security` test files and one `metadata-core` test (listed under Readers). Each is its own lane's test-string stage. - **`origin/main` moved** five commits past the base before this PR opened (#21752, #21754, #21753, #21751, #21743). None touches `packages/spec`, so nothing was merged. #21756, which also edits `contracts/security-service.test.ts`, has no PR yet; whichever lands later merges `origin/main`. --- _Generated by [Claude Code](https://claude.ai/code/session_01T9u38rswFp5Rw8DswRUReJ)_ Co-authored-by: Claude <noreply@anthropic.com>
1 parent ebfe658 commit 8256a4b

34 files changed

Lines changed: 96 additions & 96 deletions

‎packages/spec/src/contracts/action-confirmation-contract.pin.test.ts‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ const OWNER = '@objectstack/runtime';
6060
const asDetails = (d: ActionConfirmationRequiredDetails) => d;
6161
const asConfirmation = (c: AIActionConfirmation) => c;
6262

63-
describe('action-confirmation contract (#16293)', () => {
63+
describe('action-confirmation contract — an unconfirmed gated action is refused', () => {
6464
it('the refusal code is ADMITTED by the closed `ErrorCode` union', () => {
6565
expect(ErrorCode.parse(CODE)).toBe(CODE);
6666
// Control: the union is closed, so a one-character near-miss is refused.

‎packages/spec/src/contracts/approval-service.test.ts‎

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ import type {
2020
IApprovalService,
2121
} from './approval-service';
2222

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

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

@@ -187,7 +187,7 @@ const minimalService = (): IApprovalService => ({
187187
listActions: async () => [],
188188
});
189189

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

‎packages/spec/src/contracts/automation-context-caller-param-keys.pin.test.ts‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ export const contextSupplyingSubject: AutomationContext = {
4646
// @ts-expect-error — a per-key boolean map is not the shape: the key lists names.
4747
export const contextWithAMap: AutomationContext = { params: { subject: 'x' }, callerParamKeys: { subject: true } };
4848

49-
describe('[#19846] AutomationContext.callerParamKeys', () => {
49+
describe('AutomationContext.callerParamKeys — the keys the caller supplied', () => {
5050
it('reads back absent, empty and populated as three different values', () => {
5151
expect('callerParamKeys' in contextWithoutTheKey).toBe(false);
5252
expect(contextSupplyingNothing.callerParamKeys).toEqual([]);

‎packages/spec/src/contracts/automation-context-record-load-denied.pin.test.ts‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ export const contextWithTheKey: AutomationContext = { record: { id: 'rec-1' }, o
6969
// @ts-expect-error — `false` is not a member: the key is ABSENT, never `false` (handler-face convention, mirrored).
7070
export const contextWithFalse: AutomationContext = { record: { id: 'rec-1' }, object: 'crm_deal', recordLoadDenied: false };
7171

72-
describe('[#14244] AutomationContext.recordLoadDenied mirrors the producer signal', () => {
72+
describe('AutomationContext.recordLoadDenied mirrors the producer signal', () => {
7373
it('reads the key back as exactly `true`, and its absence as `undefined` (anti-vacuity)', () => {
7474
expect(contextWithTheKey.recordLoadDenied).toBe(true);
7575
expect(contextWithoutTheKey.recordLoadDenied).toBeUndefined();

‎packages/spec/src/contracts/automation-result-status.pin.test.ts‎

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,7 @@ export type WireStatusMatchesContract = Assert< Eq< WireStatus, ContractStatus >
8383
/** The wire enum, unwrapped from `.optional()` through the `lazySchema` Proxy. */
8484
const wireStatusEnum = TriggerFlowResponseSchema.shape.data.shape.status.unwrap();
8585

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

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

118-
it("names the refused run 'refused' (#14945) — beside `'failed'`, never folded into it", () => {
118+
it("names the refused run 'refused' — beside `'failed'`, never folded into it", () => {
119119
expect(AUTOMATION_RESULT_STATUSES).toContain('refused');
120120
expect(wireStatusEnum.options).toContain('refused');
121121
expect(wireStatusEnum.options).toContain('failed');

‎packages/spec/src/contracts/automation-service.test.ts‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -302,7 +302,7 @@ describe('Automation Service Contract', () => {
302302
// `verb(runId)` shorthand), and their docblocks carry the ruling's
303303
// persistent-face statement. The type-level identities are the exported
304304
// aliases above the suite; the compile of the literals below is the rest.
305-
describe('[#16495] cancelRun / restoreConsumedSuspension — the operator verbs, declared', () => {
305+
describe('cancelRun / restoreConsumedSuspension — the operator verbs, declared', () => {
306306
it('are optional: the minimal implementation still conforms and has no operator door', () => {
307307
const service: IAutomationService = {
308308
execute: async () => ({ success: true }),
@@ -419,7 +419,7 @@ describe('Automation Service Contract', () => {
419419
* passes these rows to Studio verbatim, so a shape with no reason field made a
420420
* policy-disabled flow indistinguishable from a broken binding on the wire.
421421
*/
422-
describe('FlowRuntimeState — the unbound reason (#18235)', () => {
422+
describe('FlowRuntimeState — carries the reason a flow is unbound', () => {
423423
it('a row that explains itself and one that does not both satisfy the contract', () => {
424424
// PROBE: the reason-carrying row, in the shape the engine emits for a flow
425425
// the deployment switch refused.

‎packages/spec/src/contracts/confirmed-blueprint-identity-contract.pin.test.ts‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ const asOptions = (o: ChatWithToolsOptions) => o;
4949
/** A plausible digest — the shape cloud stamps, opaque to this contract. */
5050
const DIGEST = 'sha256:3f6a1c0e9b2d4a7f8c5e1b0d9a2f4c6e8b0d3a5f7c9e1b3d5a7f9c1e3b5d7a9f';
5151

52-
describe('confirmedBlueprintIdentity contract (#15937)', () => {
52+
describe('confirmedBlueprintIdentity — declared on the protocol ToolExecutionContext', () => {
5353
it('is declared on `ToolExecutionContext` and round-trips the digest', () => {
5454
const ctx = asCtx({
5555
actor: { id: 'usr_1' },

‎packages/spec/src/contracts/core-service-contracts.test.ts‎

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ import type { IShareLinkService } from './share-link-service';
2424
type Expect<T extends true> = T;
2525
type Equals<A, B> = (<G>() => G extends A ? 1 : 2) extends (<G>() => G extends B ? 1 : 2) ? true : false;
2626

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

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

99-
it('resolves objectql to the FULL engine contract, a strict widening of data (#4251 B3)', () => {
99+
it('resolves objectql to the FULL engine contract, a strict widening of data', () => {
100100
// Same instance, two views: `data` is the engine as IDataEngine (the
101101
// data plane), `objectql` is the whole engine. The subtype relation is
102102
// the claim that they cannot drift apart — every IObjectQLEngine IS an

‎packages/spec/src/contracts/data-driver.test.ts‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -287,7 +287,7 @@ describe('IDataDriver', () => {
287287
// unused directive is itself an error, so `pnpm --filter @objectstack/spec
288288
// typecheck` goes red on regression in either direction.
289289

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

‎packages/spec/src/contracts/data-engine.test.ts‎

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -213,7 +213,7 @@ describe('Data Engine Contract', () => {
213213
* `IDataEngine[…]`, so nothing here can drift from the contract by being
214214
* modelled beside it.
215215
*/
216-
describe('the narrowed verb declarations are pinned, not just guarded (#16231)', () => {
216+
describe('the narrowed verb declarations are pinned, not just guarded', () => {
217217
type FindOneAnswer = Awaited<ReturnType<IDataEngine['findOne']>>;
218218
type UpdateAnswer = Awaited<ReturnType<IDataEngine['update']>>;
219219
type DeleteAnswer = Awaited<ReturnType<IDataEngine['delete']>>;
@@ -266,7 +266,7 @@ describe('Data Engine Contract', () => {
266266
* re-opening Option A or has moved the member, and either way it is a
267267
* maintainer decision, not a merge conflict to resolve by hand.
268268
*/
269-
describe('strictReadonlyWrites stays OFF the serializable options bags (#5126)', () => {
269+
describe('strictReadonlyWrites stays OFF the serializable options bags', () => {
270270
const shapeKeys = (schema: unknown): string[] =>
271271
Object.keys((schema as { shape: Record<string, unknown> }).shape);
272272

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

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

@@ -572,7 +572,7 @@ describe('Data Engine Contract', () => {
572572
});
573573
});
574574

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

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

682682
it('is optional — only engines owning drivers and DDL answer', () => {

0 commit comments

Comments
 (0)