Skip to content

feat(expression): ADR-0032 phase 1 — validate-by-default expression layer (no silent failure)#1517

Merged
xuyushun441-sys merged 2 commits into
mainfrom
feat/adr-0032-expression-layer
Jun 2, 2026
Merged

feat(expression): ADR-0032 phase 1 — validate-by-default expression layer (no silent failure)#1517
xuyushun441-sys merged 2 commits into
mainfrom
feat/adr-0032-expression-layer

Conversation

@xuyushun441-sys

Copy link
Copy Markdown
Contributor

What

Phase 1 of ADR-0032 — the AI-safety spine: make a malformed expression impossible to ship silently, and give authors (esp. agents) a precise, fixable error. Fixes the #1491 class where a brace-in-CEL condition ({record.rating} >= 4) was silently swallowed to false, so a flow "fired" with success but did nothing.

Scope = the parts that are non-breaking and verifiable; the breaking cutovers are staged follow-ups (see below).

Changes

  • service-automationevaluateCondition no longer swallows a CEL failure to false; it throws an attributed, corrective error. registerFlow now parse-validates every predicate (start / decision / edge condition) at registration and fails loudly with location + source + the fix.
  • formula — new shared validator validateExpression(role, src, schema?) + introspectScope + CEL_STDLIB_FUNCTIONS (schema-aware field-existence with did-you-mean). The {{ }} template engine gains a formatter whitelist (currency/number/percent/date/datetime/truncate/upper/lower/default/json) with defined value→string semantics; arbitrary-logic holes rejected; plain {{ path }} stays back-compatible.
  • cliobjectstack compile validates every flow / validation-rule / field-formula predicate against the resolved object schema and fails the build with located, corrective messages. (Resolves ADR open question Add metamodel interfaces for ObjectQL/ObjectUI contract #1.)
  • service-ai — agent-callable validate_expression tool for author-time self-correction.
  • spec — fix the FlowSchema JSDoc example that taught the bad single-brace condition: "{amount} < 500" form.

Both ADR open questions resolved: #1 (schema available at compile) and #2 (formatter catalog decided).

Verification

All green locally: formula 74, service-automation 149, service-ai 412, cli 152, spec 6608, objectql 484, runtime 334. All touched packages build. New negative tests cover brace-in-CEL rejection at runtime/registration/build; formatter tests cover the catalog.

Deliberately NOT in this PR (staged, breaking / cross-repo)

  • Step 3 cutover — remove string→CEL coercion + migrate authoring sites to typed builders (examples + templates).
  • Step 6 finish — delete the single-brace resolver + migrate ~191 {x} node-field usages to {{x}}.
  • Step 7 — designer (../objectui, separate repo).
  • Step 4 v2 — bool-return / type inference (CEL type env) + converging remaining objectql runtime swallows.

Phase 1 already contains the #1491 risk (loud at runtime, registration, and build).

🤖 Generated with Claude Code

…ayer, no silent failure

Fixes the #1491 class: a malformed predicate (notably the `{record.x}`
template-brace-in-CEL mistake) was silently swallowed to `false`, so a flow
"fired" with success but did nothing.

- service-automation: evaluateCondition throws an attributed/corrective error
  instead of returning false; registerFlow parse-validates every predicate at
  registration (loud, located).
- formula: shared validator (validateExpression / introspectScope /
  CEL_STDLIB_FUNCTIONS) with schema-aware field-existence + did-you-mean; the
  {{ }} template engine gains a formatter whitelist with defined value→string
  semantics (plain {{ path }} stays back-compatible; arbitrary-logic holes
  rejected).
- cli: objectstack compile validates flow / validation-rule / field-formula
  predicates against the resolved object schema, failing the build with
  located corrective messages.
- service-ai: agent-callable validate_expression tool for author-time
  self-correction.
- spec: fix FlowSchema JSDoc example that taught the bad single-brace form.

Tests: formula 74, service-automation 149, service-ai 412, cli 152, spec 6608,
objectql 484, runtime 334 — all green.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@vercel

vercel Bot commented Jun 2, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
spec Ready Ready Preview, Comment Jun 2, 2026 4:51am

Request Review

@github-actions github-actions Bot added documentation Improvements or additions to documentation dependencies Pull requests that update a dependency file tests tooling size/xl labels Jun 2, 2026
while ((m = PATH_RE.exec(source)) !== null) {
refs.push(m[1]);
HOLE_RE.lastIndex = 0;
while ((m = HOLE_RE.exec(source)) !== null) {
CodeQL flagged the template hole matcher `/\{\{\s*([^}]*?)\s*\}\}/` as a
polynomial-ReDoS: `\s` ⊆ `[^}]`, so wrapping the lazy group in `\s*` makes the
matcher ambiguous on untrusted template source. Switch to a single greedy
`/\{\{([^}]*)\}\}/` and strip surrounding whitespace in parseHole — provably
linear, identical behavior (74 formula tests green).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@xuyushun441-sys xuyushun441-sys merged commit c4a4cbd into main Jun 2, 2026
12 of 13 checks passed
@xuyushun441-sys xuyushun441-sys deleted the feat/adr-0032-expression-layer branch June 2, 2026 05:03
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

dependencies Pull requests that update a dependency file documentation Improvements or additions to documentation size/xl tests tooling

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants