Repository navigation
metadata forms: one row each for object.access, object.highlightFields, object.requiredPermissions, object.searchableFields and permission.adminScope (#19332 flight G1a) #20349
Description
Activity
- addedenhancementNew feature or requestNew feature or requestpriority:p2Medium: important, M3Medium: important, M3
on Sep 28, 2026 objectstack-fleet commented
on Sep 28, 2026 ContributorAuthorMore actionsClaim: PM loop round 1
Session:session_01CiCTczDo7tGhafXjf61dUJ
Account:os-sales(the seat's linked user asGET /useranswers it; the card's assignee)
Branch:claude/issue-20349-g1a-object-permission-rows
Worktree:objectstack-issue-20349
Domain:domain:spec
Seat:domain:spec#4(seat post #18917)
File surface:packages/spec/src/data/object.form.ts: rows foraccess,highlightFields,requiredPermissionsandsearchableFieldsonly.packages/spec/src/security/permission.form.ts: a row foradminScopeonly.- The four
packages/platform-objects/src/apps/translations/*.metadata-forms.generated.tscatalogues, produced by the repo's i18n pipeline as feat(spec): give the 45 declared-but-unoffered scalar metadata keys a form row each #19673 (408ca2e36) produced them. - The platform-objects echo-decision tests only if the new rows move them, and the reconciliation test's expectations only if they pin the residue count.
.changeset/.- ⛔ Not
field.*/action.*(flight G1b). ⛔ NotfieldGroups/indexesor the other G2 keys. ⛔ Not the ledger rows (#19188 split: 39 top-level zod-only keys are structured controls needing a designed widget, not a row #19332's ledger flight).
(stop on breach; explain in the report)
Container & model:M,mode:subagent,model: default judgment tier(dispatch-gates --tier: no path-derived mandate). The*.form.tsfiles are non-testpackages/spec/src/**, so the at-tier review is owed before enqueue.
Clause-②: no
Thread-read: none
Serial constraints cleared: read at 2026-09-28T01:07Z. - The parent's ledger flight (
5861529325) writes only the reconciliation test file, so the two are disjoint unless this flight's residue pin moves; the later lander mergesmain. - No open PR touches
object.form.tsorpermission.form.ts. - One open PR regenerates the four catalogues: feat(spec)!: retire currencyConfig.precision — a currency's decimal places are its currency's (ADR-0049) #20251 ([finding] currencyConfig.precision is declared and validated against ISO 4217, but no renderer or runtime reads it — an ADR-0049 enforce-or-remove case, filed on ruling 乙 on #19910 #19992, seat 1). They are generated files, so whichever lands second regenerates them on its merge with
scripts/pm/os-regen-merge.sh. - No live claim names them.
Ruling carried:
5861442317· batch #229 item 3 · letter A · maintainer 「同意」 (G1, quoted in this card's body). This is the first form flight, so it re-checks the ruling's carried premise on objectui's widget bounds at the.objectui-shapin.objectstack-fleet commented
on Sep 28, 2026 ContributorAuthorMore actionsRelease: clock-out, round stopped before its PR
domain:specseat 4 (session_01CiCTczDo7tGhafXjf61dUJ), 2026-09-28T03:31Z. Clock-out on the maintainer's word in the seat session, verbatim: 「当前任务处理完,合并后就下班」, then 「快没token了」. The dev run was stopped mid-round. Only the pushed branch head below counts; nothing local survives.pm:dispatched→pm:queuein this act, withos-salesunassigned. The next claimant re-claims under the full protocol and re-measures on the day'smain.State. The branch is
claude/issue-20349-g1a-object-permission-rows, remote headbc1d395d3. There is no PR yet. When stopped, the dev was updating the platform-objects echo-decision pins, after the five rows and the catalogues. Its completeness and its re-check of the ruling's objectui widget-bound premise are NOT MEASURED; read the branch against claim5861551344.Next. Finish the flight:
- run spec
test+test:repoand the platform-objects suite; - merge
mainwithos-regen-merge.sh(seat 1's PR feat(spec)!: retire currencyConfig.precision — a currency's decimal places are its currency's (ADR-0049) #20251 regenerates the same catalogues); - open a draft PR with
Fixes #20349andClause-②: no; - run the at-tier review.
The later flights stay as the parent's ruling
5861442317orders them: G1b, then G2a and G2b.domain:specseat 4 · #18917 ·session_01CiCTczDo7tGhafXjf61dUJ
Generated by Claude Code
- run spec
objectstack-fleet commented
on Sep 28, 2026 ContributorAuthorMore actionsClaim: PM loop round 1
Session:session_01ARcDurZ5j34RdqsGgc4jgH
Account:os-warren(the seat's linked user asGET /useranswers it; the card's assignee)
Branch:claude/issue-20349-g1a-object-permission-rows
Worktree:objectstack-issue-20349
Domain:domain:spec
Seat:domain:spec#4(seat post #18917)
Ruling-ref: 5861442317
File surface: the surface of the released claim5861551344, continued from the branch's pushed headbc1d395d3(release5862816545). The branch is re-used; its commits are UNVERIFIED hand-over, re-read hunk by hunk.packages/spec/src/data/object.form.ts: one row each forobject.access,highlightFields,requiredPermissions,searchableFields.packages/spec/src/security/permission.form.ts: one row forpermission.adminScope.- The four-locale
*.metadata-forms.generated.tscatalogue rows and the platform-objects re-extract and echo-decision pins that follow (regenerated, never hand-edited), plus.changeset/. - ⛔ Not G1b (
field.*,action.*), not G2, not the reconciliation ledger, not thezodOnlywiring (#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).
(stop on breach; explain in the report)
Container & model:S/M,mode:subagent,model: default judgment tier(no path-derived mandate). The diff's forms and catalogues are not among the review surfaces incontract-review.mdunless it reachespackages/spec/src/**schemas; the seat re-checks the final file list before landing.
Clause-②: no
Thread-read: 5862816545
Serial constraints cleared: read at 2026-09-28T06:15Z onorigin/main15bf186f5. origin/mainis 16 commits past the branch's merge base and moved all four catalogues (seat 1's PR feat(spec)!: retire currencyConfig.precision — a currency's decimal places are its currency's (ADR-0049) #20251 is no longer open). Open PR feat(spec)!: retire the list view's owntabskey; named presets arelistViewsentries #20357 (spec(ui): retirelist.tabsand the view container's bodyname(2 keys);listViews+ ViewTabBar and the row name already deliver both #20301,domain:specseat 2) also regenerates the catalogues andobject-lifecycle-panel-echo-decisions.test.ts. That is ordinary concurrency, merged withscripts/pm/os-regen-merge.sh.- No other open PR touches
object.form.tsorpermission.form.ts, and no live claim names them. - #19188 split: 39 top-level zod-only keys are structured controls needing a designed widget, not a row #19332's ledger flight landed as
b1cbd9277, so the reconciliation residue base is 28.
Ruling carried:
5861442317· batch #229 item 3 · letter A · maintainer 「同意」: G1 rows, the objectui widget-bound premise re-checked in this first form flight,Clause-②: no.domain:specseat 4 · #18917 ·session_01ARcDurZ5j34RdqsGgc4jgH
Generated by Claude Code
objectstack-fleet commented
on Sep 28, 2026 ContributorAuthorMore actionsos-dev-report
{ "issue": 20349, "status": "done", "branch": "claude/issue-20349-g1a-object-permission-rows", "pr": "https://github.com/objectstack-ai/objectstack/pull/20405", "session": "session_01ARcDurZ5j34RdqsGgc4jgH (subagent run; the parent PM session's id, as CLAUDE_CODE_REMOTE_SESSION_ID resolves it)", "premise_still_valid": true, "summary": "Resumed branch head bc1d395d3 into worktree objectstack-issue-20349, reread every hunk and reverified it all. object.form.ts now has one row each for highlightFields and searchableFields (string-tags, in Basics), access (a composite over a declared default select) and requiredPermissions (json, the union), both in Advanced. permission.form.ts has one json row for adminScope. The four-locale catalogue rows are in, and the platform-objects echo pins are updated. Hand-over, per acceptance item. The five rows (7ce01726): complete, kept; every help-text claim was checked against its runtime reader. Catalogue rows and re-extract (3820f4a7, 3ae44a78): complete, kept; after the merge, check:i18n reports all 9 packages in sync, so the catalogues regenerate byte-for-byte. Echo pins (abbf9c7f): already complete; the platform-objects suite is green with no further pin edit. Changeset: half-done; it lacked the Clause-② line, and this run added it (353e708a). Merge: origin/main 15bf186f5 merged with os-regen-merge.sh as e505f724; no conflict, and check:generated is green with no regeneration. Ruling premise, re-checked by reading objectui f8a9d0fb0 source (no browser): both halves HOLD. widgets.tsx:1290 reads a non-array as an empty array, and add/remove write it back. ResourceEditPage.tsx:889-893 takes the field catalogue from interfaceConfig.source, data.object, object or objectName, and the object type declares none of the four. Residue, measured with the reconciliation test's own helper block: 28 at 15bf186f5, 23 on the head src; exactly the five keys removed and none added. Assumption 3 confirmed. Draft PR #20405 is open. CI was in progress when this report was written.", "tests": "All through scripts/pm/os-verify-lock.sh (slot issue-20349), each VERDICT command-exit 0. For the two wrapper scripts, each inner exit was recorded separately, and all were 0. Commands and their real lines: pnpm --filter @objectstack/spec test = 'Test Files 557 passed (557) / Tests 16497 passed | 1 todo (16498)'. pnpm --filter @objectstack/spec test:repo = 'Test Files 35 passed (35) / Tests 634 passed (634)'. pnpm --filter @objectstack/platform-objects test = 'Test Files 55 passed (55) / Tests 911 passed (911)'. pnpm --filter @objectstack/spec typecheck: exit 0 (check:test-typecheck OK: 53 files, 255 errors, 142 signatures held by the ledger). pnpm --filter @objectstack/platform-objects typecheck: exit 0 (1 file, 3 errors, 2 signatures held). Downstream readers of the form registry: lint src/validate-predicate-path-refs.test.ts = 1 file, 54 tests passed; cli unit test/i18n-coverage.test.ts = 1 file, 20 tests passed. Builds: spec build exit 0; the i18n closure build (turbo, cli + 9 packages) = 'Tasks: 59 successful, 59 total'. pnpm check:i18n: 'check-i18n-bundles: OK (9 package(s) — all bundles in sync, no undeclared authoring keys)'. spec check:generated: 'All 15 generated artifacts are up to date'. Residue probe: the reconciliation test file copied whole, plus one appended probe block; scratch only, never committed. Before tree = 15bf186f5; after tree = the same tree with object.form.ts and permission.form.ts restored from 353e708a (git diff vs 353e708a over packages/spec/src = 0 lines). Each probe run: 1 file, 58 tests passed. Lit control field.accept was present in both; dark control object.zzFabricated20349 was absent in both. No ablation: no guard or gate was added.", "mcp_calls": "0 — no MCP GitHub tool was called", "api_writes": "3 — all through the fleet-write relay (repository_dispatch, executed as objectstack-fleet[bot]): (1) pr_create = POST /repos/objectstack-ai/objectstack/pulls (draft; relay run 36393424556, success); (2) label-write assign = POST /repos/objectstack-ai/objectstack/issues/20405/assignees [os-warren] (relay run 36393508455, success; read-back matches); (3) this os-dev-report comment = POST /repos/objectstack-ai/objectstack/issues/20349/comments. Plus 2 git pushes (e505f724, 353e708a), which are not REST. Reads were direct REST GETs only.", "gates": { "derived_by": "node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack at 353e708a (identical to the list derived at e505f724)", "derived": 85, "ran": 85, "exit_nonzero_final": 0, "not_measured": 0, "unrun": 0, "ran_verdict": "✓ dispatch-gates --ran: 85 derived famil(ies) accounted for — 85 run, 0 NOT-MEASURED (a DERIVED zero — all 85 recorded an exit code and none of them is 3).", "first_run_nonzero": [ "pnpm check:dual-build-cjs-loads :: exit 3 (PREREQUISITE NOT MET: nine packages had no dist/). Rerun on the same tree once the dist/ directories existed :: exit 0, '104 published require entry point(s) across 66 package(s) load'. The ran.list records the rerun's code." ], "partial_notes": [ "pnpm --filter @objectstack/spec run check:entry-nameability exit 0, printing its standing 'NOT MEASURED: no callable export on @objectstack/spec/api-assembled, @objectstack/spec/qa'. That line is independent of this diff." ], "ci_at_report": "head 353e708a: 32 check runs — 12 success, 3 skipped, 17 in_progress, 0 failure" }, "line_budget": { "changed_lines": 188, "additions": 182, "deletions": 6, "files": 9, "human_merge_threshold": 5000, "verdict": "under", "skills_budget": "n/a — no skills/** path" }, "files_changed": [ ".changeset/20349-object-permission-form-rows.md", "packages/platform-objects/src/apps/translations/en.metadata-forms.generated.ts", "packages/platform-objects/src/apps/translations/es-ES.metadata-forms.generated.ts", "packages/platform-objects/src/apps/translations/ja-JP.metadata-forms.generated.ts", "packages/platform-objects/src/apps/translations/zh-CN.metadata-forms.generated.ts", "packages/platform-objects/src/apps/translations/object-collapsed-sections-echo-decisions.test.ts", "packages/platform-objects/src/apps/translations/object-lifecycle-panel-echo-decisions.test.ts", "packages/spec/src/data/object.form.ts", "packages/spec/src/security/permission.form.ts" ], "deviations": [ "Worktree created from the remote branch, with no empty-branch push, as the dispatch ordered (rule-1 deviation by order).", "The residue probe ran in a second scratch worktree at 15bf186f5, not in the issue worktree. The after-tree was that worktree with the two form files restored from 353e708a. This kept the gate run's change set free of untracked files. The worktree was removed cleanly afterwards.", "check:dual-build-cjs-loads is recorded in ran.list with its rerun exit 0; its first run exited 3 (prerequisite)." ], "open_questions": [], "out_of_scope_findings": [ "carrier: #19333 item 2 (the zodOnly wiring; edits metadata-form-zod-reconciliation.test.ts) · noted, not filed — a dark-control comment there reads 'object.access is authorable and no form offers it', and that is stale after this PR. Its assertions (ruled-class admission) still hold. The file is the ledger, which is outside this flight's surface.", "carrier: #19333 item 2 · noted, not filed — nothing pins the ruling's 'union values never take string-tags' across the registry. A future edit could flip requiredPermissions back to string-tags with no test turning red. Not a defect today.", "carrier: 承接者:无 · noted, not filed — objectui's nested-form face cannot unset an object key. Once adminScope is touched, clearing every sub-field leaves an empty object, and the parse refuses it loudly (businessUnit is required). Loud, generic to every nested-form row.", "carrier: PM (ruling text) · noted, not filed — the ruling says a misspelt field-name entry 'is refused loudly at parse'. It is refused at the object publish door and by os validate: validateObjectFieldRefs and validateSearchableFields at error, runtimeTypes including object. The Zod parse does not judge field names. The changeset and the PR body say so." ] }
Generated by Claude Code
objectstack-fleet commented
on Sep 28, 2026 ContributorAuthorMore actionsReview: ACCEPT · PR #20405 at head
353e708aa7808c39a649d8254cf2895a59f9f648· 2026-09-28T08:21Zdomain:specseat 4 (session_01ARcDurZ5j34RdqsGgc4jgH), reviewer of record under claim5864511529. The readings below were taken on GitHub or on the tree by this seat.check reading Shape Draft, base main. Body line 1Fixes #20349; line 2 names the parent without a closing verb (Flight G1a of #19332);Clause-②: nostands alone.Scope 9 files, +182/−6: two form files, four generated catalogues, two echo-decision pins, the changeset. It matches the claim. Changeset @objectstack/specminorand@objectstack/platform-objectspatch,Clause-②: no, on the #19673 (408ca2e36) precedent. Its prose correctly places the misspelt-field-name refusal at the publish door andos validate, not at the Zod parse.Contract review At-tier record PASS 5866196177, same head. It checks every row's widget against its schema shape and the ruling (requiredPermissions, the one union, takesjson), and every help-text claim against its runtime reader. It re-read the objectui widget premise at the pin (both halves hold), and derives the reconciliation residue 28 → 23 exactly.CI at this head 32 success, 3 skipped, all on the roster ( check-expected-skips.mjs --pr 20405, exit 0).mergeable_state:clean.origin/mainis 6 commits past the merge base and touches none of this PR's files, so the generated catalogues need no re-sync.Governed / size Not governed, 188 changed lines. Out-of-scope findings:
- The stale dark-control comment in
metadata-form-zod-reconciliation.test.ts(「no form offers it」 forobject.access) and the missing registry-wide pin that a union never takesstring-tags→ Acceptance notes, carrier: #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 item 2, which edits that file. - The objectui nested form cannot unset an object key. A cleared
adminScopeis refused loudly by the schema. This is a generic renderer bound → Acceptance notes, no carrier. - The ruling's 「refused loudly at parse」 is in fact the publish door and
os validate. The changeset says so accurately, and this is noted here for the ruling's readers.
Landing next: ready + auto-merge through the relay. At MERGED, this card closes by
Fixes, and #19332's G1b becomes the next flight.domain:specseat 4 · #18917 ·session_01ARcDurZ5j34RdqsGgc4jgH
Generated by Claude Code
- The stale dark-control comment in
objectstack-fleet commented
on Sep 28, 2026 ContributorAuthorMore actionsLanded: PR #20405 →
main7db1332f19e8c4fabbed1f0cb3d62e577e4295bb· 2026-09-28T08:47Zdomain:specseat 4 (session_01ARcDurZ5j34RdqsGgc4jgH), landing record for claim5864511529. ACCEPT5866208907on the at-tier PASS5866196177. Queue path: ready at 08:21Z,added_to_merge_queueat 08:23Z, merged at 08:46Z.- Verified on
origin/main:7db1332fhas one parent,2c310705, and is an ancestor oforigin/main. Its diff against that parent is 9 files, +182/−6, the same as the PR. The content control:field: 'adminScope'has 1 hit inpackages/spec/src/security/permission.form.tsatorigin/mainand 0 at the parent. No queue branch for feat(spec): a metadata-form row each for object.access, highlightFields, requiredPermissions, searchableFields and permission.adminScope (#20349) #20405 remains. - This card was closed
completedby the PR'sFixesline.pm:dispatchedcomes off in this act. - #19188 split: 39 top-level zod-only keys are structured controls needing a designed widget, not a row #19332: flight G1a is in, and the reconciliation residue is 23. The next flight is G1b (
field.*/action.*, 16 keys), in the ruling's order.
domain:specseat 4 · #18917 ·session_01ARcDurZ5j34RdqsGgc4jgH
Generated by Claude Code
- Verified on
- added a commit that references this issue
on Sep 28, 2026
Part of #19332 — flight G1a of ruling
5861442317(batch #229 item 3, letter A, maintainer 「同意」).Filed by the
domain:specseat 4 (session_01CiCTczDo7tGhafXjf61dUJ, seat post #18917). It is an in-scope sub-issue of an in-flight card, so it inherits the parent'sdomain:specandpriority:p2. The parent carries the ledger flight (claim5861529325). This card exists so that flight G1a can run beside the ledger flight under its own claim.What
An author who opens the Studio form for an object or a permission set cannot see or set five live settings that the platform honours once they are written in code. Each gets one form row, mirroring a row a registered form already has, with the four-locale catalogue rows in the same PR.
object.accesspackages/spec/src/data/object.form.tsobject.highlightFieldsobject.form.tsobject.requiredPermissionsobject.form.tsobject.searchableFieldsobject.form.tspermission.adminScopepackages/spec/src/security/permission.form.tsThe ruling, quoted (G1)
This is the first form flight, so it re-checks that premise.
Acceptance
5859943900on #19188 split: 39 top-level zod-only keys are structured controls needing a designed widget, not a row #19332.408ca2e36) generated them.Clause-②: no. The precedent is408ca2e36.Order
G1b (
field.*andaction.*, 16 keys) follows this flight. G2's two flights and #19333 item 2 follow as the parent's ruling orders them.Dedupe words:
metadata form row object.access highlightFields searchableFields·permission.adminScope form row