Skip to content

fix(formula): retire the js expression dialect (#3278)#3291

Merged
os-zhuang merged 3 commits into
mainfrom
fix/3278-retire-js-expression-dialect
Jul 19, 2026
Merged

fix(formula): retire the js expression dialect (#3278)#3291
os-zhuang merged 3 commits into
mainfrom
fix/3278-retire-js-expression-dialect

Conversation

@os-zhuang

Copy link
Copy Markdown
Contributor

Closes #3278.

What & why

The js expression dialect was declared in ExpressionDialect but never shipped — it existed only as a registry stub with no engine and no author helper (cel/F/P → CEL, tmpl → template, cron → cron; nothing ever emitted js). Given CEL already covers L1 declarative predicates and sandboxed JS already exists at L2 (ScriptBody { language: 'js' }), a js-as-expression layer is redundant and works against the AI-native safety story (CEL is non-Turing, statically lintable/explainable/diffable; arbitrary js is not). Per ADR-0049 (enforce-or-remove), retire it.

This also corrects the issue's original premise: hasDialect('js') actually returned a false-positive true, because the stub-detection (dialect.startsWith('stub:')) was dead code — stubs are registered under their real name, so the check never fired.

Changes

  • spec — narrow ExpressionDialect to {cel, cron, template}; regenerate the 37 reference docs (js drops from the ~50 Expression-holding declarations — the only generated churn, verified diff is exclusively the enum narrowing).
  • formula — remove the js stub + the dead stub-detection; hasDialect now reports only registered real engines; the registry test asserts hasDialect('js') === false (the false-green test previously only checked the cel case, so the broken detection shipped green).
  • ADR-0058 — addendum + inline amendments recording the retire.
  • comments — fix stale references (registry module doc called cron a stub; cel-engine bounds comment pointed at dialect: js instead of the L2 ScriptBody).

L1 vs L2 — the two js surfaces (kept distinct)

Surface Slot This PR
js expression dialect L1 expression envelope (same slot as CEL) removed
ScriptBody { language: 'js' } L2 hook/action body, sandboxed + capability-gated (separate z.literal('js') enum) unaffected

Verification

  • @objectstack/spec tsc --noEmit; all 57 packages build (no downstream consumer of the enum breaks)
  • ✅ formula tests (233) + full spec suite (6763) green
  • ✅ generated-artifact gates: check:docs (regenerated, in sync), check:skill-refs, check:react-blocks
  • check:role-word / check:nul-bytes / check:doc-authoring
  • ✅ Blast radius: dialect: 'js' producers = 0 in framework/cloud/objectui (only test fixtures reference it)

Breaking-change note

Narrows a public @objectstack/spec enum. Marked patch (fixes declared≠enforced drift; no valid artifact ever used js). Maintainers may reclassify if preferred.

Follow-up (non-blocking)

objectui clientValidation.fieldRules.test.ts uses { dialect: 'js' } as a bad-input fixture; it consumes published spec so it won't break until objectui bumps. Tracked separately.

🤖 Generated with Claude Code

os-zhuang and others added 2 commits July 18, 2026 22:38
feat(evaluator): route CEL-dialect component/action predicates to the canonical engine (#2664)

objectui@2e7d7f0f7ee76b838f580e8a36b74f1309b204fc
`js` was declared in `ExpressionDialect` but never shipped — only a registry
stub with no engine and no author helper (`cel`/`F`/`P` → CEL, `tmpl` →
template, `cron` → cron; nothing ever emitted `js`). Remove it from the enum
(now `{cel, cron, template}`) per ADR-0049 (enforce-or-remove), and fix a
latent `hasDialect` bug that reported the stub as a real engine (a
false-positive `true` — the stub-detection checked for a `stub:` prefix that
no registered engine ever carries).

Procedural JS is unaffected: it remains the L2 `ScriptBody { language: 'js' }`
sandboxed, capability-gated surface — a separate enum, not an expression
dialect.

- spec: narrow `ExpressionDialect`; regenerate reference docs (js drops from
  the ~50 Expression-holding declarations — the only generated churn)
- formula: drop the stub + dead stub-detection; `hasDialect` now reports only
  registered real engines; registry test asserts `hasDialect('js') === false`
  so the gate can actually go red
- ADR-0058: addendum + inline amendments recording the retire

No runtime behavior changes for any valid persisted artifact — no producer
ever emitted `dialect: 'js'` (open-core, cloud: 0).

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

vercel Bot commented Jul 19, 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 Jul 19, 2026 4:42pm

Request Review

…pression-dialect

# Conflicts:
#	content/docs/references/ui/app.mdx
@github-actions github-actions Bot added documentation Improvements or additions to documentation tests tooling size/m labels Jul 19, 2026
@github-actions

Copy link
Copy Markdown
Contributor

📓 Docs Drift Check

This PR changes 2 package(s): @objectstack/formula, @objectstack/spec.

104 hand-written doc(s) reference the affected code and may need an implementation-accuracy re-verification:

  • content/docs/ai/agents.mdx (via @objectstack/spec)
  • content/docs/ai/skills-reference.mdx (via @objectstack/spec)
  • content/docs/ai/skills.mdx (via @objectstack/spec)
  • content/docs/api/client-sdk.mdx (via @objectstack/spec)
  • content/docs/api/environment-routing.mdx (via @objectstack/spec)
  • content/docs/api/error-catalog.mdx (via @objectstack/spec)
  • content/docs/api/error-handling-client.mdx (via @objectstack/spec)
  • content/docs/api/error-handling-server.mdx (via @objectstack/spec)
  • content/docs/api/index.mdx (via @objectstack/spec)
  • content/docs/automation/approvals.mdx (via packages/spec)
  • content/docs/automation/flows.mdx (via @objectstack/spec)
  • content/docs/automation/hook-bodies.mdx (via packages/spec)
  • content/docs/automation/hooks.mdx (via @objectstack/spec)
  • content/docs/automation/index.mdx (via @objectstack/spec)
  • content/docs/automation/webhooks.mdx (via @objectstack/spec)
  • content/docs/automation/workflows.mdx (via @objectstack/spec)
  • content/docs/concepts/architecture.mdx (via @objectstack/spec)
  • content/docs/concepts/design-principles.mdx (via packages/spec)
  • content/docs/concepts/index.mdx (via @objectstack/spec)
  • content/docs/concepts/metadata-driven.mdx (via @objectstack/spec)
  • content/docs/concepts/metadata-lifecycle.mdx (via packages/spec)
  • content/docs/concepts/north-star.mdx (via packages/spec)
  • content/docs/data-modeling/analytics.mdx (via @objectstack/spec)
  • content/docs/data-modeling/drivers.mdx (via @objectstack/spec)
  • content/docs/data-modeling/external-datasources.mdx (via @objectstack/spec)
  • content/docs/data-modeling/field-types.mdx (via @objectstack/spec)
  • content/docs/data-modeling/fields.mdx (via @objectstack/spec)
  • content/docs/data-modeling/formulas.mdx (via @objectstack/formula, @objectstack/spec)
  • content/docs/data-modeling/index.mdx (via @objectstack/spec)
  • content/docs/data-modeling/objects.mdx (via @objectstack/spec)
  • content/docs/data-modeling/queries.mdx (via @objectstack/spec)
  • content/docs/data-modeling/schema-design.mdx (via @objectstack/spec)
  • content/docs/data-modeling/seed-data.mdx (via @objectstack/spec)
  • content/docs/data-modeling/validation-rules.mdx (via @objectstack/spec)
  • content/docs/data-modeling/validation.mdx (via @objectstack/formula, @objectstack/spec)
  • content/docs/deployment/troubleshooting.mdx (via @objectstack/spec)
  • content/docs/getting-started/build-with-claude-code.mdx (via @objectstack/spec)
  • content/docs/getting-started/cli.mdx (via @objectstack/spec)
  • content/docs/getting-started/common-patterns.mdx (via @objectstack/spec)
  • content/docs/getting-started/examples.mdx (via @objectstack/spec)
  • content/docs/getting-started/quick-reference.mdx (via @objectstack/spec)
  • content/docs/getting-started/quick-start.mdx (via @objectstack/spec)
  • content/docs/getting-started/validating-metadata.mdx (via @objectstack/spec)
  • content/docs/getting-started/your-first-project.mdx (via @objectstack/spec)
  • content/docs/kernel/cluster.mdx (via @objectstack/spec)
  • content/docs/kernel/contracts/auth-service.mdx (via packages/spec)
  • content/docs/kernel/contracts/cache-service.mdx (via packages/spec)
  • content/docs/kernel/contracts/data-engine.mdx (via @objectstack/spec)
  • content/docs/kernel/contracts/index.mdx (via @objectstack/spec)
  • content/docs/kernel/contracts/metadata-service.mdx (via packages/spec)
  • content/docs/kernel/contracts/storage-service.mdx (via packages/spec)
  • content/docs/kernel/index.mdx (via packages/spec)
  • content/docs/kernel/runtime-services/email-service.mdx (via packages/spec)
  • content/docs/kernel/runtime-services/index.mdx (via packages/spec)
  • content/docs/kernel/runtime-services/queue-service.mdx (via packages/spec)
  • content/docs/kernel/runtime-services/sharing-service.mdx (via packages/spec)
  • content/docs/kernel/runtime-services/sms-service.mdx (via packages/spec)
  • content/docs/kernel/runtime-services/storage-service.mdx (via packages/spec)
  • content/docs/kernel/services-checklist.mdx (via @objectstack/spec)
  • content/docs/permissions/authorization.mdx (via @objectstack/spec)
  • content/docs/permissions/permission-sets.mdx (via @objectstack/spec)
  • content/docs/permissions/permissions-matrix.mdx (via @objectstack/spec)
  • content/docs/permissions/positions.mdx (via @objectstack/spec)
  • content/docs/permissions/rls.mdx (via @objectstack/spec)
  • content/docs/permissions/sharing-rules.mdx (via @objectstack/spec)
  • content/docs/plugins/adding-a-metadata-type.mdx (via @objectstack/spec)
  • content/docs/plugins/development.mdx (via @objectstack/spec)
  • content/docs/plugins/index.mdx (via @objectstack/spec)
  • content/docs/plugins/packages.mdx (via @objectstack/formula, @objectstack/spec)
  • content/docs/protocol/backward-compatibility.mdx (via @objectstack/spec)
  • content/docs/protocol/diagram.mdx (via packages/spec)
  • content/docs/protocol/kernel/config-resolution.mdx (via @objectstack/spec)
  • content/docs/protocol/kernel/i18n-standard.mdx (via @objectstack/spec)
  • content/docs/protocol/kernel/index.mdx (via @objectstack/spec)
  • content/docs/protocol/kernel/lifecycle.mdx (via @objectstack/spec)
  • content/docs/protocol/kernel/plugin-spec.mdx (via @objectstack/spec)
  • content/docs/protocol/kernel/runtime-capabilities.mdx (via @objectstack/spec)
  • content/docs/protocol/knowledge.mdx (via @objectstack/spec)
  • content/docs/protocol/objectql/index.mdx (via @objectstack/spec)
  • content/docs/protocol/objectql/query-syntax.mdx (via @objectstack/spec)
  • content/docs/protocol/objectql/schema.mdx (via @objectstack/spec)
  • content/docs/protocol/objectql/security.mdx (via packages/spec)
  • content/docs/protocol/objectql/state-machine.mdx (via @objectstack/spec)
  • content/docs/protocol/objectui/actions.mdx (via @objectstack/spec)
  • content/docs/protocol/objectui/concept.mdx (via @objectstack/spec)
  • content/docs/protocol/objectui/index.mdx (via @objectstack/spec)
  • content/docs/protocol/objectui/layout-dsl.mdx (via @objectstack/spec)
  • content/docs/protocol/objectui/record-alert.mdx (via @objectstack/formula, @objectstack/spec)
  • content/docs/protocol/objectui/widget-contract.mdx (via @objectstack/spec)
  • content/docs/releases/implementation-status.mdx (via @objectstack/spec)
  • content/docs/releases/index.mdx (via @objectstack/spec)
  • content/docs/releases/v12.mdx (via @objectstack/spec)
  • content/docs/releases/v13.mdx (via @objectstack/spec)
  • content/docs/releases/v15.mdx (via @objectstack/formula)
  • content/docs/releases/v9.mdx (via @objectstack/spec)
  • content/docs/ui/actions.mdx (via @objectstack/spec)
  • content/docs/ui/create-vs-edit-form.mdx (via @objectstack/spec)
  • content/docs/ui/dashboards.mdx (via @objectstack/spec)
  • content/docs/ui/forms.mdx (via @objectstack/spec)
  • content/docs/ui/index.mdx (via @objectstack/spec)
  • content/docs/ui/public-data-collection.mdx (via @objectstack/spec)
  • content/docs/ui/setup-app.mdx (via @objectstack/spec)
  • content/docs/ui/translations.mdx (via @objectstack/spec)
  • content/docs/ui/views.mdx (via @objectstack/spec)

Advisory only. To re-verify, run the docs-accuracy-audit workflow scoped to these files:
node scripts/docs-audit/affected-docs.mjs origin/main → pass the list as args.docs.

@os-zhuang
os-zhuang merged commit e0859b1 into main Jul 19, 2026
16 of 17 checks passed
@os-zhuang
os-zhuang deleted the fix/3278-retire-js-expression-dialect branch July 19, 2026 16:21
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentation Improvements or additions to documentation size/m tests tooling

Projects

None yet

Development

Successfully merging this pull request may close these issues.

formula: retire the js expression dialect — redundant with L2 ScriptBody; hasDialect also mis-reports the stub as real

1 participant