You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
`validateStackExpressions` no longer throws on a non-record entry in an object's `fields:` list.
6
+
7
+
An empty item in a YAML `fields:` list deserialises to `null`, and `buildFieldIndex` cast each member of the list inline (`fields.map(f => (f as AnyRec).name)`) before the `.filter` two calls later could drop it. `Array.isArray` proves the LIST, never its MEMBERS, so linting such a stack failed with `TypeError: Cannot read properties of null (reading 'name')` out of the whole rule instead of reporting anything about the file.
8
+
9
+
The list is now read through `recordsOf` — the one place that coercion is decided — which drops a non-record member of the array shape whole and in **silence**: it carries no author-written name, so there is nothing to report about it. That matches what the two sibling field readers in the same module (`buildFieldTypeIndex`, `fieldEntries`) already did with the same member, so the three readers now agree. The readable siblings of the junk member are still indexed, so unknown-field findings on that object continue to be reported.
10
+
11
+
The map shape (`fields: { amount: { … } }`) is unchanged: there the author's key is the field name, which is what this index needs.
docs(spec): mark `PromptTemplate.system` / `.user``[EXPERIMENTAL — not enforced]` (#15954, #16321)
6
+
7
+
Prose only. `Clause-②: no` — no accept-set change, no new/narrowed authorable
8
+
key, no matrix declaration. Every value that parsed before parses now, and
9
+
every value refused before is refused identically.
10
+
11
+
Under the #15954 ruling (decision batch #56, option B) the template-typed pair
12
+
is **marked, not retired**. Both `.describe()` strings on
13
+
`ai/PromptTemplateSchema` now carry the repo's existing
14
+
`[EXPERIMENTAL — not enforced]` prefix and state that no runtime renders or
15
+
executes the template today:
16
+
17
+
```ts
18
+
system: TemplateExpressionInputSchema.optional().describe('[EXPERIMENTAL — not enforced] System prompt — supports {{var}} interpolation. No runtime renders or executes the template today.'),
19
+
user: TemplateExpressionInputSchema.describe('[EXPERIMENTAL — not enforced] User prompt template — supports {{var}} interpolation. No runtime renders or executes the template today.'),
20
+
```
21
+
22
+
**Why an author sees this.**`PromptTemplateSchema` has no consumer outside
23
+
`packages/spec`, so the `{{var}}` holes are never interpolated and the declared
24
+
`variables` are never checked against them. The ADR-0058 D7 conformance ledger
25
+
already recorded that verdict (`template-prompt`, `state: 'experimental'`,
26
+
`PARSE ONLY — NO EVALUATOR FOUND`); until now nothing said it at the
27
+
declaration, so the generated reference page advertised a capability the
28
+
runtime does not deliver.
29
+
30
+
**What does NOT change.**`.user` remains **required** and `.system` remains
31
+
optional — the schema shape is untouched. Optionalising or retiring a required
32
+
key is a parse-breaking change and is deliberately left to its own card. No
33
+
tombstone and no ADR-0087 entry is owed: nothing is renamed, retired or
Copy file name to clipboardExpand all lines: content/docs/api/error-catalog.mdx
+14-3Lines changed: 14 additions & 3 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -3,7 +3,13 @@ title: Error Code Catalog
3
3
description: Complete reference for all ObjectStack error codes with causes, fixes, and retry strategies
4
4
---
5
5
6
-
ObjectStack uses a structured error system with **9 error categories** and **50 standardized error codes**. Every error includes a machine-readable code, HTTP status mapping, and retry guidance.
6
+
ObjectStack uses a structured error system with **9 error categories** and **51 error codes reachable on the wire**. Every error includes a machine-readable code, HTTP status mapping, and retry guidance.
7
+
8
+
This catalog documents the **wire face** — the codes a client can actually receive. That is not quite the
9
+
`StandardErrorCode` enum: the enum also carries in-process spellings the REST door translates at the
10
+
boundary, and the catalog carries [error-code ledger](/docs/references/api/error-code-ledger) codes the
11
+
enum does not. A translated code is documented under the spelling clients receive, and named in that
12
+
entry's cross-reference sentence so the in-process one stays findable.
7
13
8
14
<Callouttype="info">
9
15
**Source:**`packages/spec/src/api/errors.zod.ts`
@@ -361,11 +367,16 @@ result set — a response indistinguishable from a successful query.
361
367
**Fix:** Delete or reassign dependent records first, then retry the delete.
362
368
**Retry:**`no_retry`
363
369
364
-
### `DUPLICATE_RECORD`
370
+
### `UNIQUE_VIOLATION`
365
371
**Cause:** A record with the same unique key already exists.
366
372
**Fix:** Update the existing record instead, or use a different unique key value.
367
373
**Retry:**`no_retry`
368
374
375
+
The engine throws `DuplicateRecordError`, whose in-process `code` is
376
+
`DUPLICATE_RECORD`; the REST door translates that envelope at the boundary, so
377
+
every route answers the wire code `UNIQUE_VIOLATION` and the in-process spelling
378
+
never crosses HTTP.
379
+
369
380
### `LOCK_CONFLICT`
370
381
**Cause:** The record is locked by another process or user.
371
382
**Fix:** Wait for the lock to be released, or contact the lock holder.
@@ -802,7 +813,7 @@ async function handleApiCall() {
| 422 |`validation`|`MISSING_REQUIRED_FIELD` on an absent `controlled_by_parent` master reference (see [above](#missing_required_field)) — this row is an exception to the 400 row, not a second home for the code |
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.',
385
+
// Ruling: #15954 (decision batch #56, option B for the template family). The tracker ids live
386
+
// here, not in the string: `note` is runtime prose (check:doc-authoring, cross-package prose-id leg).
387
+
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.',
system: TemplateExpressionInputSchema.optional().describe('[EXPERIMENTAL — not enforced] System prompt — supports {{var}} interpolation. No runtime renders or executes the template today.'),
122
+
user: TemplateExpressionInputSchema.describe('[EXPERIMENTAL — not enforced] User prompt template — supports {{var}} interpolation. No runtime renders or executes the template today.'),
0 commit comments