Skip to content

feat(spec): declare editMode?: 'modal' | 'page' on the object document - #12208

Merged
os-litant merged 3 commits into
mainfrom
claude/issue-11408-editmode-declare
Aug 25, 2026
Merged

feat(spec): declare editMode?: 'modal' | 'page' on the object document#12208
os-litant merged 3 commits into
mainfrom
claude/issue-11408-editmode-declare

Conversation

@os-litant

Copy link
Copy Markdown
Collaborator

Fixes#11408

What

Declares editMode?: 'modal' | 'page' as an optional authored key on the spec's object document, per the maintainer ruling recorded on the issue (2026-08-24, declare — the #10144 declare-or-rule-out family; ruling comment quotes 「接受你的建议。」 on the aligned four-facet analysis).

  • packages/spec/src/data/object.zod.ts: the key joins the Display & UI Hints block beside nameField / highlightFields / stageField. TSDoc + .describe() state the cross-renderer semantics ('modal' = edit form as a dialog over the current view; 'page' = dedicated full-page edit route), the absent-key behaviour (renderer picks its own default; objectui defaults to modal), and the objectui read points (recordFormNavigation.ts branches on editMode !== 'page'; AppContent's handleEdit dispatcher routes on it).
  • Liveness ledger: packages/spec/liveness/object.json classifies object/editMode as live (objectui runtime read, prose evidence per the ledger's convention for renderer-side readers); state-counts.md regenerated.
  • Generated artifacts, regenerated only where check:generated proved them stale: authorable-surface/data.json (+data/Object:editMode) and content/docs/references/data/object.mdx (new row in the object reference table).
  • Changeset: minor for @objectstack/spec (accept-set widening; nothing removed, no existing document changes meaning). check-adr-0087-registration verdict: "this PR adds no declared-breaking changeset (1 non-breaking changeset(s) seen)" — no ADR-0087 entry required, matching the dispatch's expectation for a pure widening.

Before / after (both measured on the freshly built dist, not src)

  • Before (base 577fabf): ObjectSchema.safeParse({ name, fields, editMode: 'page' })success: false, issues[0] = { code: 'unrecognized_keys', keys: ['editMode'], path: [] }; positive control without the key parses green. (Matches the issue's measurement on published spec 17.2.0.)
  • After (this branch): 'modal' and 'page' accepted and carried on the parsed output; absent accepted; editMode: 'drawer' rejected as { code: 'invalid_value', values: ['modal','page'], path: ['editMode'] } — the failure moved from key-level unrecognized_keys to a located value error, proving the key is recognised and its value contract enforced.

Tests

Four new tests in packages/spec/src/data/object.test.ts (ObjectSchema editMode (#11408 ...) describe block): both enum values accepted end-to-end (full parse green, not merely "no unrecognized_keys"); optionality; out-of-enum values ('drawer', 'inline', true, 3) each fail with a non-unrecognized_keys issue at path ['editMode']; the authoring path (create()) accepts it. Full @objectstack/spec suite green — see the union run cited below.

Scope

  • Spec-side adoption only. objectui's ObjectSchemaClientExtensions.editMode member retires in a follow-up the accepting seat files in objectui, release-gated on the @objectstack/spec release containing this change (per the recorded ruling) — its pinned rejection tests flip by design there. This PR touches no objectui code and no pins on sibling behaviour.
  • No *.form.ts files change — titleFormat precedent: object-level display keys carry no authoring-form row; also keeps this batch disjoint from the spec: minLength still has the pre-#11566 defect pair — validated as no more than a number, authorable on every field type #11949 form-row work.
  • Clause-②: yes (widens the accept set) — contract-review tier; this PR stays draft for the PM's review chain.

Verification at the final head

Union re-run at the final commit (git rev-parse --short HEAD = b7be080): spec build + check:generated "All 14 generated artifacts are up to date" (includes check:authorable-surface, check:api-surface, check:docs, check:liveness, check:strictness-ledger — the ratchet families) · full @objectstack/spec vitest suite (426 files / 11352 tests passed) · @objectstack/spec typecheck · and the per-card gate list below, every one exit 0 with exits captured before any pipe:

check:merge-driver · check:published-files · check:slot-lookup · check:spec-parsed-alias · check:test-source-alias · check:type-source-resolution · check-adr-0087-registration · check-changeset-no-major · check-empty-changeset · check:nul-bytes · check:changeset-gate-self-tests · check:objectui-changeset · check-ci-filter-parity · check:cross-package-test-inputs · check-plugin-teardown-shape · docs-audit check-affected-docs + check-drift-comment · release-rehearsal-clone --self-test · spec check:empty-state / check:strictness-ledger / check:variant-docs · lint check:doc-formula-expressions · check:query-options-erasure · check:type-check-coverage · check:engine-double-contract · check:where-matcher

Declared local narrowings (CI runs the full farm regardless):

  • check-dev-prereqs — red locally only on its workspace-built precondition: 66 of 67 packages have no dist/ in this fresh worktree. Not a diff finding; the one diff-coupled row (packages/spec/dist freshness, content-hashed) is green — spec was rebuilt at the final head with its .build-input-hash written.
  • check:type-check-debt --re-measure — refuses on an unbuilt workspace closure (its own doc: the throw means NOT MEASURED). Spec-scoped equivalents ran green at head: @objectstack/spec typecheck, and check:test-typecheck --package packages/spec "OK — test layer compiles; 55 file(s) / 263 error(s) held" (ledger unchanged). My diff touches only packages/spec + .changeset + generated docs, so no other ledger entry's tsc program gains an input from this diff.

Generated by Claude Code

#11408)
Maintainer ruling 2026-08-24 (declare — #10144 declare-or-rule-out family):
objectui's shipped runtime reads objectDef.editMode for record-edit routing
while the spec's strict parse rejected the key with unrecognized_keys. The
object document now declares it beside the other display hints; values
outside the enum fail as a located value error at editMode. Accept-set
widening; consumer-side retirement of ObjectSchemaClientExtensions.editMode
is a release-gated objectui follow-up per the recorded ruling.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NDGG54XF5gbTLdQzCtnaVV
@github-actions

github-actionsBot commented Aug 25, 2026

Copy link
Copy Markdown
Contributor

📓 Docs Drift Check

This PR changes 1 package(s): @objectstack/spec, touching 2 documentable anchor(s). ⚠️3 changed file(s) yielded no anchor (packages/spec/authorable-surface/data.json, packages/spec/liveness/object.json, packages/spec/liveness/state-counts.md), so the pages documenting them are NOT COVERED by this run — this is not a clean bill of health for those files.

1 hand-written doc(s) NAME something this change touched and may need an implementation-accuracy re-verification:

  • content/docs/concepts/metadata-driven.mdx(via ObjectSchemaBase (symbol))
What this run could not see
  • 3 changed file(s) yielded no anchor (packages/spec/authorable-surface/data.json, packages/spec/liveness/object.json, packages/spec/liveness/state-counts.md) — pages documenting those are invisible to this run
  • the SDK route bridge reached 45 of 222 client-bound route-ledger rows — the other 177 have no registrar path: tail to select them, so pages documenting THEIR client methods cannot appear above, on this or any run: node scripts/docs-audit/affected-docs.mjs --bridge-coverage
  • a page that states a rule by its inputs shares no identifier with the emitter that implements the rule, so an emitter-only diff cannot list it — not on this run and not on any run. Measured on fix(driver-sql): emit varchar(maxLength) for a text field a declared index keys on #11430: content/docs/protocol/objectql/types.mdx documents the text-family column mapping by the ObjectQL type names it maps FROM (text / textarea / html) while the diff changed createColumn; it went unlisted, and it was the page that diff falsified, in four places. No shared token exists to detect this on, so a rule your change carries has to be re-read by hand in the pages that restate it.

Coarse fallback — 126 page(s) merely mention a changed package (the pre-#9192 predicate, kept for the deliberately-wide backstop): node scripts/docs-audit/affected-docs.mjs --json 494279cb31f1d92adab959763085e19c923a8652packageMentionDocs.

Which tree this was computed on

This run read content/docs from 5e531b0adb7d51a64a4282c4712081f66743856c — the merge of head 08da3eb5c33461ee942b8b8d6613d3fb90fd9718 into base 494279cb31f1d92adab959763085e19c923a8652, which is what actions/checkout gives a pull_request run. Not the PR head.

A worktree cut from an older main holds a different content/docs, so re-deriving there can legitimately return a different list — that is a different tree, not a wrong row. To answer on the same tree:

# while this PR is open — GitHub drops the merge commit once it closes
git fetch origin 5e531b0adb7d51a64a4282c4712081f66743856c && git checkout 5e531b0adb7d51a64a4282c4712081f66743856c
# afterwards, rebuild it from the two parents, which stay fetchable
git fetch origin 494279cb31f1d92adab959763085e19c923a8652 08da3eb5c33461ee942b8b8d6613d3fb90fd9718 && git checkout -B drift-repro 494279cb31f1d92adab959763085e19c923a8652 && git merge --no-ff 08da3eb5c33461ee942b8b8d6613d3fb90fd9718
node scripts/docs-audit/affected-docs.mjs --json 494279cb31f1d92adab959763085e19c923a8652

⚠️ That checkout carried uncommitted changes, so the commit above does not fully identify what was read.

Advisory only, and a precision-first one (#9192): a page is listed because it names a
symbol, wire route or SDK method this diff touched — not because it mentions a changed
package. Each row says which anchor put it there, so a wrong row is reportable rather than
merely annoying. To re-verify, run the docs-accuracy-audit workflow scoped to these files:
node scripts/docs-audit/affected-docs.mjs 494279cb31f1d92adab959763085e19c923a8652 → pass the list as
args.docs, on the commit named under Which tree this was computed on.

@os-litant
os-litant marked this pull request as ready for review August 25, 2026 13:48
@os-litant
os-litant added this pull request to the merge queueAug 25, 2026
Merged via the queue into main with commit f11fc61Aug 25, 2026
35 checks passed
@os-litant
os-litant deleted the claude/issue-11408-editmode-declare branch August 25, 2026 14:32
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentationImprovements or additions to documentationprotocol:datasize/steststooling

Projects

None yet

Development

Successfully merging this pull request may close these issues.

spec: editMode is read off the object document by objectui's runtime but the strict parse rejects it — declare or rule out

2 participants

@os-litant@claude