Skip to content

Commit 0a34803

Browse files
test(spec): security, ai, identity, integration, migrations, marketplace, meta-spelling and studio test titles state each cited decision in words instead of a tracker number (stage 14) (#21799)
Part of #20749 Clause-②: no Stage 14 of this card, and the fifth area of class (e): the test strings shipped under `packages/spec/src`, as ruled in `5902360492` on #20513. This stage takes the eight small directories together: `security/`, `ai/`, `identity/`, `integration/`, `migrations/`, `marketplace/`, `meta-spelling/` and `studio/`. Their 91 test-title and test-string literals carried 96 tracker ids citing 65 records. 94 ids in 89 literals now either state what their record decided, in words (form D), or are dropped where the title already says it. Two ids stay, for the reason given below. Text only: no assertion, identifier, test count or code comment changes. ## Census at the base (`e83c9f6154`) Instruments: `census10.cjs` (md5 `9d08602ab972b4b8643c90d64d40fa41`), `census.cjs` (md5 `6e42a45a926d375013c32d62f16a296e`) and `census-wide.cjs` (md5 `c98410a19529c439adb0afbfb00026a2`), byte-identical to the copies stages 10 to 13 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. The worktree was cut from `origin/main` at `e83c9f6154`, one commit past the claim's `8256a4b272`. That commit touches only `api/error-code-ledger.zod.ts`, which is not a test file, so the test census is the same at both. Both instruments read **1414 messages / 1500 ids in 315 files**, the seat's reading at `8256a4b272`. That is one more than stage 13's head reading (1413 / 1499 at `72513933ee`), and the one id is in `ui/component-props-unknown-members.pin.test.ts`. It moved from 1 / 1 to 2 / 2 when #21764 (`4331a6b16c`, 2026-10-04T17:33Z) landed between the two readings. That commit removed one id-bearing string and added two: a `ruling:` value at `:322` that the assertion at `:417` matches with a regular expression on its number, and a `describe` title at `:596`. It joins the `ui/` stages. | directory | files | messages / ids | titles | other | |:--|--:|--:|--:|--:| | `data/` | 95 | 468 / 501 | 445 / 475 | 23 / 26 | | `ui/` | 81 | 393 / 416 | 375 / 398 | 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 | | **`security/`** (this PR) | 8 | **28 / 28** | 28 / 28 | 0 | | **`ai/`** (this PR) | 9 | **18 / 20** | 13 / 15 | 5 / 5 | | **`identity/`** (this PR) | 6 | **15 / 15** | 14 / 14 | 1 / 1 | | **`integration/`** (this PR) | 4 | **14 / 14** | 13 / 13 | 1 / 1 | | **`migrations/`** (this PR) | 2 | **9 / 12** | 9 / 12 | 0 | | **`marketplace/`** (this PR) | 2 | **3 / 3** | 3 / 3 | 0 | | **`meta-spelling/`** (this PR) | 1 | **2 / 2** | 2 / 2 | 0 | | **`studio/`** (this PR) | 2 | **2 / 2** | 2 / 2 | 0 | | `contracts/` | 1 | 1 / 1 | 0 | 1 / 1 | | **total** | **315** | **1414 / 1500** | **1330 / 1412** | **84 / 88** | The eight directories read **91 messages / 96 ids in 34 files**, the seat's figures. - **Controls.** Lit, a title with three ids: `migrations/migrations.test.ts:293`. Lit, an `expect` message: `identity/api-key-retirement.test.ts:82`. Dark: the comment at `security/permission.test.ts:309` ("The #12497 refusal shape was measured as") reads 0. Planted in a scratch copy of the head `security/explain.test.ts`: an id put back into a title reads 1 / 1, and an id put into a comment reads 0. - **A wider pattern** (any `#` plus digits) reads the same totals in seven of the eight directories. In `studio/` it reads 5 / 5 at the base, because three literals in two test files are hex colours (`#7c3aed`, `#2563eb`, `#94a3b8`). None matches the gate's pattern. - **At the head:** 1325 messages / 1406 ids in 282 files. `ai/` reads 2 / 2 (the two needles below), and the other seven directories read 0 / 0. Nothing outside the eight moved. The wider pattern adds only the three hex colours. ## How the area was chosen Stage 10's rule ranks whole first-level directories by ids and takes the busiest within about 10% of the ~100-id bound. `data/` (501), `ui/` (416), `api/` (201) and `system/` (165) each exceed it alone, and the files directly in `src/` (120) are 20% over. The eight small directories read 96 together, within the bound. That is the group the stage-12 and stage-13 ACCEPTs named, so the rule needed no second pass. **Named for the next stages** (the head census, 1325 / 1406): - `data/` 501 in five stages. It has one subdirectory, so the files directly under it go in name order, in groups near the bound: 1. `aggregate-field-type-compatibility.test.ts` to `default-value-tokens.test.ts`: 22 files, 109 ids; 2. `document.test.ts` to `filter-dotted-head.test.ts`: 21 files, 109 ids; 3. `filter-empty-operator.test.ts` to `hook-body.test.ts`: 21 files, 108 ids; 4. `hook.test.ts` to `record-surface.test.ts`: 16 files, 107 ids; 5. `search-fields.test.ts` to `validation.test.ts` (8 files, 16 ids) with `data/driver/` (7 files, 52 ids): 68 ids. - `ui/` 416, about four stages. - `api/` 201, two. - `system/` 165, two. - The files directly in `src/`, 120, one. - The two needles left in `ai/build-progress.test.ts` and the one in `contracts/approval-service.test.ts`. Each leaves only together with the source docblock it pins. ## What each id became 29 literals (33 ids) now state a decision in words. 60 literals (61 ids) drop a number the title already explains. Every cited record was read with its comments through REST: 60 answer 200. #6362, #8715 and #14676 answer 404, and their decisions were read from the landing commits. `cloud#1967` and `cloud#2172` answer 403, because the cloud repository is not attached to this session. `cloud#1967`'s decision was read from what landed, and `cloud#2172` is one of the two needles that stay. | record(s) | literal | now reads | |:--|:--|:--| | #16870 | `security/explain.test.ts:413` | "the AUTHORING accept set refuses a readScope beside viewAllRecords, the pair this snapshot shape tolerates". The record refuses a depth axis beside the super-user bit that short-circuits it. | | #17189 | `security/high-privilege.test.ts:30` | "describeHighPrivilegeBits — an app-declared capability is not a platform system permission". Ruling (i): a name on the stack's declared capability list does not count as a system permission. | | #3391 | `security/permission.test.ts:545` | "EffectiveObjectPermissionSchema (response side: the server-resolved operations the UI renders)". The contract: the server resolves each object's effective operations, and the UI only renders what it is served. | | #6762 | `security/rls.test.ts:704` | "RowLevelSecurityPolicySchema.using — the published description advertises what the compiler lowers". The description was corrected to the subset ADR-0058 widened. | | #12699 (2) | `security/tenancy-posture.test.ts:21`, `:50` | "PlatformGlobalObjectsSchema — the objects a deployment exempts from the Layer 0 wall" and "OrgScopingEntitlementSchema — the deployment facts Layer 0 arming reads". | | #15813 | `security/tenant-layer0-verdict.test.ts:16` | "TenantLayer0VerdictSchema — the four verdicts the wall records on an operation". Ruling (i): `plugin-security` records the Layer 0 verdict it computed, and the publish site reads it. | | #3820, #3894 | `ai/agent.test.ts:74` | "agent.tools retirement (ADR-0064) — tombstoned; tools move into skills". `agent.tools[]` was removed, and the docs teach the action-to-skill path. | | #3278 | `ai/knowledge-source.test.ts:97` | An `it.each` row: "a dialect the protocol does not declare (`js`, a retired expression dialect, ADR-0058 addendum)". | | #7113 (2) | `ai/skill-trigger-condition-value-shape.test.ts:47`, `:175` | "a set operator carrying a scalar is refused at authoring time" and "the value-shape refinement does not disturb the carrier". The value is shaped by its operator at authoring time. | | #3896 | `ai/skill.test.ts:195` | "retired `triggerPhrases` — phrases never routed a skill; triggerConditions do". See the note below the table. | | #8715 | `identity/api-key-retirement.test.ts:82` | A declared `expect` message: "... must have zero holders after the ApiKeySchema retirement". The record answers 404. `2c86fe3ea7` retired the fictional `ApiKeySchema`, so `sys_api_key` has one declaration. | | #18509 (2) | `identity/identity.test.ts:88`, `identity/organization.test.ts:132` | "UserSchema.image accept set — null, the shape better-auth serves", and the same for `OrganizationSchema.logo` (landed as `b9d5422142`). | | #11965 | `identity/platform-admin-capabilities.test.ts:10` | "ADMIN_FULL_ACCESS_CAPABILITIES — the one platform-admin list plugin-security imports". Choice 6A. | | #8681 | `identity/platform-admin-capabilities.test.ts:34` | "the wildcard grants NO export — export stays an opt-in axis, pinned at the declaration's new home". Direction (a): `allowExport` left the admin sets' wildcard entry. | | #3017 | `integration/connector-provider-errors.test.ts:13` | "connector provider upstream-unavailable classification — an unreachable upstream degrades instead of aborting boot". Configuration faults stay fatal. | | #4395 | `integration/connector.test.ts:244` | "ConnectorActionSchema.effect — declares whether an action reads or writes". The ruling: an optional read-or-write declaration the run summary counts. | | #6362 | `integration/connector.test.ts:846` | "ADR-0010 protection envelope — preserved, never silently stripped". The record answers 404. The decision is read from `b5404f496f`. | | #14676 (2) | `integration/connector.test.ts:1163`, `:1195` | A declared `expect` message, "... after the errorMapping retirement", and "the errorMapping retirement is registered under ADR-0087". The record answers 404. The decision is read from `13c48c2a55`, which retired the eleven `connector.errorMapping` keys. | | #4722 | `migrations/migrations.test.ts:258` | "keeps `visible` client-side only — the half the server-side item gate did NOT change". The record made the server filter the nav entries inside `areas[]`. | | #4651 | `migrations/migrations.test.ts:268` | "still carries the area-gate removal history the step exists to explain". Ruling B removed the fail-open area keys. | | #5015, #4610, #5781 | `migrations/migrations.test.ts:293` | "protocol-17 NotificationAction / EmbedConfig entry — stops republishing the falsified zero-consumer claim". | | #4610 | `migrations/migrations.test.ts:299` | "finds the entry, and it still explains the dual-source orphaning (anti-vacuity)". | | #5561, #6844 | `migrations/migrations.test.ts:333` | "protocol-17 resumeAuthority default-flip entry — supportsPause is enforced now, so stop asking for a hand-audit". | | #17594 | `migrations/migrations.test.ts:455` | "protocol-18 element:filter / element:form entry — the chain NAMES the bare node it leaves standing". | | #19056 | `migrations/migrations.test.ts:555` | "every major the floor move to 16 dropped is refused, by name". The maintainer's ruling raised the migration support floor from 10 to 16. | **Dropped only (61 ids):** #123, #3544, #4001 (4), #4641, #4703, #4737, #4911, #5337, #5481, #5515 (4), #5685, #5955, #6628, #6698, #6861, #6919, #7113 (4), #7319 (2), #7990, #8326 (6), #8424, #8715, #9885, #11503, #12497, #12840 (2), #14103, #14676 (2), #14825, #15028, #15680, #15813, #16870, #17425, #17487, #18728 (4), #18978, #20321, #21260 (2), `cloud#1967`. - Each of these titles already states the decision it pins: for example "the cap is 200: exactly 200 ids parse, 201 are refused (never truncated)" for #8326, or "unknown keys are rejected, not stripped" for #4001. In `skill-trigger-condition-value-shape.test.ts:130`, "(#5685: no stricter than the runtime)" became "— no stricter than the runtime". - **`#123`** in `ai/conversation.test.ts:294` (`'Support Chat - Case #123'`) is a placeholder that cites no record: objectstack#123 is an unrelated broken-links report. The string is a fixture's session name, an input only. No assertion reads it, so dropping the number moves nothing. - **`cloud#1967`** in `ai/solution-blueprint.test.ts:674`: the record answers 403. Its decision is read from `3e3ecb0e8f` and its CHANGELOG entry: the strict mirror the design model generates against carries the applier's `SNAKE_CASE` constraints. The title already says "VALUE parity". - **`#3896`** is the sharing-rule card (`POST /data/sharing/rules` bypassing `SharingRuleSchema`). The skill title cited it as an "audit close-out", the batch that removed `triggerPhrases` along with other dead clusters. The title now states the decision that landed with the key's tombstone (`ai/skill.zod.ts:386`) and its conversion entry (`conversions/registry.ts:2744`): phrases were never matched, and activation is `triggerConditions` intersected with the agent's `skills[]`. - **The `it.each` rows** at `ai/knowledge-source.test.ts:97` and `:98` feed a `%s` placeholder. vitest 4.1.11 formats `%s` with `String(value)` and does not truncate it (`@vitest/utils` `baseFormat`). Only `$name` interpolation goes through the 40-character `objDisplay`. Both rows are short anyway, and the name comparison below confirms both full names. ## The two ids that stay `ai/build-progress.test.ts:236` and `:237` are `expect(SOURCE).toContain('cloud#2172')` and `expect(SOURCE).toContain('objectui#7388 block 2')`. They are not titles. They are the expected values of assertions that read the `ai/build-progress.zod.ts` docblock and pin that its liveness watch names its two carriers (`:84-85`). Changing them needs a code comment and assertion logic, which this claim excludes. They leave together with that docblock's citations, like the `contracts/approval-service.test.ts:274` needle. ## 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. No `__snapshots__` directory exists under the eight directories, and no `.snap` file is tracked under `packages/spec`. - **Projects:** two touched files are listed in `packages/spec/vitest.repo-tests.json`: `ai/tool-confirmation-prescription-tense.pin.test.ts` and `identity/position-delegatable-enforcer.pin.test.ts`. Both were run in the `repo` project at the base and at the head, and the other 32 in `local`. - **By substring:** every old literal, plus a window around each id (263 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 hits are: - **the plan's own siblings:** `unknown keys are rejected, not stripped (#4001)` in the four files this PR edits; - **this card's later stages:** same-text titles in `data/driver-nosql.test.ts:375`, `data/driver/memory.test.ts:548`, `data/driver/turso.test.ts:172` and `ui/dashboard.test.ts:717` (`carries its unit (#15680)`), `data/object.test.ts:105` (`(#5955)`) and `ui/action.test.ts:1612` (`#3896 close-out`). They are already in the `data/` and `ui/` census; - **comments and release text:** the comment at `ai/agent.test.ts:193`, the `security/sharing.zod.ts:261` docblock, two `packages/spec/CHANGELOG.md` entries and `content/docs/releases/v17/17-0.mdx:326`. None reads a test title, and none is this card's share. - **Migration tooling and generated files:** `docs/protocol-upgrade-guide.md`, `packages/spec/spec-changes.json`, `packages/spec/src/migrations/registry.ts` and the 842 files under `migrations/entries/`, together with `spec-changes.ts`, `chain.ts`, `index.ts` and `types.ts`. Searched for every changed literal whole, at the base and at the head (178 needles), they read 0 hits. The lit controls `resumeAuthority`, `ui-notification-action-embed-config-retired` and `element-filter-and-form-node-refused` hit 5, 4 and 2 files. `migrations.test.ts` finds each entry by its `id`, never by a title. ## 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 `ai/conversation.test.ts:294`, `ai/knowledge-source.test.ts:97` and `:98`, `identity/api-key-retirement.test.ts:82` and `integration/connector.test.ts:1163`. - **Result:** 34 of 34 files SAME on all three legs, as predicted in writing before the run. `ai/build-progress.test.ts` reads SAME with 0 changed. - **Totals:** 89 changed literals, 84 titles and 5 declared. The diff's `+` and `-` lines are exactly the 89 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 `e83c9f6154`, and at the head, with `--project local --project repo`. Both sides read 911 / 911 passed, with the same count and status sequence per file in 34 of 34. 310 full test names change, and each equals the base name with the planned replacements applied (0 mismatches). No full name repeats on either side. ## 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/security/permission.zod.ts`, `src/ai/knowledge-source.zod.ts` and `dist/security/index.js` are in it. - In the built `dist/`, five new phrases and four old literals 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 `b364b8179b`) - `pnpm turbo run build` over all packages: 71 / 71. - `@objectstack/spec`: - `vitest run --project local`: 615 files, 18358 passed, 1 todo. - `typecheck` exit 0, including `check:test-typecheck` (52 files / 246 errors / 135 pinned signatures held). Its program holds all 34 touched files, counted with `tsc --listFilesOnly -p tsconfig.test.json`. - **Gates:** `dispatch-gates --commands` derived 79 families, the same set as stage 13, 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 reads 0 errors and 0 warnings. The population comes from ESLint's own config: 34 configured, 0 ignored. No file sets `parserOptions.project` or `projectService`, so no untouched file's verdict can move. - `check-governed-merges --test`: NOT governed, 178 changed lines. ## Acceptance notes - **The two `build-progress` needles** stay with the `ai/build-progress.zod.ts` docblock they pin. The `contracts/approval-service.test.ts:274` needle is untouched, as the claim required. - **Same-id test titles in other packages** are their lanes' test-string shares. A search of `describe` / `it` / `test` lines outside `packages/spec` finds 90 lines citing ids this PR handled, in 16 packages: `plugin-security` 28 (14 files), `rest` 20 (7), `service-automation` 11 (7), `lint` 5 (4), `plugin-audit` 4 (3), `runtime` 4 (2), `qa/dogfood` 3 (2), `plugin-hono-server` 3 (1), `client` 2, `platform-objects` 2, `plugin-sharing` 2, `cli` 2, `objectql` 1, `connectors` 1, `formula` 1 and `plugin-approvals` 1. - **Code comments still carry ids** in these files and their sources, for example `ai/agent.test.ts:193` and `security/sharing.zod.ts:261`. Comments are not this card's share, and none is touched here. - **`origin/main` moved** two commits past the base before this PR opened (#21780, #21783). Neither touches `packages/spec` or any file here, so nothing was merged. The gate reconciliation noted that two baselines changed across them (`query-options-erasure`, `slot-lookup`). This diff feeds neither, and the queue re-runs both on the merged generation. --- _Generated by [Claude Code](https://claude.ai/code/session_01T9u38rswFp5Rw8DswRUReJ)_ Co-authored-by: Claude <noreply@anthropic.com>
1 parent d13df0c commit 0a34803

33 files changed

Lines changed: 89 additions & 89 deletions

‎packages/spec/src/ai/agent.test.ts‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ describe('AIModelConfigSchema', () => {
7171
});
7272
});
7373

