Skip to content

fix(spec): field and object form expression help states what the engine does - #24803

Merged
objectstack-fleet[bot] merged 5 commits into
mainfrom
claude/issue-24735-expression-form-help
Oct 20, 2026
Merged

objectstack-fleet[bot] merged 5 commits into
mainfrom
claude/issue-24735-expression-form-help

Conversation

@objectstack-fleet

Copy link
Copy Markdown
Contributor

Closes #24735

Clause-②: no

What

The expression help text in the field designer (packages/spec/src/data/field.form.ts) said the expression "makes it read-only". The engine does not do that. The object designer's field grid (packages/spec/src/data/object.form.ts) showed the expression row for formula fields only, with the help text "CEL formula expression". Both rows now carry the same sentence, which matches the landed FieldSchema.expression describe:

CEL expression the field's value is computed from. On a formula field: computed on read, no stored column. On any other field: computed by the engine from the row each write stores, and stored, so a client-sent value never stands.

Nothing changes in behaviour, and no gate is added.

Engine behaviour the text was checked against (origin/main 46bb5e3)

  • planStoredExpressions (packages/objectql/src/engine.ts): every non-formula field that declares an expression is computed over the row the write stores and written onto the payload. A client-sent value is overwritten.
  • stripComputedWriteFields: strips formula fields only. A formula has no column and is computed on read.
  • settleBulkStoredExpressions: a predicate update that moves an input stores the single value when every matched row agrees, and refuses the update otherwise.
  • Only readonly: true makes a client value a readonly drop.

The sentence makes no claim about whether the overwrite is reported. It stays true before and after the open draft for #24690, which would add a stored_expression dropped-field report. "A client-sent value never stands" holds either way.

Grid row decision: widened to every type

FieldSchema accepts expression on every field type: there is no type gate in field.zod.ts, and planStoredExpressions acts on any non-formula type. The field designer's own row has no visibleWhen. With the formula-only row, a stored field's live expression could not be seen or edited in the grid, while the field form showed it. I found no concrete reason to keep the narrower row, so the visibleWhen is removed and the help text matches field.form.ts. A comment at the row records why.

Translations

The zh-CN, ja-JP and es-ES values of both leaves made the same false claim, or the formula-only one. Two examples: zh-CN "自动设为只读" and es-ES "lo hace de solo lectura". AGENTS.md says translated-locale values are hand-written. The extractor's merge mode keeps every existing translated value, and authored leaves carry no source hash, so regenerating could not correct them. I re-translated the six leaves by hand. The en bundle was regenerated with node scripts/check-i18n-bundles.mjs --write --filter=platform-objects, which rewrote only en.metadata-forms.generated.ts. The en pin for object.fields['fields.expression'].helpText in object-field-editor-panel-echo-decisions.test.ts follows the new source, with its reason amended.

Verification (head 28b565d)

  • pnpm --filter @objectstack/spec build: exit 0. Then pnpm --filter @objectstack/spec check:generated: "All 14 generated artifacts are up to date".
  • pnpm --filter @objectstack/spec test: 702 files / 21352 tests passed. pnpm --filter @objectstack/spec typecheck: exit 0.
  • pnpm --filter @objectstack/platform-objects test: 79 files / 1195 tests passed. pnpm --filter @objectstack/platform-objects typecheck: exit 0.
  • pnpm check:i18n: "OK (10 package(s) — all bundles in sync, no undeclared authoring keys)". check:i18n-stale-fill: OK.
  • node scripts/pm/dispatch-gates.mjs --ran: 88 derived families accounted for, 87 run at exit 0. NOT MEASURED: check:dual-build-cjs-loads. It exited 3 with PREREQUISITE NOT MET because unrelated workspace packages have no dist/. CI builds the whole workspace and runs it.
  • pnpm lint (repo-wide eslint) was not run locally and is left to CI.

Acceptance notes

  • Nothing was driven in a browser. The objectui grid renders the row from this form metadata, and the only change it sees is that visibleWhen is gone.

Generated by Claude Code

@github-actions

github-actions Bot commented Oct 20, 2026 •

Copy link
Copy Markdown
Contributor

📓 Docs Drift Check

4 anchor(s) derived from 2 changed package(s); no hand-written page names any of them, so this run has nothing to list — not a clean bill of health. This check sees only pages that NAME a derived anchor: one that documents this change in prose, or enumerates it in an authoring dialect, names none and stays invisible to it on every run.

What this run could not see

Coarse fallback — 143 page(s) merely mention a changed package (the pre-#9192 predicate, kept for the deliberately-wide backstop): node scripts/docs-audit/affected-docs.mjs --json ddb3360a4954c1ccb6878deb3ca0b303c79d3289 → packageMentionDocs.

Which tree this was computed on

This run read content/docs from 1ba96e6be2aae70d6c8ce0826c556a9726ba9952 — the merge of head b2ea2ae8dee92d688b900c91e1a989ce1a3780bc into base ddb3360a4954c1ccb6878deb3ca0b303c79d3289, which is what actions/checkout gives a pull_request run. Not the PR head.

A worktree cut from an older main holds a different content/docs, so re-deriving there can legitimately return a different list — that is a different tree, not a wrong row. To answer on the same tree:

# while this PR is open — GitHub drops the merge commit once it closes
git fetch origin 1ba96e6be2aae70d6c8ce0826c556a9726ba9952 && git checkout 1ba96e6be2aae70d6c8ce0826c556a9726ba9952
# afterwards, rebuild it from the two parents, which stay fetchable
git fetch origin ddb3360a4954c1ccb6878deb3ca0b303c79d3289 b2ea2ae8dee92d688b900c91e1a989ce1a3780bc && git checkout -B drift-repro ddb3360a4954c1ccb6878deb3ca0b303c79d3289 && git merge --no-ff b2ea2ae8dee92d688b900c91e1a989ce1a3780bc

node scripts/docs-audit/affected-docs.mjs --json ddb3360a4954c1ccb6878deb3ca0b303c79d3289

⚠️ That checkout carried uncommitted changes, so the commit above does not fully identify what was read.

@objectstack-fleet
objectstack-fleet Bot marked this pull request as ready for review October 20, 2026 07:07
@objectstack-fleet
objectstack-fleet Bot enabled auto-merge October 20, 2026 07:07
…'s expression gate went

The object form's `expression` row no longer carries
`visibleWhen: "data.type == 'formula'"`, so the three census counts in
validate-predicate-path-refs.test.ts each drop by one: 89 -> 88 shipped
predicates, 66 -> 65 literal comparisons, 19 -> 18 object-form
`data.type`-rooted predicates.

Claude-Session: https://claude.ai/code/session_01D6F9axfoPzR7t8G1J7Ytzz
Co-authored-by: Claude <noreply@anthropic.com>
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 protocol:data size/s tests tooling

Projects

None yet

2 participants