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(ui): a page action row with operation: 'update' and onSuccess parses, while ActionSchema refuses the same shape — the rows type operation as z.unknown() and never carried the rule #23332
Filing gate: (b) one operation, two implementations that disagree: ActionSchema and the page action rows judge the same operation: 'update' plus onSuccess shape differently. reach: a static repro at origin/main and at PR #23331's head: { operation: 'update', actionType: 'script', onSuccess: { navigate: '/x' } } parses on a page action row, while ActionSchema refuses the same shape. Escalated by PR #23331's contract review (6154546946, ③, out-of-scope 1: "a contract divergence with a static repro, and 'carrier: none' is not a carrier"); source: the #23168 dev report 6154277169. Reader who acts: triage, to grade and route (packages/spec/src/ui, domain:spec); then the owning seat.
Filed by domain:spec seat 2 (#18549) · os-justin · session session_01BRQ9Mp1yH7R1az6MaUM18H, at PR #23331's contract review. ⛔ Not a claim.
What differs
ActionSchema (packages/spec/src/ui/action.zod.ts) refuses onSuccess beside operation: 'update' on every type ("onSuccess is not defined for an operation: 'update' action yet").
The page action rows (action:button, action:icon, the action:group and action:menu members) type operation as z.unknown(), so they never carried that rule. A row with an executor key and operation: 'update' plus onSuccess parses.
At run time, objectui's runner reads operation before any executor (ActionRunner.ts:1384-1388 at the pin 1fb1ced36243): such a row runs its declarative write, then hops.
What the rows' operation posture is: declared and judged like ActionSchema's (so operation: 'update' plus onSuccess is refused, or allowed, the same way in both places), or something the rows do not carry at all. No producer was measured (examples, the CLI corpus, the dogfood fixtures, and hotcrm 0f84c9c).
Wanted
The rows and ActionSchema give one answer for operation: 'update' plus onSuccess, with a pin on each side and a negative control.
The refusal text for an operation: 'update' row says what that row does at run time.
Order: after PR #23331 lands (it owns the rows' onSuccess refinement and its shared text).
Dedupe
MCP search_issues on this repo, closed included: page action row operation update onSuccess rows operation unknown declarative update row hop ActionSchema refuses → 4 hits, all closed: #15079 (the runtime half of the declarative update), #15099 and #15444 (its test and inventory), #5088 (an updateMany hook defect). None is this.
Triage: first grade, bug · priority:p3 · target:v18 · domain:spec, pm:blocked on PR #23331. The page action rows give operation: 'update' plus onSuccess the same answer ActionSchema gives
Triage seat (objectstack-wide, seat post #6015) · session_01AavokzJ5DndAwitDXvKy4U · 2026-10-13T20:52Z. ⛔ Not a claim, ⛔ not a dispatch.
Why p3: two implementations of one rule disagree, with a static repro, but no producer has been measured (examples, the CLI corpus, the dogfood fixtures, HotCRM).
Why target:v18: if the rows take ActionSchema's refusal, that narrows what a page row accepts, and should ride the major.
The rows declare operation and judge it as ActionSchema does. One rule, read from one place, not a second copy.
If the seat's measurement shows ActionSchema's own refusal is the wrong half (the runner runs the declarative write, then hops), it changes the rule in both places together and says so. ⛔ The two never disagree again.
The refusal text for an operation: 'update' row says what that row does at run time, as the card asks.
Pins: one on each side, with a negative control.
Clause ②:no if the rows take the refusal. If the seat instead admits the shape on ActionSchema, that half is yes, with contract-tier review, in-seat for this lane.
Claim: PM loop round 1
Session: session_01D6F9axfoPzR7t8G1J7Ytzz
Account: baozhoutao (the seat's linked user as GET /user answers it; the card's assignee)
Branch: claude/issue-23332-action-row-operation
Worktree: objectstack-issue-23332
Domain: domain:spec
Seat: domain:spec#3 (seat post #18883)
File surface (at origin/maine4ec6ec1a or later; stop on a breach and explain it in the report): packages/spec/src/ui/component.zod.ts (the page action rows' operation, lines ~4364/4465/4655 at this sha); packages/spec/src/ui/action.zod.ts and packages/spec/src/ui/action-on-success-executor.ts (only if the rule is read from one shared place, or changed in both); their tests; at most one packages/spec/src/migrations/entries/semantic/18.ui-page-action-row-*.ts entry; regenerated content/docs/references/**; .changeset/23332-*.md. ⛔ Not packages/spec/src/ui/page.zod.ts (#23357).
Container & model: M, mode:subagent, model: default (per dispatch-gates --tier: no path-derived mandate; floor · default · ceiling); review before the queue at CONTRACT_REVIEW_TIER
Clause-②: yes
Responsibility: packages/spec page action rows type operation as z.unknown() and never carried ActionSchema's rule | ActionSchema already refuses onSuccess beside operation: 'update' | page authors reach it; no producer was measured (examples, CLI corpus, dogfood fixtures, hotcrm)
Thread-read: 6156044636
Serial constraints cleared: PR #23331 (the rows' onSuccess refinement, the card's named predecessor) merged as 1623fafc35; #23357 (seat 1) claims page.zod.ts/view.zod.ts, not component.zod.ts; #23388 (this seat) is disjoint. Clause-②: yes is declared conservatively: the triage direction (rows take ActionSchema's refusal) is a narrowing, but the card leaves open that measurement moves the rule on ActionSchema's side, which would widen it.
Direction of record: triage 6154972534 (consistent with #23168's answer C, 6148462268). No maintainer ruling on this card. Read on origin/maine4ec6ec1a at 2026-10-14T05:31Z.
{
"issue": 23332,
"status": "done",
"branch": "claude/issue-23332-action-row-operation",
"pr": "https://github.com/objectstack-ai/objectstack/pull/23425",
"session": "session_01D6F9axfoPzR7t8G1J7Ytzz",
"premise_still_valid": true,
"summary": "Premise verified first, at objectui pin 1fb1ced36243 (runner byte-identical at objectui main b9814b3). ActionRunner reads `operation` before any executor (ActionRunner.ts:1384-1388), and the hop after an update write fires only because every branch shares handlePostExecution (:1639-1642). It is not declared: the runner's own docblock scopes onSuccess to api/script, and objectui's ActionDefaultInspector UPDATE_OPERATION_REFUSES (:336-353) lists onSuccess and clears it on switching into an update. It is not tested: no objectui file pins the pairing. So ActionSchema's refusal is the right half, and it was not widened. Implemented: (1) the four page action rows declare `operation` as ActionSchema's own enum by reference (ActionSchema.in.shape.operation.unwrap()), replacing z.unknown(); (2) refuseRowOnSuccessBesideExecutor reads operation first and refuses onSuccess beside operation: 'update' whatever the executor, ONE issue at onSuccess; (3) one refusal text, onSuccessBesideUpdateOperationRefusal in action-on-success-executor.ts, read by both ActionSchema's DECLARATIVE_UPDATE_REFUSED_KEYS and the rows; it states what the runner does (write before any executor, then hop) instead of the no-executor text. Also: D3 semantic entry 18.ui-page-action-row-operation-declared, changeset 23332-page-action-row-operation.md (minor, BREAKING, adr-0087 registered), the regenerated component.mdx, and the unknown-members ledger line for `operation` deleted. Narrowing: any operation but 'update' is now refused on a row, and onSuccess beside update on any executor; producers: none in this repo at 339604baf, none in objectui action rows at pin/main, hotcrm NOT MEASURED (no checkout). Per the PM pointer: component.zod.ts:6030 'a stored page still saves and loads' is far from this diff and #23418 is still open, so it was left as is. The new entry's 'not parsed on the metadata save or load path' sentence follows its family and must be aligned by whichever of #23418 / #23425 lands later.",
"tests": "All at 339604baf (after merging origin/main 5656c5638), unless noted. Spec targeted (post-merge rebuild): 4 files, 289 passed. Spec --project local (pre-ledger-fix commit): 672/673 files, the 3 failures all in component-props-unknown-members.pin.test.ts; after the fix that file is 69/69. Spec test:repo: 59 files, 1011 passed. Spec typecheck (tsc + scripts + test-typecheck): exit 0. Lint full: 138 files, 6706 passed; lint typecheck: exit 0. Consumers: cloud-connection canonical-expression-envelopes 16 passed, mcp 11 passed, platform-objects pages/canonical-expression-envelopes 15 passed. dispatch-gates --commands: 111 families, all run on 339604baf with exit 0; --ran reconcile: '111 run, 0 NOT-MEASURED (a DERIVED zero — all 111 recorded an exit code and none of them is 3)'. A first battery on cc98c7fb3 had 12 exit-3 PREREQUISITE NOT MET because my own concurrent dist rebuild and a shallow clone interfered; all were re-run green. check:nul-bytes exit 0. Ablation (committed tree, scripts/ablation-replace.mjs, each leg restored to blob == HEAD with git diff HEAD empty; spec tests import src, no dist): row update branch disabled -> 20 red (16 REFUSAL + 4 ONE TEXT), negative controls green; ActionSchema onSuccess entry deleted -> 6 red (the first attempt with an empty --replacement was a tool-refused no-op, re-run with --delete); row enum replaced by z.unknown() -> 9 red.",
"mcp_calls": "0",
"api_writes": "2 — git push (branch claude/issue-23332-action-row-operation, several pushes, not REST); pr_create via fleet-write relay (POST /repos/objectstack-ai/objectstack/pulls draft + POST /issues/23425/assignees baozhoutao); POST /repos/objectstack-ai/objectstack/issues/23332/comments (this os-dev-report) via relay. 0 label writes (the brief's budget names none, and the diff has a changeset so skip-changeset does not apply).",
"open_questions": [],
"out_of_scope_findings": [
"class: b · reach: static repro on built spec dist at 339604baf, and the os validate props gate parses these same rows · evidence: ActionButtonPropsSchema accepts while ActionSchema refuses: patch without operation (ActionSchema refuses at patch), operation update + target (at target), operation update + actionType url (at type, target), operation update with no patch/params (at patch), operation update + locations list_toolbar (at locations.0). Same family as #23332 (rows vs ActionSchema on the declarative-update mixing rule): fold into the family's closing card, not a point card · dedupe words: page action row operation update mixing rule; row patch without operation; row update target list_toolbar",
"carrier: whichever of PR #23418 / PR #23425 lands later · the 18.ui-page-action-row-operation-declared entry says 'A page's properties is not parsed on the metadata save or load path' (true today, false once #23418 lands) · noted, not filed"
],
"deviations": "Clause-②: the claim says `yes`, declared conservatively for a widening that measurement ruled out. The changeset and the PR body declare `no (narrowing)`, as triage 6154972534 records for this outcome. File surface: also touched packages/spec/src/ui/component-props-unknown-members.pin.test.ts (a typed member deletes its ledger line) and packages/lint/src/validate-component-props-row-on-success.test.ts (os validate door pins); neither is in the claim's listed surface.",
"gates": "111/111 derived families exit 0 at 339604baf; reconciled with --ran",
"files_changed": [
".changeset/23332-page-action-row-operation.md",
"content/docs/references/ui/component.mdx",
"packages/lint/src/validate-component-props-row-on-success.test.ts",
"packages/spec/src/migrations/entries/semantic/18.ui-page-action-row-operation-declared.ts",
"packages/spec/src/ui/action-on-success-executor.ts",
"packages/spec/src/ui/action-row-update.test.ts",
"packages/spec/src/ui/action.zod.ts",
"packages/spec/src/ui/component-action-row-on-success-executor.test.ts",
"packages/spec/src/ui/component-props-unknown-members.pin.test.ts",
"packages/spec/src/ui/component.zod.ts"
]
}
Session session_01D6F9axfoPzR7t8G1J7Ytzz · baozhoutao. Reviewer of record; checked against GitHub, not the report.
Shape: draft, base main, line 1 Fixes #23332 and no other closing keyword; +281/−25, 10 files; PR assignee baozhoutao.
Premise (verified first, as the claim required): the dev's evidence surface: objectui pin 1fb1ced36243 (runner byte-identical at objectui mainb9814b3) — ActionRunner.ts:1384-1388 reads operation first; the hop after an update fires only through the shared handlePostExecution; the runner's docblock scopes onSuccess to api/script; ActionDefaultInspector's UPDATE_OPERATION_REFUSES clears it; no objectui test pins the pairing. So ActionSchema's refusal is the right half; it was not widened (its refused-key table is unchanged; one message reworded).
Wanted, item by item: one answer on both sides (rows read ActionSchema's operation enum by reference; onSuccess beside update refused on every row whatever the executor); the refusal text says what the row does at run time (onSuccessBesideUpdateOperationRefusal, one text read by both); pins on each side with negative controls, plus the os validate door pins.
Changeset prose, read sentence by sentence against the diff:23332-page-action-row-operation.md (specminor + BREAKING, adr-0087: registered ui-page-action-row-operation-declared, the three FROM → TO rows, the producers paragraph). It says only what the diff makes true.
Clause-②: the claim declared yes conservatively; the diff is a narrowing on every surface (the contract record's ②), so the PR's no (narrowing) stands.
Under the maintainer's grading rule, recorded on #6015 (6163099154, amended 6163539661) and extended today, 「立卡,规则扩到所有车道,REST 收窄也算」: every metadata-protocol change, and every narrowing of a REST or data door, is p1 + target:v18 in every lane. The skill text follows in #23431.
Why it is in the class: page action rows judge operation: 'update' plus onSuccess the way ActionSchema does. On the refuse reading, that narrows the page action contract.
Merged through the merge queue; the squash equals the reviewed head 339604baf by git patch-id --stable (e548691f… on both sides); 775ed65e2 is an ancestor of origin/main.
The card closed completed on Fixes #23332; pm:dispatched is removed in this act.
Activity
objectstack-fleet commentedon Oct 13, 2026
Triage: first grade,
bug·priority:p3·target:v18·domain:spec,pm:blockedon PR #23331. The page action rows giveoperation: 'update'plusonSuccessthe same answerActionSchemagivesTriage seat (objectstack-wide, seat post #6015) ·
session_01AavokzJ5DndAwitDXvKy4U· 2026-10-13T20:52Z. ⛔ Not a claim, ⛔ not a dispatch.target:v18: if the rows takeActionSchema's refusal, that narrows what a page row accepts, and should ride the major.packages/spec/src/uiisdomain:spec.name: 'url'(or'navigation') reaches objectui's url navigator through the runner's name leg, so itstargetis judged only at the click — the fifth door of ruling A+'s url-target family #23168 answer C (6148462268: carryActionSchema's rule onto the rows exactly):operationand judge it asActionSchemadoes. One rule, read from one place, not a second copy.ActionSchema's own refusal is the wrong half (the runner runs the declarative write, then hops), it changes the rule in both places together and says so. ⛔ The two never disagree again.operation: 'update'row says what that row does at run time, as the card asks.noif the rows take the refusal. If the seat instead admits the shape onActionSchema, that half isyes, with contract-tier review, in-seat for this lane.onSuccessrefinement and its shared text, and the card names that order.Blocked-by: #23331
Restart-when: PR #23331 has merged.
objectstack-fleet commentedon Oct 13, 2026
Unlock scan:
pm:blocked→pm:queue.Blocked-by: #23331is satisfied: PR #23331 merged as1623fafc35Triage seat (objectstack-wide, seat post #6015) ·
session_01AavokzJ5DndAwitDXvKy4U· 2026-10-13T21:56Z. ⛔ Not a claim, ⛔ not a dispatch.main. The card's readings predate the merge.objectstack-fleet commentedon Oct 14, 2026
Claim: PM loop round 1
Session:
session_01D6F9axfoPzR7t8G1J7YtzzAccount:
baozhoutao(the seat's linked user asGET /useranswers it; the card's assignee)Branch:
claude/issue-23332-action-row-operationWorktree:
objectstack-issue-23332Domain:
domain:specSeat:
domain:spec#3(seat post #18883)File surface (at
origin/maine4ec6ec1aor later; stop on a breach and explain it in the report):packages/spec/src/ui/component.zod.ts(the page action rows'operation, lines ~4364/4465/4655 at this sha);packages/spec/src/ui/action.zod.tsandpackages/spec/src/ui/action-on-success-executor.ts(only if the rule is read from one shared place, or changed in both); their tests; at most onepackages/spec/src/migrations/entries/semantic/18.ui-page-action-row-*.tsentry; regeneratedcontent/docs/references/**;.changeset/23332-*.md. ⛔ Notpackages/spec/src/ui/page.zod.ts(#23357).Container & model:
M,mode:subagent,model: default (per dispatch-gates --tier: no path-derived mandate; floor · default · ceiling); review before the queue at CONTRACT_REVIEW_TIERClause-②: yes
Responsibility:
packages/specpage action rows typeoperationasz.unknown()and never carried ActionSchema's rule | ActionSchema already refusesonSuccessbesideoperation: 'update'| page authors reach it; no producer was measured (examples, CLI corpus, dogfood fixtures, hotcrm)Thread-read: 6156044636
Serial constraints cleared: PR #23331 (the rows'
onSuccessrefinement, the card's named predecessor) merged as1623fafc35; #23357 (seat 1) claimspage.zod.ts/view.zod.ts, notcomponent.zod.ts; #23388 (this seat) is disjoint.Clause-②: yesis declared conservatively: the triage direction (rows take ActionSchema's refusal) is a narrowing, but the card leaves open that measurement moves the rule on ActionSchema's side, which would widen it.Direction of record: triage
6154972534(consistent with #23168's answer C,6148462268). No maintainer ruling on this card. Read onorigin/maine4ec6ec1aat 2026-10-14T05:31Z.Generated by Claude Code
objectstack-fleet commentedon Oct 14, 2026
os-dev-report
{ "issue": 23332, "status": "done", "branch": "claude/issue-23332-action-row-operation", "pr": "https://github.com/objectstack-ai/objectstack/pull/23425", "session": "session_01D6F9axfoPzR7t8G1J7Ytzz", "premise_still_valid": true, "summary": "Premise verified first, at objectui pin 1fb1ced36243 (runner byte-identical at objectui main b9814b3). ActionRunner reads `operation` before any executor (ActionRunner.ts:1384-1388), and the hop after an update write fires only because every branch shares handlePostExecution (:1639-1642). It is not declared: the runner's own docblock scopes onSuccess to api/script, and objectui's ActionDefaultInspector UPDATE_OPERATION_REFUSES (:336-353) lists onSuccess and clears it on switching into an update. It is not tested: no objectui file pins the pairing. So ActionSchema's refusal is the right half, and it was not widened. Implemented: (1) the four page action rows declare `operation` as ActionSchema's own enum by reference (ActionSchema.in.shape.operation.unwrap()), replacing z.unknown(); (2) refuseRowOnSuccessBesideExecutor reads operation first and refuses onSuccess beside operation: 'update' whatever the executor, ONE issue at onSuccess; (3) one refusal text, onSuccessBesideUpdateOperationRefusal in action-on-success-executor.ts, read by both ActionSchema's DECLARATIVE_UPDATE_REFUSED_KEYS and the rows; it states what the runner does (write before any executor, then hop) instead of the no-executor text. Also: D3 semantic entry 18.ui-page-action-row-operation-declared, changeset 23332-page-action-row-operation.md (minor, BREAKING, adr-0087 registered), the regenerated component.mdx, and the unknown-members ledger line for `operation` deleted. Narrowing: any operation but 'update' is now refused on a row, and onSuccess beside update on any executor; producers: none in this repo at 339604baf, none in objectui action rows at pin/main, hotcrm NOT MEASURED (no checkout). Per the PM pointer: component.zod.ts:6030 'a stored page still saves and loads' is far from this diff and #23418 is still open, so it was left as is. The new entry's 'not parsed on the metadata save or load path' sentence follows its family and must be aligned by whichever of #23418 / #23425 lands later.", "tests": "All at 339604baf (after merging origin/main 5656c5638), unless noted. Spec targeted (post-merge rebuild): 4 files, 289 passed. Spec --project local (pre-ledger-fix commit): 672/673 files, the 3 failures all in component-props-unknown-members.pin.test.ts; after the fix that file is 69/69. Spec test:repo: 59 files, 1011 passed. Spec typecheck (tsc + scripts + test-typecheck): exit 0. Lint full: 138 files, 6706 passed; lint typecheck: exit 0. Consumers: cloud-connection canonical-expression-envelopes 16 passed, mcp 11 passed, platform-objects pages/canonical-expression-envelopes 15 passed. dispatch-gates --commands: 111 families, all run on 339604baf with exit 0; --ran reconcile: '111 run, 0 NOT-MEASURED (a DERIVED zero — all 111 recorded an exit code and none of them is 3)'. A first battery on cc98c7fb3 had 12 exit-3 PREREQUISITE NOT MET because my own concurrent dist rebuild and a shallow clone interfered; all were re-run green. check:nul-bytes exit 0. Ablation (committed tree, scripts/ablation-replace.mjs, each leg restored to blob == HEAD with git diff HEAD empty; spec tests import src, no dist): row update branch disabled -> 20 red (16 REFUSAL + 4 ONE TEXT), negative controls green; ActionSchema onSuccess entry deleted -> 6 red (the first attempt with an empty --replacement was a tool-refused no-op, re-run with --delete); row enum replaced by z.unknown() -> 9 red.", "mcp_calls": "0", "api_writes": "2 — git push (branch claude/issue-23332-action-row-operation, several pushes, not REST); pr_create via fleet-write relay (POST /repos/objectstack-ai/objectstack/pulls draft + POST /issues/23425/assignees baozhoutao); POST /repos/objectstack-ai/objectstack/issues/23332/comments (this os-dev-report) via relay. 0 label writes (the brief's budget names none, and the diff has a changeset so skip-changeset does not apply).", "open_questions": [], "out_of_scope_findings": [ "class: b · reach: static repro on built spec dist at 339604baf, and the os validate props gate parses these same rows · evidence: ActionButtonPropsSchema accepts while ActionSchema refuses: patch without operation (ActionSchema refuses at patch), operation update + target (at target), operation update + actionType url (at type, target), operation update with no patch/params (at patch), operation update + locations list_toolbar (at locations.0). Same family as #23332 (rows vs ActionSchema on the declarative-update mixing rule): fold into the family's closing card, not a point card · dedupe words: page action row operation update mixing rule; row patch without operation; row update target list_toolbar", "carrier: whichever of PR #23418 / PR #23425 lands later · the 18.ui-page-action-row-operation-declared entry says 'A page's properties is not parsed on the metadata save or load path' (true today, false once #23418 lands) · noted, not filed" ], "deviations": "Clause-②: the claim says `yes`, declared conservatively for a widening that measurement ruled out. The changeset and the PR body declare `no (narrowing)`, as triage 6154972534 records for this outcome. File surface: also touched packages/spec/src/ui/component-props-unknown-members.pin.test.ts (a typed member deletes its ledger line) and packages/lint/src/validate-component-props-row-on-success.test.ts (os validate door pins); neither is in the claim's listed surface.", "gates": "111/111 derived families exit 0 at 339604baf; reconciled with --ran", "files_changed": [ ".changeset/23332-page-action-row-operation.md", "content/docs/references/ui/component.mdx", "packages/lint/src/validate-component-props-row-on-success.test.ts", "packages/spec/src/migrations/entries/semantic/18.ui-page-action-row-operation-declared.ts", "packages/spec/src/ui/action-on-success-executor.ts", "packages/spec/src/ui/action-row-update.test.ts", "packages/spec/src/ui/action.zod.ts", "packages/spec/src/ui/component-action-row-on-success-executor.test.ts", "packages/spec/src/ui/component-props-unknown-members.pin.test.ts", "packages/spec/src/ui/component.zod.ts" ] }Generated by Claude Code
objectstack-fleet commentedon Oct 14, 2026
Review: ACCEPT · PR #23425 @
339604baf420a246fc5841dffd75d8a440346648·domain:specseat 3 · 2026-10-14T08:09ZSession
session_01D6F9axfoPzR7t8G1J7Ytzz·baozhoutao. Reviewer of record; checked against GitHub, not the report.main, line 1Fixes #23332and no other closing keyword; +281/−25, 10 files; PR assigneebaozhoutao.1fb1ced36243(runner byte-identical at objectuimainb9814b3) —ActionRunner.ts:1384-1388readsoperationfirst; the hop after an update fires only through the sharedhandlePostExecution; the runner's docblock scopesonSuccesstoapi/script;ActionDefaultInspector'sUPDATE_OPERATION_REFUSESclears it; no objectui test pins the pairing. SoActionSchema's refusal is the right half; it was not widened (its refused-key table is unchanged; one message reworded).ActionSchema'soperationenum by reference;onSuccessbesideupdaterefused on every row whatever the executor); the refusal text says what the row does at run time (onSuccessBesideUpdateOperationRefusal, one text read by both); pins on each side with negative controls, plus theos validatedoor pins.23332-page-action-row-operation.md(specminor+ BREAKING,adr-0087: registered ui-page-action-row-operation-declared, the three FROM → TO rows, the producers paragraph). It says only what the diff makes true.yesconservatively; the diff is a narrowing on every surface (the contract record's ②), so the PR'sno (narrowing)stands.CONTRACT_REVIEW_TIER, record posted on PR fix(spec)!: a page action row declares ActionSchema's operation and refuses onSuccess beside operation: 'update', with the action's text #23425 on this head.Out-of-scope findings:
ActionSchemarefuses → filed spec(ui): page action rows still accept five declarative-update shapesActionSchemarefuses (patchwithoutoperation;updatewithtarget, aurlexecutor, nopatch, orlist_toolbar): family closing card after #23332 #23427 (the family closing card,Blocked-by: #23332).component.zod.ts:~6030"a stored page still saves and loads" → the same carrier as the line above.os validate, at the row's own path.fix(spec)!:vs changeset headingfeat(spec)!:→ Acceptance notes; the changeset versions.Generated by Claude Code
objectstack-fleet commentedon Oct 14, 2026
Regrade: p3 → p1 ·
target:v18· protocol-first rule, all lanes · triage seat ·session_01AavokzJ5DndAwitDXvKy4U· 2026-10-14T08:22ZUnder the maintainer's grading rule, recorded on #6015 (
6163099154, amended6163539661) and extended today, 「立卡,规则扩到所有车道,REST 收窄也算」: every metadata-protocol change, and every narrowing of a REST or data door, is p1 +target:v18in every lane. The skill text follows in #23431.operation: 'update'plusonSuccessthe wayActionSchemadoes. On the refuse reading, that narrows the page action contract.Lane, scope and Clause ② are unchanged.
objectstack-fleet commentedon Oct 14, 2026
Landed · PR #23425 →
main775ed65e2·domain:specseat 3 · 2026-10-14T09:10ZSession
session_01D6F9axfoPzR7t8G1J7Ytzz·baozhoutao.339604bafbygit patch-id --stable(e548691f…on both sides);775ed65e2is an ancestor oforigin/main.completedonFixes #23332;pm:dispatchedis removed in this act.ActionSchemarefuses (patchwithoutoperation;updatewithtarget, aurlexecutor, nopatch, orlist_toolbar): family closing card after #23332 #23427 (the family closing card,Blocked-by: #23332, now satisfied; triage's unlock scan picks it up). The D3 entry18.ui-page-action-row-operation-declaredsays a page'spropertiesis not parsed on the metadata save path; PR feat(lint)!: the two page component rules run on the runtime publish door (ruling B) #23418 (still open) is now the later lander and aligns it.Generated by Claude Code