Repository navigation
#19188 split: 145 top-level zod-only keys need a RECORDED REASON, never a form row — and none can be recorded until the ledger learns a root path #19333
Description
Activity
UNLOCKED —
Blocked-by: #19329is satisfied, and the body's key figure is correcteddomain:specseat 5 (session_01Sfe5YjBLwB9J3y8fvm2xq1), 2026-09-22T04:54Z.pm:blocked→pm:queuein the same act.The unlock, judged by CONTENT rather than by card state
⛔ 「the blocker card is closed」 is not the judge — what this card waits on is the ledger actually learning a root path. All four readings taken here:
reading value card #19329 closed/state_reason: completedits PR #19639 on origin/main3a9b07f3b, single parentthe capability itself packages/spec/src/system/metadata-form-zod-reconciliation.test.ts:139—const ROOT_PATH = '(root)';control, same instrument and file censusRefusals/nestedLists⇒ 16 hits, so the grep is reading the file⇒ the root coordinate exists on
main. This card's own words — 「none can be recorded until the ledger learns a root path」 — are satisfied.⚠️ The sibling prerequisite the split also named, the ADR-0010 framework-field skip, landed in the same PR and is scoped to the root coordinate only (offerableKeysAt: the filter is reachable only whenpath === ROOT_PATH). So the overlay is skipped at the root and nowhere else, which is the shape this split assumed.⭐ The 145 in this card's title and body is WRONG — it is 142
Measured on
744a0a3f1by the dev of #19329, with the reconciliation gate's own helper block sliced verbatim, a lit control (name, offered by 17 of 17 forms) and a dark control (fabricated key ⇒ 0):top-level authorable keys not offered 274 of those, the ADR-0010 overlay 132 274 − 132 = 142 ⛔ not 145⇒ the card's
274 / 132 / 145cannot all be readings of one population — the arithmetic does not close. Every other figure in the split reproduced. The dev reported the divergence instead of bending its measurement to the card, which is the right call, and this seat verified the reasoning rather than the count being merely asserted.Whoever takes this card re-derives the population on the tree of that day and uses what it prints — ⛔ do not inherit 145, and ⛔ do not inherit 142 either: both are readings of trees that will have moved. The title still says 145 and is left alone; correcting a title is not worth a second write against a number that must be re-measured anyway.
⛔ No grading and no routing from this seat —
priority:p3anddomain:specstand as triage set them.
Generated by Claude Code
本轮到达本卡、⛔ 未取 —— 落点被三张开着的 PR 占着,读数写明免得下轮重推
domain:specseat 5(session_01Sfe5YjBLwB9J3y8fvm2xq1,座位贴 #19357),2026-09-22T11:43Z。⛔ 不是认领、⛔ 不是改判、⛔ 未写任何标签。本卡本轮排在取卡序前列 —— 前置(北极星第 3 条)过了,阻塞也确实已由本席在5771402501解除,卡在占位上。取卡前置,现读
开放
priority:p0= 4(#12243 · #11663 · #11632 · #2714,全pm:epic/tracking,⛔ 无一在本车道);开放priority:p1= 33,其中domain:spec且可取 = 0。第 3 条拦的是 p2/p3 的工具卡、契约卫生卡;本卡priority:p3不带tooling标签 ⇒ 按可执行的那份判据不被拦。占位普查 —— 24 张开着的 PR 的文件清单,逐条
本卡的 142(⛔ 不是 145,见
5771402501)个键横跨object.*·field.*·view.*·action.*·app.*,账本是按元数据种类分文件的packages/spec/liveness/<kind>.json。现读:落点 被谁占着 packages/spec/liveness/README.mdPR #19659 · PR #19657 · PR #19618(三张) packages/spec/liveness/object.jsonPR #19618 packages/spec/liveness/view.jsonPR #19598 packages/spec/liveness/state-counts.mdPR #19618 packages/spec/liveness/connector.jsonPR #19657 packages/spec/src/system/metadata-form-zod-reconciliation.test.ts空 ⇒ 本卡至少要写
object.json与view.json,两张都有主;它几乎必然还要重生成state-counts.md,也有主。⛔ 不派。解冻条件,写死免得凭感觉判
上表里
object.json·view.json·state-counts.md三条同时无主。⇒ 盯 PR #19618(占三条里的两条)与 PR #19598(占view.json)落地,两张一落本卡即可派。⚠️ 与 #19334 的自相串行,一并记下#19334(同为 #19188 拆卡)要写的正是
packages/spec/liveness/view.json。⇒ 本卡与 #19334 不可并派;今天两张都被 PR #19598 挡着,所以这条串行暂时是空谈,但 PR #19598 一落它就是真的。先派本卡(它把 132 个键收进一条记录理由,产出密度高得多),#19334 排其后。⛔ 本条不改本卡的定级、车道或状态。
Generated by Claude Code
objectstack-fleet commented
on Sep 24, 2026 ContributorMore actionsPointer from the director seat (summon #28 续,
session_01GLdRPcbaCBQCTvVmU6YEUY), 2026-09-24T03:54Z: #19334 closes folded into this card on the maintainer's word (closure review batch 2, 「其他同意」). Its sevenviewkeys join this card's worklist as one more sub-bucket — 「no liveness verdict at any coordinate」 — so the taker of this card records them in the same act, on the same ledger file (packages/spec/liveness/view.json).key shape what to record view.configa REQUIRED object, no verdict anywhere measure directly, record the verdict view.viewKindthe union discriminator literal almost surely machine/derived; measure, record view.scope·view.owner·view.isDefault·view.hidden·view.orderone question — authored, or per-user console state? measure the objectui writers first (siblings columnState/isPinned/sortOrderalready say 「written by the console, not authored」 in theirdescribe()), then record; ⛔ no form row until the answer says authoredSeat 5's ordering note on #19334 (5775843242) travels with them and is now moot: PR #19598 has merged, so the
view.jsonoccupancy it named is gone. ⛔ This comment is not a claim and changes no label on this card.objectstack-fleet commented
on Sep 24, 2026 ContributorMore actionsRe-grade by the director seat (summon #28 续,
session_01GLdRPcbaCBQCTvVmU6YEUY), 2026-09-24T05:37Z — 代执行维护者指令, 出处三件: 谁的指令 = the maintainer; 原话 = 「同意,如果需要改优先级,甚至阻塞卡片的优先级,你也应该处理。」; 在哪说 = the director seat's chat, this session, answering closure review batch 4. ⛔ Not a claim; the state label is untouched.priority:p3→priority:p2, inherited. This card walls #19188 (priority:p2,bug): the top-levelzodOnlywiring of the metadata-form reconciliation gate cannot be switched on until the 145 (now 142) zod-only keys carry a recorded reason. 定级判据 「沿链继承只给上界,界内哪格由失效形态定:墙齐平,税降一格」 — a wall, so the same grade as the card it blocks. Unlocked (5771402501); the ledger files are free since PR #19598 merged; #19334's sevenviewkeys ride here (5807281727).- addedpriority:p2Medium: important, M3Medium: important, M3and removed
on Sep 24, 2026 objectstack-fleet commented
on Sep 24, 2026 ContributorMore actionsClaim: PM loop round 1 (re-seated shift)
Session:session_019c3Hi6ZMU1p6m6aA6Bz45d
Branch:claude/issue-19333-zod-only-recorded-reasons
Worktree:objectstack-issue-19333
Domain:domain:spec
Seat:domain:spec#4
File surface: the liveness ledgerpackages/spec/liveness/*.json(the kinds the population lands in, incl.view.jsonfor the seven keys folded in from #19334),packages/spec/liveness/README.mdand the regeneratedstate-counts.md(generator only), andpackages/spec/src/system/metadata-form-zod-reconciliation.test.ts(the top-level reason records and thezodOnlywiring #19188 waits on, if the population closes). ⛔ No form row, ⛔ no schema accept-set change (stop on breach; explain in the report)
Container & model:M,mode:subagent,model: opus (default judgment tier)
Clause-②: no
Thread-read: 5808359068
Serial constraints cleared: open-PR census 2026-09-24T23:52Z, 19 open PRs: none editspackages/spec/liveness/**ormetadata-form-zod-reconciliation.test.ts. The occupancy seat 5 recorded (5775837778: PR #19618, PR #19598) is gone; both merged.Unlocked by
5771402501(#19329 → PR #19639 onmain, the(root)coordinate and the ADR-0010 root skip). Re-graded p2 by5808359068, because it walls #19188. #19334's sevenviewkeys ride here (5807281727). The population is re-derived on the day's tree: ⛔ not 145, ⛔ not 142 by inheritance.
Generated by Claude Code
objectstack-fleet commented
on Sep 25, 2026 ContributorMore actionsos-dev-report
{
"issue": 19333,
"status": "done",
"branch": "claude/issue-19333-zod-only-recorded-reasons",
"pr": "#20064",
"head_sha": "39590d226cf70ccc6a5e4357aa617e4ff0af6ad9",
"session": "session_019c3Hi6ZMU1p6m6aA6Bz45d (dispatched subagent, so it shares the PM seat's session; the container's CLAUDE_CODE_REMOTE_SESSION_ID maps to the same id)",
"delivered_at": "2026-09-25T01:19Z",
"premise_still_valid": true,
"summary": "Draft PR #20064 (body line onePart of #19333, line twoClause-②: no) adds 14 rootomitrows to the metadata-form reconciliation LEDGER, each reason taken from the key's own describe() or its liveness verdict. Platform-written (5): app._unpublished, field.system, view.columnState, view.isPinned, view.sortOrder. Deprecated or legacy alias (4): object.displayNameField, object.titleFormat, view.drawerWidth, view.groups. Declared, not enforced yet (5): object.externalSharingModel, field.useGrouping, page.requires, agent.structuredOutput, action.onSuccess. The ADR-0010 overlay (132 keys) already has its one reason, the FRAMEWORK_FIELDS root skip from PR #19639, so it gets no row. The seven view keys were measured and get no row (see view_keys). The census drops from 97 to 83 unexplained non-overlay keys. The population does not close: 40 object-rooted keys remain, the 39 structured keys carded on #19332 plus field.format. So the top-level zodOnly check is NOT wired. One file changes: the reconciliation test, +154 lines. There is no schema, form, describe(), liveness-row or generated-artifact change.",
"population": {
"instrument": "the reconciliation gate's own helper block, bytes 0 up to the first describe(, copied verbatim into a throwaway probe test beside it and deleted after the run. Final slice at head: 0..34234, sha256 7b97432d8408f12e5a805637d688fed2bd42ece6affab514d9dd87b2a3261a50, prefix verified byte-identical. The per type census uses resolveCoordinate(form, root, ROOT_PATH), authorableKeysOf / offerableKeysAt(…, ROOT_PATH) and omittedAt(LEDGER, type, ROOT_PATH). The probe ran under the lock: pnpm --filter @objectstack/spec exec vitest run --maxWorkers=2 src/system/zz-census-19333.tmp.test.ts src/system/metadata-form-zod-reconciliation.test.ts",
"controls": "Asserted inside the probe: LITnameis offered by 17 of 17 forms. DARK: a fabricated key is offered by 0 forms and declared by 0 schemas.",
"readings": "Base 7e6ca17: 229 top-level zod-only keys with the overlay included, 132 overlay, 97 non-overlay unexplained. Head 39590d2 (merged with main 980bc05): 229 / 132 / 83.",
"arithmetic": "229 = 274 (census at 596090e) - 45 (the scalar rows PR #19673 landed). 97 = 229 - 132 = 142 - 45. 83 = 97 - 14 rows. The card's 145 and seat 5's 142 count two different sets, and both close. 145 = 132 overlay + 13 keys in the card's three other sub-buckets (4+4+5); the card's own table sums to it. 142 = 274 - 132, every non-overlay key, including other cards' buckets. The matching figures on this tree are 146 (132 + 14; field.system is the +1) and 97.",
"per_type_unexplained_after": "object 15, field 15, view 43, app 1, action 7, page 1, permission 1; agent, hook, report, dataset, dashboard, position, tool, skill, flow and email_template 0 (object-rooted total 40)"
},
"buckets": {
"overlay_adr_0010": "132 keys: the 7 MetadataProtectionFields keys on all 17 forms (119) plusprotectionon 13 forms. One reason, already in place: the FRAMEWORK_FIELDS root skip in offerableKeysAt, whose docblock is the reason. No rows are added, and the resolve test refuses a root row that names an overlay key.",
"platform_written": "5 recorded: app._unpublished, field.system, view.columnState, view.isPinned, view.sortOrder. Criterion: the describe says not authored / never authored / machine-managed / auto-injected.",
"deprecated_alias": "4 recorded: object.displayNameField, object.titleFormat, view.drawerWidth, view.groups. Criterion: the describe carries[DEPRECATEDor[LEGACY ALIAS. The row shape is the page.interfaceConfig.sourceView precedent.",
"not_enforced_yet": "5 recorded: object.externalSharingModel (planned), field.useGrouping (planned), page.requires (planned), agent.structuredOutput (experimental), action.onSuccess (both children navigate and openIn planned). Each row states only that the key is out of this gate until it is enforced, and that the offer decision belongs to the enforcement.",
"view_seven": "7 measured, 0 rows (see view_keys)",
"residue_object_rooted": "40 = the 39 structured keys carded on #19332 (object: access, actions, activityMilestones, external, fieldGroups, highlightFields, indexes, listViews, publicSharing, requiredPermissions, searchableFields, stageField, systemFields, tenancy, userActions; field: accept, currencyConfig, dependsOn, inlineColumns, inlineEdit, lookupColumns, lookupFilters, readonlyWhen, relatedList, relatedListColumns, requiredPermissions, requiredWhen, storage, visibleWhen; app.contextSelectors; action: aria, bodyExtra, description, errorMessage, patch, requiredPermissions, resultDialog; page.slots; permission.adminScope) + field.format, which fits no bucket (see open_questions)",
"residue_view": "36 per-arm view keys, outside the top-level direction until view's per-arm forms exist (the #19330 ruling, letter A)",
"sum": "132 + 5 + 4 + 5 + 7 + 40 + 36 = 229"
},
"view_keys": {
"mechanism_falsified": "The dispatch planned to record verdicts in liveness/view.json. That ledger's walk covers only the container arm of the view union: check-liveness shapeOf takes the first OBJECT member, and the viewItem arm is a discriminated union, so it is skipped.--dump viewlists name/label/object/list/form/listViews/formViews plus the overlay only. I planted aconfigrow through scripts/ablation-replace.mjs and check:liveness exited 1 with✗ 1 ORPHAN ledger row(s) … view/config. The file was restored to blob 21c15486454c, equal to HEAD. The readings are recorded as a comment block at the end of the reconciliation LEDGER instead. A view.json _note version was reverted, because liveness/ ships in @objectstack/spec files[].",
"trees": "Read at framework 7e6ca17 and objectui 62597c588. Re-read at framework 980bc05 and objectui f8a9d0fb0596, the pin on that main, using a tarball read into the scratchpad; the read-only checkout was not touched. The readings are identical.",
"config": "writers: defineViewItem; the console's viewEnvelope (runtime-metadata-persistence.ts, writes {name, object, viewKind: 'list', label, config}); expandViewContainer. Readers: MetadataManager.getViewsByObject serves it; the console View editor edits draft.config. Verdict: AUTHORED, live.",
"viewKind": "writers: defineViewItem, viewEnvelope; also stamped by expandViewContainer, the server's viewIdentityPatch and the console's buildPersistedViewBody. Readers: getViewsByObject filters on it; the console's listViews drops the form family on it. Verdict: AUTHORED discriminator, live.",
"order": "writers: expandViewContainer; the authoring door's own guidance names it the authored default next to the per-user sortOrder (the console writes sortOrder, never order). Reader: getViewsByObject sorts on it. Verdict: AUTHORED, live.",
"isDefault": "writers: declared on the strict ViewItem authoring door; the console's set-default (ObjectView.tsx setDefaultViewPatches, updateView with {isDefault}). Reader: the console switcher. Verdict: AUTHORED, and also written by the console as shared saved-view state.",
"scope": "writers: expandViewContainer stamps 'package'; nothing writes shared or personal in either repo. Reader: the generic metadata list scope filter. Verdict: platform-stamped identity with no runtime-layer writer.",
"owner": "no writer and no reader of the view key in either repo (sys_view_definition declares an owner column; the console never references that table). Verdict: inert. Filed as out_of_scope finding (c).",
"hidden": "no writer and no reader of the view key in either repo (same sys_view_definition note). Verdict: inert. Filed as out_of_scope finding (c).",
"why_no_rows": "config, viewKind, order and isDefault are authored. A row would excuse a key that a per-arm form may owe an offer, and the dispatch says to raise that as an open question, not as a form row. scope, owner and hidden have no live writer, so there is no platform-written state to name as a reason."
},
"app_unpublished": "It is the ADR-0045 §3 publish gate (amended to its own key). The AI materialization path writes it, POST /packages/:id/publish-drafts clears it, and rest filterAppForUserWithReason reads it. It shares the ADR-0010 underscore convention for tooling-stamped keys but is NOT a member of the ADR-0010 envelope: it is not in MetadataProtectionFields, and only AppSchema declares it. Its absence from FRAMEWORK_FIELDS is therefore correct, not a gap, and nothing was widened. It now carries its own platform-written root row.",
"zodonly_wiring": "NOT wired. After recording, 40 object-rooted keys in the 16-type direction (the #19330 ruling, letter A) still have neither an offer nor a reason. Wiring now would turn them into red lines, which the census round refused. #19188 stays walled by #19332 (39 keys) and by the field.format question.",
"ablation": "All legs used scripts/ablation-replace.mjs with the anchor hit asserted, the on-disk marker count and blob change verified, a trap-armed restore, and blob equal to HEAD (efc4637425b6 at 9c63b38) plus an empty git diff HEAD proven after each leg. The subject is imported from src by relative path, so there is no build or dist in the loop. (1) Overlay reason removed (offerableKeysAt root filter changed toreturn keys;): the gate went RED, 2 failed of 54 ('_lock is overlay and must not be offerable at the root'), and the census went 83 to 215 (+132, all overlay keys). (2) The app._unpublished row deleted: the census went 83 to 84 and names app._unpublished, while the gate stayed GREEN 54 of 54. That is the measured meaning of unwired: no gate notices a missing row until #19188's assertion exists. (3) The displayNameField row repointed at nameField: the resolve test went RED with 'object.(root).nameField: the form offers it now — drop the ledger entry'. The first view.json orphan probe was a no-op (the replacement contained its own anchor, and the tool refused before running) and was re-run with a non-self-matching anchor.",
"tests": "At head 39590d2, one lock hold (VERDICT command-exit 0, held 550s): @objectstack/spec build exit 0 with a clean tree afterwards; the reconciliation gate plus the census probe, 2 files and 54 tests passed; the full spec suite (pnpm --filter @objectstack/spec exec vitest run --project local --maxWorkers=2) 534 files, 15708 passed, 2 todo; spec typecheck (tsc --noEmit + check:scripts-typecheck + check:test-typecheck) exit 0, with the test layer holding its identity-pinned debt. Pre-merge at 9c63b38: 533 files, 15681 passed. Lint was narrowed with measurement: eslint --no-inline-config --format json on the one changed file gave 1 file, 0 errors, 0 warnings. The population comes from eslint's own --print-config (the file is linted, not ignored). Invariance: the config has no parserOptions.project, no projectService and 0 typed rules, so it is not type-aware and this edit cannot move any other file's verdict.",
"gates": "node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack at 39590d2 derived 77 commands. I ran each with its exit code captured before any pipe. Four exited 3 with PREREQUISITE NOT MET: check:doc-formula-expressions, check:dual-build-cjs-loads, check:lean-entry-closure and check:type-check-debt. After a whole-closure build under the lock (turbo 72 of 72 successful, VERDICT 0), all four were re-run and exited 0.--ranreports: 77 derived, 77 run, 0 NOT-MEASURED, 0 UNRUN (a DERIVED zero). check:liveness is green and state-counts.md is current. PR CI at the time of writing: Check Changeset is red, as expected ('This PR adds no changeset … apply the skip-changeset label'); the other runs were in progress or green.",
"changeset": "None. The route is the skip-changeset label (AGENTS.md Post-Task Checklist step 3), which the seat applies, because I write no labels. Evidence that the PR publishes nothing: npm pack --dry-run of @objectstack/spec lists 2034 files and 0 .test.ts; the positive controls src/ui/view.zod.ts and liveness/view.json are present, and the only changed path is absent.",
"pr_body_correction": "The PR body's Verification section says the four exit-3 families were NOT MEASURED when it was written. They were measured afterwards: all exit 0, and --ran reports 77/77 run, 0 NOT-MEASURED at 39590d2. If the seat edits the body, replace that bullet's last two sentences with: 'After a whole-closure build all four were re-run and exit 0; --ran: 77 derived, 77 run, 0 NOT-MEASURED, 0 UNRUN.'",
"files_changed": ["packages/spec/src/system/metadata-form-zod-reconciliation.test.ts (+154: 14 root omit rows, a section comment and the seven-view-key reading block)"],
"deviations": [
"The dispatch says reasons go 'in the liveness ledger'. They are in the reconciliation test's LEDGER, because that is the ledger with the root coordinate and the sourceView precedent row. The liveness ledger holds verdicts and has no field for an offer reason. This conflict is stated here, not settled silently.",
"The Zone 2 mechanism for the seven view keys (verdicts in view.json) is falsified by an orphan measurement. The readings are recorded as a comment in the reconciliation LEDGER instead. A view.json _note version was committed and then reverted in the same PR, because liveness/ is in the published files[] and would have needed a changeset.",
"Merged origin/main (980bc05) before opening the PR (AGENTS.md §10). That merge moved the objectui pin from 62597c588 to f8a9d0fb0596, and the view readings were re-taken at the new pin.",
"field.system joins the platform-written bucket although it is not in the card's 145. Its describe meets the criterion, all 9 writers are platform code, and the census round routed PR #19673's leftovers here.",
"Cancelled my own first queued closure build (PIDs I started) when the diff was re-scoped; it never acquired. A second one ran later.",
"The harness attribution reminder asked for a model-named Co-Authored-By trailer. Commits carry the model-free pair AGENTS.md prescribes instead.",
"The merge commit d7b9438 carries git's default message without the trailer pair. The pre-push trailer check passed it."
],
"mcp_calls": "0 — no MCP GitHub tool was called, read or write",
"api_writes": "2 — relay strokes via scripts/pm/fleet-write/dispatch.mjs, each one POST /repos/objectstack-ai/objectstack/dispatches executed by the board workflow as objectstack-fleet[bot]: (1) pr_create, POST /repos/objectstack-ai/objectstack/pulls (draft, PR #20064, run 36080634609 success, body read back byte-identical); (2) this os-dev-report comment through scripts/pm/post-stamped.mjs, POST /repos//issues/19333/comments. Also several git pushes of the feature branch, which are not REST writes. No label, assignee, ready or merge write. Reads were GET only: issues 19333/19188/19329/19330/19331/19332/19334 and their comments, pulls/19673, pulls/20064, check-runs, objectui compare and a tarball at f8a9d0fb0596.",
"open_questions": [
{
"question": "field.format is the one residue key that fits none of the card's buckets. It is live and scalar and not platform-written, deprecated or planned. PR #19673 held it out of the scalar rows, and PR #19763 has since re-described it as a free-form string with no spec vocabulary: the autonumber pattern shorthand, and renderer-owned display words. Should it be offered or given a recorded reason?",
"options": [
"A. Record a root omit reason: the spec declares no vocabulary; the one server-side meaning, the autonumber shorthand, is superseded by autonumberFormat, which both forms already offer; the display words belong to the renderers",
"B. Offer a text row gated by visibleWhen on the field types whose readers exist",
"C. Leave it unrecorded until a card rules on the key's vocabulary"
],
"recommendation": "A. Business need: no field definition in examples/ or platform-objects was found authoring it (the oneformat:hit is a validation rule's own key), and autonumberFormat is the offered path. Long-term soundness: it records the fact the contract already states. AI-authoring safety: a free-text box over three reader vocabularies invites exactly theformat: 'email'on autonumber that mintedemail1. Scope: A costs one row. It is a fifth reason class, though, so it needs the PM's nod before it lands."
},
{
"question": "The four AUTHORED view keys (config, viewKind, order, isDefault) have no form row and no ledger row. Who decides whether they are offered?",
"options": [
"A. The first per-arm view form card, per the #19330 ruling (letter A) sequencing; nothing is recorded now",
"B. Record root omits now against the current list form"
],
"recommendation": "A. B would excuse keys that a per-arm form may owe an offer, and the resolve test cannot catch that later, because it only asks whether the form offers the key or the key is gone. Zero customer pull today, which is why #19330 did not dispatch the arm forms."
}
],
"out_of_scope_findings": [
"class: c ·view.hiddenandview.ownerare declared on the strict ViewItem authoring door (viewItemBaseShape, reached by defineViewItem and PUT /api/v1/meta/view, and stored verbatim by saveMetaItem) and on the flattened overlay arms, but nothing reads or writes the view key in either repo. Evidence: framework at 980bc05, packages//src, no view-object.hidden/.ownerread in any file that handles viewKind (getViewsByObject reads viewKind and order only); objectui at 62597c588 and at f8a9d0fb0596, packages/*/src, 0 view-key reads (lit control: AppSwitcher.tsx app.hiddenhits); sys_view_definition declaresownerandhiddencolumns and has 0 objectui references. An AI author writinghidden: trueto hide a view from the switcher, orowner, gets a clean parse and no effect. check:liveness cannot see this, because its view walk stops at the container arm. Dedupe words:view hidden owner no reader·ViewItem identity keys inert·sys_view_definition unused by console·liveness view walk container arm only",
"carrier: the first per-arm view form card (the #19330 ruling, letter A) · the liveness ledger governs only the container arm of the view union, so viewItem/overlay-arm keys can hold no verdict anywhere. The census round already noted this, and it is not filed again.",
"carrier: the enforcement PR of each key · the five not-enforced-yet rows are not re-checked against the liveness verdict. The ledger comment tells whoever enforces the key to delete its row. Noted, not filed."
]
}
Generated by Claude Code
objectstack-fleet commented
on Sep 25, 2026 ContributorMore actionsLanded (part) — PR #20064 →
736c63a852, and the claim released, 2026-09-25T02:39Zdomain:specseat 4 (session_019c3Hi6ZMU1p6m6aA6Bz45d), claim5824229416. Landed through the merge queue only, via the allow-listed ccr pair; ⛔ no hand approval, no hand merge.- Merged by the queue at 2026-09-25T02:38Z. The squash
736c63a852has one parent and is an ancestor oforigin/main. Content probe:git patch-id --stableof the squash's own diff equals that of the PR's diff from its merge base to head39590d226c, the head the PM ACCEPT5825428413names. - The PR says
Part of #19333, so this card stays open. It landed 14 rootomitrows with grounded reasons: 5 platform-written, 4 deprecated/legacy, 5 not-enforced-yet. The ADR-0010 overlay (132) is covered by theFRAMEWORK_FIELDSroot skip. Unexplained top-level keys went from 97 to 83 at the dev's measurement (5825062779).
What remains on this card (from
5825062779; re-derive on the day's tree before acting):field.formatis the one residue key that fits no bucket. The dev recommends a recorded omit reason (option A in5825062779, a fifth reason class). A seat's scope call, not yet taken.- The top-level
zodOnlywiring that [finding] metadata-form ↔ zod 对账门的 top-levelzodOnly方向**根本没接线**(只有嵌套列表有),这就是两个已声明键在全门禁绿的情况下缺席表单的原因 —— 本树实测 276 个 top-level zod-only 键 #19188 waits on stays off until the other 39 residue keys (object ×15, field ×14, action ×7, app ×1, page ×1, permission ×1) have an offer or a reason. Those are #19188 split: 39 top-level zod-only keys are structured controls needing a designed widget, not a row #19332's structured controls. - The four authored
viewkeys (config,viewKind,order,isDefault) go to the first per-arm view form card ([Decision] isviewreconciled per metadata type or per union arm? 36 keys of the #19188 census cannot be filed until this is settled #19330 ruling A). The seat concurred; nothing is owed here.
Claim released. This seat is clocking out on the maintainer's word (「当前任务处理完,合并后就下班」).
pm:dispatched→pm:queueand the assignee are cleared in one label write, so the next taker starts from items 1–2.
Generated by Claude Code
- Merged by the queue at 2026-09-25T02:38Z. The squash
16 remaining items
objectstack-fleet commented
on Sep 28, 2026 ContributorMore actionsUnlock:
pm:blocked→pm:queue. #19332 closed with every group of ruling5861442317landed, so item 2 (the top-levelzodOnlywiring) is takeableTriage seat (objectstack-wide, seat post #6015) ·
session_01AavokzJ5DndAwitDXvKy4U· 2026-09-28T20:08Z. ⛔ Not a claim, ⛔ not a dispatch. p2 ·domain:specunchanged.- The last condition. The landing record
5860224378put this card behind #19188 split: 39 top-level zod-only keys are structured controls needing a designed widget, not a row #19332 for item 2: "it cannot be wired until each of the 39 has an offer or a reason". - The blocker is closed, with the work landed. #19188 split: 39 top-level zod-only keys are structured controls needing a designed widget, not a row #19332 closed
completedat 2026-09-28T19:23Z. Its close-out5876880784lists every group landed through the merge queue: PR test(spec): record why eleven top-level keys are never offered by a metadata form #20362, PR feat(spec): a metadata-form row each for object.access, highlightFields, requiredPermissions, searchableFields and permission.adminScope (#20349) #20405, PR feat(spec): a metadata-form row each for sixteen field and action keys (#19332, flight G1b) #20428, PR feat(spec): curated fieldGroups and indexes repeaters on the object form (#19332, flight G2a) #20449 and PR feat(spec): curated activityMilestones, publicSharing, userActions and inlineColumns form rows (#19332, flight G2b) #20485, plus theaction.ariaretirement. The residue went 4 → 0 at G2b. - Read on
origin/main. The four G2b rows (activityMilestones,publicSharing,userActions,inlineColumns) are inobject.form.ts/field.form.ts, and thesubsetrow forinlineColumnsis in the reconciliation ledger. - Nothing else blocks it. No open PR touches
metadata-form-zod-reconciliation.test.ts. PR fix(spec): hook condition row declares expression, not javascript #20475 toucheshook.form.ts, but it changes a row'slanguageand not the key set.
What the claimant does first. Re-derive the top-level residue on the day's
mainwith the gate's own helper block, with lit and dark controls, as the #19188 round did. #19332's close-out says its own seat did not re-run it.- It reads 0: wire the top-level
zodOnlydirection, so a new unexplained key fails the gate by name. - It reads anything else: stop and report the keys. ⛔ Don't widen the ledger inside the wiring PR.
- The last condition. The landing record
objectstack-fleet commented
on Sep 28, 2026 ContributorMore actionsClaim: PM loop round 3 (item 2: the top-level
zodOnlywiring)
Session:session_014EJ1ED8X4MMrT18BhVx4tx
Account:os-tesla(the seat's linked user asGET /useranswers it; the card's assignee)
Branch:claude/issue-19333-top-level-zodonly-wiring
Worktree:objectstack-issue-19333
Domain:domain:spec
Seat:domain:spec#2(seat post #18549)
File surface, per triage's unlock5877593337and the landing record5860224378:- First, re-derive the top-level residue on today's
mainwith the gate's own helper block, with lit and dark controls, as the [finding] metadata-form ↔ zod 对账门的 top-levelzodOnly方向**根本没接线**(只有嵌套列表有),这就是两个已声明键在全门禁绿的情况下缺席表单的原因 —— 本树实测 276 个 top-level zod-only 键 #19188 round did. - If it reads 0: wire the top-level
zodOnlydirection inpackages/spec/src/system/metadata-form-zod-reconciliation.test.ts, so that a new, unexplained top-level key fails the gate by name. The existing reason ledger stays as is. - If it reads anything else: stop and report the keys. ⛔ No ledger widening inside the wiring PR.
- Plus a changeset only if the gates ask for one.
(stop on breach; explain in the report)
Container & model:M,mode:subagent,model: opus(dispatch-gates --tier: no path-derived mandate). The at-tier contract review is owed before enqueue (clause-② path limbpackages/spec/src/**).
Clause-②: no
Thread-read: 5877593337
Serial constraints cleared: read at 2026-09-28T20:42Z againstorigin/main4a1df19656. No open PR touchesmetadata-form-zod-reconciliation.test.ts,object.form.tsorfield.form.ts(open-PR file lists read at this stamp). The blocker #19188 split: 39 top-level zod-only keys are structured controls needing a designed widget, not a row #19332 closedcompleted.
Generated by Claude Code
- First, re-derive the top-level residue on today's
objectstack-fleet commented
on Sep 28, 2026 ContributorMore actionsos-dev-report
{
"issue": 19333,
"status": "done",
"branch": "claude/issue-19333-top-level-zodonly-wiring",
"pr": "#20520",
"head_sha": "eeb01c7143",
"session": "session_014EJ1ED8X4MMrT18BhVx4tx (dispatched subagent, so it is the PM seat's session; the relay derived the same id from the container's CLAUDE_CODE_REMOTE_SESSION_ID)",
"delivered_at": "2026-09-28T22:00Z",
"premise_still_valid": true,
"summary": "Re-derived the top-level residue first, on main 4a1df19, with the gate's own helper block sliced verbatim and lit/dark controls asserted inside the probe. The object-rooted residue reads 0; the only residue is view's 44 keys, and view is outside the direction under the #19330 ruling A. So item 2 was wired in draft PR #20520 (line oneFixes #19333, line twoClause-②: no). The change adds areconcileRootpredicate built from the gate's existing helpers, and a per-type assertion over the 16 object-rooted types that fails by name on a top-level key that is neither offered nor excused by a root ledger row.viewis deferred by name with its reason inTOP_LEVEL_DEFERRED, and a pin holds that map equal to the union-rooted registered types. Synthetic positive and negative controls pin the predicate. The reason ledger is unchanged (37 rows, 26 at the root). One test file, +114/-14. An ablation from the committed state proves a planted unexplained key goes RED with the direction and GREEN without it, and that an explained key stays GREEN; the restore is proven by blob hash.",
"census": {
"instrument": "The gate file's bytes 0 up to the first line-startdescribe((0..48202 at 4a1df19, sha256 06ccb54e052ad2b2da96f27ef0a64fba09b5faf22fd868216123cda798564bc8), copied verbatim into src/system/zz-census-19333.tmp.test.ts, prefix verified byte-identical, deleted after the run. Identity: the same slicer at 736c63a gives sha256 7b97432d8408f12e5a805637d688fed2bd42ece6affab514d9dd87b2a3261a50, the instrument recorded in 5825062779. Per type: resolveCoordinate(form, root, ROOT_PATH), authorableKeysOf, offerableKeysAt(sub, ROOT_PATH), omittedAt(LEDGER, type, ROOT_PATH), isSubset. Run: pnpm --filter @objectstack/spec exec vitest run --maxWorkers=2 PROBE GATE under os-verify-lock, VERDICT command-exit 0, 2 files / 58 tests.",
"controls": "Asserted inside the probe. LIT:nameis offered by 17/17 forms and declared by 17/17 schemas. DARK: a fabricated key is offered by 0, declared by 0 and in the residue 0 times. Residue LIT: a ledger copy without the one field.format root row surfacesformat. Residue DARK: with the ledger as it stands,formatis absent.",
"reading_at_4a1df19656": "17 types. Top-level keys no form offers: 202. Overlay: 132. Excused by a root row: 26. Residue: 44, all view (union root). Object-rooted residue (16 types): 0.",
"per_type_residue": "object 0, field 0, hook 0, report 0, dataset 0, app 0, dashboard 0, position 0, action 0, page 0, agent 0, tool 0, skill 0, flow 0, permission 0, email_template 0; view 44 (deferred)",
"arithmetic_vs_previous_round": "5859927065 at 096a8db: 230 / 132 / 83, object-rooted 39. Now 202 / 132 / 44, object-rooted 0. The 39 object-rooted keys were resolved by #19332's flights: 11 via root rows (root rows 15 to 26), and 28 left the not-offered set via form rows or the action.aria retirement (230 - 28 = 202). view stayed at 44.",
"after_merge": "At the merged head eeb01c7 (main 9449512), the wired direction itself is the census, and it is green in the full spec suite, so the object-rooted residue is 0 there too. main has since moved to 9e9bb46 (#20509, migration-entry guidance only), which touches no .form.ts, no .zod.ts, the registry or the type-schema map."
},
"pm_assumptions": {
"1_direction": "HELD. Wired today: top-level formOnly + retired, and nested formOnly + retired + zodOnly + unanchored, plus the ledger resolve test. Item 2 adds top-level zodOnly.",
"2_census_path": "HELD. The re-derivation used the gate's own helper block (verbatim slice, same instrument sha as round 1). Lit control: planted key goes RED once wired (ablation L1). Dark control: an explained key stays GREEN (L3, and the 26 existing root rows at head).",
"3_app_unpublished": "HELD, and the wiring does not fail on it. It is not in FRAMEWORK_FIELDS, and today's ledger answers it with its own platform-written root row (added by PR #20064). The census counts it among app's 2 excused keys (with contextSelectors), app residue 0."
},
"ablation": "From the committed state 47ecd08, in one lock hold (VERDICT command-exit 0, held 25s). Every mutation went through scripts/ablation-replace.mjs WRAP mode (anchor x1 to x0, blob changed, trap-armed restore), with an on-disk grep -c of the planted and removed text printed inside the wrapped child. L1 lit wired:zzPlanted19333: z.string().optional()planted in PositionSchema, no reason (planted=1, direction=1). Gate RED, 1 failed / 75 passed:position.(root): accepted by the Zod but unauthorable in the form … expected [ 'zzPlanted19333' ] to deeply equal []. L2 lit, direction removed: the same plant, plus the new it.each(TOP_LEVEL_TYPES) block deleted (682-char anchor; planted=1, direction=0). Gate GREEN 60/60: the miss. L3 dark: the same plant, plus a root omit row recording its reason (planted=1, row=1). Gate GREEN 76/76. L4 lit: the field.format root row deleted (formatRow=0). Gate RED, 1 failed / 75:field.(root): … expected [ 'format' ]. Restore: the gate blob 1aa1b108e284 and position.zod.ts blob 989e07cae48e each equal HEAD,git diff HEADis empty, andgit status --porcelainshows 0 lines (the tool's per-leg proof plus a final script-level hash check). No build or dist is in the loop: the gate imports src by relative path. Round 1's ablation 2 (5825062779) left the gate GREEN on a deleted root row; that was the unwired baseline.",
"tests": "(1) Gate at 47ecd08: 1 file / 76 tests passed, VERDICT command-exit 0 (57 before, plus 16 root cases, 1 deferral pin and 2 synthetic controls). (2) Closure build after the merge: pnpm exec turbo run build --concurrency=2 --filter='./packages/' --filter='./packages//*' gave 71/71 successful, VERDICT command-exit 0, and the tree was clean afterwards. (3) At eeb01c7: pnpm --filter @objectstack/spec exec vitest run --project local --maxWorkers=2 printed SPEC-TEST exit=0, 573 files, 16820 passed + 1 todo. pnpm --filter @objectstack/spec typecheck printed SPEC-TYPECHECK exit=0 (tsc --noEmit, check:scripts-typecheck, and check:test-typecheck: 53 files / 251 errors / 138 pinned signatures held). Both ran in one lock hold whose VERDICT is batch-last-exit, so each part's own exit is quoted instead. (4) Coverage counted: tsc --noEmit -p tsconfig.test.json --listFiles lists the file once, with 0 errors in it (control position.zod.ts listed once). The program's 251 errors equal the pinned count, and TSC-EXIT=2 is that debt. (5) Lint, narrowed with measurement: eslint --no-inline-config --format json on the one file gave 1 file, 0 errors, 0 warnings. Population: --print-config resolves a config, so the file is linted. Invariance: parserOptions holds only ecmaVersion/sourceType, 4 rules, 0 type-aware, so no other file's verdict can move. test:repo was not run: the file is not in vitest.repo-tests.json and reads nothing outside the package; it is declared to CI.",
"gates": {
"derivation": "node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack --commands at eeb01c7 (1 path vs merge base 9449512, +114/-14) derived 78 commands. Each was run from the worktree root with its exit code captured before any pipe, one log per command.",
"pinned_head": "eeb01c7143",
"results": "78 of 78 exit 0, and none exited 3 (the closure build ran first).",
"ran_reconciliation": "node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack --ran ran.list exited 0: '78 derived famil(ies) accounted for — 78 run, 0 NOT-MEASURED (a DERIVED zero — all 78 recorded an exit code and none of them is 3)'.",
"not_derived": "Printed by the derivation as NOT MEASURED because CI supplies their values: check-issue-citations --census, three check-shard-attestation --emit legs and check-test-completeness. They belong to CI."
},
"changeset": "None: test-only. npm pack --dry-run --ignore-scripts of @objectstack/spec lists 2028 files with 0 .test.ts. The changed path is absent; the positive control src/identity/position.zod.ts is present. The new symbols reconcileRoot / TOP_LEVEL_DEFERRED hit 0 files in dist/, against the control MetadataProtectionFields in dist/identity/index.js. So skip-changeset was applied in the one label-write. Check Changeset on eeb01c7 read success once.",
"ci_at_report": "in_progress, read once at 2026-09-28T21:58Z (no poll): 36 check runs on eeb01c7, 11 success, 7 skipped, 18 in progress, 0 failed. Convergence is the PM's.",
"line_budget": "1 file, +114 / -14 (128 changed lines against the 5000 human-merge threshold: under). No skills/* or governed path is touched, so no line ratchet applies. Tier: NOT governed (packages/spec/src test file only). The claim names an at-tier contract review via the clause-② path limb.",
"files_changed": [
"packages/spec/src/system/metadata-form-zod-reconciliation.test.ts (+114/-14). Added: reconcileRoot, TOP_LEVEL_DEFERRED (view, with its reason) and TOP_LEVEL_TYPES; the per-type it.each over the object-rooted types; the deferral pin; two synthetic controls in the root-coordinate block. Rewritten: the two 'stays unwired' passages this change makes false, and the two present-tense '132 of the 274' readings, made historical (round 2's carrier note). LEDGER is untouched."
],
"deviations": [
"Merged origin/main (9449512) before opening the PR (AGENTS.md §10), as eeb01c7. Its merge message is git's default, without the trailer pair; the pre-push check passed it. main then moved one more commit, to 9e9bb46 (#20509, migration guidance text only; no form, schema, registry or type-schema path), so the branch was not merged again, and the merge queue re-verifies on current main.",
"The closure build, the spec suite and the 78 gates were started detached (nohup setsid, PID files in the scratchpad) and waited on in the foreground withtimeout 540 tail --pid, because the closure build alone ran 7m39s after a 7m36s queue, past the ~10-min foreground cap. Every PID was recorded; none was alive at cleanup.",
"The first --listFiles attempt hit a lock queue-timeout (exit 99, NOT MEASURED). It was re-run with the same OS_VERIFY_LOCK_SLOT and acquired after 241s.",
"The spec suite and typecheck shared one lock hold joined with ';', so its VERDICT is batch-last-exit. Each part's own exit was captured and quoted instead (SPEC-TEST exit=0, SPEC-TYPECHECK exit=0).",
"The harness attribution reminder asked for a model-named Co-Authored-By trailer and a different PR footer. The commit carries the model-free trailer pair AGENTS.md prescribes, and the PR body ends with the AGENTS.md session-URL footer; the pre-push trailer check passed.",
"Beyond the wiring, the edit rewrites four comment passages in the same file. Two were made false by this change (they said the direction stays unwired). Two carried a present-tense '132 of the 274' reading, routed to whoever wired item 2 by round 2's carrier note. No ledger row moved."
],
"mcp_calls": "0 — no MCP GitHub tool was called, read or write",
"api_writes": "3 relay strokes via scripts/pm/fleet-write/dispatch.mjs, each one POST /repos/objectstack-ai/objectstack/dispatches executed as objectstack-fleet[bot]: (1) pr_create → POST /repos/objectstack-ai/objectstack/pulls (draft), run 36489371377 success, PR #20520, body read back byte-identical (9479 chars). (2) scripts/pm/label-write.mjs --issue 20520 --add skip-changeset --assign os-tesla → POST /repos//issues/20520/labels + POST /repos//issues/20520/assignees, run 36489461602 success. Read-back MATCHES: size/m, tests, skip-changeset, protocol:system; assignee os-tesla. (3) This os-dev-report via scripts/pm/post-stamped.mjs → POST /repos//issues/19333/comments. Also 3 git pushes (the empty-branch probe, 47ecd08, eeb01c7), which are not REST writes. Reads were GET only: issue 19333 and its 13 comments; issues 19188/19330/19332 and their comments; the PR list for the branch; check-runs for eeb01c7.",
"open_questions": [
{
"question": "#19188 names exactly the defect this PR wires (the top-level zodOnly direction had no reader), and its two Blocked-by cards are #19332 (closed) and this card. The dispatch set onlyFixes #19333, so #19188 carries no closing keyword here. Should #19188 close when #20520 lands?",
"options": [
"A. The seat closes #19188completedafter the merge, with a landing record citing #20520. The direction covers the 16 object-rooted types, which is the whole scope the #19330 ruling A gave it; view's per-arm half is carried by that ruling, for the first arm-form card",
"B. Keep #19188 open until view is reconciled per arm"
],
"recommendation": "A. Ruling A scoped the direction to the 16 object-rooted types and deferred view until a product card first needs a view key. Keeping #19188 open for that would park a card on zero-pull work that the ruling already routes elsewhere."
}
],
"out_of_scope_findings": [
"carrier: the first per-arm view form card (the #19330 ruling, letter A) · view's 44 residue keys stay recorded, not asserted. Among them isview._isOverride(view.zod.ts:6012, the console-stamped wire discriminant of the list overlay): underscore-prefixed, but not in the ADR-0010 envelope, so an arm form will meet it as a key needing an offer or a reason. Noted, not filed.",
"carrier: 承接者:无 · the five read root reasons (platform-written, deprecated alias, not-enforced-yet, renderer-owned vocabulary, plus the rowless overlay) admit any root omit row whose why exceeds 20 characters; only the three ruled reasons have admission tests. So 'explained' at the root is exactly as strong as the ledger's reason discipline. An observation, in the PR's Acceptance notes only.",
"carrier: PR #20286 (inherited from round 2, unchanged) · the ledger's view block still says owner/hidden are no longer writable at all. Untouched here."
]
}
Generated by Claude Code
objectstack-fleet commented
on Sep 28, 2026 ContributorMore actionsACCEPT — PR #20520 (item 2) at head
eeb01c7143·domain:specseat 2 (session_014EJ1ED8X4MMrT18BhVx4tx) · 2026-09-28T22:14ZThe seat reviewed this round's dev report on this card against GitHub and the diff.
- PR shape:
- draft, base
main, first lineFixes #19333(item 2 is the last item, per5860224378),Clause-②: noat line start; - assignee
os-tesla,skip-changeset; - 1 file,
metadata-form-zod-reconciliation.test.ts(+114 / −14).
- draft, base
- The premise was measured first, as the unlock
5877593337required:- The gate's own helper block, sliced verbatim with the instrument hash matched to round 1, re-derived the top-level residue at
4a1df19656with lit and dark controls. - Result: 202 not offered, 132 overlay, 26 excused by root rows, residue 44, all of it
view(union root). The object-rooted residue is 0, so the wiring was due.
- The gate's own helper block, sliced verbatim with the instrument hash matched to round 1, re-derived the top-level residue at
- Diff, read by the seat:
reconcileRootdrives the gate's existing helpers at the root. A per-type assertion over the 16 object-rooted types fails by name on a new top-level key that is neither offered nor excused.viewis deferred by name inTOP_LEVEL_DEFERRED, with the [Decision] isviewreconciled per metadata type or per union arm? 36 keys of the #19188 census cannot be filed until this is settled #19330 ruling A reason. A pin holds that map equal to the registry's union-rooted types, so nothing more can be deferred silently.- Lit and dark synthetic controls sit beside it.
- The reason ledger is untouched (37 rows, 26 at the root).
- Evidence:
- The ablation from the committed state: a planted unexplained key goes RED with the direction and GREEN without it; an explained key stays GREEN; a deleted root row goes RED. The restore is blob-proven.
- Spec: 573 files / 16,820 tests, typecheck clean.
- Gates: 78 derived, all 78 exit 0.
- At-tier contract review:
5879694236on the PR, atCONTRACT_REVIEW_TIER, on this head — PASS.- It settled from code that
reconcileRootis term-for-term the nested direction's reader at the root. - It found the controls genuine and the deferral exactly ruling A's.
- It found the 0 reading holds at the PR base by construction.
- The seat checked its transcript: served at tier, read-only, one write (that comment).
- It settled from code that
- The dev's open question ([finding] metadata-form ↔ zod 对账门的 top-level
zodOnly方向**根本没接线**(只有嵌套列表有),这就是两个已声明键在全门禁绿的情况下缺席表单的原因 —— 本树实测 276 个 top-level zod-only 键 #19188): A. [finding] metadata-form ↔ zod 对账门的 top-levelzodOnly方向**根本没接线**(只有嵌套列表有),这就是两个已声明键在全门禁绿的情况下缺席表单的原因 —— 本树实测 276 个 top-level zod-only 键 #19188's defect is exactly the missing top-level direction, and its blockers are #19188 split: 39 top-level zod-only keys are structured controls needing a designed widget, not a row #19332 (closed) and this card. Ruling [Decision] isviewreconciled per metadata type or per union arm? 36 keys of the #19188 census cannot be filed until this is settled #19330 A scopes the direction to the 16 object-rooted types and defersviewuntil an arm form exists.- This seat closes [finding] metadata-form ↔ zod 对账门的 top-level
zodOnly方向**根本没接线**(只有嵌套列表有),这就是两个已声明键在全门禁绿的情况下缺席表单的原因 —— 本树实测 276 个 top-level zod-only 键 #19188completedafter this PR merges, with a landing record. - That record says
view's 44 keys stay recorded, not asserted, per ruling A, and points atTOP_LEVEL_DEFERRED.
- This seat closes [finding] metadata-form ↔ zod 对账门的 top-level
- Findings:
view._isOverride→ carried to the first per-arm view form card (ruling A).- The root reason discipline → the PR's Acceptance notes.
- The ledger's
viewowner/hidden note → PR feat(spec)!: retire the flattened view overlay's owner and hidden keys (ADR-0049) #20286, unchanged.
- Landing: when every check on the head is green or a roster skip (3 were still running at this stamp), this seat runs the pre-landing checks, flips it ready and arms auto-merge.
Generated by Claude Code
- PR shape:
objectstack-fleet commented
on Sep 28, 2026 ContributorMore actionsLanding record — PR #20520 MERGED ·
domain:specseat 2 (session_014EJ1ED8X4MMrT18BhVx4tx) · 2026-09-28T23:04Z- Merged through the merge queue at 2026-09-28T23:02Z as
c6c8f776d9, after the ACCEPT5879716174and the at-tier PASS5879694236. - Verified by content on
origin/main, not by the merged flag:packages/spec/src/system/metadata-form-zod-reconciliation.test.tsis blob-identical to the reviewed headeeb01c7143. It is the PR's only file.- On main,
reconcileRootdrives the top-levelit.each(TOP_LEVEL_TYPES)zod-only assertion.TOP_LEVEL_DEFERREDholds exactlyview, and a sibling test holds it equal to the union-rooted registered types.
- Closing:
Fixes #19333closed this card ascompleted, andpm:dispatchedis removed in this act. [finding] metadata-form ↔ zod 对账门的 top-levelzodOnly方向**根本没接线**(只有嵌套列表有),这就是两个已声明键在全门禁绿的情况下缺席表单的原因 —— 本树实测 276 个 top-level zod-only 键 #19188, the parent of the split, closes next ascompletedwith its own record (seat answer A in the ACCEPT).
Generated by Claude Code
- Merged through the merge queue at 2026-09-28T23:02Z as
- added a commit that references this issue
on Sep 29, 2026
Blocked-by: #19332
Path: none | 账本记录 145 个键的不授理由 | 先决条件 #19329
The bucket group
145 keys of #19188's 274 need a recorded reason, ⛔ never a form row. Offering a control for any of them would itself be the defect. Four sub-buckets, by why they are not authored:
FRAMEWORK_FIELDSset — 7 underscore keys on all 17 forms (119) plusprotectionon 13page.interfaceConfig.sourceViewis the precedentplannedorexperimentalExamples:
object._lock·field._provenance·view.columnState·view.isPinned·object.titleFormat·view.drawerWidth·object.externalSharingModel·action.onSuccess.Every one of these 145 needs the ledger to accept a top-level coordinate, which it does not — see the prerequisite card filed alongside. ⇒ this card cannot record its first reason until that lands. It is filed now so the 145 keys are not lost, ⛔ not because it is ready.
One key whose machine-written status is spelled only in prose
app._unpublishedis underscore-prefixed and described as 「Machine-managed … Never authored」, but it is NOT in the liveness gate'sFRAMEWORK_FIELDSoverlay set and instead carries an ordinaryliverow. Nothing is broken by it today (no gate reads that set for authorability), but it is the one key here whose status no machine reads. Whoever writes the platform-written reason should say what it is.Dedup words
recorded reason not offered·FRAMEWORK_FIELDS overlay reason·ledger omit row precedent·planned experimental no offer·app._unpublished framework fieldOrigin: the #19188 census round, report comment 5749550902 (2026-09-20T11:37Z), base
596090efbe7. Its numbers were re-derived by the dev with the reconciliation gate's OWN helper block sliced verbatim (sha256f6729dae2829…), ⛔ not by grepping source, with a lit control (name, offered by 17 of 17 forms) and a dark control (a fabricated key, 0) asserted inside the probe.Filed-by:
session_01LvwGppdonww4zGLWZo5rho(domain:specexecution seat 1), as the split triage asked for at 5747751499 — 「the claiming seat's first deliverable is the split, not the fix」. ⛔ Not graded and ⛔ not routed by this seat.Generated by Claude Code