diff --git a/.changeset/prompt-template-experimental-marking.md b/.changeset/prompt-template-experimental-marking.md new file mode 100644 index 0000000000..e1f3afff30 --- /dev/null +++ b/.changeset/prompt-template-experimental-marking.md @@ -0,0 +1,34 @@ +--- +"@objectstack/spec": patch +--- + +docs(spec): mark `PromptTemplate.system` / `.user` `[EXPERIMENTAL — not enforced]` (#15954, #16321) + +Prose only. `Clause-②: no` — no accept-set change, no new/narrowed authorable +key, no matrix declaration. Every value that parsed before parses now, and +every value refused before is refused identically. + +Under the #15954 ruling (decision batch #56, option B) the template-typed pair +is **marked, not retired**. Both `.describe()` strings on +`ai/PromptTemplateSchema` now carry the repo's existing +`[EXPERIMENTAL — not enforced]` prefix and state that no runtime renders or +executes the template today: + +```ts +system: TemplateExpressionInputSchema.optional().describe('[EXPERIMENTAL — not enforced] System prompt — supports {{var}} interpolation. No runtime renders or executes the template today.'), +user: TemplateExpressionInputSchema.describe('[EXPERIMENTAL — not enforced] User prompt template — supports {{var}} interpolation. No runtime renders or executes the template today.'), +``` + +**Why an author sees this.** `PromptTemplateSchema` has no consumer outside +`packages/spec`, so the `{{var}}` holes are never interpolated and the declared +`variables` are never checked against them. The ADR-0058 D7 conformance ledger +already recorded that verdict (`template-prompt`, `state: 'experimental'`, +`PARSE ONLY — NO EVALUATOR FOUND`); until now nothing said it at the +declaration, so the generated reference page advertised a capability the +runtime does not deliver. + +**What does NOT change.** `.user` remains **required** and `.system` remains +optional — the schema shape is untouched. Optionalising or retiring a required +key is a parse-breaking change and is deliberately left to its own card. No +tombstone and no ADR-0087 entry is owed: nothing is renamed, retired or +re-typed. diff --git a/content/docs/references/ai/model-registry.mdx b/content/docs/references/ai/model-registry.mdx index 3b3d7a96d8..45f80f0b7f 100644 --- a/content/docs/references/ai/model-registry.mdx +++ b/content/docs/references/ai/model-registry.mdx @@ -171,8 +171,8 @@ const result = ModelCapabilitySchema.parse(data); | **id** | `string` | ✅ | Unique template identifier | | **name** | `string` | ✅ | Template name (snake_case) | | **label** | `string` | ✅ | Display name | -| **system** | `string \| { dialect: 'template'; source?: string; ast?: any; meta?: object }` | optional | System prompt — supports `{{var}}` interpolation | -| **user** | `string \| { dialect: 'template'; source?: string; ast?: any; meta?: object }` | ✅ | User prompt template — supports `{{var}}` interpolation | +| **system** | `string \| { dialect: 'template'; source?: string; ast?: any; meta?: object }` | optional | [EXPERIMENTAL — not enforced] System prompt — supports `{{var}}` interpolation. No runtime renders or executes the template today. | +| **user** | `string \| { dialect: 'template'; source?: string; ast?: any; meta?: object }` | ✅ | [EXPERIMENTAL — not enforced] User prompt template — supports `{{var}}` interpolation. No runtime renders or executes the template today. | | **assistant** | `string` | optional | Assistant message prefix | | **variables** | `{ name: string; type?: Enum<'string' \| 'number' \| 'boolean' \| 'object' \| 'array'>; required?: boolean; defaultValue?: any; … }[]` | optional | Template variables | | **modelId** | `string` | optional | Recommended model ID | @@ -260,8 +260,8 @@ const result = ModelCapabilitySchema.parse(data); | **id** | `string` | ✅ | Unique template identifier | | **name** | `string` | ✅ | Template name (snake_case) | | **label** | `string` | ✅ | Display name | -| **system** | `string \| { dialect: 'template'; source?: string; ast?: any; meta?: object }` | optional | System prompt — supports `{{var}}` interpolation | -| **user** | `string \| { dialect: 'template'; source?: string; ast?: any; meta?: object }` | ✅ | User prompt template — supports `{{var}}` interpolation | +| **system** | `string \| { dialect: 'template'; source?: string; ast?: any; meta?: object }` | optional | [EXPERIMENTAL — not enforced] System prompt — supports `{{var}}` interpolation. No runtime renders or executes the template today. | +| **user** | `string \| { dialect: 'template'; source?: string; ast?: any; meta?: object }` | ✅ | [EXPERIMENTAL — not enforced] User prompt template — supports `{{var}}` interpolation. No runtime renders or executes the template today. | | **assistant** | `string` | optional | Assistant message prefix | | **variables** | `{ name: string; type?: Enum<'string' \| 'number' \| 'boolean' \| 'object' \| 'array'>; required?: boolean; defaultValue?: any; … }[]` | optional | Template variables | | **modelId** | `string` | optional | Recommended model ID | diff --git a/packages/qa/dogfood/test/expression-conformance.ledger.ts b/packages/qa/dogfood/test/expression-conformance.ledger.ts index 0ce30ac240..86035776cf 100644 --- a/packages/qa/dogfood/test/expression-conformance.ledger.ts +++ b/packages/qa/dogfood/test/expression-conformance.ledger.ts @@ -382,7 +382,9 @@ export const EXPRESSION_SURFACE: ExprSurface[] = [ 'ai/model-registry.zod.ts:PromptTemplateSchema.system', 'ai/model-registry.zod.ts:PromptTemplateSchema.user', ], - note: 'EXPERIMENTAL — declared prompt templates with no runtime evaluator (ADR-0049). Ownership was checked before classifying rather than assumed: the card that appeared to own these keys is closed as completed, and its delivered diff (`d355c361157`) touched exactly one file, `skills/objectstack-ai/SKILL.md` — it corrected a prose clause that called these keys CEL, and never owned a ledger row. No open card owns them.', + // Ruling: #15954 (decision batch #56, option B for the template family). The tracker ids live + // here, not in the string: `note` is runtime prose (check:doc-authoring, cross-package prose-id leg). + note: 'EXPERIMENTAL — declared prompt templates with no runtime evaluator (ADR-0049), and MARKED as such at the declaration under the marking ruling (option B: this pair is marked, NOT retired). Both positions this row covers — `PromptTemplateSchema.system` and `PromptTemplateSchema.user` — now carry the `[EXPERIMENTAL — not enforced]` prefix in their own `.describe()`, stating that no runtime renders or executes the template today, so an author reading the generated reference page gets the same verdict this row records instead of having to find this ledger. The marking is PROSE ONLY: `.user` remains REQUIRED (no `.optional()`) and `.system` keeps the `.optional()` it already had — optionalising or retiring a required key is parse-breaking and is its own card. Ownership was checked before classifying rather than assumed: the card that appeared to own these keys is closed as completed, and its delivered diff (`d355c361157`) touched exactly one file, `skills/objectstack-ai/SKILL.md` — it corrected a prose clause that called these keys CEL, and never owned a ledger row. No open card owns them.', }, { id: 'template-title-format', diff --git a/packages/spec/src/ai/model-registry.zod.ts b/packages/spec/src/ai/model-registry.zod.ts index cc44195c6d..11128d5562 100644 --- a/packages/spec/src/ai/model-registry.zod.ts +++ b/packages/spec/src/ai/model-registry.zod.ts @@ -118,8 +118,8 @@ export const PromptTemplateSchema = lazySchema(() => z.object({ label: z.string().describe('Display name'), /** Template Content */ - system: TemplateExpressionInputSchema.optional().describe('System prompt — supports {{var}} interpolation'), - user: TemplateExpressionInputSchema.describe('User prompt template — supports {{var}} interpolation'), + system: TemplateExpressionInputSchema.optional().describe('[EXPERIMENTAL — not enforced] System prompt — supports {{var}} interpolation. No runtime renders or executes the template today.'), + user: TemplateExpressionInputSchema.describe('[EXPERIMENTAL — not enforced] User prompt template — supports {{var}} interpolation. No runtime renders or executes the template today.'), assistant: z.string().optional().describe('Assistant message prefix'), /** Variables */