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
fix(lint): refuse a blank structural condition at author time, by the rule registerFlow already applies (#17495) (#17665)
`validateStackExpressions` — the pass behind `objectstack validate` — reported
NOTHING for a `config.condition` that is blank after trimming, at either
structural node slot (a `start` node's trigger gate, a `decision` node's
predicate) and on an edge. #17322 rebound `AutomationEngine.registerFlow` to the
edge door's non-blank rule, so the same value now stops the flow registering at
boot behind a single `warn` line — an author ran validate, got a clean bill,
deployed, and the trigger was never armed.
`checkStructuralCondition` gains the same second gate the engine's copy has, in
the same position (after the shape refusal, before the CEL pass), asking the
same IMPORTED schema: `EvaluatedExpressionInputSchema`, the rule
`FlowEdgeSchema.condition` has composed since #15807. Not a second hand-written
notion of "blank" — that is the drift #15662 built one shared refusal to
prevent — so the sentence is the spec's published constant and the three doors
cannot answer differently.
Two pins re-judged IN PLACE, with the reason recorded, never deleted:
* `validate-expressions.test.ts` — "a whitespace-only STRING is untouched —
ruled correct, not a defect" recorded that author time and run time AGREED
about the blank. #15807 and #17322 removed that ground; the case is flipped
and says so, and still pins that the blank refusal and #15662's shape
refusal stayed distinct.
* `lint-flow-patterns.test.ts` — the `flow-inert-node-condition` zero still
stands (that rule is about a key nothing reads, and has no opinion on
blankness), but it was readable as "validate says nothing about a blank
condition". A cross-site assertion now pins where the refusal actually
lives, so the zero cannot be read as silence again.
Measured on `d46deba195`, same probe, both structural node slots at once —
before: blank `' '` 0, `''` 0; after: 2 and 2. Controls unmoved and proving
the probe reaches both slots: brace trap 2, `ast`-only envelope 2, valid CEL 0.
Closes#17495
Claude-Session: https://claude.ai/code/session_012GKcPZbMoGq7WPzKLfRBTU
Co-authored-by: claude <noreply@anthropic.com>
fix(lint)!: `objectstack validate` refuses a blank structural `condition`, the rule `registerFlow` has carried since #17322 (#17495)
6
+
7
+
<!-- adr-0087: not-required (already-registered flow-edge-condition-evaluated-slot-source-required) this is the AUTHOR-TIME face of the decision that entry already carries — an evaluated slot requires a non-blank `source`, refused with EVALUATED_EXPRESSION_SOURCE_REQUIRED — reached by importing the same schema rather than deriving a second rule. No key is renamed, retired or given a new meaning here, and no stored document needs rewriting that the entry does not already prescribe. ⚠️ That entry's `surface` / `acceptanceCriteria` name only `edges[].condition` and still want widening to `config.condition`; the registry file is in packages/spec, outside this card's surface, and is already filed as #17493. -->
8
+
9
+
**BREAKING** in the accept-set sense, landing in the launch window as `minor`
10
+
(the lockstep convention: `major` is refused by `check-changeset-no-major`, and
11
+
breaking-ness is carried by this banner plus the ADR-0087 disposition):
12
+
`validateStackExpressions` — the pass behind `objectstack validate` — now
13
+
reports an `error` for a structural `condition` whose source is blank after
14
+
trimming. It reported nothing at all before.
15
+
16
+
The value was already refused by two of the three doors. `FlowEdgeSchema.condition`
17
+
composes `EvaluatedExpressionInputSchema` (#15807), so `' '` on an edge is
18
+
refused at `FlowSchema.parse`; #17322 rebound `AutomationEngine.registerFlow` to
19
+
that same rule, so the same value on a node's `config.condition` stops the flow
20
+
registering. `objectstack validate` was the door that still said nothing — so an
21
+
author got a clean bill, deployed, and the flow never registered: each boot path
22
+
in `service-automation`'s plugin wraps `registerFlow` in `try`/`catch`, logs one
23
+
`warn` naming the flow, and continues. On a `start` node that key is the
24
+
**trigger gate**, so the whole flow is armed by nothing.
25
+
26
+
FROM → TO, for a build that used to pass and now fails:
27
+
28
+
```yaml
29
+
# FROM — validate said nothing; registerFlow refuses it at boot
0 commit comments