Skip to content

views: declare userActions.editInline: true on every grid and list view, so cell editing survives the objectui upgrade (objectstack-ai/objectui#5144) #2048

Description

@objectstack-fleet

Filing gate: a platform behaviour change that reaches this app's metadata. Filed by the objectstack director seat (summon #35, seat post objectstack-ai/objectstack#12708, session_01VYToj6PQehTEKNrjGM9akg) on the maintainer's instruction in that session, verbatim: 「只需要处理已经交代的 userActions.editInline: true」. ⛔ Not a claim, ⛔ not a dispatch; the hotcrm lane claims and lands it.

What changed on the platform

  • @objectstack/spec declares ListView.userActions.editInline with .default(false) since 17.0: "Off by default: the list is read-only unless the author opts in" (packages/spec/src/ui/view.zod.ts:1535).
  • objectui read an absent key as "offer the toggle" until objectui#5144 (the maintainer's 2026-08-18 ruling, the B-fold). PR fix(plugin-list): read userActions.editInline with the spec default, folding a stored inlineEdit into it (objectui#5144) objectui#12036 (merged 2026-10-09) reads the key with the spec default: a grid view that declares neither userActions.editInline nor inlineEdit offers no inline-edit toggle and never opens in edit mode. The console's toggle is session-only now and writes nothing into the view.
  • The permission gate is unchanged and still applies on top: the toggle is offered only when the object is editable in place (ADR-0103 bucket, userActions.edit, the server's effective API operations) and the current principal can update the object (packages/plugin-list/src/ListView.tsx:2007).

Measured in this repo (main f0afcbd, 2026-10-09)

  • 40 type: 'grid' views and 1 type: 'list' view across 14 *.view.ts files under src/*/views/ (marketing, revenue, sales, service).
  • 0 of them declare userActions.editInline or inlineEdit. Only src/sales/pages/account_workbench.page.ts:62 carries a userActions block at all.
  • So after the objectui upgrade, every HotCRM table loses cell editing. Users can still open the record form and edit there.

What to do

  • Each grid and list view of a business object declares userActions: { editInline: true } (the spec key; inlineEdit: true would also fold into it, but the spec key is the one to write). Expected: all 41, one block per view.
  • A view whose records are read-only by nature (a forecast roll-up, a published knowledge-article list, an audit or history list) may be left without the key, with a one-line comment above the view stating why cell editing is not offered. The default is to declare it; the exception carries the reason.
  • The decision stays the author's per view, as the spec and objectui#5144 model it. ⛔ No wrapper or helper that injects the key behind the view files: the view file is the metadata of record, and the showcase demonstrates the written form.

Acceptance

  • Every type: 'grid' and type: 'list' view in src/** either declares userActions.editInline: true or carries the recorded reason.
  • A test lists the grid and list views of the app and checks each against that rule, so a new view without the key fails here and not in a customer's console.
  • Measured in the console against objectui main at or after 1b2d0160fe: the inline-edit toggle is offered on a declared view for a user with update on the object, and absent for a user without it.

Related


Filed by the director seat; generated by Claude Code

Activity

  1. added
    pm:queueReady for the PM dispatch loop
    pm:dispatchedDispatched to a dev agent by /pm-dispatch
    and removed
    pm:queueReady for the PM dispatch loop
    on Oct 10, 2026
  2. objectstack-fleet commented on Oct 10, 2026

    @objectstack-fleet
    ContributorAuthor

    Claim: PM loop round R77
    Session: session_012zh91QzFgePbkmuHnugLN3
    Account: os-zhuang (the seat's linked user as GET /user answers it; always the card's assignee)
    Branch: claude/issue-2048-views-edit-inline
    Worktree: hotcrm-issue-2048
    Domain: repo:hotcrm (single-lane repo, no domain:* taxonomy)
    Seat: repo:hotcrm#1
    File surface: the 14 src/*/views/*.view.ts files (one userActions: { editInline: true } per grid / list view, or the one-line reason above a view left read-only); one new test under test/ that walks every grid and list view; one .changeset/2048-*.md. ⛔ No helper or wrapper that injects the key (stop on breach; explain in the report)
    Container & model: M, mode:subagent (the os-dev definition and the scripts/pm write tools live in this container's objectstack checkout), model: default (dispatch-gates --tier --repo objectstack-ai/hotcrm answers "the tier stays the PM's per-card judgment call"; governedPathsIn over the surface: none)
    Clause-②: no
    Responsibility: the app's 41 grid / list views (none declares userActions.editInline) | the platform changed its reading of an absent key to the spec default false (objectui#12036), as ruled in objectui#5144 | every console user editing a cell in a HotCRM table, once the runtime's objectui moves past 1b2d0160fe
    Thread-read: none
    Serial constraints cleared: nothing is in flight. This lands BEFORE the 3.2.0 version PR, which consumes every changeset and so comes last.


    Generated by Claude Code

  3. objectstack-fleet commented on Oct 10, 2026

    @objectstack-fleet
    ContributorAuthor

    os-dev-report
    {
    "issue": 2048,
    "status": "done",
    "branch": "claude/issue-2048-views-edit-inline",
    "pr": "#2050",
    "session": "session_012zh91QzFgePbkmuHnugLN3 (subagent: the parent PM seat's session)",
    "premise_still_valid": true,
    "summary": "Each of the app's 40 grid views now declares userActions: { editInline: true }. There is one block per view, written in its own view file just below its label, using the spec key. No helper or wrapper injects it. No view was left read-only: every object behind a grid view lists update in enable.apiMethods and has fields people write. Forecasts carry hand-entered quota, notes and manual rows. Published articles are not locked. The app has no audit or history list. A new test, test/view-inline-edit.test.ts, walks every list and listViews entry of the composed stack. It fails on a grid or list view that neither declares editInline: true nor appears in the READ_ONLY_BY_NATURE roster (empty today). It also fails on a stale roster entry. Draft PR #2050 is assigned to os-zhuang. Files changed: the 14 src//views/.view.ts files (40 lines added), test/view-inline-edit.test.ts (new), .changeset/2048-views-edit-inline.md (new, hotcrm patch). Deviations and premise detail: (1) The card counted 41 views, 40 grid and 1 list. The composed stack holds 40 grid views and 0 list views. The 41st grep hit is src/sales/pages/account_workbench.page.ts:32, the type: 'list' line of an interface Page, not a view. It is outside the rule and the claim surface and is left untouched (see Acceptance notes). (2) Measured before the fix on f0afcbd: GET /api/v1/meta/view served 40 grid views, and none carried a userActions block. The console this repo pins (@objectstack/console 17.7.0 = objectui 0abd4f9f8769) predates objectui#12036. Its toolbar gate is userActions?.editInline !== false && editable && can(update), so the loss cannot be seen there yet. Measured in Chromium, before and after the fix: on Products, admin is offered Edit inline and na.rep@objectos.ai (crm_product allowEdit false) is not. On Leads, both are offered it. After the fix, all 40 served views carry editInline: true. Each toolbar is identical before and after, even though defineView fills in the other nine userActions defaults, and the toggle starts off. (3) The leg 'against objectui main at or after 1b2d0160fe' is NOT MEASURED, because the objectui repo is out of this session's scope. (4) objectstack dev serves dist/objectstack.json and warned that the artifact was stale, so the post-fix reading was taken after pnpm build. (5) Token ratchet: no scope is over its ceiling and no ceiling moved. src/revenue authored total is ~18,781 of 19,000 (headroom 248 -> 219). src/service authored total is ~21,836 of 22,000 (245 -> 164). (6) The harness attribution reminder names a model in its Co-Authored-By trailer and asks for a different PR footer. Per the dispatch and the os-dev definition, the commit carries the model-free trailers and the PR body ends with the session-URL footer. Not imitated, reported here. (7) The worktree was removed (node_modules first, no --force). No dev server or browser of mine is left running.",
    "tests": "pnpm verify: OS_VERIFY_LOCK_SLOT=hotcrm-2048 bash os-verify-lock.sh -c 'pnpm verify' on d4764b9 -> 'os-verify-lock: VERDICT command-exit 0 · held the lock 459s'. Inside it: validate '✓ Validation passed', typecheck (tsc --noEmit, chain continued), lint '18 suggestion(s)' with 0 errors, '✓ i18n lint gate: 0 i18n/missing-* issues', '✓ source hygiene clean', '✓ source token ratchet clean', '✓ Build complete', test 'Test Files 175 passed (175) · Tests 3622 passed | 1 skipped (3623)'. New test alone: vitest run --maxWorkers=2 test/view-inline-edit.test.ts -> 'Tests 3 passed (3)', VERDICT command-exit 0. Ablations ran on the committed fix (HEAD d4764b9) through objectstack scripts/ablation-replace.mjs in wrap mode on src/revenue/views/product.view.ts. Each mutation landed on disk ('ok mutation landed: anchor 1 -> 0', blob 88cb8f3b6408 -> a06e8bbe87d7 / f465dedfb485 / 8aabdc379151) and was restored ('ok restored: blob == HEAD (88cb8f3b6408) and git diff HEAD is empty'). Results: (a) delete the block -> red, 'expected [ crm_product.all_products ] to deeply equal []', 1 failed | 2 passed, VERDICT command-exit 1. (b) editInline: false -> red, 1 failed | 2 passed. (c) legacy inlineEdit: true instead of the block -> red, 1 failed | 2 passed. No rebuild was needed: the test imports TS source through test/helpers/composed-stack.ts (objectstack.composition.ts), with no dist on the path. pnpm changeset status --since=origin/main -> exit 0, 'hotcrm patch'. Public door: GET /api/v1/meta/view on a dev boot at port 4936 -> before (f0afcbd) 40 grid views, 0 with userActions; after (d4764b9, rebuilt) 40/40 with editInline true. Chromium (/opt/pw-browsers/chromium) data-testid toolbar-inline-edit-toggle count, before -> after: admin/crm_product 1 -> 1, na.rep/crm_product 0 -> 0, admin/crm_lead 1 -> 1, na.rep/crm_lead 1 -> 1; all four toolbars identical. NOT MEASURED: console at objectui main >= 1b2d0160fe, reason: the objectui repo is out of session scope. NOT MEASURED locally: pnpm test:e2e, declared to CI. CI on d4764b9 when this report was written: Check Changeset, Quality Checks, link-check, Label Pull Request = success; Build and Test (22.x), Playwright, Analyze Code = in_progress.",
    "mcp_calls": "0",
    "api_writes": "3 REST writes, all through the fleet-write relay as objectstack-fleet[bot]: POST /repos/objectstack-ai/hotcrm/pulls (pr_create, draft, #2050); POST /repos//issues/2050/assignees (os-zhuang, via label-write.mjs, read-back MATCHES); POST /repos//issues/2048/comments (this os-dev-report, via post-stamped.mjs). Each was carried by one POST /repos/objectstack-ai/objectstack/dispatches relay request. Separately, one git push of the branch (the empty probe and then d4764b9), which is not a REST write. No other writes: no claim, no card assignee, no labels added.",
    "open_questions": [],
    "out_of_scope_findings": [
    "carrier: none (承接者:无) · noted, not filed · account_workbench (src/sales/pages/account_workbench.page.ts) is an interface Page with its own interfaceConfig.userActions block and no editInline. The pinned console's InterfaceListPage reads inlineEdit: userActions.editInline === true, so it already offers no cell editing, which matches the page's documented 'deliberately closed' design. This is the card's 41st grep hit, not a view and not a defect. Dedupe words: account_workbench editInline interface page",
    "carrier: none (承接者:无) · noted, not filed · defineView fills in all ten UserActionsConfigSchema defaults once any userActions key is declared, so the served view carries sort/search/filter/refresh/rowHeight/group true and addRecordForm/hideFields/rowColor false. On the pinned console this measured toolbar-identical to an absent block, so it is not a defect. Dedupe words: userActions defaults materialised defineView"
    ]
    }

  4. objectstack-fleet commented on Oct 10, 2026

    @objectstack-fleet
    ContributorAuthor

    Verdict: os-dev report 6095951504, PR #2050 — ACCEPT, Tier S (not governed, +123 / −0): the seat lands it through the merge queue once every check on head d4764b99 is green. repo:hotcrm seat, session_012zh91QzFgePbkmuHnugLN3, 2026-10-10T09:06Z.

    Checked in git, not taken from the report:

    • PR shape: draft, base main; first line Fixes #2048, then Clause-②: no. 16 files:
      • the 14 src/*/views/*.view.ts, each adding only userActions: { editInline: true }, (40 lines across the 14 files, one per grid view, nothing removed);
      • test/view-inline-edit.test.ts (new);
      • a 'hotcrm': patch changeset.
        No helper or wrapper injects the key; it is written in each view file, as the card requires.
    • The count: the composed stack holds 40 grid views and 0 list views. The card's 41st grep hit is the type: 'list' line of the interface page account_workbench, which is not a view and is deliberately closed to cell editing (its own userActions block). Accepted as measured.
    • The test walks every list / listViews entry of the composed stack and fails on a grid or list view that neither declares editInline: true nor sits in READ_ONLY_BY_NATURE (empty: no object behind a grid is read-only by nature). It also fails on a stale roster entry. Ablations on product.view.ts, each restored to HEAD, turned it red: the block removed, editInline: false, the legacy inlineEdit: true.
    • Measured at the door: GET /api/v1/meta/view served 40 grid views with 0 userActions before, and 40 / 40 with editInline: true after. On the pinned console (objectui 0abd4f9f8769, before objectui#12036) the toolbars are identical before and after, and the permission gate holds: na.rep has no Edit inline on Products and has it on Leads.
    • Token ratchet: clean, no ceiling moved. src/revenue ~18,781 / 19,000; src/service ~21,836 / 22,000.
    • pnpm verify green on d4764b99: 3,622 passed, 1 skipped.

    Not measured, accepted: the console against objectui main ≥ 1b2d0160fe. objectui is outside this session's repository scope; the pinned console's toolbar gate and the served metadata are the measured halves.

    Next: #2049 (the 3.2.0 version PR) unblocks on this landing.


    Generated by Claude Code

  5. objectstack-fleet commented on Oct 10, 2026

    @objectstack-fleet
    ContributorAuthor

    Landed: PR #2050 MERGED as 81f86440 on main (squash, single parent f0afcbda). The seat landed it through the merge queue after 9 of 9 checks went green on head d4764b99: ready and queued at 09:15Z, merged 09:15:36Z. repo:hotcrm seat, session_012zh91QzFgePbkmuHnugLN3, 2026-10-10T09:15Z.

    Two readings:

    • the PR object reads merged, merge commit 81f86440;
    • git diff f0afcbda 81f86440 is the reviewed 16 files, +123 / −0.

    Closed as it should be: Fixes #2048 closed this card (completed). No other card was closed by a keyword.

    What now holds: all 40 HotCRM grid views declare userActions: { editInline: true }. Cell editing therefore survives a console at or after objectui#12036, still gated by the user's update permission. A test fails on any new grid view that does not declare it. This ships in 3.2.0 (#2049).

    This act: removes pm:dispatched and the assignee here.


    Generated by Claude Code

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions