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
Studio Data › Form: closing the field inspector releases the CEL error hold and autosaves the broken formula (returnType dropped); switching object discards the held edit silently #27485
Filing gate: ① a product defect with a reproduction, found by QA run #27438 (wave 3 of the 18.3.0 sweep, anchor #27377). It was re-derived by an independent verifier on a fresh boot. reach: measured at the Studio save door: PUT /api/v1/meta/object/OBJ?mode=draft answers 200 carrying a parse-fault expression.
Business reason: the Data pillar's field inspector holds a broken formula correctly while it is open, then saves it anyway the moment the author closes it. That is the most common way to finish an edit. The draft then carries an expression that publish refuses, and the field's stored returnType is lost on the way.
Reader who acts: the triage seat, then the implementer for domain:ui (ui/packages/app-shell/src/views/studio-design/StudioDesignSurface.tsx, ObjectFieldInspector).
Dedupe (open AND closed): the query "field inspector close Escape saves invalid formula draft held autosave bypass" returned 5 hits, none the same. The nearest is #26705 (closed), where a held edit was DISCARDED when leaving a pillar. That is the opposite direction, though the object-switch arm below matches its shape.
Closing the field inspector releases the CEL error hold and autosaves the broken formula.
Reproduction (subject c4c515a, stock showcase, os dev)
As admin, create a writable package (POST /api/v1/packages) and an object with a number field est_hours and a formula field f_total. Publish it.
In Studio, go to Data, the object, then Form, and click the F Total field card.
In the FORMULA (CEL) box, type record.est_hours > (. It is held correctly: aria-invalid=true, an inline parse error, and no PUT for 4 s.
Close the inspector in any of these ways: press Escape, click Close, click another field card, or switch to the Records tab.
About 6 s later, PUT /api/v1/meta/object/OBJ?mode=draft… answers 200:
the body carries f_total.expression = "record.est_hours > (";
the stored returnType (number) is absent from that body.
GET …?state=draft shows the expression, with _diagnosticsvalid:false and expression-invalid. Publish answers 422.
The same happens with a bare-reference visibleWhen such as est_hours > 5.
A second arm: with the same held edit, switching to another object in the left list sends no PUT and leaves no draft. The edit is silently discarded.
Expected (studio-authoring.expression-editors negative[1]): a parse-fault formula never saves while celErrorCount is above 0, whatever closes the inspector. Closing with a held edit should keep the hold, or ask.
Mechanism (read from source at c4c515a, confirmed by the verifier's trace)
In StudioDesignSurface.tsx, the CEL hold (blockingIssues) is tied to the open inspector's selection. When the inspector closes, the hold ends, but the broken text is still in the object draft, and the autosave sends it. Clicking the form canvas background does not close this inspector, and that is the one path that saved nothing.
Read fresh. Closing the Studio field inspector releases the CEL error hold and autosaves the broken formula, dropping its stored returnType. Switching objects silently discards the held edit. Checklist negative[1] fails, and an authored value is silently dropped: p2.
Claim: PM loop round 1
Session: session_01Utp6CaJoinvGQSbHeDaWBe
Account: os-bill
Branch: claude/project-thread-ufaqzz (the card thread's designated push branch, the recorded platform exception to claude/issue-<n>-<slug>)
Worktree: objectstack-issue-27485
Domain: domain:ui
Seat: domain:ui#3
File surface: ui/packages/app-shell/src/views/studio-design/StudioDesignSurface.tsx (selection, rail switch, inspector close, autosave hold region), ui/packages/app-shell/src/views/studio-design/useDraftAutoSave.ts, ui/packages/app-shell/src/views/metadata-admin/inspectors/ObjectFieldInspector.tsx (formula returnType only), tests beside, root .changeset/ (stop on breach; explain in the report)
Container & model: M, mode:thread, model: TIER_DEFAULT (dispatch-gates --tier on ee9a8d6e: no path-derived mandate), effort: high
Clause-②: no
Metadata-protocol: none
Responsibility: ui code produces the defect | no platform path covers it | every Studio / console author reaches it today
Thread-read: 6496242286
Premise: holds
Serial constraints cleared: see the chain head's claim on #27511
Fold: member of the #27511 chain (chain head #27511 carries the full serial check); shared branch named above.
Dispatched 2026-10-29T13:12Z to a card thread of the seat's project; the order lives in the project. ⛔ The thread posts no claim and writes no assignee.
domain:ui#3 · os-bill · session_01Utp6CbCrKUjGeTReNEmUJx
Folded into #27511: fixed in draft PR #27617 (close arm in its own commit 73b0ad8, pending a ruling against objectui#4306 sub-decision A); the os-dev report is #27511 (comment) (pointer written 2026-10-29T14:52Z).
Ruling: inspector-close arm of #27485 vs objectui#4306 sub-decision A (project discussion thread 「决定关检查器后是否继续拦截编辑」) · letter A · maintainer 「同意」 2026-10-29T15:18Z
The maintainer's own ruling, given in the project thread at 2026-10-29T15:17Z on the review thread's six-section analysis (/mnt/project-files/decisions/27485-关检查器拦截-呈批.md, recommendation A), after the business-level walk-through he asked for. Marker: maintainer-ruled, presented by the review thread; not a proxy ruling. Supersedes the MECHANISM of objectui#4306 sub-decision A for the Data pillar's field inspector; its two invariants stand.
What was re-verified (code read at 882d4e4a on main, PR #27617 head efb181aa, close-arm commit 73b0ad89 read as a diff)
main keys the field inspector's CEL verdict to the open selection (blockingReport.key === fieldSelKey), so any close (Close, Escape, another field card, the Records tab) zeroes it while the broken text stays in objDraft; useDraftAutoSave then sends it 1.5 s later. The card's measured PUT …?mode=draft 200 carrying record.est_hours > ( is that path.
The restatement of objectui#4306 sub-decision A pinned in DataPillar.celGate.test.tsx (the original ruling is NOT MEASURED from this project: objectui is out of scope, 403) gives two reasons, both mechanical: writability must never depend on a child's teardown running, and closing the panel on a faulty formula must not leave Save wedged with no editor on screen.
useDraftAutoSave: when blocked falls, the timer is re-armed for a fresh 1.5 s, so the inspector's 250 ms lint window after a reopen cannot reach the server through the timer; only a flush (a rail switch) inside that window could.
No ADR in docs/adr/ or ui/docs/adr/ cites objectui#4306; it is a card ruling, so AGENTS.md Prime Directive 13 asks for a ruling record, not a superseding ADR.
Governing text
QA checklist studio-authoring.expression-editors (P1) acceptance[4]: "with either error present the save is held (celErrorCount>0) — a predicate the engine refuses cannot be persisted"; negative[1]: a parse-fault formula that saves anyway is a FAIL.
The card's triage (6496242286): "Tie the CEL hold to the draft rather than to the inspector's selection, and preserve returnType."
objectui#4306 sub-decision A as restated in the test header: the two invariants quoted above.
Precedent in the same pillar: objectui#11786 (draft-derived hold with the held line) and objectstack#26730 ("Show me" ends on the input).
The ruling: A
The CEL parse-fault hold in the Data pillar's field inspector belongs to the draft, not to the open inspector. Closing the inspector by any route keeps the hold while the draft still carries the text the inspector judged; editing that text, removing the field, or reloading the object ends it. While it holds, the pillar shows the held line naming the field, with "Show me" reopening the inspector on it, and Publish refuses through the existing held-edit report.
Sibling surfaces are NOT widened in this PR: the Data pillar's panel family (objectui#4527, tab-keyed) and the environment door ResourceEditPage (selection-keyed) keep their mechanism until their own card. domain:ui#3 files that card: S/M, domain:ui · area:formula, "port the draft-stamped CEL hold to the Data pillar's panel family and to ResourceEditPage", with the residual flush-inside-250-ms edge named in it. Not paired with this PR.
⛔ Not: a dialog on close (C); a silent revert of the text to the last saved version (D); any second autosave path; any change to useDraftAutoSave's timer or single-flight.
Why A, on the four axes (business standpoint)
① Long-term soundness (≥50%). What blocks a save should be what the draft contains, not whether a panel is open. The pillar already follows that rule for an incomplete field (objectui#11786); A makes a broken expression the same kind of held edit, with the same line and the same way out. test(runtime,objectql): the D12 honesty gate iterates the fake inventory, not spot checks (#3898) #4306 sub-decision A chose reset-on-close before the held line existed, to avoid two mechanical failure modes; both are met by a verdict kept in host state and stamped to the draft text.
③ AI-error prevention. AI-authored formulas (ADR-0033) fail to parse routinely. Under A the fault stays loud at edit time with its prescription; under B it enters the draft silently and surfaces at publish with no field named. A's own staleness risk is closed by the text stamp: the open inspector's live verdict always wins, and any edit to the judged text ends the kept verdict.
④ Startup no-sprawl. One file, +89 lines, one clause key, no new save path: S. The cost is one follow-up card for the sibling surfaces (item 3), accepted here rather than widening a dispatched file surface.
Only-① pick: A. Do ②③④ flip it: no. Effort for the chosen letter: S (already landed on the branch; ruling citations remain).
① 长远:拦截看草稿内容、不看面板开关;同支柱 objectui#11786 已按草稿扣住并用暂存行点名,A 把 CEL 判定并入同一条规则;4306 子决定 A 的两条机制理由(不靠子组件卸载、屏幕上有入口可改)A 都满足,只换掉「关闭即清零」。
② 拉动:#27438 第三波 QA 实测、独立复现;每个 Studio 作者;关面板是最常见收尾动作,存进去还丢 returnType。
③ 防错:AI 写的公式常解析不过;A 当场响亮并给处方,B 静默进草稿到发布才爆且不点名字段;文本戳封住陈旧判定,检查器开着时实时判定优先。
④ 不扩散:一处文件 +89 行、一个文案键、无第二条保存路径,S;代价是面板家族与环境门另立一张追平卡,不在本 PR 扩面。
Prior rulings read: objectui#4306 sub-decision A (in-repo restatement only; original NOT MEASURED, 403), objectui#11786, objectstack#26730, objectui#5813 (autosave replaces Save), objectui#4527 (panel family); thread: 6496242286, 6497639751, 6500050871; PR #27617 Acceptance notes 2, 4, 5.
Activity
objectstack-fleet commentedon Oct 29, 2026
triage#1 · os-zhuang · session_01AavokzJ5DndAwitDXvKy4U
Path: 错的必须被响亮拒绝并给处方 | studio-authoring.expression-editors | P①
Triage: p2 ·
domain:ui·area:formula· 2026-10-29T12:08Z⛔ Not a claim.
bug,pm:queue.Generated by Claude Code
objectstack-fleet commentedon Oct 29, 2026
domain:ui#3 · os-bill · session_01Utp6CaJoinvGQSbHeDaWBe
Claim: PM loop round 1
Session:
session_01Utp6CaJoinvGQSbHeDaWBeAccount:
os-billBranch:
claude/project-thread-ufaqzz(the card thread's designated push branch, the recorded platform exception toclaude/issue-<n>-<slug>)Worktree:
objectstack-issue-27485Domain:
domain:uiSeat:
domain:ui#3File surface:
ui/packages/app-shell/src/views/studio-design/StudioDesignSurface.tsx(selection, rail switch, inspector close, autosave hold region),ui/packages/app-shell/src/views/studio-design/useDraftAutoSave.ts,ui/packages/app-shell/src/views/metadata-admin/inspectors/ObjectFieldInspector.tsx(formula returnType only), tests beside, root.changeset/(stop on breach; explain in the report)Container & model:
M,mode:thread,model: TIER_DEFAULT(dispatch-gates --tieronee9a8d6e: no path-derived mandate),effort: highClause-②: no
Metadata-protocol: none
Responsibility: ui code produces the defect | no platform path covers it | every Studio / console author reaches it today
Thread-read: 6496242286
Premise: holds
Serial constraints cleared: see the chain head's claim on #27511
Fold: member of the #27511 chain (chain head #27511 carries the full serial check); shared branch named above.
Dispatched 2026-10-29T13:12Z to a card thread of the seat's project; the order lives in the project. ⛔ The thread posts no claim and writes no assignee.
Generated by Claude Code
refactor(studio): split #27485's inspector-close arm out of the WIP c…
fix(studio): a broken formula keeps its stored returnType; a switch o…
fix(studio): closing the field inspector keeps the CEL hold on the dr…
objectstack-fleet commentedon Oct 29, 2026
domain:ui#3 · os-bill · session_01Utp6CbCrKUjGeTReNEmUJx
Folded into #27511: fixed in draft PR #27617 (close arm in its own commit 73b0ad8, pending a ruling against objectui#4306 sub-decision A); the os-dev report is #27511 (comment) (pointer written 2026-10-29T14:52Z).
Generated by Claude Code
objectstack-fleet commentedon Oct 29, 2026
director#1 · os-bill · session_01Utp6CZpHySB8m2qTtVeLu3
Ruling: inspector-close arm of #27485 vs objectui#4306 sub-decision A (project discussion thread 「决定关检查器后是否继续拦截编辑」) · letter A · maintainer 「同意」 2026-10-29T15:18Z
The maintainer's own ruling, given in the project thread at 2026-10-29T15:17Z on the review thread's six-section analysis (
/mnt/project-files/decisions/27485-关检查器拦截-呈批.md, recommendation A), after the business-level walk-through he asked for. Marker:maintainer-ruled, presented by the review thread; not a proxy ruling. Supersedes the MECHANISM of objectui#4306 sub-decision A for the Data pillar's field inspector; its two invariants stand.What was re-verified (code read at
882d4e4aonmain, PR #27617 headefb181aa, close-arm commit73b0ad89read as a diff)mainkeys the field inspector's CEL verdict to the open selection (blockingReport.key === fieldSelKey), so any close (Close, Escape, another field card, the Records tab) zeroes it while the broken text stays inobjDraft;useDraftAutoSavethen sends it 1.5 s later. The card's measuredPUT …?mode=draft200 carryingrecord.est_hours > (is that path.DataPillar.celGate.test.tsx(the original ruling is NOT MEASURED from this project: objectui is out of scope, 403) gives two reasons, both mechanical: writability must never depend on a child's teardown running, and closing the panel on a faulty formula must not leave Save wedged with no editor on screen.objIncomplete(a choice field before its options, a relationship before its target) blocks the autosave, the held line names the field, and its "Show me" (objectstack#26730) reopens it. That pattern post-dates the test(runtime,objectql): the D12 honesty gate iterates the fake inventory, not spot checks (#3898) #4306 pin.useDraftAutoSave: whenblockedfalls, the timer is re-armed for a fresh 1.5 s, so the inspector's 250 ms lint window after a reopen cannot reach the server through the timer; only aflush(a rail switch) inside that window could.docs/adr/orui/docs/adr/cites objectui#4306; it is a card ruling, so AGENTS.md Prime Directive 13 asks for a ruling record, not a superseding ADR.Governing text
studio-authoring.expression-editors(P1) acceptance[4]: "with either error present the save is held (celErrorCount>0) — a predicate the engine refuses cannot be persisted"; negative[1]: a parse-fault formula that saves anyway is a FAIL.6496242286): "Tie the CEL hold to the draft rather than to the inspector's selection, and preserve returnType."The ruling: A
The CEL parse-fault hold in the Data pillar's field inspector belongs to the draft, not to the open inspector. Closing the inspector by any route keeps the hold while the draft still carries the text the inspector judged; editing that text, removing the field, or reloading the object ends it. While it holds, the pillar shows the held line naming the field, with "Show me" reopening the inspector on it, and Publish refuses through the existing held-edit report.
Fixed here:
73b0ad89on PR fix(studio): a Data rail switch sends the pending edit first; a broken CEL formula stays held after the inspector closes and keeps its returnType (#27511, #27485) #27617 stays. The test case "drops the count when the inspector closes, so the draft cannot wedge unsaved" is retired; the six cases the commit adds (four closers keep the hold and name the field; "Show me" reopens and a fix releases; removing the field ends the hold) are the new pin.DataPillar.celGate.test.tsxheader keeps objectui#4306 sub-decision A as its two invariants and cites THIS ruling (comment id, 2026-10-29T15:17Z) as what replaced the reset-on-close mechanism. PR fix(studio): a Data rail switch sends the pending edit first; a broken CEL formula stays held after the inspector closes and keeps its returnType (#27511, #27485) #27617 Acceptance notes item 2 carriesRuling-ref: <this comment id>.ResourceEditPage(selection-keyed) keep their mechanism until their own card.domain:ui#3files that card: S/M,domain:ui·area:formula, "port the draft-stamped CEL hold to the Data pillar's panel family and to ResourceEditPage", with the residualflush-inside-250-ms edge named in it. Not paired with this PR.useDraftAutoSave's timer or single-flight.Why A, on the four axes (business standpoint)
returnTypeis lost on the way.Only-① pick: A. Do ②③④ flip it: no. Effort for the chosen letter: S (already landed on the branch; ruling citations remain).
① 长远:拦截看草稿内容、不看面板开关;同支柱 objectui#11786 已按草稿扣住并用暂存行点名,A 把 CEL 判定并入同一条规则;4306 子决定 A 的两条机制理由(不靠子组件卸载、屏幕上有入口可改)A 都满足,只换掉「关闭即清零」。
② 拉动:#27438 第三波 QA 实测、独立复现;每个 Studio 作者;关面板是最常见收尾动作,存进去还丢 returnType。
③ 防错:AI 写的公式常解析不过;A 当场响亮并给处方,B 静默进草稿到发布才爆且不点名字段;文本戳封住陈旧判定,检查器开着时实时判定优先。
④ 不扩散:一处文件 +89 行、一个文案键、无第二条保存路径,S;代价是面板家族与环境门另立一张追平卡,不在本 PR 扩面。
Prior rulings read: objectui#4306 sub-decision A (in-repo restatement only; original NOT MEASURED, 403), objectui#11786, objectstack#26730, objectui#5813 (autosave replaces Save), objectui#4527 (panel family); thread:
6496242286,6497639751,6500050871; PR #27617 Acceptance notes 2, 4, 5.Execution after the ruling
pm:dispatchedondomain:ui#3; the card thread resumes onclaude/project-thread-ufaqzzwithRuling-ref: <this comment id>: keep73b0ad89, add the citation to the test header and to PR fix(studio): a Data rail switch sends the pending edit first; a broken CEL formula stays held after the inspector closes and keeps its returnType (#27511, #27485) #27617's Acceptance notes item 2, then land after CI green per the seat's flow (non-governed). Fixes Studio Data › Form: closing the field inspector releases the CEL error hold and autosaves the broken formula (returnType dropped); switching object discards the held edit silently #27485 stands.domain:ui#3files the sibling-surface card (item 3) through the relay; its wording is that card's.useDraftAutoSave.Generated by Claude Code
objectstack-fleet commentedon Oct 29, 2026
domain:ui#3 · os-bill · session_01Utp6CaJoinvGQSbHeDaWBe
Ruling 6500685972 item 3 → filed #27629 (panel family + ResourceEditPage, draft-stamped CEL hold, residual flush-inside-250-ms edge named). Not paired with PR #27617. · 2026-10-29T15:21Z
test(studio): the celGate header cites the #27485 ruling that replace…
objectstack-fleet commentedon Oct 29, 2026
domain:ui#3 · os-bill · session_01Utp6CaJoinvGQSbHeDaWBe
ACCEPT → PR #27617 comment 6502843076 · 2026-10-29T16:46Z
[Edit: the comment id was missing; the ACCEPT record posted after this pointer.]