Repository navigation
Commit f53f14b
Part of #22605
Clause-②: no
The spec half of #22605: `ListView.userActions.editInline` defaults to
`true` on the v18 line, and `userActions: { editInline: false }` is the
opt-out. The `skills/**` paragraph the card also asks for is a separate
pull request (Tier H), so this one is `Part of`, not `Fixes`.
## The ruling
Maintainer, 2026-10-10, verbatim (filed by the director seat on the
card): 「乙 v18 把 spec 默认翻成 true,editInline: false 变成关法。」 A list view is
editable in place by default, under the permission gate that already
exists. The rule of objectui#5144 stands (one vocabulary, the
`inlineEdit` fold, declared = enforced); only the default's value
changes. Not taken: declaring `editInline: true` on every existing view
(objectstack-ai/hotcrm#2048 and #22604 are superseded by the ruling, and
stay open here — this PR does not act on either), and an app-level
default. The permission gate is untouched. The consumer half is
objectui's, objectstack-ai/objectui#12086; in the window the console at
the pinned objectui still reads an absent key as off, so nothing
regresses against today.
## What changed
- `packages/spec/src/ui/view.zod.ts` —
`UserActionsConfigSchema.editInline` is `z.boolean().default(true)`,
`describe` rewritten (on by default; a user who may update the object
edits a cell in place with the field's type-aware widget, under the
permission gate; declare `editInline: false` to make the list read-only
in place). The schema docblock records the ruling beside the
group/hideFields/rowColor asymmetry it already explains.
- `packages/spec/scripts/lib/default-changes.ts` —
`DEFAULT_CHANGES_BY_MAJOR[17]` gains `ui/UserActionsConfig:editInline`
`false` → `true` with its reason. This is what lets
`check:authorable-surface` accept the moved fingerprint; `CURRENT_MAJOR`
is the package major (17) until the version pass takes the group to 18.
The build printed `📌 1 declared default change(s) accepted (#4666):
ui/UserActionsConfig:editInline: false → true`.
-
`packages/spec/src/migrations/entries/semantic/18.list-view-edit-inline-default-on.ts`
— the D3 semantic entry (protocol 18), concatenated into `registry.ts`
by `gen:migration-registry`.
- `packages/spec/authorable-defaults/ui.json` — regenerated by the
build: `ui/UserActionsConfig:editInline = true`.
- `content/docs/references/ui/view.mdx` (3 rows),
`content/docs/references/ui/page.mdx` (1 row) — regenerated by
`gen:docs`: `optional (default: true)` with the new describe.
- `.changeset/22605-spec-list-view-edit-inline-default-on.md` —
`@objectstack/spec: minor`, `Clause-②: no` (a moved default changes no
accept set; the breaking signal is the banner and the ADR-0087 marker),
the launch-window BREAKING banner naming the author who relied on the
documented default for a read-only list and the remedy `editInline:
false`, the FROM → TO table, the measured reach, and the ADR-0087 marker
`registered list-view-edit-inline-default-on`. `minor` because the
launch-window convention ships a breaking change as `minor`
(`check-changeset-no-major`), and the fixed group already carries the
pending `major` that opens the v18 line, so the level moves no version
on its own.
- `packages/spec/src/ui/view.test.ts` — the defaults pin flips to
`true`, plus four pins: an absent key parses to `true` (on
`UserActionsConfigSchema` and through `ListViewSchema`), an explicit
`false` stays `false`, an explicit `true` stays `true`, and the
view-level `inlineEdit: true` still parses as before with no
`userActions` block materialised (the fold is the renderer's; the spec
keeps both spellings as declared).
## Measured first (the PM's mechanism assumptions)
1. **Other sites stating the old default.** `view.zod.ts:1535` read
`.default(false)` with the "Off by default" describe — corrected. The
four reference rows regenerate. Nothing else in the tree states the old
default: `content/docs/ui/views.mdx` lists the view-level `inlineEdit`
with no default; `content/docs/protocol/objectui/layout-dsl.mdx:667` is
about `record:details`' own `inlineEdit` (a different key, renderer
default on); `packages/spec/src/data/object.zod.ts` retired-key guidance
says only that `editInline` is a view key;
`object-strictness-batch20.test.ts` lists key names. Left as they are,
with reasons: `.changeset/console-20c6d351ad74.md` describes the console
at pin `20c6d351ad74`, which still reads an absent key as off until
objectui#12086 lands and the pin moves (true of that build);
`CHANGELOG.md:1677` and `packages/spec/CHANGELOG.md` are release-owned
history.
2. **ADR-0087 disposition.** `check:adr-0087-registration` demands a
marker on a declared-breaking changeset; `not-required
(no-migration-prescription)` is refused when the body carries a
prescription, and this one prescribes `editInline: false`. The honest
disposition is `registered`: a D3 semantic entry at step 18, the same
class as `view-pagination-page-size-default-50` and protocol 12's
`rest-requireauth-default-flip`. No key is removed (no tombstone, no
`RETIRED_KEYS_BY_MAJOR` row) and no D2 conversion exists — a mechanical
pass writing `editInline: false` into every silent view would preserve
the old posture and defeat the ruling. The registry regenerated
byte-exact after merging `origin/main` (which brought the sibling entry
`page-slots-details-beside-tabs-refused`, not adjacent in id order;
`check:migration-registry` green). A second ledger also applies: the
authorable-defaults ratchet refuses an undeclared default move, so
`DEFAULT_CHANGES_BY_MAJOR` carries the hop.
3. **Reach of the remedy**, at `e11ef3a7bd` (`git grep`, tests and
changelogs excluded): 0 `editInline: false` and 0 `editInline: true`
across `examples/**` and `packages/**` metadata. Views that declare
nothing and now gain the toggle: 38 list-kind views with an explicit
`type` across 10 example `*.view.ts` files (entries with no `type` are
grid by default and count the same way), 12 `interfaceConfig` page lists
across 5 showcase page files (11 declare a `userActions` block, none
naming `editInline`), 105 list-kind views across 40 platform
`*.object.ts` files in `packages/**`. One view declares the view-level
`inlineEdit: true` (the showcase `task` grid saved view) and keeps
opening in edit mode. The only test that asserted the old default is
`view.test.ts` (`expect(config.editInline).toBe(false)`), flipped here;
no other package's tests read the view-level `userActions` default
(consumer tests on `userActions` are the object-level CRUD block). The
card's readings outside this repository (cloud `sys-package.page.ts:105`
declares `editInline: false`; HotCRM's 41 undeclared views) were not
re-measured here.
4. **The skill file** `skills/objectstack-ui/rules/list-views.md` is
hand-written: the only generated lifts inside `skills/**` are
`references/_index.md` and `references/react-blocks.md`
(`GENERATED_SURFACE_EXCEPTIONS`). Its paragraph is PR 2.
## Tests (post-merge head `24d9bdcbf0`, shared-box readings under the
verify lock)
- `pnpm --filter @objectstack/spec build` — green; `check:generated` —
`✓ All 15 generated artifacts are up to date`.
- `pnpm --filter @objectstack/spec exec vitest run --project local
--maxWorkers=2` (the package's `test` script) — `Test Files 642 passed
(642) · Tests 19150 passed | 1 todo (19151)`.
- Targeted, before and after the merge: `src/ui/view.test.ts
src/ui/page.test.ts src/migrations/migrations.test.ts
src/migrations/semantic-relevance.test.ts` — `4 passed · 740 passed`;
the `repo`-project files `scripts/step18-rationale-merge.test.ts
scripts/authorable-defaults.test.ts
scripts/build-schemas-check-mode.test.ts` — `4 passed · 146 passed`
(with `semantic-relevance`).
- `pnpm --filter @objectstack/spec typecheck` — `tsc --noEmit`,
`check:scripts-typecheck` and `check:test-typecheck` green (`52 file(s)
/ 246 error(s) / 135 pinned signature(s) held`, the shrink-only debt
ledger unchanged).
- `test:repo` beyond those three files is declared to CI (Test Core).
## Ablation (reverse verification)
`node scripts/ablation-replace.mjs --file
packages/spec/src/ui/view.zod.ts --anchor 'editInline:
z.boolean().default(true)' --replacement 'editInline:
z.boolean().default(false)' -- pnpm --filter @objectstack/spec exec
vitest run --project local --maxWorkers=2 src/ui/view.test.ts`, at head
`24d9bdcbf0`, after the fix was committed. Mutation proved on disk:
anchor 1 → 0, replacement 0 → 1, blob `6979ade6158a` → `e0e02cd7f858`.
Direction observed: red, exactly the two default pins — `should apply
default values` and `an absent key parses to true` (`expected false to
be true`), `2 failed | 462 passed (464)`. Restore proved: blob after
restore `6979ade6158a` == blob at HEAD, `git diff HEAD` empty, tree
clean. Resolution path: the pin imports the schema from the package's
own `src` (no `dist` in the path), so no rebuild sits between the
mutation and the reading.
## Gates (local, at `24d9bdcbf0`)
Derived with `node scripts/pm/dispatch-gates.mjs --commands --repo
objectstack-ai/objectstack` (no paths; the tool reads the change set off
the merge base): 115 families. Reconciled with `--ran`: 115 derived, 114
run, 0 NOT-MEASURED, 1 UNRUN — the UNRUN is `pnpm
check:dual-build-cjs-loads`, declared NOT MEASURED by the dispatch (it
needs a whole-workspace build). Every other derived family exited 0,
after building the prerequisites some of them load
(`@objectstack/formula`, `lint`, `client`, `client-react`, `objectql`),
except `pnpm check:dts-closure`, which exited 1 for a missing `dist/`
under `plugin-approvals` and `plugin-dev`: it reads every package's
built declarations, so without the whole-workspace build it is NOT
MEASURED, not red (CI's Build Core covers it). The artifact-roster block
(49 families): 46 run, every one exit 0 except `pnpm
check:published-readme-exports`, exit 3 (44 unbuilt packages, NOT
MEASURED for the same reason); the three PR-context guards
(`check-closing-target-claim`, `check-partof-closing-keyword`,
`check-single-claim-paths`) run once this PR has a number, and their
readings go in the report comment on the card. Staleness note the tool
prints: the derivation tree is two commits behind `origin/main`
`83b8b80728`, and the one derivation input that moved is
`scripts/platform-object-tenancy-census.json` (the tenancy-census
roster); that family ran green on the older copy, and no path of this
diff overlaps those two commits.
Lint, as a proven narrowing rather than the CI-owned `pnpm lint`: `pnpm
exec eslint --no-inline-config --format json` over the `.ts`/`.mjs`
files in the two-point diff — 24 files linted, 0 errors, 0 warnings (the
count is from the JSON output; the set is wider than this PR's own 9
files (233 insertions, 7 deletions off the merge base `e22315238f`)
because the two-point diff includes the merged sibling commits).
Population, read from `eslint.config.mjs`:
`**/*.{ts,tsx,mts,cts,js,jsx,mjs,cjs}` minus its `ignores`, so the
`.md`, `.mdx` and `.json` files of this diff are outside it (eslint
reports them "ignored because no matching configuration"). Invariance:
the config declares no `parserOptions.project` and no typed
`@typescript-eslint` rules, so this diff cannot move the verdict of any
file it does not touch.
## Acceptance notes
- `packages/spec/spec-changes.json` and `docs/protocol-upgrade-guide.md`
are not regenerated here. Since #22449 B′ the PR-stage
`check:spec-changes` and `check:upgrade-guide` project the registry in
memory and compare no committed copy (the publish lane generates the
shipped one), and `origin/main` turned the upgrade guide into a pointer
stub while this branch was open; a regeneration on the pre-merge tree
carried 30-odd lines of sibling drift this diff does not own, so it was
reverted. The entries README still says to regenerate both; the
generator header is the newer authority. Noted, not filed.
- The objectui consumer half (`editInline !== false` in `ListView.tsx`
and `InterfaceListPage.tsx`, the `plugin-view.mdx` row, the flipped
pins) is objectstack-ai/objectui#12086, filed by the claiming seat;
nothing in objectui moves here.
---
_Generated by [Claude
Code](https://claude.ai/code/session_01KNKBCRDJCu5tGy3TEbvtrF)_
---------
Co-authored-by: Claude <noreply@anthropic.com>
1 parent 86da194 commit f53f14b
9 files changed
Lines changed: 241 additions & 7 deletions
File tree
- .changeset
- content/docs/references/ui
- packages/spec
- authorable-defaults
- scripts/lib
- src
- migrations
- entries/semantic
- ui
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
145 | 145 | | |
146 | 146 | | |
147 | 147 | | |
148 | | - | |
| 148 | + | |
149 | 149 | | |
150 | 150 | | |
151 | 151 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
1081 | 1081 | | |
1082 | 1082 | | |
1083 | 1083 | | |
1084 | | - | |
| 1084 | + | |
1085 | 1085 | | |
1086 | 1086 | | |
1087 | 1087 | | |
| |||
1464 | 1464 | | |
1465 | 1465 | | |
1466 | 1466 | | |
1467 | | - | |
| 1467 | + | |
1468 | 1468 | | |
1469 | 1469 | | |
1470 | 1470 | | |
| |||
1635 | 1635 | | |
1636 | 1636 | | |
1637 | 1637 | | |
1638 | | - | |
| 1638 | + | |
1639 | 1639 | | |
1640 | 1640 | | |
1641 | 1641 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
107 | 107 | | |
108 | 108 | | |
109 | 109 | | |
110 | | - | |
| 110 | + | |
111 | 111 | | |
112 | 112 | | |
113 | 113 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
554 | 554 | | |
555 | 555 | | |
556 | 556 | | |
| 557 | + | |
| 558 | + | |
| 559 | + | |
| 560 | + | |
| 561 | + | |
| 562 | + | |
| 563 | + | |
| 564 | + | |
| 565 | + | |
| 566 | + | |
| 567 | + | |
| 568 | + | |
| 569 | + | |
| 570 | + | |
| 571 | + | |
| 572 | + | |
| 573 | + | |
| 574 | + | |
| 575 | + | |
| 576 | + | |
| 577 | + | |
| 578 | + | |
| 579 | + | |
| 580 | + | |
557 | 581 | | |
558 | 582 | | |
559 | 583 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
| 41 | + | |
| 42 | + | |
| 43 | + | |
| 44 | + | |
| 45 | + | |
| 46 | + | |
| 47 | + | |
| 48 | + | |
| 49 | + | |
| 50 | + | |
| 51 | + | |
| 52 | + | |
| 53 | + | |
| 54 | + | |
| 55 | + | |
| 56 | + | |
0 commit comments