Skip to content

Commit 3c418c4

Browse files
os-steveclaude
andauthored
fix(spec): rewrite skill.zod.ts's two @example blocks off the retired triggerPhrases (#11402)
Both TSDoc examples in packages/spec/src/ai/skill.zod.ts passed `triggerPhrases`, removed in @objectstack/spec 17.0.0 (#3896 audit close-out) and carried as a retiredKey() tombstone ~120 lines below the first of them. defineSkill calls SkillSchema.parse(), so both documented blocks threw when run: invalid_type at path triggerPhrases, expected never. Measured against the built dist before the repair: 2 of 2 blocks threw; after it, 2 of 2 parse. The blocks now demonstrate the tombstone's own prescription instead of contradicting it. That prescription is a SPLIT, not a rename: routing intent to triggerConditions, natural-language intent to description/instructions. The defineSkill block shows both halves with each named. `tools` is required with no default, so both blocks carry it, and each block opens with its own import so it is self-contained the way a consumer resolves it. The retiredKey() tombstone and every line of its guidance prose are unchanged, verbatim. Claude-Session: https://claude.ai/code/session_01T9cDbY2NBiVJWYx3BpWfH2 Co-authored-by: Claude <noreply@anthropic.com>
1 parent 6dd8d27 commit 3c418c4

2 files changed

Lines changed: 32 additions & 4 deletions

File tree

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
---
2+
"@objectstack/spec": patch
3+
---
4+
5+
**Docs:** `skill.zod.ts`'s two `@example` blocks stop handing the author a retired key that throws on parse (#11026).
6+
7+
Both TSDoc examples in `packages/spec/src/ai/skill.zod.ts` — the one over `SkillSchema` and the one over `defineSkill` — passed `triggerPhrases`, removed in `@objectstack/spec` 17.0.0 (#3896 audit close-out) and carried as a `retiredKey()` tombstone ~120 lines below the first of them. `defineSkill` calls `SkillSchema.parse()`, so both documented blocks **threw** when run: `invalid_type` at path `triggerPhrases`, expected `never`. A reader copying either block got a refusal on their first move.
8+
9+
The blocks now demonstrate the tombstone's own prescription instead of contradicting it. That prescription is a **split**, not a rename — routing intent belongs in `triggerConditions` (an AND of context field/operator/value), natural-language intent in `description` / `instructions`, the strings actually put in front of the model — and the `defineSkill` block shows both halves with each named. `tools` is required with no default, so both blocks carry it. Each block also opens with its own `import { defineSkill } from '@objectstack/spec';`, matching the convention the marked SDK examples in `packages/client-react/src` already use, so the block is self-contained as a consumer would resolve it.
10+
11+
The tombstone and every line of its guidance prose are **unchanged**, verbatim — they were always correct, and they are what the repaired examples now agree with.
12+
13+
Prose only: no schema shape, no `.describe()` text, no runtime behaviour, no authorable-surface movement, and `check:generated` moves nothing (the generated reference page `content/docs/references/ai/skill.mdx` renders the tombstoned row as `[REMOVED]` and carries neither example). It is graded rather than skipped because the text ships to consumers: the rewritten blocks are present in the built `dist/skill.zod-*.d.ts`, which is what an editor surfaces on hover, and `@objectstack/spec`'s `files` list publishes `src/**/*.zod.ts` so the docblock also travels in the npm tarball as source.

packages/spec/src/ai/skill.zod.ts

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -247,13 +247,18 @@ export type SkillTriggerCondition = z.input<typeof SkillTriggerConditionSchema>;
247247
*
248248
* @example
249249
* ```ts
250+
* import { defineSkill } from '@objectstack/spec';
251+
*
250252
* const skill = defineSkill({
251253
* name: 'case_management',
252254
* label: 'Case Management',
253255
* description: 'Handles support case lifecycle',
254-
* instructions: 'Use these tools to create, update, and resolve support cases.',
256+
* // Natural-language intent lives in the strings actually put in front of
257+
* // the model. A skill is never activated by matching a phrase list.
258+
* instructions:
259+
* 'Use these tools to create, update, and resolve support cases. Reach for this '
260+
* + 'skill when the user wants to open a ticket, chase an existing case, or close one out.',
255261
* tools: ['create_case', 'update_case', 'resolve_case', 'query_cases'],
256-
* triggerPhrases: ['create a case', 'open a ticket', 'resolve issue'],
257262
* });
258263
* ```
259264
*/
@@ -432,14 +437,24 @@ export type SkillParsed = z.infer<typeof SkillSchema>;
432437
* Validates the config at creation time using Zod `.parse()`.
433438
*
434439
* @example
440+
* Activation is a SPLIT, and this block shows both halves: programmatic
441+
* routing in `triggerConditions`, natural-language intent in
442+
* `description` / `instructions`.
443+
*
435444
* ```ts
445+
* import { defineSkill } from '@objectstack/spec';
446+
*
436447
* const skill = defineSkill({
437448
* name: 'order_management',
438449
* label: 'Order Management',
439450
* description: 'Handles order lifecycle operations',
440-
* instructions: 'Use these tools to manage customer orders.',
451+
* // Half one — natural language, read by the LLM.
452+
* instructions:
453+
* 'Use these tools to manage customer orders. Reach for this skill when the user '
454+
* + 'wants to place an order, change one, or cancel one.',
441455
* tools: ['create_order', 'update_order', 'cancel_order'],
442-
* triggerPhrases: ['place an order', 'cancel my order'],
456+
* // Half two — a programmatic AND of context field/operator/value,
457+
* // evaluated by the cloud agent runtime.
443458
* triggerConditions: [
444459
* { field: 'objectName', operator: 'eq', value: 'order' },
445460
* ],

0 commit comments

Comments
 (0)