74-
describe('agent.tools retirement (ADR-0064 / #3820, tombstoned in #3894)', () => {
74+
describe('agent.tools retirement (ADR-0064) — tombstoned; tools move into skills', () => {
7575
it('REJECTS a legacy inline tools array, with the fix in the message', () => {
7676
// Tombstoned, not deleted: AgentSchema is `strictObject`, so a plain
7777
// deletion would reject the key with a generic unknown-key error.

‎packages/spec/src/ai/conversation.test.ts‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -291,7 +291,7 @@ describe('ConversationSessionSchema', () => {
291291
it('should accept full session with messages', () => {
292292
const session = {
293293
id: 'session-1',
294-
name: 'Support Chat - Case #123',
294+
name: 'Support Chat - Case',
295295
context: {
296296
sessionId: 'session-1',
297297
userId: 'user-1',
@@ -590,7 +590,7 @@ describe('Real-World Conversation Examples', () => {
590590
// `ConversationAnalytics` is runtime-emitted, so the silent-strip alternative
591591
// is the real hazard: this shape is not strict, and a producer still writing
592592
// `duration` would have lost the one measurement on the row with no error at all.
593-
describe('ConversationAnalytics.duration carries its unit (#15680)', () => {
593+
describe('ConversationAnalytics.duration carries its unit', () => {
594594
const base = {
595595
sessionId: 'session-1',
596596
totalMessages: 10,

‎packages/spec/src/ai/knowledge-source.test.ts‎

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ const SOURCE: KnowledgeSource = {
4848

4949
const CRON_5_FIELD = '0 3 * * *';
5050

51-
describe('KnowledgeRefreshPolicySchema.cron — the typed cron slot (#14825)', () => {
51+
describe('KnowledgeRefreshPolicySchema.cron — the typed cron slot', () => {
5252
it('positive control: a 5-field cron on a full knowledge source parses and normalizes to the cron envelope', () => {
5353
const r = KnowledgeSourceSchema.safeParse({ ...SOURCE, refresh: { cron: CRON_5_FIELD } });
5454
expect(r.success, r.success ? '' : JSON.stringify(r.error.issues)).toBe(true);
@@ -94,8 +94,8 @@ describe('KnowledgeRefreshPolicySchema.cron — the typed cron slot (#14825)', (
9494
});
9595

9696
it.each([
97-
['a dialect the protocol does not declare (`js`, retired at #3278, ADR-0058 addendum)', 'js'],
98-
['a declared dialect that is not this slot\'s (`cel`, #15028)', 'cel'],
97+
['a dialect the protocol does not declare (`js`, a retired expression dialect, ADR-0058 addendum)', 'js'],
98+
['a declared dialect that is not this slot\'s (`cel`)', 'cel'],
9999
])('refuses an envelope naming %s with ONE `invalid_union` at `cron` whose message is the cron dialect-only sentence', (_label, dialect) => {
100100
const r = KnowledgeRefreshPolicySchema.safeParse({ cron: { dialect, source: 'x' } });
101101
expect(r.success).toBe(false);

‎packages/spec/src/ai/skill-trigger-condition-value-shape.test.ts‎

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ function valueIssue(result: ReturnType<typeof parse>) {
4444
return issues[0]!;
4545
}
4646

47-
describe('#7113 — the reported shape is refused at authoring time', () => {
47+
describe('a set operator carrying a scalar is refused at authoring time', () => {
4848
it('refuses the card example: a set operator carrying a scalar', () => {
4949
const result = parse({ field: 'userRole', operator: 'in', value: 'admin' });
5050
const issue = valueIssue(result);
@@ -72,7 +72,7 @@ describe('#7113 — the reported shape is refused at authoring time', () => {
7272
});
7373
});
7474

75-
describe('#7113 — list operators require an array', () => {
75+
describe('list operators require an array', () => {
7676
it.each(SKILL_TRIGGER_LIST_VALUE_OPERATORS)('%s refuses a scalar', (operator) => {
7777
const issue = valueIssue(parse({ field: 'objectName', operator, value: 'lead' }));
7878
expect(issue.code).toBe('custom');
@@ -109,7 +109,7 @@ describe('#7113 — list operators require an array', () => {
109109
});
110110
});
111111

112-
describe('#7113 — identity operators require a string', () => {
112+
describe('identity operators require a string', () => {
113113
it.each(SKILL_TRIGGER_SCALAR_VALUE_OPERATORS)('%s refuses an array', (operator) => {
114114
const issue = valueIssue(parse({ field: 'objectName', operator, value: ['lead'] }));
115115
expect(issue.code).toBe('custom');
@@ -127,7 +127,7 @@ describe('#7113 — identity operators require a string', () => {
127127
});
128128
});
129129

130-
describe('#7113 — `contains` keeps BOTH shapes (#5685: no stricter than the runtime)', () => {
130+
describe('`contains` keeps BOTH shapes — no stricter than the runtime', () => {
131131
it('accepts a string comparand — the substring branch', () => {
132132
expect(parse({ field: 'viewName', operator: 'contains', value: 'kanban' }).success).toBe(true);
133133
});
@@ -147,7 +147,7 @@ describe('#7113 — `contains` keeps BOTH shapes (#5685: no stricter than the ru
147147
});
148148
});
149149

150-
describe('#7113 — the exported vocabularies are the contract, not a copy', () => {
150+
describe('the exported vocabularies are the contract, not a copy', () => {
151151
it('the two vocabularies are disjoint and both subsets of the operator enum', () => {
152152
const all = [
153153
...SKILL_TRIGGER_LIST_VALUE_OPERATORS,
@@ -172,7 +172,7 @@ describe('#7113 — the exported vocabularies are the contract, not a copy', ()
172172
});
173173
});
174174

175-
describe('#7113 — the refinement does not disturb the carrier', () => {
175+
describe('the value-shape refinement does not disturb the carrier', () => {
176176
it('an unrelated operator/value pair still parses through Skill.triggerConditions', () => {
177177
const skill = SkillSchema.parse({
178178
name: 'order_management',

‎packages/spec/src/ai/skill.test.ts‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -192,7 +192,7 @@ describe('defineSkill', () => {
192192
});
193193
});
194194

195-
describe('#3896 close-out — retired `triggerPhrases`', () => {
195+
describe('retired `triggerPhrases` — phrases never routed a skill; triggerConditions do', () => {
196196
it('REJECTS the retired key with the routing prescription', () => {
197197
let message = '';
198198
try {

‎packages/spec/src/ai/solution-blueprint.test.ts‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -671,7 +671,7 @@ describe('strict mirror ↔ lenient schema — key parity', () => {
671671
// because the model happened to retry with a repaired blueprint the user never
672672
// saw. Two declarations of one contract, disagreeing about values.
673673
// ---------------------------------------------------------------------------
674-
describe('strict mirror ↔ lenient schema — VALUE parity (cloud#1967)', () => {
674+
describe('strict mirror ↔ lenient schema — VALUE parity', () => {
675675
/** The regex a zod string leaf enforces, or null when it enforces none. */
676676
const patternOf = (schema: any): string | null => {
677677
const checks = schema?.def?.checks;

‎packages/spec/src/ai/tool-confirmation-prescription-tense.pin.test.ts‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -142,7 +142,7 @@ function aiDoorBody(): string {
142142
return source.slice(start, end === -1 ? source.length : end);
143143
}
144144

145-
describe('[#17487] the confirmation-gate prescriptions match the door that runs', () => {
145+
describe('the confirmation-gate prescriptions match the door that runs', () => {
146146
it('anchors on real text in all three carriers', () => {
147147
// Anti-vacuity for every assertion below: an empty carrier would pass
148148
// "carries no denial" by reading nothing.

‎packages/spec/src/ai/tool.test.ts‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -250,7 +250,7 @@ describe('defineTool', () => {
250250
expect(message).not.toContain('Did you mean');
251251
});
252252

253-
it('emission order: which key is wrong → the fix → the history, last (#5955)', () => {
253+
it('emission order: which key is wrong → the fix → the history, last', () => {
254254
// The template's ordering contract, asserted on this surface because the
255255
// fold is what brings this surface under it. `history` sat in the middle
256256
// until #5955 and pushed the fix past ~character 220 on the single-line

‎packages/spec/src/identity/api-key-retirement.test.ts‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ import {
5252
//
5353
// Form follows #4988 / #5055 / #8075: resolved symbol identity over every
5454
// public entry via the build-time `export-origins/` artifact.
55-
describe('[#8715] identity/ ApiKeySchema retirement', () => {
55+
describe('identity/ ApiKeySchema retirement', () => {
5656
/** The 3 names the retired def exported (1 schema const + 2 types). */
5757
const RETIRED_NAMES = ['ApiKeySchema', 'ApiKey', 'ApiKeyParsed'] as const;
5858

@@ -79,7 +79,7 @@ describe('[#8715] identity/ ApiKeySchema retirement', () => {
7979

8080
// ── ABSENCE (every entry, not just ./identity) ────────────────────────
8181
for (const name of RETIRED_NAMES) {
82-
expect(holdersOf(name), `${name} must have zero holders after #8715`).toEqual([]);
82+
expect(holdersOf(name), `${name} must have zero holders after the ApiKeySchema retirement`).toEqual([]);
8383
}
8484

8585
// ── SURVIVAL ──────────────────────────────────────────────────────────

‎packages/spec/src/identity/identity.test.ts‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,7 @@ describe('UserSchema', () => {
8585
* drop of `.url()` (which would start admitting `''` and `'not-a-url'`) goes
8686
* red here rather than passing as "still accepts null".
8787
*/
88-
describe('[#18509] UserSchema.image accept set', () => {
88+
describe('UserSchema.image accept set — null, the shape better-auth serves', () => {
8989
const base = {
9090
id: 'user_123',
9191
email: 'test@example.com',
@@ -199,7 +199,7 @@ describe('AccountSchema', () => {
199199
});
200200
});
201201

202-
describe('Session is not declared here (#4641)', () => {
202+
describe('Session is not declared here', () => {
203203
// Pin: this module no longer declares the bare `SessionSchema` name. The pin is
204204
// compile-time (`typeof import` is type-level only — no runtime barrel load):
205205
// if the name is re-added here, the conditional type flips to `true` and the

0 commit comments

Comments
 (0)