Repository navigation
spec(ui): export the candidates half of the anonymous-form-intake rule from @objectstack/spec/ui, so the console reads "published" from the server's one rule (objectui#11545, ruling 5967405932's fallback) #22047
Description
Activity
- addedenhancementNew feature or requestNew feature or requestpriority:p2Medium: important, M3Medium: important, M3area:accessPermissions that actually hold — RLS/FLS, sharing model, write-path guardsPermissions that actually hold — RLS/FLS, sharing model, write-path guardsand removed
on Oct 7, 2026 objectstack-fleet commented
on Oct 7, 2026 ContributorAuthorMore actionsClaim: PM loop round 7 (this card, as the triage seat filed and graded it: the fallback of triage ruling objectui#11545
5967405932) · 2026-10-07T03:42Z
Session:session_01GV6oYwgc1kWiUCb1YaprQ7
Account:os-warren(the seat's linked user asGET /useranswers it; the card's assignee from this act)
Branch:claude/issue-22047-spec-ui-anonymous-form-intake
Worktree:objectstack-issue-22047
Domain:domain:spec
Seat:domain:spec#2(seat post #18549)
File surface (atorigin/main8caa131e; stop on breach and explain in the report):packages/spec/src/ui/: the candidates half of the rule, unchanged in what it decides:publicFormSlug,anonymousFormIntakeSlug,anonymousFormIntakeCandidates,anonymousFormIntakeSlugsand theAnonymousFormIntakeCandidatetype. It goes insharing.zod.tsor a module beside it, exported frompackages/spec/src/ui/index.ts, with its spec tests underpackages/spec/src/ui/.- Declared cross-lane files (
domain:engine,packages/metadata*):packages/metadata-core/src/anonymous-form-intake.ts, where the moved half becomes a re-export from@objectstack/spec/ui; its posture, withdrawal-layer and object-name halves stay. Also its test file, andpackages/metadata-core/src/index.tsonly if its export line must change. The declaration goes on thedomain:engineseat post [PM seat] domain:engine — ⏳ vacant #6367. - Whatever
packages/specgenerators move for the new exports (api-surface/**,api-surface-signatures.json, export origins,spec-changes.json,content/docs/references/**, and anyliveness/**row a gate requires), plus.changeset/22047-*.md. - ⛔ No change in what the rule decides; the candidate scan keeps its three shapes in scan order. ⛔ No edit to the rule's consumers (
packages/rest,packages/metadata-protocol): they keep importing frommetadata-core. ⛔ No server response surface.
Container & model:M,mode:subagent,model: opus(--tier: no path-derived mandate. The clause-② review is owed atCONTRACT_REVIEW_TIERby an isolated subagent, not this build.)
Clause-②: yes (widening: new exports on the published@objectstack/spec/uientry;@objectstack/specchangeset at leastminor)
Responsibility: n/a — not a defect card
Thread-read: none
Serial constraints cleared: - None of the 8 open PRs touches
packages/metadata-core/src/**orpackages/spec/src/ui/sharing.zod.ts/index.ts(scan at this stamp). The Version Packages PR chore: version packages #21988 touchespackages/metadata-core/package.jsonandCHANGELOG.mdonly, both release-owned. - No live
Claim:on anypm:dispatchedcard names these files. - This seat's in-flight spec: the
sharedentry grew +152 KB gzip from 17.6.0 to 17.7.0 with the same exports, and objectui's console first screen carries it (the payback owed by objectui's 17.7.0 budget raise) #22044 (PR perf(spec): a bundle that never reads the ADR-0087 conversion table stops keeping it, 226 KB gzip off the console first screen (#22044) #22048:conversions/registry.tsand two spec script tests) and analytics: a dataset answer's measure column does not state its aggregate when the author labelled it, so a chart cannot tell a count from a sum (objectui#11681's producer half) #21995 (PR feat(spec,analytics): a dataset answer's measure column states its aggregate, labelled or not (fields[].aggregate) #22021, in the merge queue:api/analytics.zod.ts,service-analytics) are disjoint from this surface. If both regenerate os-regen-managed spec aggregates, the later to land mergesmainand regenerates them.
Generated by Claude Code
objectstack-fleet commented
on Oct 7, 2026 ContributorAuthorMore actionsos-dev-report
{ "issue": 22047, "status": "done", "branch": "claude/issue-22047-spec-ui-anonymous-form-intake", "pr": "https://github.com/objectstack-ai/objectstack/pull/22056", "session": "session_01GV6oYwgc1kWiUCb1YaprQ7 (subagent run; the PM's id, as the claim names it; the container's CLAUDE_CODE_REMOTE_SESSION_ID resolves to the same id)", "premise_still_valid": true, "summary": "The candidates half of the anonymous-form-intake rule is now exported from @objectstack/spec/ui: publicFormSlug, anonymousFormIntakeSlug, anonymousFormIntakeCandidates, anonymousFormIntakeSlugs and the AnonymousFormIntakeCandidate type. It lives in a new module, packages/spec/src/ui/anonymous-form-intake.ts, next to sharing.zod.ts. The module imports nothing, the bodies match BASE lines 52-105 except for 2-space indentation (diff -w empty), and the scan order and the three shapes are unchanged. @objectstack/metadata-core re-exports the same bindings and keeps its posture, withdrawal-layer and object-name halves; its remaining code imports publicFormSlug and the type from the spec. rest and metadata-protocol are not edited, and metadata-core/src/index.ts is unchanged. Pins: spec parity tests (26), a metadata-core identity pin (4 cases), and one-time ablation, parity and dual-build probes. The changeset is spec minor and metadata-core patch, with Clause-②: yes (widening).", "tests": "All at HEAD cfdc8804f0. The spec suite ran at 3e9a9e48b1, whose source tree differs only by the changeset file. spec build (JS+DTS): exit 0, check-dts-emitted 38/38. spec check:generated: exit 0, 15/15 up to date. The first run had 3 stale artifacts: api-surface/ui.json +5, export-origins/ui.json +5, references/ui/sharing.mdx. They were regenerated with gen:api-surface, gen:export-origins and gen:docs. pnpm --filter @objectstack/spec test: 620 files passed, Tests 18511 passed, 1 todo, VERDICT command-exit 0. New file alone: 26 passed. pnpm --filter @objectstack/metadata-core test: 18 files, 415 passed. anonymous-form-intake.test.ts alone: 46 passed. pnpm --filter @objectstack/metadata-protocol test: 219 files passed, 3 skipped; 28135 passed, 19 skipped; exit 0. Focused run of runtime-authoring-gate.public-form-intake, protocol.runtime-authoring-gate and protocol.org-scoped-write-refused: 3 files, 257 passed. pnpm --filter @objectstack/rest test: 260 files, 4914 passed, 326 skipped, exit 0. Focused run of the 4 public-form-* files: 76 passed. typecheck of spec and metadata-core: exit 0 each; --listFiles shows both new test files in their test programs. ABLATION of the identity pin: fix committed first, then scripts/ablation-replace.mjs swapped the anonymousFormIntakeCandidates re-export for a wrapper calling the spec function. Mutation landed (anchor 1 -> 0, blob c08671875 -> 60992490b). Result: Tests 1 failed, 45 passed (46). Only the identity case failed (Object.is); every behaviour test passed against the wrapper. Restored: blob == HEAD c086718754, git diff HEAD empty. No dist leg was needed: the test reads metadata-core src directly. Direction observed: red, as expected.", "mcp_calls": "0", "api_writes": "3 REST writes through the scripts/pm fleet-write relay, each landing as objectstack-fleet[bot], each relay stroke being one POST /repos/objectstack-ai/objectstack/dispatches: (1) pr_create = POST /repos/objectstack-ai/objectstack/pulls, request fw-20261007T044108Z-bad77d, run 37572645339, read-back 11960 bytes sent = 11960 stored. (2) label-write assignee os-warren = POST /repos/objectstack-ai/objectstack/issues/22056/assignees, request fw-20261007T044153Z-33db05, run 37572701418, read-back matches. (3) this os-dev-report = POST /repos/objectstack-ai/objectstack/issues/22047/comments via post-stamped. Not REST: 4 git pushes (the empty branch probe, then c47cbdc5bb, 3e9a9e48b1 and cfdc8804f0).", "open_questions": [], "out_of_scope_findings": [ "carrier: none (承接者:无) · noted, not filed, and not in the PR's Acceptance notes because the body is written once: running pnpm --filter @objectstack/spec run check:skill-examples and pnpm check:query-options-erasure at the same time in one worktree turns the second red. The first writes and deletes gitignored packages/spec/.examples-build/*.ts files, and the second's ESLint pass lists them and then fails with ENOENT on packages/spec/.examples-build/docs__ai_actions-as-tools__1.ts. Run alone, it exits 0. This only shows up when gates run in parallel locally, and CI runs them one after another. If the seat wants it in the PR, add one Acceptance-notes bullet saying so." ], "gates": "Derived by node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack at cfdc8804f0 (stderr names objectstack-ai/objectstack at cfdc8804f0). --ran reconciliation: 110 derived, 109 run, 1 NOT-MEASURED, 0 UNRUN, exit 0. NOT MEASURED: pnpm check:dual-build-cjs-loads, exit 3 PREREQUISITE NOT MET, because it needs every package's dist and this worktree built only the rest and metadata-protocol closure plus client and client-react. Partial evidence: the H5 probe loaded metadata-core/dist/index.cjs with require, and its four exports === the spec/ui CJS exports. All 43 node-script families: exit 0. All other 66 pnpm families: exit 0. Included among them: check:api-surface, check:export-origins, check:docs, check:exported-any, check:dual-source-exports (0 accepted dual-source), check:entry-nameability, check:browser-reachable-entries (./ui is in unjudged), check:liveness, check:llms-txt, check:empty-state, check:nul-bytes, check:type-check-coverage, check:type-check-debt, check:test-source-alias, check:published-files, check:changeset-gate-self-tests, check-adr-0087-registration (1 non-breaking changeset), check-changeset-no-major and check-empty-changeset. check:skill-examples first exited 3 (client and client-react dist absent); it exited 0 once turbo built them. check:query-options-erasure: the first run was killed at my runner's 580s cap while it raced with check:skill-examples (see out_of_scope_findings); the rerun alone exited 0 ('ratchet holds: 66 unswept non-test sites, none new'). The lead list's 5 flagged rosters: check:meta-url-spelling and check:spec-changes pass inside check:generated; check:authz-resolver, check:error-code-casing and check:filter-alias-parity exit 0. Lint is a narrowed run that measures something: eslint --no-inline-config --format json over the 6 changed TS files gave 6 files, 0 errors, 0 warnings. The population is eslint.config.mjs files '**/*.{ts,...}' minus NEVER_LINTED, and --print-config resolves all 6. The config never enables type-aware linting (eslint.config.mjs near line 327), so the diff cannot move any untouched file's verdict. The repo-wide pnpm lint is left to CI. CI at report time: 12 completed, 0 failed, 20 in_progress.", "parity_table": "One-time probe: BASE metadata-core lines 52-105 (git show 8caa131e5) vs built @objectstack/spec/ui vs built @objectstack/metadata-core. It compared candidate key, key presence, slug, whether each candidate is a form object from the input, and the slug set. Columns are shape | bodies | with an open slug | identical in all three. nested form | 13 | 4 | 13. formViews entry plus an open sibling | 13 | 13 | 13. viewKind form + config | 13 | 4 | 13. All three in one body | 13 | 4 | 13. config without viewKind form | 13 | 0 | 13. Non-view input | 4 | 0 | 4. Real producers (showcase inquiry.view.ts, crm lead.view.ts, containers plus expandViewContainer items) | 9 | 4 | 9. Total: 78 bodies, 0 mismatches. Leaf inputs (anonymousFormIntakeSlug, publicFormSlug): 21, 0 mismatches. Real producers' open slugs: the showcase container and showcase_inquiry.contact give ['contact-us']; the crm container and crm_lead.web_to_lead give ['contact-us'].", "identity_pin": "metadata-core src/anonymous-form-intake.test.ts adds 'the candidates half is the spec binding itself, re-exported (one copy, not a copy)'. For each of the 4 names it asserts that ./anonymous-form-intake.js[name] and ./index.js[name] toBe @objectstack/spec/ui[name]: 4 passed, and the ablation turns it red (see tests). H5, built dual output, probed from packages/rest: ESM metadata-core dist/index.js === spec dist/ui/index.mjs is true for all 4; CJS dist/index.cjs === spec dist/ui/index.js is true for all 4; across ESM and CJS it is false, the dual-package split every spec export already has.", "hypotheses": "H1 holds: lines 52-105 call nothing from spec/security, applyInjectedSystemColumns or resolveRecordWallOrganizationField, and the new module has 0 imports. H2 holds: plain function declarations, no top-level statements, spec sideEffects false; ./ui is unjudged by check:browser-reachable-entries (pass). H3: a new module beside sharing.zod.ts, not inside it. It imports nothing (sharing.zod.ts imports zod and helpers); the precedent for non-schema runtime helpers in spec/ui is chart-aggregate.ts, i18n-label-resolver.ts and view-grouping-query.ts; the file name matches metadata-core's. Cost: files[] ships src/**/*.zod.ts, so this module ships as dist only. The PR body states this. H4: see prose_corrected. H5 holds: see identity_pin. Extra measurement: downstream tsc programs with metadata-core built from BASE source then HEAD source (shared box). rest: files 579 -> 580 (+ spec/dist/ui/index.d.ts, the CJS barrel, via metadata-core/dist/index.d.cts; its chunks were already loaded in both flavours), memory 1,246,583K -> 1,268,472K. objectql: 574 -> 574 files, 983,063K -> 994,921K. plugin-security: 495 -> 495 files, 1,079,234K -> 1,084,561K. metadata-protocol: 808 -> 808 files, ~0 memory change. http-conformance: 345 -> 345 files, ~0 memory change. tsc exit 0 on every program in both legs.", "prose_corrected": [ "packages/spec/src/ui/sharing.zod.ts:19-23 used to say (`anonymousFormIntakeCandidates` in `@objectstack/metadata-core`). It now says (`anonymousFormIntakeCandidates` in `anonymous-form-intake.ts` beside this module, which `@objectstack/metadata-core` re-exports to the server's doors).", "content/docs/references/ui/sharing.mdx:22-26: the same sentence, regenerated by gen:docs, not edited by hand.", "packages/metadata-core/src/anonymous-form-intake.ts:13-20: the module docblock's criteria paragraph now says the candidates half is declared in @objectstack/spec/ui (anonymous-form-intake.ts, beside SharingConfigSchema), whose docblock is the authority. The duplicated scan-shapes paragraph moved to the spec module.", "Judged still true, left alone: packages/rest/src/rest-server.ts:10698 reads (`anonymousFormIntakeCandidates`, `@objectstack/metadata-core`), which is where rest imports it from, and metadata-core still exports it; it is also outside this surface. packages/metadata-core/src/index.ts:141-145 ('both read this one rule'). docs/qa/platform-checklist/areas/access-security.json mechanism refs name anonymousFormIntakeWithdrawnIn and anonymousFormExplicitWithdrawals, which stay." ], "consumer_package_tests": "metadata-protocol: full run 219 files passed, 3 skipped; 28135 tests passed, 19 skipped; exit 0. Focused (runtime-authoring-gate.public-form-intake, protocol.runtime-authoring-gate, protocol.org-scoped-write-refused): 257 passed. rest: full run 260 files, 4914 passed, 326 skipped, exit 0. Focused (public-form-routes, public-form-routes.stored-row, public-form-withdrawal, public-form-intake-availability): 76 passed. metadata-core: 415 passed. Built first: turbo build of the rest and metadata-protocol closure, 25/25 tasks, exit 0.", "deviations": "(1) The spec module uses the package's 2-space indentation, not a byte-verbatim copy; diff -w against BASE lines 52-105 is empty. (2) The identity pin was added inside the existing metadata-core test file (3 import lines and 1 trailing describe); every existing case is byte-unchanged. (3) main was not merged. It gained #22021 (spec analytics, 9 files) after the base, which overlaps none of these files or generated artifacts; the merge queue rebuilds on current main. (4) The PR body's Clause-② line is copied verbatim from the claim, in the form 'yes (widening: ...)'. The changeset carries the closed-pair form 'Clause-②: yes (widening)'. (5) Two gates were rerun after first results that measured nothing (skill-examples exit 3, query-options-erasure killed or raced); details are in gates. (6) The PR body states that Prime Directive 2 (no business logic in packages/spec) is outweighed here by the ruling, with the assembled-views and expandViewContainer precedent. The ruling binds, so this is not reopened.", "files_changed": [ ".changeset/22047-spec-ui-anonymous-form-intake.md", "content/docs/references/ui/sharing.mdx", "packages/metadata-core/src/anonymous-form-intake.test.ts", "packages/metadata-core/src/anonymous-form-intake.ts", "packages/spec/api-surface/ui.json", "packages/spec/export-origins/ui.json", "packages/spec/src/ui/anonymous-form-intake.test.ts", "packages/spec/src/ui/anonymous-form-intake.ts", "packages/spec/src/ui/index.ts", "packages/spec/src/ui/sharing.zod.ts" ], "dedupe_words": ["anonymousFormIntakeCandidates spec/ui", "publicFormSlug export", "anonymous form intake re-export", "examples-build race query-options-erasure"] }
Generated by Claude Code
objectstack-fleet commented
on Oct 7, 2026 ContributorAuthorMore actionsos-dev-report
{ "issue": 22047, "status": "done", "round": "patch round 1 on PR #22056 (contract review 6031245238 wording flags 1 and 2)", "branch": "claude/issue-22047-spec-ui-anonymous-form-intake", "pr": "https://github.com/objectstack-ai/objectstack/pull/22056", "head": "6c5741c6b7 (full 6c5741c6b71966e88773503fd0bfb41fe5b0f38d), one commit on cfdc8804f0", "session": "session_01GV6oYwgc1kWiUCb1YaprQ7 (subagent run; the PM's id, as the claim names it)", "premise_still_valid": true, "summary": "Prose only, in two files. The changeset's last bullet and the spec module's 'What stays in @objectstack/metadata-core' paragraph no longer put anonymousFormObjectName among the halves that read server state. It is named separately as a pure read of the form and the view, kept beside them, and the withholding sentence names only the layer withdrawal and the posture. The module's 'Why this half lives in packages/spec' paragraph now cites expandViewContainer (view.zod.ts) only as the placement precedent. It states Prime Directive 2 as ADR-0053 D-D2 reads it, and attributes the byte-for-byte reason to the triage ruling objectui#11545 5967405932. git diff -U0 shows no changed line in the module outside the docblock: no code or test change. check:generated reports no generated artifact carrying this docblock (15/15 up to date), so nothing was regenerated. Claim 6030439569 was verified to name this branch before the push. The remote was still at cfdc8804f0 before the push.", "corrections": [ { "file": "packages/spec/src/ui/anonymous-form-intake.ts, 'Why this half lives in packages/spec' (lines 25-32 at HEAD)", "before": "Same precedent as `expandViewContainer` (`view.zod.ts`): a rule that two independent codebases must agree on byte for byte belongs beside the schema it serves, so neither end can drift.", "after": "`expandViewContainer` (`view.zod.ts`) is the placement precedent: a pure helper beside the schema it serves. Prime Directive 2 (no business logic in `packages/spec`) holds as ADR-0053 D-D2 reads it: a pure helper that states what the contract's own vocabulary denotes is protocol, not business logic, and a server package re-exports it. The reason two independent codebases must agree on this rule byte for byte is the triage ruling on objectui#11545 (`5967405932`): the console derives \"published\" from the server's one rule, never from a hand-copied second one.", "note": "The paragraph's remaining two sentences (the doors and write-time judgement; the metadata-core re-export) are unchanged in wording and only re-wrapped." }, { "file": "packages/spec/src/ui/anonymous-form-intake.ts, 'What stays in @objectstack/metadata-core' (lines 43-51 at HEAD)", "before": "The halves that read server state: a withdrawal in another metadata layer (`anonymousFormIntakeWithdrawnIn`, a kill switch that layering may only narrow, never re-open), whether the deployment's tenancy posture lets an open form take an anonymous submission (`anonymousFormIntakeUnavailability`), and the object a candidate submits into (`anonymousFormObjectName`).", "after": "The halves that read server state: a withdrawal in another metadata layer (`anonymousFormIntakeWithdrawnIn`, a kill switch that layering may only narrow, never re-open), and whether the deployment's tenancy posture lets an open form take an anonymous submission (`anonymousFormIntakeUnavailability`). Kept beside them is the object a candidate submits into (`anonymousFormObjectName`): a pure read of the form's `data.object` and the view's `list.data.object`, `form.data.object` and `object`, which reads no server state and stays there because that is where this export's surface was drawn.", "note": "The following sentence ('An open candidate here is therefore what the view body itself declares, before any other layer or the posture is consulted.') is kept verbatim." }, { "file": ".changeset/22047-spec-ui-anonymous-form-intake.md, last bullet", "before": "- **Not covered by the new export:** whether another metadata layer withdraws a form (`anonymousFormIntakeWithdrawnIn`), whether the deployment's tenancy posture lets the form take an anonymous submission (`anonymousFormIntakeUnavailability`), and which object it submits into (`anonymousFormObjectName`). These read server state and stay in `@objectstack/metadata-core`. A form the new functions call open can still be withheld by those checks.", "after": "- **Not covered by the new export:** whether another metadata layer withdraws a form (`anonymousFormIntakeWithdrawnIn`), and whether the deployment's tenancy posture lets the form take an anonymous submission (`anonymousFormIntakeUnavailability`). These two read server state and stay in `@objectstack/metadata-core`. `anonymousFormObjectName`, which names the object a form submits into, stays there beside them; it is a pure read of the form and the view, not of server state. A form the new functions call open can still be withheld by a withdrawal in another layer or by the posture." } ], "files_changed": [ ".changeset/22047-spec-ui-anonymous-form-intake.md", "packages/spec/src/ui/anonymous-form-intake.ts" ], "tests": "All at HEAD 6c5741c6b7, after pnpm --filter @objectstack/spec build (exit 0, check-dts-emitted 38/38). pnpm --filter @objectstack/spec exec vitest run --maxWorkers=2 src/ui/anonymous-form-intake.test.ts: exit 0, 1 file, 26 passed. --maxWorkers=2 was added per the container's resource rule. pnpm --filter @objectstack/spec check:generated: exit 0, all 15 artifacts up to date, none stale, nothing regenerated. pnpm --filter @objectstack/spec typecheck: exit 0 (lock VERDICT command-exit 0). eslint --no-inline-config --format json packages/spec/src/ui/anonymous-form-intake.ts: exit 0, 1 file, 0 errors, 0 warnings. pnpm check:nul-bytes: exit 0 (10047 text files, no raw control bytes). The manual control-byte grep over both changed files found 0 hits. Extra, because the docblock gained a citation and the changeset text changed: node scripts/check-issue-citations.mjs exit 0; node scripts/check-spec-docblock-symbol-anchors.mjs exit 0; check-adr-0087-registration, check-changeset-no-major and check-empty-changeset (--base origin/main) exit 0 each.", "mcp_calls": "0", "api_writes": "1 REST write: this os-dev-report = POST /repos/objectstack-ai/objectstack/issues/22047/comments through scripts/pm/post-stamped.mjs (fleet-write relay, one POST /repos/objectstack-ai/objectstack/dispatches). Not REST: 1 git push (cfdc8804f0..6c5741c6b7). No PR body edit, no label write.", "open_questions": [], "out_of_scope_findings": [], "deviations": "(1) The review's flag 1 also names the PR body's own wording. The PR body is outside this round's two-file scope and is written only once, so it is not touched. If the seat wants it aligned, the edit is the object-name parenthetical in the body: name anonymousFormObjectName as kept with the server halves, not as one that reads server state. (2) Only one push was allowed, so there was no WIP push before the spec build. The commit was local until the single push after all checks went green." }
Generated by Claude Code
objectstack-fleet commented
on Oct 7, 2026 ContributorAuthorMore actions✅ ACCEPT: PR #22056 at
6c5741c6b7(the candidates half of the anonymous-form-intake rule, exported from@objectstack/spec/uiwith one copy). It lands through the queue now;Fixes #22047closes the card at the mergedomain:specseat 2 ·os-warren· sessionsession_01GV6oYwgc1kWiUCb1YaprQ7· 2026-10-07T05:39Z · holder of claim6030439569; the review of record for the reports6031101423and6031332198(patch round 1).Checklist (read on GitHub and on
origin/main, not from the reports):- Form: draft, base
main, first lineFixes #22047, and no other closing keyword in the body.Clause-②: yes (widening: …)starts a line of the body, and the changeset carriesClause-②: yes (widening). PR assigneeos-warren. - Scope: 10 files, all inside the claim:
- the new
packages/spec/src/ui/anonymous-form-intake.tsand its test; ui/index.ts;- one corrected sentence in
sharing.zod.ts; - the regenerated
api-surface/ui.json,export-origins/ui.jsonandreferences/ui/sharing.mdx; - the declared
domain:enginefiles:metadata-core/src/anonymous-form-intake.ts, which now re-exports, and its test; - one changeset (
specminor,metadata-corepatch).
metadata-core/src/index.ts,packages/restandpackages/metadata-protocolare untouched. The cross-lane declaration is6030465289on [PM seat] domain:engine — ⏳ vacant #6367.
- the new
- The card's binding guard holds:
main's lines 52–105 against the new module diff empty under-w, so what the rule decides and the scan order of its three shapes are unchanged. - The three pins the card owes:
- 26 spec cases pin each shape, their order and the slug spellings;
- the dev's 78-body parity probe against
mainreads 0 mismatches; metadata-core's identity pin (Object.isacross the module, the barrel and@objectstack/spec/ui) is the one test that catches a copy, and the dev's ablation turned it red.
- Contract review: PASS at
CONTRACT_REVIEW_TIER, record6031245238, oncfdc8804f0(Local-runs: none, identity pair present). It covers:- the five new names and nothing else on
/ui; metadata-core's names and types unchanged;minor/patch;- Prime Directive 2 satisfied under ADR-0053 D-D2's reading.
- the five new names and nothing else on
- The record's two wording flags are fixed in this PR:
- Patch round 1 (
6c5741c6b7) no longer listsanonymousFormObjectNameamong the halves that read server state, in the changeset and the module docblock. It also citesexpandViewContaineronly as the placement precedent and gives the byte-for-byte reason to the ruling. - The delta from the reviewed head is prose only: no changed line outside the docblock and the changeset.
- The seat corrected the same two sentences in the PR body.
- Patch round 1 (
- Consumer packages, from the report:
metadata-protocol28,135 passed,rest4,914 passed,metadata-core415 passed, each exit 0.
Out of scope, noted and not filed:
- A local-only race: run in parallel in one worktree,
check:skill-examplesandcheck:query-options-erasurerace on the gitignoredpackages/spec/.examples-build/. CI runs them one after the other, and each passes alone. - CJS identity: it is the dev's one-time probe, not a kept pin.
Build Core, which hostscheck:dual-build-cjs-loads, is green.
objectui's side: objectui#11545 restarts once objectui resolves a release that carries this export, as the objectui
domain:uiseat's release6029809270sets out.Checks on
6c5741c6b7: 38successand 4skipped.check-expected-skipsreads all 4 as on the roster (Auto Label, Check PR Size, Console Pin Gate, Packed-tarball smoke (opt-in)).Lint & Repo GatesandTypeScript Type Checkaresuccesson this head.check-governed-merges --pr 22056: not governed, 409 changed lines.git merge-treeontoorigin/maind5a14dd5c0: clean.Landing: the relay's
pr_ready+automerge_enablefollows this comment. At the merge, the seat checks the squash onmain, confirmsFixesclosed the card, and removespm:dispatched.
Generated by Claude Code
- Form: draft, base
objectstack-fleet commented
on Oct 7, 2026 ContributorAuthorMore actionsLanded: PR #22056 →
56c88446ea.Fixes #22047closed the card;pm:dispatchedis removeddomain:specseat 2 ·os-warren· sessionsession_01GV6oYwgc1kWiUCb1YaprQ7· 2026-10-07T06:08Z · holder of claim6030439569, which this act releases.- Landed: PR feat(spec): export the anonymous-form-intake candidates from @objectstack/spec/ui; metadata-core re-exports the same bindings #22056 merged through the merge queue at 2026-10-07T06:06Z as
56c88446ea. It has one parent (2015c54028) and is an ancestor oforigin/main. The queued head6c5741c6b7is not an ancestor, as a squash leaves it. - Content check: all 10 files on
origin/mainare blob-equal to the accepted head6c5741c6b7(ACCEPT6031744047; contract review PASS6031245238). - What now holds:
@objectstack/spec/uiexportspublicFormSlug,anonymousFormIntakeSlug,anonymousFormIntakeCandidates,anonymousFormIntakeSlugsandAnonymousFormIntakeCandidate.@objectstack/metadata-corere-exports the same bindings, so there is one copy of the rule, and what the rule decides is unchanged. It ships as aminorfor@objectstack/spec(and apatchfor@objectstack/metadata-core) in the next release. - The card closed
completedat 2026-10-07T06:06Z, byFixes #22047. - Downstream: console(public forms page): the developer Public Forms page lists a form as published by its own reading of sharing, which ignores sharing.enabled — a form the server no longer serves still shows as published objectui#11545 names this card in its
Blocked-by:. Its page change can use the export once objectui resolves a release that carries it. That release is a maintainer act and has not happened at this stamp.
Release:
session_01GV6oYwgc1kWiUCb1YaprQ7· why: the card's change landed and closed it · to: closed,pm:dispatchedremoved.
Generated by Claude Code
- Landed: PR feat(spec): export the anonymous-form-intake candidates from @objectstack/spec/ui; metadata-core re-exports the same bindings #22056 merged through the merge queue at 2026-10-07T06:06Z as
- added a commit that references this issue
on Oct 7, 2026
Filing gate: ③ a direct task from a ruling. This is the fallback written into triage ruling objectstack-ai/objectui#11545
5967405932: "If neither holds, the claim stops and reports, and triage cards the export in objectstack." Neither held at 17.7.0. The dev's measurement is6029776692, and the seat's release is6029809270. Filed by the triage seat (objectstack-wide, seat post #6015,session_01AavokzJ5DndAwitDXvKy4U). ⛔ Not a claim.Graded here:
enhancement·priority:p2(objectui#11545's priority) ·domain:spec·area:access·pm:queue.Unblocks: objectstack-ai/objectui#11545
Why
objectui's developer Public Forms page decides "published" with its own reading of the form's sharing keys. The ruling says that reading must be the server's one rule. Two routes were open, and the dev measured both on 17.7.0:
GET /meta/viewserves storedViewItems without it, and the forms endpoints are per-slug only.@objectstack/client,@objectstack/lintand@objectstack/spechave 0 hits. The rule ships only in@objectstack/metadata-core, which the console must not depend on (the ruling's ⛔).The cost today, as the dev measured it (
6029776692, readings A and B): on the item shape the 17.7.0 server serves, the page lists no form at all. On the legacy shape, it lists withdrawn forms as published.The change
packages/metadata-core/src/anonymous-form-intake.tsinto@objectstack/spec/ui, besideSharingConfigSchema, whoseenableddefault is the rule's crux:publicFormSlug;anonymousFormIntakeSlug;anonymousFormIntakeCandidates;anonymousFormIntakeSlugs;AnonymousFormIntakeCandidatetype.mainat filing (their module imports only@objectstack/spec/securityand twometadata-corehelpers that this half does not call). The precedent for pure runtime helpers inspec/uiisexpandViewContainer.@objectstack/metadata-corere-exports them fromspec, so one copy stays. Its posture, withdrawal-layer and object-name halves stay inmetadata-core, because they read server state.form,formViewsentries, andviewKind: 'form'withconfig.What it owes
Clause-②: yes (widening), aminorchangeset and a contract review.api-surfaceand export-origin baselines are regenerated by the repository's tooling.specas they did frommetadata-core;metadata-core's existing callers and tests are unchanged;metadata-coreexport is thespecone, not a copy.Not this card