Repository navigation
DroppedFieldsEvent.reason 只有 readonly / readonly_when 两值,写路径上新增的合法剥离对 onFieldsDropped / strictReadonlyWrites 不可见 #6437
Description
Activity
Findings triage — verdict: HOLD (
findingretained). Routing recorded: this belongs todomain:specif and when it is promoted — see below; nodomain:*applied while it is held, since the label is only consumed by dispatch.Why still held: the author's grading is right and re-checked rather than taken on trust. The new strip did not exist before PR #6433 — before it, the payload went into the SET clause verbatim, which was the #6262 data corruption — so no caller has lost a signal they previously had. The gap only bites a caller who has opted into
onFieldsDroppedorstrictReadonlyWritesand wrote a non-id value intodata.idand declared multi; awarnis emitted on that path. That is a narrowed observable surface on an author-error path, not a live defect.Why not promoted: the fix is vocabulary design, not a small edit — add a value, or split
reasonintocategory+ specific cause — and it ships through three protocol consumers (packages/spec/src/api/batch.zod.ts,.../api/protocol.zod.ts) plus regenerated spec baselines. PR #6433 was right not to reusereadonly/readonly_when: that would makereasonlie, which is strictly worse than the current silence.Routing when promoted:
domain:spec, notdomain:spec-surface. The enum atpackages/spec/src/data/data-engine.zod.ts:228is the accepted set — widening it changes what validates — so the reverse red line applies however small the diff (precedents #6245, #6235). Only the.describe()half would be surface, and it cannot travel without the enum.Restart condition: promote when a second non-readonly strip lands on the write path. One instance is a special case that a
warncovers; two make the enum's closed shape a recurring lie, and at that point the design question ("new value vs.category+ cause") has two data points instead of one to answer it. Also promote immediately if a caller reports relying onstrictReadonlyWritesfor total coverage — that would convert this from a narrowed surface into a broken promise.Stale-premise check:
reason: z.enum(['readonly', 'readonly_when'])is verbatim onorigin/mainatdata-engine.zod.ts:228, describe text unchanged. The deliberate "not reporting this one" comment in PR #6433's new strip block is the externalised half this card records, and item 3 of the body's own landing-site list correctly requires deleting it whenever the enum moves.No
target:<major>: no shipped-surface defect — the strip itself is correct, only a machine-readable signal is absent, and thewarnis present.本评论来自分诊座位 Routine(#5474 试点),不构成认领。
Generated by Claude Code
os-project-manager commented
on Aug 8, 2026 CollaboratorMore actionsFindings sweep (maintainer-authorized one-off, 2026-08-07 — registered on #6015): promoted to the queue. The seam's declared observability is now narrower than the strips it reports on: yesterday's legal
data.idstrip (PR #6433) is invisible toonFieldsDroppedand tostrictReadonlyWrites— the loud/observable pair #3407/#5126 built loses coverage silently as new legal strips appear. Widen the enum (acceptance-surface change ⇒ spec seat).finding→pm:queue+domain:spec.
Generated by Claude Code
CLAIM — PM seat
domain:spec(sessionsession_01PiRUoQkTSBBmpyXBY3cVn2), dispatching to an os-dev subagent.- Branch:
claude/issue-6437-dropped-fields-reason-vocabulary - Worktree:
../objectstack-issue-6437(per-task, per Prime Directive Migrate documentation site to Fumadocs with monorepo structure and shared content #11) - Dispatch basis (findings-sweep promotion, quoted as ruling): "The seam's declared observability is now narrower than the strips it reports on … Widen the enum (acceptance-surface change ⇒ spec seat)." Direction is the enum-widening route, NOT the
category+cause split the earlier HOLD comment surveyed. - File surface (from the card's own landing-site list):
packages/spec/src/data/data-engine.zod.ts(DroppedFieldsEventSchema.reason+ describe), the protocol-response consumerspackages/spec/src/api/batch.zod.ts/protocol.zod.ts,packages/objectql/src/engine.ts(the PR fix(objectql): multi update 的 SET 载荷剥掉非 id 的data.id(#6262) #6433 strip block — its deliberate "not reporting this one" comment must be deleted when the enum moves, per the card), regenerated api-surface/JSON-schema baselines. - Concurrency note: [finding][spec] ViewFilterRuleSchema.value 不按算子约束形状 —— 集合算子配标量在发布期通过,直到运行时才拿到 400 #6227 (
view.zod.ts) and An action param'sdefaultValueis typedz.unknown(), so a default that can never satisfy the param's own value contract is accepted at authoring time and only 400s at submit #6970 (action.zod.ts) devs in flight in the same package — disjoint source files, overlapping generated artifacts; serial landing via the PM relay, do not pre-resolve.
Generated by Claude Code
- Branch:
PM bookkeeping:
pm:dispatched→pm:queue. The dispatched os-dev was stopped externally (mass session-level cancellation, 15:21Z patrol census) before pushing any code — no branch, zero work product. Claim released; card returns to the queue intact. Re-dispatch awaits the maintainer's word; the brief (ruling: widen the enum; strict-mode posture measured in-PR) remains valid.
Generated by Claude Code
RE-CLAIM — PM seat (session
session_01PiRUoQkTSBBmpyXBY3cVn2), fresh os-dev dispatched under the maintainer's re-acceleration (2026-08-09 chat). Branchclaude/issue-6437-dropped-fields-reason-vocabulary, worktree../objectstack-issue-6437. All constraints in the 12:28Z claim comment remain binding.
Generated by Claude Code
- added 3 commits that reference this issue
on Aug 17, 2026 - added a commit that references this issue
on Oct 7, 2026
观察类发现(
finding,不入队),来自 #6262 / PR #6433 的实施过程(PD #10)。不是今天用户会撞到的缺陷,是一处「声明的可观测面比实际剥离面窄」的漂移,记录下来免得只活在一条代码注释里。事实
packages/spec/src/data/data-engine.zod.ts:228起,DroppedFieldsEventSchema.reason是闭合枚举:而
#3407给这个 seam 的定位是通用的 —— 「写路径上被合法剥掉的、调用方提交过的字段」,因为调用方(典型是 flow 的update_record步骤)会逐字段汇报成功,而库里那一列根本没变(#4632 的二等形状:调用方以为落库了,数据库不同意,服务端日志是唯一痕迹)。#5126的strictReadonlyWrites是同一 seam 的响亮那一半:要么静默可观测,要么整笔拒绝。PR #6433 在 update 的 multi 分支新增了一次剥离(把派发已裁定「不是主键」的
data.id从 SET 载荷去掉)。它是一次调用方提交过的、被引擎合法丢弃的字段,但它既不是readonly也不是readonly_when,所以:onFieldsDropped监听器收不到这次剥离;strictReadonlyWrites: true的调用方不会因此被拒,它仍拿到一个成功返回。PR #6433 里刻意没有硬塞进那两个值里(那会让 reason 说谎),改为记一条
warn,并把理由写在注释里:扩这个词表是packages/spec的改动,有packages/spec/src/api/batch.zod.ts与.../api/protocol.zod.ts两处协议响应消费者,不该搭引擎修复的车。本 issue 就是那条注释的外化。为什么标
finding而不是入队data.id(#6262) #6433 之前根本不存在(载荷原样进 SET,那才是data.id是算子对象 +multi: true时,{"$in":[...]}作为普通列进入updateMany的 SET 载荷,写向主键列 #6262 的数据损坏);剥离之后行为是正确的,只是少一路机器可读信号,warn日志在。onFieldsDropped/ 开了strictReadonlyWrites的调用方,且只在「作者把非 id 的东西写进data.id又声明 multi」这一种作者错误上。category+ 具体原因?)以及两处协议响应的兼容,属于需要先想清楚再做的那类,不适合当作一个小修派发。若将来处理,面在哪
packages/spec/src/data/data-engine.zod.ts——DroppedFieldsEventSchema.reason枚举 + 其 describe;packages/spec/src/api/batch.zod.ts/packages/spec/src/api/protocol.zod.ts—— 三处droppedFields响应字段的消费者;packages/objectql/src/engine.ts—— update 的reportDroppedFields调用点(by-id 与 multi 各一组),以及 PR fix(objectql): multi update 的 SET 载荷剥掉非 id 的data.id(#6262) #6433 新增剥离块里那段「刻意不上报」的注释(改了要一并删);packages/spec的 api-surface / JSON schema 基线随枚举变动重生成。关联:#3407(
onFieldsDropped的由来)、#5126(strictReadonlyWrites)、#4632(二等形状)、#3042 / #2948(现有两个 reason)、#6262 / PR #6433(触发本条的新剥离)。