Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 31 additions & 0 deletions .changeset/skill-hook-condition-aborts.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
---
---

Docs-only: the `objectstack-data` skill's hook reference taught the pre-17
failure mode for an unevaluable `condition`.

`skills/objectstack-data/references/data-hooks.md` had been updated for #4770
(the condition reads the record, not the payload) and #4784 (`previous` is
bound), but its closing bullet still said an undeclared key leaves the condition
"logged at WARN and treated as false" — the behaviour #4775 replaced. An
unevaluable condition now **aborts the operation**.

This is the AI-authoring reference for hooks, so the stale sentence pointed the
wrong way on the one axis that matters: it told an author a typo is a soft
failure. It also silently downgraded the two bullets above it — `previous` is
unbound on inserts and on `multi: true` writes, and `has()` is not a null guard —
from "this breaks your write" to "this quietly disables your hook".

Replaced with a callout carrying the #4775 rule and the reason the two outcomes
had to split (a `before*` guard swallowed into `false` lets writes through; an
audit hook swallowed into `false` drops records — opposite failures), plus the
practical authoring consequence.

Swept the rest of `skills/` and `.claude/skills/` against the same rc.2 window;
nothing else was stale. `objectstack-automation` already documents #4343's
`script`-node retirements, `objectstack-query` already carries the #4286
`cursor` / `joins` / `windowFunctions` prescriptions, and
`objectstack-formula` already documents #4649 fail-closed predicates and #4763's
build-time `has()` rejection.

Releases nothing.
17 changes: 15 additions & 2 deletions skills/objectstack-data/references/data-hooks.md
Original file line number Diff line number Diff line change
Expand Up @@ -260,8 +260,21 @@ in neither). So:
`has(record.spent) && record.spent > record.budget` still faults on
`null > null`. `has()` answers "is this key declared at all", which is a
question about your spelling, not about your data.
- An **undeclared** key (a typo) stays unevaluable: the condition is logged at
WARN and treated as false.

⚠️ **An unevaluable condition ABORTS the operation (#4775).** A typo'd key
(`record.stauts`), a `previous` reference on an insert, or a comparison CEL has
no overload for does **not** degrade to "the hook did not fire" — it **fails the
write**. Until protocol 17 the gate emitted a `logger.warn` and returned `false`,
which is why the two bullets above are load-bearing rather than stylistic: a
`before*` guard swallowed into `false` silently let writes through, and an audit
hook swallowed into `false` silently dropped records. Those are opposite
failures, so "the condition said no" and "the platform could not work out what
the condition says" are now different outcomes and the second one is loud.

Practical consequence when authoring: spell keys against the object's **declared**
fields, and never reach for `previous` in a hook that can fire on insert or on a
`multi: true` write — that mistake used to cost you a hook that quietly never
ran, and now costs you every write the hook is attached to.

#### `onError` — Error Handling

Expand Down
Loading