Skip to content

Commit 83d1eb3

Browse files
committed
test(spec): automation test titles state each cited decision in words instead of a tracker number
The 105 test-title and test-message literals under packages/spec/src/automation that carried a tracker id (110 ids, 55 records) now either state what the cited record decided, or drop a citation the title already explains. Text only: no assertion, fixture value, test count or code comment changes. Claude-Session: https://claude.ai/code/session_01T9u38rswFp5Rw8DswRUReJ Co-authored-by: Claude <noreply@anthropic.com>
1 parent 7e0066a commit 83d1eb3

21 files changed

Lines changed: 105 additions & 105 deletions

‎packages/spec/src/automation/approval.test.ts‎

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -132,7 +132,7 @@ describe('ORG_MEMBERSHIP_LEVELS derives from BUILTIN_MEMBERSHIP_ROLES', () => {
132132
// record-backed kinds MUST match the engine's resolution semantics
133133
// (`plugin-approvals` resolveApproverSpec / expand*Users) — these assertions
134134
// pin the object names and stored fields the engine actually queries.
135-
describe('APPROVER_VALUE_BINDINGS (#3508)', () => {
135+
describe('APPROVER_VALUE_BINDINGS — an approver value is picked from the records the engine resolves', () => {
136136
it('covers every ApproverType member', () => {
137137
for (const t of ApproverType.options) {
138138
expect(APPROVER_VALUE_BINDINGS[t]).toBeDefined();
@@ -173,7 +173,7 @@ describe('APPROVER_VALUE_BINDINGS (#3508)', () => {
173173
// #3508 follow-up: `xRef.map` names a picker KIND but never said where that
174174
// picker's candidates live — which is how the designer came to query the
175175
// metadata registry for data records. The data contract now ships on the wire.
176-
describe('APPROVER_VALUE_SOURCES (#3508 follow-up)', () => {
176+
describe('APPROVER_VALUE_SOURCES — where each picker finds its candidates, published on the wire', () => {
177177
it('covers every ApproverType member, exactly like the bindings it projects', () => {
178178
for (const t of ApproverType.options) {
179179
expect(APPROVER_VALUE_SOURCES[t], `no source published for '${t}'`).toBeDefined();
@@ -309,7 +309,7 @@ describe('ApprovalNodeConfigSchema', () => {
309309
expect(() => ApprovalNodeConfigSchema.parse({ ...minimal, behavior: 'weighted' })).toThrow();
310310
});
311311

312-
it('accepts quorum / per_group behaviors with minApprovals and grouped approvers (#3266)', () => {
312+
it('accepts quorum / per_group behaviors with minApprovals and grouped approvers', () => {
313313
const quorum = ApprovalNodeConfigSchema.parse({ ...minimal, behavior: 'quorum', minApprovals: 2 });
314314
expect(quorum.behavior).toBe('quorum');
315315
expect(quorum.minApprovals).toBe(2);
@@ -486,7 +486,7 @@ describe('ApprovalEscalationSchema', () => {
486486
// escalation block exists at all; within a block carrying timeoutHours,
487487
// escalation is ON unless explicitly turned off. Declared in
488488
// DEFAULT_CHANGES_BY_MAJOR (17) — this pin is what keeps the fingerprint honest.
489-
it('defaults enabled to true — a block carrying timeoutHours is live unless explicitly off (#12278)', () => {
489+
it('defaults enabled to true — a block carrying timeoutHours is live unless explicitly off', () => {
490490
const omitted = ApprovalEscalationSchema.parse({ timeoutHours: 24 });
491491
expect(omitted.enabled).toBe(true);
492492
const explicit = ApprovalEscalationSchema.parse({ enabled: false, timeoutHours: 24 });
@@ -512,7 +512,7 @@ describe('normalizeDecisionOutputs', () => {
512512
]);
513513
});
514514

515-
it('carries the widget hints and the required flag through (objectui#2955)', () => {
515+
it('carries the widget hints and the required flag through, for the decision dialog to render and enforce', () => {
516516
expect(normalizeDecisionOutputs([
517517
{ key: 'positions', label: 'Co-signers', type: 'position', multiple: true, required: true },
518518
])).toEqual([
@@ -540,7 +540,7 @@ describe('normalizeDecisionOutputs', () => {
540540
// a v17-new surface, tightened before stored volume exists. The published JSON
541541
// schema now carries additionalProperties:false into the Studio form AND
542542
// registerFlow()'s per-node config validation (#4027/#4040) — asserted below.
543-
describe('unknown keys are rejected, not stripped (#4001)', () => {
543+
describe('unknown keys are rejected, not stripped', () => {
544544
const unknownKeyIssue = (schema: { safeParse: (v: unknown) => any }, value: unknown) => {
545545
const result = schema.safeParse(value);
546546
expect(result.success).toBe(false);
@@ -607,7 +607,7 @@ describe('unknown keys are rejected, not stripped (#4001)', () => {
607607
* cases fail loudly instead, which is what "declared = enforced" needs on
608608
* the declaring side.
609609
*/
610-
it('accepts `required` — the key the runtime enforces (#4525)', () => {
610+
it('accepts `required` — the key the runtime enforces', () => {
611611
expect(DecisionOutputDefSchema.parse({ key: 'next_reviewers', required: true }))
612612
.toEqual({ key: 'next_reviewers', required: true });
613613
expect(DecisionOutputDefSchema.parse({ key: 'note', required: false }))

‎packages/spec/src/automation/builtin-node-config.test.ts‎

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ function unknownKeyMessage(schema: Parseable, value: unknown): string | undefine
5252
return result.error!.issues.find((i) => i.code === 'unrecognized_keys')?.message;
5353
}
5454

55-
describe('CRUD config contracts — strict as of #4001 批 9', () => {
55+
describe('CRUD config contracts — an unknown key is refused, not stripped', () => {
5656
it('accepts every declared key on each of the four', () => {
5757
expect(GetRecordConfigSchema.parse({
5858
objectName: 'lead', filter: { status: 'new' }, fields: ['id'], limit: 5, outputVariable: 'leads',
@@ -85,7 +85,7 @@ describe('CRUD config contracts — strict as of #4001 批 9', () => {
8585
['update_record', UpdateRecordConfigSchema, { objectName: 'lead' }],
8686
['delete_record', DeleteRecordConfigSchema, { objectName: 'lead' }],
8787
] as ReadonlyArray<[string, Parseable, Record<string, unknown>]>)(
88-
'%s: prescribes `filter` for the retired `filters` spelling, and names the #3810 hazard',
88+
'%s: prescribes `filter` for the retired `filters` spelling, and names the match-everything-write hazard',
8989
(_nodeType, schema, base) => {
9090
const message = unknownKeyMessage(schema, { ...base, filters: { status: 'stale' } })!;
9191
expect(message).toContain('flow-node-crud-filter-alias');
@@ -204,7 +204,7 @@ describe('CRUD config contracts — strict as of #4001 批 9', () => {
204204
});
205205
});
206206

207-
describe('ScreenConfigSchema / ScreenFieldConfigSchema — strict as of #4001 批 9', () => {
207+
describe('ScreenConfigSchema / ScreenFieldConfigSchema — an unknown key is refused, not stripped', () => {
208208
it('accepts the flat and object-form shapes in full', () => {
209209
expect(ScreenConfigSchema.safeParse({
210210
title: 'Details', description: 'Fill this in', waitForInput: true,
@@ -249,7 +249,7 @@ describe('ScreenConfigSchema / ScreenFieldConfigSchema — strict as of #4001
249249
});
250250
});
251251

252-
describe('ScreenFieldConfigSchema — the bound pair, help text and lookup target (#17306)', () => {
252+
describe('ScreenFieldConfigSchema — the bound pair, help text and lookup target', () => {
253253
const BASE = { name: 'discount', type: 'number' };
254254

255255
// ── Direction 1: the three intents are now expressible ──────────────────
@@ -397,7 +397,7 @@ describe('ScreenFieldConfigSchema — the bound pair, help text and lookup targe
397397
});
398398
});
399399

400-
describe('MapConfigSchema — strict as of #4001 批 9', () => {
400+
describe('MapConfigSchema — an unknown key is refused, not stripped', () => {
401401
it('accepts every declared key', () => {
402402
expect(MapConfigSchema.parse({
403403
collection: '{tasks}', flowName: 'one_task_signoff', iteratorVariable: 'item',
@@ -430,7 +430,7 @@ describe('MapConfigSchema — strict as of #4001 批 9', () => {
430430

431431
// ─── assignment (#14149) ─────────────────────────────────────────────
432432

433-
describe('assignment value contract — a CEL envelope beside `{token}` interpolation (#14149)', () => {
433+
describe('assignment value contract — a CEL envelope beside `{token}` interpolation', () => {
434434
const DIGEST_SOURCE = 'joinNonEmpty(overdue_tasks.map(t, t.subject), "\\n")';
435435
const DIGEST_ENVELOPE = { dialect: 'cel', source: DIGEST_SOURCE };
436436

@@ -568,7 +568,7 @@ describe('assignment value contract — a CEL envelope beside `{token}` interpol
568568
* registered, and faulted at run time (the `ast`-only one with the engine's
569569
* own prescription; the blank one with a parse error on `" "`).
570570
*/
571-
describe('assignment value envelope — an evaluated slot requires what the engine can evaluate (#15430)', () => {
571+
describe('assignment value envelope — an evaluated slot requires what the engine can evaluate', () => {
572572
const AST_ONLY = { dialect: 'cel', ast: { kind: 'const', value: 1 } };
573573
const BLANK_SOURCE = { dialect: 'cel', source: ' ' };
574574

@@ -627,7 +627,7 @@ describe('assignment value envelope — an evaluated slot requires what the engi
627627
* same structural reason as the sibling slot: `z.record()`'s open-key branch
628628
* skips it before any key schema — including `.min(1)` — ever runs.
629629
*/
630-
describe('AssignmentConfigSchema.assignments — __proto__ pre-parse guard, constructor/prototype UNCHANGED (#17852 / #18847)', () => {
630+
describe('AssignmentConfigSchema.assignments — __proto__ pre-parse guard, constructor/prototype UNCHANGED', () => {
631631
it('refuses `assignments` carrying a `__proto__` own key, named at `assignments.__proto__`', () => {
632632
// `JSON.parse` is what makes `__proto__` an OWN enumerable key — an
633633
// object literal's `{ __proto__: ... }` sets the actual prototype
@@ -688,7 +688,7 @@ describe('AssignmentConfigSchema.assignments — __proto__ pre-parse guard, cons
688688
* `__proto__` must be refused LOUDLY — told apart here from the two silent
689689
* outcomes it could otherwise have (silently dropped, silently kept).
690690
*/
691-
describe('AssignmentConfigSchema — top-level __proto__ refused at the catchall (#19151)', () => {
691+
describe('AssignmentConfigSchema — top-level __proto__ refused at the catchall', () => {
692692
/**
693693
* The three outcomes an authored key can meet, discriminated by one
694694
* function so a test cannot accidentally assert the wrong one. A bare
@@ -807,7 +807,7 @@ describe('AssignmentConfigSchema — top-level __proto__ refused at the catchall
807807
* CEL value envelope), the edge #14149 accepted on `assignments.*`. Everything
808808
* else parses exactly as before.
809809
*/
810-
describe('CRUD `fields` value contract — the CEL value envelope beside `{token}` templates (#19938)', () => {
810+
describe('CRUD `fields` value contract — the CEL value envelope beside `{token}` templates', () => {
811811
const PRICE_ENVELOPE = { dialect: 'cel', source: 'round(price * 100) / 100.0' };
812812
const configs = [
813813
['create_record', CreateRecordConfigSchema, (fields: unknown) => ({ objectName: 'quote', fields })],

‎packages/spec/src/automation/control-flow.test.ts‎

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ describe('LoopConfigSchema', () => {
6161
).toThrow();
6262
});
6363

64-
it('emits the xExpression:"template" marker on `collection` through z.toJSONSchema (objectui #2670)', () => {
64+
it('emits the xExpression:"template" marker on `collection` through z.toJSONSchema, so the flow designer renders it as a template', () => {
6565
// The marker rides the same `.meta()` → JSON-Schema channel as
6666
// `xRef` / `xEnumDeprecated`, telling the flow designer `collection` is an
6767
// `interpolate()` `{var}` template (not bare CEL).
@@ -77,7 +77,7 @@ describe('LoopConfigSchema', () => {
7777
);
7878
});
7979

80-
it('accepts an inline array collection — the union map.collection declares (#4277)', () => {
80+
it('accepts an inline array collection — the union map.collection declares', () => {
8181
// The executor has always resolved an already-an-array collection (shared
8282
// logic with `map`); the string-only declaration under-declared what it
8383
// reads, which the execute-time parse wiring surfaced.
@@ -272,7 +272,7 @@ describe('validateControlFlow', () => {
272272

273273
// ─── [#4001 批 10] unknown keys are rejected, not stripped ──────────────────
274274

275-
describe('[#4001] control-flow strictness — per shape', () => {
275+
describe('control-flow strictness — an unknown key is refused, per shape', () => {
276276
it('FlowRegion: `name` and `label` get wrong-layer prescriptions, not renames', () => {
277277
for (const [key, expected] of [
278278
['name', 'A region is not named'],
@@ -438,7 +438,7 @@ describe('TryCatchErrorValueSchema', () => {
438438
expect(TryCatchErrorValueSchema.parse(both)).toEqual(both);
439439
});
440440

441-
it('`code` is an OPEN string, not a closed enum — a third-party or tenant-authored code parses (ADR-0112 D3/D4 + #9106)', () => {
441+
it('`code` is an OPEN string, not a closed enum — a third-party or tenant-authored code parses (ADR-0112 D3/D4)', () => {
442442
// `NodeExecutor` is third-party-registrable and the code vocabulary is
443443
// `StandardErrorCode` ∪ registered ledger codes ∪ tenant-authored codes,
444444
// so a closed type would be false the moment anyone registers an executor.
@@ -491,7 +491,7 @@ describe('TryCatchErrorValueSchema', () => {
491491
// `MAX_REGION_DEPTH` (32) `analyzeRegion`'s own `duplicate node id` line is
492492
// the only refusal of a within-region duplicate. `flow.test.ts`'s
493493
// `the seam at MAX_REGION_DEPTH` case pins that hand-off.
494-
describe('[#4001] validateControlFlow and the key gate meet at the region-slot seam', () => {
494+
describe('validateControlFlow and the unknown-key gate meet at the region-slot seam', () => {
495495
const flowWith = (cfg: Record<string, unknown>, type = LOOP_NODE_TYPE) =>
496496
({ nodes: [{ ...node('c1', type), config: cfg }] } as never);
497497

@@ -540,7 +540,7 @@ describe('[#4001] validateControlFlow and the key gate meet at the region-slot s
540540
expect(() => validateControlFlow(flowWith({ collection: '{items}', iteratorVariable: 'x' }))).not.toThrow();
541541
});
542542

543-
it('nested regions are key-checked at depth, like the structural check (#4389)', () => {
543+
it('nested regions are key-checked at depth, like the structural check', () => {
544544
let message = '';
545545
try {
546546
validateControlFlow(flowWith({

‎packages/spec/src/automation/end-node-outcome.test.ts‎

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ const flowEndingWith = (config: Record<string, unknown> | undefined): Flow => ({
4040

4141
const endConfigOf = (flow: { nodes: Array<{ config?: unknown }> }) => flow.nodes[1].config;
4242

43-
describe('EndConfigSchema — the `end` node contract (#14945)', () => {
43+
describe('EndConfigSchema — the `end` node contract: it may refuse the run with a message', () => {
4444
it('defaults `outcome` to `completed` on an empty config', () => {
4545
expect(EndConfigSchema.parse({})).toEqual({ outcome: 'completed' });
4646
expect(EndConfigSchema.parse({ outcome: 'completed' })).toEqual({ outcome: 'completed' });
@@ -127,7 +127,7 @@ describe('EndConfigSchema — the `end` node contract (#14945)', () => {
127127
});
128128
});
129129

130-
describe('FlowSchema applies the `end` contract — the structural node\'s only door (#14945)', () => {
130+
describe('FlowSchema applies the `end` contract — the structural node\'s only door', () => {
131131
it('accepts the card-shape probe and writes the parsed config back', () => {
132132
const result = FlowSchema.safeParse(flowEndingWith({ outcome: 'refused', message: REFUSAL }));
133133
expect(result.success).toBe(true);
@@ -217,7 +217,7 @@ describe('FlowSchema applies the `end` contract — the structural node\'s only
217217
expect(issues?.map((i) => [i.code, i.path])).toEqual([['custom', ['nodes', 1, 'config', 'message']]]);
218218
});
219219

220-
it('a region-nested `end` is refused by the FLOW parse itself (#15646/#18112) — the region-door reading this test used to pin is unreachable, because the shape is gone', () => {
220+
it('a region-nested `end` is refused by the FLOW parse itself — the region-door reading this test used to pin is unreachable, because the shape is gone', () => {
221221
// ⚠️ REPLACED, not re-spelled. This case used to assert that the flow parse
222222
// was GREEN here and that `validateControlFlow` was the door — a true
223223
// reading of `parseFlowNodeRegions` leaving a refused region raw (#4389).
@@ -278,7 +278,7 @@ describe('FlowSchema applies the `end` contract — the structural node\'s only
278278
});
279279
});
280280

281-
describe('the run row carries the refusal (#14945)', () => {
281+
describe('the run row carries the refusal', () => {
282282
const run = {
283283
id: 'exec_refused_001',
284284
flowName: 'lead_conversion',

‎packages/spec/src/automation/execution.test.ts‎

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ describe('ExecutionStatus', () => {
2424
});
2525
});
2626

27-
it('names the refused terminal (#14945) — appended LAST, so every `.options` index reader keeps its positions', () => {
27+
it('names the refused terminal — appended LAST, so every `.options` index reader keeps its positions', () => {
2828
expect(ExecutionStatus.options).toContain('refused');
2929
expect(ExecutionStatus.options.at(-1)).toBe('refused');
3030
expect(ExecutionStatus.options.slice(0, 8)).toEqual(
@@ -204,7 +204,7 @@ describe('ExecutionStepLogSchema', () => {
204204
expect(step.branch).toBe(1);
205205
});
206206

207-
it('a `success` step that delegated to a child carries the child\'s contained failures on `metrics.failures` (#15617)', () => {
207+
it('a `success` step that delegated to a child carries the child\'s contained failures on `metrics.failures`', () => {
208208
// The card's shape: `loop { subflow(child) }`, one iteration whose child
209209
// COMPLETED while losing a row. The subflow step itself succeeded — the
210210
// failure is the child's, contained — so `status` stays `success` and the
@@ -415,7 +415,7 @@ describe('FlowRunSummarySchema', () => {
415415
expect(summary.failed).toBe(summary.nodes.reduce((sum, node) => sum + node.failures, 0));
416416
});
417417

418-
it('`failed` is the fold INCLUDING what a delegating node rolled up from its child — the card\'s measured shape, as ruled (#15617)', () => {
418+
it('`failed` is the fold INCLUDING what a delegating node rolled up from its child — it answers what the run caused', () => {
419419
// Parent `loop { subflow(child) }` over five rows; the child COMPLETED on
420420
// every iteration and contained one failure on the last. The subflow node
421421
// succeeded five times — `status: success`, its own executions never
@@ -440,7 +440,7 @@ describe('FlowRunSummarySchema', () => {
440440
expect(call?.failures).toBe(1);
441441
});
442442

443-
it('the control keeps counting as before: a child that FAILED is the delegating step\'s own failure, counted once (#15617)', () => {
443+
it('the control keeps counting as before: a child that FAILED is the delegating step\'s own failure, counted once', () => {
444444
// Same parent, but the child FAILED on the last row rather than containing
445445
// the failure. That is the subflow step's own `status: failure` — one
446446
// execution failed — and nothing rides up on top of it: the child's own
@@ -457,7 +457,7 @@ describe('FlowRunSummarySchema', () => {
457457
expect(summary.failed).toBe(summary.nodes.reduce((sum, node) => sum + node.failures, 0));
458458
});
459459

460-
it('declares the roll-up at the point of use — the field describes say so, not only the paragraph above the schema (#15617)', () => {
460+
it('declares the roll-up at the point of use — the field describes say so, not only the paragraph above the schema', () => {
461461
// Triage's explicit failure mode for this card: a reconciliation that
462462
// leaves `failed`'s own `.describe()` saying the narrow thing. A consumer
463463
// reads the field's description, so the widened rule has to be there.

‎packages/spec/src/automation/flow-decision-branch-expression-absent.test.ts‎

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -60,14 +60,14 @@ const AT_BRANCH_0 = ['nodes', 1, 'config', 'conditions', 0, 'expression'];
6060
* refused row's message is the ONE judge's, byte for byte.
6161
*/
6262
const TABLE: Array<{ name: string; branch: Node; refused: boolean; refusedWith?: unknown }> = [
63-
{ name: 'no `expression` key — the #19961 shape', branch: { label: 'y' }, refused: true, refusedWith: undefined },
63+
{ name: 'no `expression` key', branch: { label: 'y' }, refused: true, refusedWith: undefined },
6464
{ name: '`expression: null`', branch: { label: 'y', expression: null }, refused: true, refusedWith: null },
6565
{ name: 'the predicate under the edge\'s spelling `condition`', branch: { label: 'y', condition: 'true' }, refused: true, refusedWith: undefined },
66-
{ name: 'a blank string — the #17493 control', branch: { label: 'y', expression: ' ' }, refused: true, refusedWith: ' ' },
66+
{ name: 'a blank string — the control: a blank predicate is already refused', branch: { label: 'y', expression: ' ' }, refused: true, refusedWith: ' ' },
6767
{ name: 'a real predicate — the accept control', branch: { label: 'y', expression: 'true' }, refused: false },
6868
];
6969

70-
describe('FlowSchema.parse refuses a decision branch with no `expression` (#19961)', () => {
70+
describe('FlowSchema.parse refuses a decision branch with no `expression`', () => {
7171
it.each(TABLE)('$name', ({ branch, refused, refusedWith }) => {
7272
const issues = issuesOf(flowWith(decision(branch)));
7373
if (!refused) {

0 commit comments

Comments
 (0)