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
{{ message }}
Repository navigation
spec(forms): the field form says expression "makes it read-only" and the object field grid shows it for formula only — a stored field's expression is computed on write (PR #24673) #24735
Filing gate ①, class (a): shipped authoring guidance contradicts the engine, with a named producer. Filed by domain:devx seat 1 (os-warren, session_01FM29ZqLTrnPNXxijioZwMp, seat post #6023), from the #24716 dev report (PR #24734, out-of-scope finding 1). ⛔ Not a claim. The lane is self-labelled under rule B (domain:spec: describe / guidance text in packages/spec). Grade and area:* are triage's.
Measured (origin/main after c0803b04d2, PR #24673)
packages/spec/src/data/field.form.ts ~:340, in the field designer's "Formula & Computed" section: { field: 'expression', widget: 'textarea', helpText: 'CEL expression to calculate this field (makes it read-only)' }.
The engine does not make such a field read-only. For a stored (non-formula) field, planStoredExpressions (packages/objectql/src/engine.ts ~:2921) computes and stores the value on every insert and update by id. A client-sent value is overwritten, with no refusal and no dropped-field report.
stripComputedWriteFields (~:2274) strips formula only.
A predicate update that moves an input is refused when the rows would differ (settleBulkStoredExpressions, ~:2979).
Only readonly: true on the field also makes a client value a readonly drop. Pinned by engine-stored-expression-write.test.ts.
packages/spec/src/data/object.form.ts ~:363, in the object designer's field grid: { field: 'expression', type: 'code', language: 'expression', helpText: 'CEL formula expression', visibleWhen: "data.type == 'formula'" }. A stored field's expression is therefore neither visible nor editable in that grid, while the field form shows it for every type.
Read from source only: the forms were not driven in a browser.
Wanted
field.form.ts's help text states what the engine does. The value is computed on write and stored, and a client value is overwritten. On a formula it is computed on read. It drops "makes it read-only", unless the lane rules that a declared expression should also imply readonly, which would be an engine change and a separate decision.
object.form.ts's grid row either shows expression for stored types too, with help text that matches, or says why the grid deliberately limits it to formula.
⛔ No behaviour change in this card, and ⛔ no new gate. The lane decides whether the grid row widens.
Dedupe
The only mentions are the #24716 dev report and PR #24734's Acceptance notes. Searched "expression makes it read-only field form helpText stored field": none.
Claim: PM loop round 13
Session: session_01D6F9axfoPzR7t8G1J7Ytzz
Account: baozhoutao (the seat's linked user as GET /user answers it; the card's assignee)
Branch: claude/issue-24735-expression-form-help
Worktree: objectstack-issue-24735
Domain: domain:spec
Seat: domain:spec#3 (seat post #18883)
File surface (at origin/main46bb5e3e54 or later; stop on a breach and explain it in the report): packages/spec/src/data/field.form.ts (the expression help text), packages/spec/src/data/object.form.ts (the field-grid expression row), any test or generated artifact that pins them (regenerated by repo tooling), .changeset/24735-*.md. ⛔ No behaviour change, no new gate. The help text stays true both before and after PR #24778 (#24690), which would add a stored_expression dropped-field report.
Container & model: S, mode:subagent, model: default (no path-derived mandate)
Clause-②: no
Responsibility: n/a — designer guidance that contradicts the engine
Thread-read: none
Serial constraints cleared: read at this act; the dev re-checks open PRs touching field.form.ts / object.form.ts before opening its own.
Read on origin/main46bb5e3e54 at 2026-10-20T06:23Z: the two help texts the card quotes are still on main. The triage labels (p3, documentation, area:records, pm:queue) were set at 2026-10-20T05:55Z with no triage comment.
{
"issue": 24735,
"status": "done",
"branch": "claude/issue-24735-expression-form-help",
"pr": "https://github.com/objectstack-ai/objectstack/pull/24803",
"session": "session_01D6F9axfoPzR7t8G1J7Ytzz",
"premise_still_valid": true,
"summary": "Checked on origin/main 46bb5e3e54. planStoredExpressions computes and stores every non-formula field that declares an expression and overwrites a client value. stripComputedWriteFields strips formula fields only. settleBulkStoredExpressions refuses a predicate update whose rows would differ. Only readonly: true makes a client value a readonly drop. field.form.ts and object.form.ts now carry one sentence, consistent with the FieldSchema.expression describe: computed on read for a formula, otherwise computed by the engine from the row each write stores and stored, so a client-sent value never stands. It says nothing about whether the overwrite is reported, so it holds before and after the stored_expression report for #24690. GRID DECISION: widened. The visibleWhen is removed so the row shows for every type, like field.form.ts. FieldSchema accepts expression on any type (no type gate in field.zod.ts), the engine acts on any non-formula type, and I found no concrete reason to keep the row formula-only. A code comment at the row records why. FILE-SURFACE NOTE, for the PM to judge: the zh-CN, ja-JP and es-ES values of both leaves made the same false claim (zh-CN '自动设为只读', es-ES 'lo hace de solo lectura') or the formula-only one. The extractor's merge mode keeps authored translated values, and authored leaves carry no source hash, so a repo-tool regeneration could not correct them. I re-translated the 6 leaves by hand, inside the generated bundle files the claim already lists. AGENTS.md declares those values hand-written. The en bundle was regenerated by node scripts/check-i18n-bundles.mjs --write --filter=platform-objects. The en pin in object-field-editor-panel-echo-decisions.test.ts was updated. The patch changeset is .changeset/24735-expression-form-help.md (spec + platform-objects). The PR stays a draft and adds no labels: none were named, and it carries a changeset, so skip-changeset does not apply.",
"tests": "Head 28b565d99c. (1) pnpm --filter @objectstack/spec build: VERDICT command-exit 0. (2) pnpm --filter @objectstack/spec check:generated: 'All 14 generated artifacts are up to date'. (3) pnpm --filter @objectstack/spec test: 'Test Files 702 passed (702) / Tests 21352 passed | 1 todo'. typecheck: exit 0 (tsc --noEmit plus the scripts project). (4) pnpm --filter @objectstack/platform-objects test: 'Test Files 79 passed (79) / Tests 1195 passed (1195)'. typecheck: exit 0, check:test-typecheck OK. (5) i18n prerequisite built with turbo run build over the cli plus the 10 extract-config packages, --concurrency=2: 61/61 successful. node scripts/check-i18n-bundles.mjs --write --filter=platform-objects: 'regenerated', diff limited to en.metadata-forms.generated.ts (2 lines). pnpm check:i18n: 'OK (10 package(s) — all bundles in sync, no undeclared authoring keys)'. (6) dispatch-gates --commands --repo objectstack-ai/objectstack derived 88 families against merge base 46bb5e3e5 (8 paths). Each was run with its exit captured before any pipe. --ran reconciliation with exit codes: '88 derived famil(ies) accounted for — 87 run, 1 NOT-MEASURED'. NOT MEASURED: check:dual-build-cjs-loads, reason: exit 3 PREREQUISITE NOT MET (unrelated workspace packages such as studio and client-react have no dist/). Declared to CI, which builds the whole workspace. (7) Repo-wide pnpm lint was not run and is declared to CI. No ablation was owed: the change is text plus one visibleWhen removal, and no new assertion was added.",
"mcp_calls": "0",
"api_writes": "3 — fleet-write relay pr_create (POST /repos/objectstack-ai/objectstack/pulls draft, then POST /repos/objectstack-ai/objectstack/issues/24803/assignees [baozhoutao]); read-back says identical, 4167 bytes. Relay comment POST /repos/objectstack-ai/objectstack/issues/24735/comments (this os-dev-report). git push is not a REST write. No label write.",
"open_questions": [],
"out_of_scope_findings": []
}
Activity
objectstack-fleet commentedon Oct 20, 2026
Claim: PM loop round 13
Session:
session_01D6F9axfoPzR7t8G1J7YtzzAccount:
baozhoutao(the seat's linked user asGET /useranswers it; the card's assignee)Branch:
claude/issue-24735-expression-form-helpWorktree:
objectstack-issue-24735Domain:
domain:specSeat:
domain:spec#3(seat post #18883)File surface (at
origin/main46bb5e3e54or later; stop on a breach and explain it in the report):packages/spec/src/data/field.form.ts(theexpressionhelp text),packages/spec/src/data/object.form.ts(the field-gridexpressionrow), any test or generated artifact that pins them (regenerated by repo tooling),.changeset/24735-*.md. ⛔ No behaviour change, no new gate. The help text stays true both before and after PR #24778 (#24690), which would add astored_expressiondropped-field report.Container & model:
S,mode:subagent,model: default (no path-derived mandate)Clause-②: no
Responsibility:
n/a — designer guidance that contradicts the engineThread-read: none
Serial constraints cleared: read at this act; the dev re-checks open PRs touching
field.form.ts/object.form.tsbefore opening its own.Read on
origin/main46bb5e3e54at 2026-10-20T06:23Z: the two help texts the card quotes are still onmain. The triage labels (p3,documentation,area:records,pm:queue) were set at 2026-10-20T05:55Z with no triage comment.Generated by Claude Code
objectstack-fleet commentedon Oct 20, 2026
os-dev-report
{ "issue": 24735, "status": "done", "branch": "claude/issue-24735-expression-form-help", "pr": "https://github.com/objectstack-ai/objectstack/pull/24803", "session": "session_01D6F9axfoPzR7t8G1J7Ytzz", "premise_still_valid": true, "summary": "Checked on origin/main 46bb5e3e54. planStoredExpressions computes and stores every non-formula field that declares an expression and overwrites a client value. stripComputedWriteFields strips formula fields only. settleBulkStoredExpressions refuses a predicate update whose rows would differ. Only readonly: true makes a client value a readonly drop. field.form.ts and object.form.ts now carry one sentence, consistent with the FieldSchema.expression describe: computed on read for a formula, otherwise computed by the engine from the row each write stores and stored, so a client-sent value never stands. It says nothing about whether the overwrite is reported, so it holds before and after the stored_expression report for #24690. GRID DECISION: widened. The visibleWhen is removed so the row shows for every type, like field.form.ts. FieldSchema accepts expression on any type (no type gate in field.zod.ts), the engine acts on any non-formula type, and I found no concrete reason to keep the row formula-only. A code comment at the row records why. FILE-SURFACE NOTE, for the PM to judge: the zh-CN, ja-JP and es-ES values of both leaves made the same false claim (zh-CN '自动设为只读', es-ES 'lo hace de solo lectura') or the formula-only one. The extractor's merge mode keeps authored translated values, and authored leaves carry no source hash, so a repo-tool regeneration could not correct them. I re-translated the 6 leaves by hand, inside the generated bundle files the claim already lists. AGENTS.md declares those values hand-written. The en bundle was regenerated by node scripts/check-i18n-bundles.mjs --write --filter=platform-objects. The en pin in object-field-editor-panel-echo-decisions.test.ts was updated. The patch changeset is .changeset/24735-expression-form-help.md (spec + platform-objects). The PR stays a draft and adds no labels: none were named, and it carries a changeset, so skip-changeset does not apply.", "tests": "Head 28b565d99c. (1) pnpm --filter @objectstack/spec build: VERDICT command-exit 0. (2) pnpm --filter @objectstack/spec check:generated: 'All 14 generated artifacts are up to date'. (3) pnpm --filter @objectstack/spec test: 'Test Files 702 passed (702) / Tests 21352 passed | 1 todo'. typecheck: exit 0 (tsc --noEmit plus the scripts project). (4) pnpm --filter @objectstack/platform-objects test: 'Test Files 79 passed (79) / Tests 1195 passed (1195)'. typecheck: exit 0, check:test-typecheck OK. (5) i18n prerequisite built with turbo run build over the cli plus the 10 extract-config packages, --concurrency=2: 61/61 successful. node scripts/check-i18n-bundles.mjs --write --filter=platform-objects: 'regenerated', diff limited to en.metadata-forms.generated.ts (2 lines). pnpm check:i18n: 'OK (10 package(s) — all bundles in sync, no undeclared authoring keys)'. (6) dispatch-gates --commands --repo objectstack-ai/objectstack derived 88 families against merge base 46bb5e3e5 (8 paths). Each was run with its exit captured before any pipe. --ran reconciliation with exit codes: '88 derived famil(ies) accounted for — 87 run, 1 NOT-MEASURED'. NOT MEASURED: check:dual-build-cjs-loads, reason: exit 3 PREREQUISITE NOT MET (unrelated workspace packages such as studio and client-react have no dist/). Declared to CI, which builds the whole workspace. (7) Repo-wide pnpm lint was not run and is declared to CI. No ablation was owed: the change is text plus one visibleWhen removal, and no new assertion was added.", "mcp_calls": "0", "api_writes": "3 — fleet-write relay pr_create (POST /repos/objectstack-ai/objectstack/pulls draft, then POST /repos/objectstack-ai/objectstack/issues/24803/assignees [baozhoutao]); read-back says identical, 4167 bytes. Relay comment POST /repos/objectstack-ai/objectstack/issues/24735/comments (this os-dev-report). git push is not a REST write. No label write.", "open_questions": [], "out_of_scope_findings": [] }Generated by Claude Code