Skip to content

feat(app-shell,i18n): Home's My work section — approvals first, then notifications, with the pending-drafts row under its heading (objectui#12602) - #12656

Merged
objectstack-fleet[bot] merged 3 commits into
mainfrom
claude/issue-12602-home-my-work
Oct 16, 2026
Merged

objectstack-fleet[bot] merged 3 commits into
mainfrom
claude/issue-12602-home-my-work

Conversation

@objectstack-fleet

Copy link
Copy Markdown
Contributor

Fixes #12602
Clause-②: yes

Summary

The "Needs your attention" card becomes the My work section of the approved home artboard (section ③ of 系统首页 · 四段式). The pending-drafts banner above the greeting moves into it.

  • Heading. "My work", 15 px / 600, with a count pill: approvals plus unread notification topics, the two numbers the bell badge adds. An "Open inbox" link goes to the inbox route the bell's view-all opens.
  • Drafts row. A 40 px row on the soft primary tint: a rocket icon, "N unpublished change(s)", the first three draft names, and their package when all drafts share one. Its 28 px Publish button calls the same usePublishAllDrafts().publishAll the banner called. The banner is gone from both places it rendered; with no app yet, the row sits where the banner was.
  • Approvals column (first). It lists the approval requests themselves, titled with the flow label and the record name. The pill, on --primary, is the request count from the one shared pending-approvals read the bell and the greeting line use. A row opens the request in the Approvals inbox through its ?request= deep link; View all opens the Approvals inbox.
  • Notifications column. The unread inbox preview, newest first. The pill is the bell's unreadTopicCount. Targets go through resolveNotificationTarget, the bell's own helper.
  • Rows and empty lines. Up to three 40 px rows per column. A column with nothing reads one muted line, and only once its read has answered. A loading or failed read says so, next to any stale rows.

The fork: two columns, not three (Target 5)

sys_inbox_message, as objectstack declares it at f7e836d, has topic (free text), title, severity (info, warning, critical), action_url and created_at. It has no declared kind and no due date. So the section ships Approvals / Notifications, and nothing infers "assigned to me", "reminder" or "overdue" from a topic or a title.

The field the three-column form needs is a declared kind on the notification and inbox row (assignment, mention, reminder, system), written by the emitter, plus a due-date datetime for the overdue line. Acceptance 1's "a notification with a past due date reads 逾期" is therefore not implemented. A test pins the opposite: a row whose topic reads like an assignment lands under Notifications, with no overdue text.

Who sees it

  • Notifications column and Open inbox link: drawn unless the loaded permissions refuse read on sys_inbox_message. Unknown permissions count as readable. This is the predicate the activity card uses for sys_activity.
  • Approvals column: needs a signed-in user. The endpoint answers every signed-in user about their own requests.
  • Whole section: not drawn when neither column is readable and there are no drafts.

Measurements: /home at 1280 px, live showcase backend (published @objectstack packages)

Items Heading total Approvals pill / rows Notifications pill / rows Bell Notes
18 18 3 / 3 15 / 3 9+ Drafts row present: 3 drafts, 40 px. Row height 40 px. Columns 554 px each. Heading 15px/600. Same in light and dark.
2 2 1 / 1 1 / 1 2 Same in light and dark.
0 no pill no pill, "Nothing waiting for your approval" no pill, "No unread notifications" no badge Greeting line: "Nothing is waiting for you today".

Drafts publish, live: with one draft present, a click sent POST /api/v1/meta/object/ticket/publish (200), and the row left the page.

18 light
18 dark
2 light
2 dark
0 light
0 dark

Tests

New pins:

  • HomePage.myWork-12602.test.tsx: the approvals column is first, the two-column form, the drafts row, and who sees the section.
  • useHomeInbox.myWork-12602.test.tsx: approval rows deduped per id with count equal to the list length; the readability predicates.
  • One new case in sharedInboxFeed.twoSurfaces.test.tsx: the approvals column pill equals the bell badge, over the real store and the real bell.

Eight one-time ablations, each red and each restored: count taken from the preview, dedupe removed, approvals column removed, publish made a no-op, drafts row put back above the greeting, hide guard removed, inbox predicate forced true, notice shown only when the column is empty.

Runs:

  • pnpm exec vitest run packages/i18n/ packages/app-shell/src/console/home/ packages/app-shell/src/hooks/ at 9bf4170: 177 files, 2066 tests passed.
  • The whole of packages/app-shell/ and packages/i18n/ at the first commit: 15000 passed, 1 failed. The failure was an i18n pin reading the renamed drafts key, repointed in 9bf4170.

Acceptance 3 names pnpm --filter @object-ui/app-shell test and pnpm check:i18n. The first is the package-cwd form AGENTS.md routes to the repo-root vitest invocation, so these runs use that form. The second does not exist; check:i18n-keys, check:i18n-drift and check:i18n-dead-keys all exit 0.

Acceptance notes

  • useSharedPendingApprovals keeps its shape (count plus status). It now reads a feed that holds the request rows, so the count is still the distinct ids from one request.
  • The count pills show a count above zero even while a re-read is failing, as the bell does. The empty line waits for an answer.
  • The drafts row keeps the banner's gate (a non-zero count from _drafts).
  • Locale keys added in all ten packs: home.myWork.* and home.pendingDrafts.title / inPackage / waiting / nameSeparator. Removed: home.actionCenter.* and the home.pendingDrafts.message family.
  • objectui#12604 (HomeContinue, HomeActivity) remains open and is untouched here.

Provenance: built by the cloud session session_015TchXBvZyEQx21tksAMaNv (claim 6212954349) and opened by the domain:ui seat 1 PM (session_011K9g23W67dy2zwnyzaoB6o) from that session's final message, because a cloud session cannot open a PR from its container. The seat changed nothing in the text.


Generated by Claude Code

…fications, with the pending-drafts row under its heading

The "Needs your attention" card becomes section 3 of the approved home
artboard: a heading with the bell's total and an "Open inbox" link, an
Approvals column listing the requests themselves (from the one shared
pending-approvals read, so its count is the bell's), and a Notifications
column. Two columns, not three: an inbox row carries no declared kind and no
due date, so nothing guesses "assigned to me" or "overdue" from a topic.
The pending-drafts banner above the greeting retires into a 40 px row under
the heading that runs the same publish. A column is drawn only for a source
the caller may read; the section renders nothing when neither is readable
and nothing is waiting to publish.

Claude-Session: https://claude.ai/code/session_015TchXBvZyEQx21tksAMaNv
Co-authored-by: Claude <noreply@anthropic.com>
…llows the drafts count key

The row's top rule sat outside its 40 px button, so each row measured 41 px
at 1280 px; the rule now belongs to the 40 px row. The (s)-marker pin in
perm-home-namespace-3546 reads `home.pendingDrafts.title`, the key that
replaced `home.pendingDrafts.message`.

Claude-Session: https://claude.ai/code/session_015TchXBvZyEQx21tksAMaNv
Co-authored-by: Claude <noreply@anthropic.com>
@github-actions

github-actions Bot commented Oct 16, 2026 •

Copy link
Copy Markdown
Contributor

changeset-claim-re-read

⚠️ 1 pending changeset(s) describe a file this change touches

Their bodies publish verbatim into the CHANGELOG at the next release, so this is a request to re-read them against your diff — addressed here because you are the one seat that can answer it without re-deriving anything.

⛔ Nothing here blocks, and nothing here is a verdict on your change. This gate exits 0, is not a required context, and judges name resolution, never meaning: it asked whether a pending body names a file you touched. "Is this sentence still true?" is the one question it will not answer, and the one you are being asked to answer.

.changeset/11659-console-record-ux.md

  • names HomePage.tsx → packages/app-shell/src/console/home/HomePage.tsx — edited by this change

    The backup-password reminder no longer appears in the user's first session. 「建议设置一个备用密码」 showed on the environment home right after a new user built their first app: the reminder was gated on a home-visit count (quiet on the first home mount, shown on the second), and coming back to home after building is the second mount inside the first sitting. It now stays quiet for 12 hours after the first home visit on the device, so it first shows on a later day's visit. The first-visit record (os:recovery-pw-first-seen) now holds a timestamp; a device that holds the old '1' flag starts the 12 hours over rather than reading it as long ago. When storage is unavailable it stays quiet. RecoveryPasswordReminder moves out of HomePage.tsx into its own module; it is not exported from the package entry, and its other conditions (dismissed, SSO-enforced, has a local password) are unchanged.

Read the paragraph, not the line: both false halves of the objectui#8617 claim sat in one paragraph, and correcting either alone would have left it asserting the same wrong thing.

If a claim did go false, correct the body. That is precedented and prose-only, frontmatter untouched; check-changeset-overwrite.mjs will report the correction as its own case 2 ("correcting a declaration on purpose … legitimate"), which is the intended shape — one gate asks for the read, the other records the write.

Not covered, stated so nobody reads this as more: a born-false claim that spells no line address at all (objectui#9495 coordinated one by ORDINAL — "a grep finds that member first" — and deciding that means reading what the sentence means), a claim spelled as a symbol or a package rather than a backticked file name, and a file named ambiguously.

Compared the checked-out tree with f62b6ff4e (merge-base with origin/main): 29 file(s) changed outside .changeset/, read against 569 pending declaration(s) that publish a body (589 pending in total). · run

@github-actions

Copy link
Copy Markdown
Contributor

⚠️ Console Performance Budget — gauge not trustworthy

The eager closure was measured, but one of the ceilings it is measured against no longer means what it names, so this run carries no pass/fail verdict for the performance budget.

This is not a budget violation. Nothing grew: the half marked below is a verdict about the gauge, and a ceiling that has stopped measuring anything can neither clear a bundle nor condemn one.

Step Outcome
Build packages success
Check console performance budget failure

Which half objected:

Eager-closure half Verdict
Aggregate closure ceiling ✅ pass
Per-chunk ceilings ✅ pass
Per-chunk membership (declared packages) ✅ pass
Ceiling sensitivity (headroom) ✅ pass
Ceiling freshness (checkout vs. base branch) ⚠️ superseded ceiling

⚠️ A superseded ceiling is neither a size regression nor a drifted gauge. The bundle was measured correctly and the ceilings on the base branch are correct — but this checkout predates a change to them, so the verdicts above were weighed against numbers that are no longer in force. Nothing grew. Update this branch onto the base branch and let Bundle Analysis run again; do not widen a ceiling to clear it. The Check console performance budget step log names each superseded constant with both values (objectui#6245).

Reason: The entry chunk measured 75.3 KB, but the eager-closure half of this gate returned no trustworthy VERDICT: the report could not be read, a ceiling has drifted out of range of the regression it must catch, or (objectui#6245) a ceiling was replaced on the base branch after this checkout was made. The step log says which. This is not a passing budget — and it is not a size regression either.

See the workflow run for details.


📦 Bundle Size Report

Package Size Gzipped
app-shell (consoleActionDispatch.js) 0.20KB 0.19KB
app-shell (index.js) 21.19KB 7.76KB
app-shell (runtime-config.js) 22.59KB 7.89KB
app-shell (types.js) 0.01KB 0.04KB
app-shell (urlParams.js) 10.11KB 3.87KB
auth (ActiveOrganizationStorage.js) 27.95KB 10.04KB
auth (AuthContext.js) 0.31KB 0.24KB
auth (AuthGuard.js) 2.07KB 1.00KB
auth (AuthProvider.js) 40.22KB 10.61KB
auth (AuthShell.js) 3.49KB 1.40KB
auth (ForgotPasswordForm.js) 12.21KB 3.45KB
auth (LoginForm.js) 20.39KB 6.02KB
auth (PreviewBanner.js) 0.90KB 0.50KB
auth (RegisterForm.js) 6.72KB 2.24KB
auth (SocialSignInButtons.js) 9.70KB 3.93KB
auth (UserMenu.js) 3.39KB 1.21KB
auth (auth-gate-events.js) 1.62KB 0.83KB
auth (authStyles.js) 5.27KB 1.86KB
auth (createAuthClient.js) 41.19KB 11.12KB
auth (createAuthenticatedFetch.js) 8.54KB 3.46KB
auth (index.js) 3.63KB 1.64KB
auth (invitation-status.js) 1.22KB 0.70KB
auth (org-roles.js) 6.66KB 2.78KB
auth (phone-identifier.js) 1.11KB 0.66KB
auth (types.js) 0.59KB 0.35KB
auth (useAuth.js) 5.30KB 1.02KB
auth (useWorkspaceAdminStatus.js) 11.08KB 4.58KB
collaboration (CommentThread.js) 27.26KB 8.03KB
collaboration (LiveCursors.js) 3.17KB 1.27KB
collaboration (PresenceAvatars.js) 6.28KB 2.60KB
collaboration (PresenceProvider.js) 2.79KB 1.13KB
collaboration (commentAuthorship.js) 1.39KB 0.78KB
collaboration (index.js) 1.93KB 0.85KB
collaboration (useCollaborationTranslation.js) 6.50KB 2.52KB
collaboration (useCommentSearch.js) 1.98KB 0.88KB
collaboration (useConflictResolution.js) 7.75KB 1.86KB
collaboration (useMentionNotifications.js) 1.81KB 0.68KB
collaboration (usePresence.js) 6.33KB 1.84KB
collaboration (useRealtimeSubscription.js) 7.91KB 2.01KB
components (index.js) 597.83KB 144.29KB
core (index.js) 10.18KB 4.04KB
create-plugin (index.js) 27.94KB 9.51KB
data-objectstack (index.js) 248.20KB 69.22KB
fields (index.js) 290.12KB 74.14KB
i18n (LocalizationContext.js) 2.92KB 1.42KB
i18n (builtinAggregateLabels.js) 0.86KB 0.49KB
i18n (currency.js) 2.59KB 1.22KB
i18n (fallbackInterpolation.js) 6.25KB 2.77KB
i18n (i18n.js) 8.87KB 3.64KB
i18n (index.js) 5.52KB 2.39KB
i18n (pickLocalized.js) 9.86KB 3.95KB
i18n (provider.js) 39.35KB 12.88KB
i18n (translateFn.js) 0.20KB 0.18KB
i18n (useDisplayLocale.js) 3.52KB 1.76KB
i18n (useObjectLabel.js) 36.87KB 9.88KB
i18n (useSafeTranslation.js) 7.14KB 2.92KB
layout (index.js) 40.67KB 11.85KB
mobile (MobileProvider.js) 0.92KB 0.49KB
mobile (ResponsiveContainer.js) 0.94KB 0.38KB
mobile (breakpoints.js) 1.51KB 0.70KB
mobile (createOfflineDataSource.js) 5.61KB 1.75KB
mobile (index.js) 1.99KB 0.87KB
mobile (offlineQueue.js) 3.91KB 1.35KB
mobile (pwa.js) 0.97KB 0.49KB
mobile (serviceWorker.js) 1.48KB 0.62KB
mobile (serviceWorkerSource.js) 3.41KB 1.48KB
mobile (useBreakpoint.js) 1.54KB 0.65KB
mobile (useGesture.js) 6.96KB 1.98KB
mobile (useOfflineSync.js) 1.99KB 0.72KB
mobile (usePullToRefresh.js) 6.62KB 2.45KB
mobile (useResponsive.js) 0.72KB 0.42KB
mobile (useSpecGesture.js) 5.52KB 2.10KB
mobile (useTouchTarget.js) 1.01KB 0.54KB
permissions (MePermissionsProvider.js) 15.35KB 5.51KB
permissions (PermissionContext.js) 0.31KB 0.25KB
permissions (PermissionGuard.js) 0.89KB 0.45KB
permissions (PermissionProvider.js) 6.82KB 2.38KB
permissions (discardProofCache.js) 1.04KB 0.55KB
permissions (evaluator.js) 8.33KB 3.07KB
permissions (index.js) 0.93KB 0.41KB
permissions (store.js) 0.91KB 0.42KB
permissions (useFieldPermissions.js) 1.28KB 0.53KB
permissions (usePermissions.js) 4.83KB 2.27KB
plugin-ai (index.js) 16.04KB 3.92KB
plugin-calendar (index.js) 54.94KB 16.05KB
plugin-charts (index.js) 84.97KB 23.36KB
plugin-chatbot (index.js) 201.89KB 48.13KB
plugin-dashboard (index.js) 146.15KB 39.55KB
plugin-designer (index.js) 233.95KB 50.08KB
plugin-detail (index.js) 262.91KB 69.49KB
plugin-editor (index.js) 2.23KB 1.05KB
plugin-form (index.js) 180.92KB 46.73KB
plugin-gantt (index.js) 178.36KB 45.08KB
plugin-grid (index.js) 265.13KB 73.29KB
plugin-kanban (index.js) 59.42KB 18.48KB
plugin-list (index.js) 131.40KB 33.50KB
plugin-map (index.js) 27.07KB 8.96KB
plugin-markdown (index.js) 13.88KB 4.80KB
plugin-report (index.js) 46.66KB 13.13KB
plugin-timeline (index.js) 39.21KB 11.85KB
plugin-tree (index.js) 15.07KB 5.33KB
plugin-view (index.js) 93.43KB 23.94KB
providers (DataSourceProvider.js) 0.75KB 0.39KB
providers (MetadataProvider.js) 1.37KB 0.59KB
providers (ThemeProvider.js) 1.90KB 0.85KB
providers (UploadProvider.js) 12.07KB 3.68KB
providers (index.js) 0.45KB 0.23KB
providers (types.js) 0.01KB 0.04KB
react-runtime (index.js) 5.62KB 2.34KB
react (LazyPluginLoader.js) 4.47KB 1.63KB
react (SchemaRenderer.js) 120.63KB 39.56KB
react (data-invalidation.js) 5.05KB 2.08KB
react (index.js) 4.50KB 2.06KB
react (schema-input.js) 4.31KB 2.07KB
react (spec-input.js) 0.20KB 0.18KB
sdui-parser (body-dialect.js) 4.50KB 1.99KB
sdui-parser (codegen.js) 9.45KB 3.76KB
sdui-parser (dashboard-widget-options.js) 3.07KB 1.30KB
sdui-parser (index.js) 7.30KB 3.12KB
sdui-parser (input-type.js) 2.84KB 1.40KB
sdui-parser (parse.js) 25.28KB 7.81KB
sdui-parser (provenance.js) 3.84KB 1.90KB
sdui-parser (types.js) 0.29KB 0.24KB
sdui-parser (validate.js) 23.87KB 7.83KB
types (ai.js) 4.39KB 2.17KB
types (api-types.js) 0.20KB 0.18KB
types (app.js) 4.12KB 1.61KB
types (authoring-nodes.js) 0.20KB 0.19KB
types (base.js) 0.20KB 0.18KB
types (blocks.js) 0.20KB 0.18KB
types (cloud.js) 0.20KB 0.18KB
types (complex.js) 4.44KB 2.07KB
types (crud.js) 0.20KB 0.18KB
types (dashboard-filter-alias.js) 6.23KB 2.74KB
types (dashboard-widget-layout.js) 2.06KB 0.96KB
types (data-display.js) 3.75KB 1.85KB
types (data-protocol.js) 0.20KB 0.19KB
types (data.js) 0.20KB 0.18KB
types (designer.js) 1.85KB 0.85KB
types (disclosure.js) 0.20KB 0.18KB
types (error-code.js) 1.54KB 0.88KB
types (expression.js) 0.20KB 0.18KB
types (feedback.js) 0.20KB 0.18KB
types (field-types.js) 1.13KB 0.65KB
types (form.js) 0.20KB 0.18KB
types (http-inflight.js) 8.87KB 3.73KB
types (http-retry.js) 4.32KB 2.02KB
types (icon-key-migration.js) 4.26KB 1.63KB
types (index.js) 5.78KB 2.70KB
types (layout.js) 0.20KB 0.18KB
types (managed-by.js) 0.19KB 0.18KB
types (mobile.js) 5.00KB 2.39KB
types (navigation.js) 0.20KB 0.18KB
types (node-slots.js) 7.18KB 2.34KB
types (objectql.js) 0.20KB 0.18KB
types (overlay.js) 0.20KB 0.18KB
types (permissions.js) 2.52KB 1.31KB
types (plugin-scope.js) 0.20KB 0.18KB
types (record-approval-decision.js) 0.20KB 0.20KB
types (record-components.js) 0.20KB 0.19KB
types (record-panels.js) 0.20KB 0.19KB
types (record-semantics.js) 1.28KB 0.67KB
types (registry.js) 0.20KB 0.18KB
types (reports.js) 0.20KB 0.18KB
types (select-option.js) 0.20KB 0.19KB
types (spec-report.js) 4.99KB 1.96KB
types (spec-ui-namespace.js) 0.20KB 0.19KB
types (strict-authoring-face.js) 19.93KB 7.26KB
types (system-fields.js) 3.33KB 1.54KB
types (theme.js) 6.28KB 2.87KB
types (ui-action.js) 8.48KB 3.50KB
types (views.js) 0.20KB 0.18KB
types (widget.js) 0.20KB 0.18KB

Size Limits

  • ✅ Core packages should be < 50KB gzipped
  • ✅ Component packages should be < 100KB gzipped
  • ⚠️ Plugin packages should be < 150KB gzipped

@objectstack-fleet

Copy link
Copy Markdown
Contributor Author

Live E2E (informational) red on 7375100114: not this PR's · domain:ui seat 1 · session_011K9g23W67dy2zwnyzaoB6o · 2026-10-16T11:27Z

  • What fails. Job 116948770247 dies in e2e/live/ci/start-backend.sh while preparing the showcase backend on published @objectstack/*@18.0.0-next.2: npm error Cannot read properties of null (reading 'edgesOut'). No spec ran, and no artifact was uploaded.
  • Why it is not this PR's. It fails before any test body, in a script this diff does not touch. The base carries the identical signature: PR deps(v18): resolve @objectstack/* 18.0.0-next.2 and follow its contract (objectui#12626) #12648 (objectui#12626, merged as main f62b6ff4e1, this head's merge parent) failed the same job the same way (job 116939199471, same cache key live-backend-Linux-3e640c78…, same npm error).
  • Fix: none exists yet. objectui#12649 (seat 4's finding) tracks it. It reproduced the crash locally on both 18.0.0-next.2 and 18.0.0-next.1 pins, so a re-run on a cold cache would only repeat it. The seat takes no re-run.
  • The lane is informational and blocks no merge. The seat's review reads this red as base-red with a matching signature. Every other check is judged on this head as usual.

Generated by Claude Code

@github-actions

Copy link
Copy Markdown
Contributor

✅ Console Performance Budget

Metric Value Budget
Eager closure (gzip, 70 chunks) 3116.2 KB 3119.4 KB
Main entry chunk (gzip) 75.2 KB 350 KB
Entry file index-Dl-RVCVn.js —
Status PASS —

The eager closure is every chunk the entry reaches through static imports — what the browser fetches and parses before the app renders. The entry chunk on its own is a small fraction of it.


📦 Bundle Size Report

Package Size Gzipped
app-shell (consoleActionDispatch.js) 0.20KB 0.19KB
app-shell (index.js) 21.19KB 7.76KB
app-shell (runtime-config.js) 22.59KB 7.89KB
app-shell (types.js) 0.01KB 0.04KB
app-shell (urlParams.js) 10.11KB 3.87KB
auth (ActiveOrganizationStorage.js) 27.95KB 10.04KB
auth (AuthContext.js) 0.31KB 0.24KB
auth (AuthGuard.js) 2.07KB 1.00KB
auth (AuthProvider.js) 40.22KB 10.61KB
auth (AuthShell.js) 3.49KB 1.40KB
auth (ForgotPasswordForm.js) 12.21KB 3.45KB
auth (LoginForm.js) 20.39KB 6.02KB
auth (PreviewBanner.js) 0.90KB 0.50KB
auth (RegisterForm.js) 6.72KB 2.24KB
auth (SocialSignInButtons.js) 9.70KB 3.93KB
auth (UserMenu.js) 3.39KB 1.21KB
auth (auth-gate-events.js) 1.62KB 0.83KB
auth (authStyles.js) 5.27KB 1.86KB
auth (createAuthClient.js) 41.19KB 11.12KB
auth (createAuthenticatedFetch.js) 8.54KB 3.46KB
auth (index.js) 3.63KB 1.64KB
auth (invitation-status.js) 1.22KB 0.70KB
auth (org-roles.js) 6.66KB 2.78KB
auth (phone-identifier.js) 1.11KB 0.66KB
auth (types.js) 0.59KB 0.35KB
auth (useAuth.js) 5.30KB 1.02KB
auth (useWorkspaceAdminStatus.js) 11.08KB 4.58KB
collaboration (CommentThread.js) 27.26KB 8.03KB
collaboration (LiveCursors.js) 3.17KB 1.27KB
collaboration (PresenceAvatars.js) 6.28KB 2.60KB
collaboration (PresenceProvider.js) 2.79KB 1.13KB
collaboration (commentAuthorship.js) 1.39KB 0.78KB
collaboration (index.js) 1.93KB 0.85KB
collaboration (useCollaborationTranslation.js) 6.50KB 2.52KB
collaboration (useCommentSearch.js) 1.98KB 0.88KB
collaboration (useConflictResolution.js) 7.75KB 1.86KB
collaboration (useMentionNotifications.js) 1.81KB 0.68KB
collaboration (usePresence.js) 6.33KB 1.84KB
collaboration (useRealtimeSubscription.js) 7.91KB 2.01KB
components (index.js) 597.83KB 144.29KB
core (index.js) 10.18KB 4.04KB
create-plugin (index.js) 27.94KB 9.51KB
data-objectstack (index.js) 248.20KB 69.22KB
fields (index.js) 290.12KB 74.14KB
i18n (LocalizationContext.js) 2.92KB 1.42KB
i18n (builtinAggregateLabels.js) 0.86KB 0.49KB
i18n (currency.js) 2.59KB 1.22KB
i18n (fallbackInterpolation.js) 6.25KB 2.77KB
i18n (i18n.js) 8.87KB 3.64KB
i18n (index.js) 5.52KB 2.39KB
i18n (pickLocalized.js) 9.86KB 3.95KB
i18n (provider.js) 39.35KB 12.88KB
i18n (translateFn.js) 0.20KB 0.18KB
i18n (useDisplayLocale.js) 3.52KB 1.76KB
i18n (useObjectLabel.js) 36.87KB 9.88KB
i18n (useSafeTranslation.js) 7.14KB 2.92KB
layout (index.js) 40.67KB 11.85KB
mobile (MobileProvider.js) 0.92KB 0.49KB
mobile (ResponsiveContainer.js) 0.94KB 0.38KB
mobile (breakpoints.js) 1.51KB 0.70KB
mobile (createOfflineDataSource.js) 5.61KB 1.75KB
mobile (index.js) 1.99KB 0.87KB
mobile (offlineQueue.js) 3.91KB 1.35KB
mobile (pwa.js) 0.97KB 0.49KB
mobile (serviceWorker.js) 1.48KB 0.62KB
mobile (serviceWorkerSource.js) 3.41KB 1.48KB
mobile (useBreakpoint.js) 1.54KB 0.65KB
mobile (useGesture.js) 6.96KB 1.98KB
mobile (useOfflineSync.js) 1.99KB 0.72KB
mobile (usePullToRefresh.js) 6.62KB 2.45KB
mobile (useResponsive.js) 0.72KB 0.42KB
mobile (useSpecGesture.js) 5.52KB 2.10KB
mobile (useTouchTarget.js) 1.01KB 0.54KB
permissions (MePermissionsProvider.js) 15.35KB 5.51KB
permissions (PermissionContext.js) 0.31KB 0.25KB
permissions (PermissionGuard.js) 0.89KB 0.45KB
permissions (PermissionProvider.js) 6.82KB 2.38KB
permissions (discardProofCache.js) 1.04KB 0.55KB
permissions (evaluator.js) 8.33KB 3.07KB
permissions (index.js) 0.93KB 0.41KB
permissions (store.js) 0.91KB 0.42KB
permissions (useFieldPermissions.js) 1.28KB 0.53KB
permissions (usePermissions.js) 4.83KB 2.27KB
plugin-ai (index.js) 16.04KB 3.92KB
plugin-calendar (index.js) 54.94KB 16.05KB
plugin-charts (index.js) 84.97KB 23.36KB
plugin-chatbot (index.js) 201.89KB 48.13KB
plugin-dashboard (index.js) 146.15KB 39.55KB
plugin-designer (index.js) 233.95KB 50.08KB
plugin-detail (index.js) 262.91KB 69.49KB
plugin-editor (index.js) 2.23KB 1.05KB
plugin-form (index.js) 180.92KB 46.73KB
plugin-gantt (index.js) 178.36KB 45.08KB
plugin-grid (index.js) 265.13KB 73.29KB
plugin-kanban (index.js) 59.42KB 18.48KB
plugin-list (index.js) 131.40KB 33.50KB
plugin-map (index.js) 27.07KB 8.96KB
plugin-markdown (index.js) 13.88KB 4.80KB
plugin-report (index.js) 46.66KB 13.13KB
plugin-timeline (index.js) 39.21KB 11.85KB
plugin-tree (index.js) 15.07KB 5.33KB
plugin-view (index.js) 93.43KB 23.94KB
providers (DataSourceProvider.js) 0.75KB 0.39KB
providers (MetadataProvider.js) 1.37KB 0.59KB
providers (ThemeProvider.js) 1.90KB 0.85KB
providers (UploadProvider.js) 12.07KB 3.68KB
providers (index.js) 0.45KB 0.23KB
providers (types.js) 0.01KB 0.04KB
react-runtime (index.js) 5.62KB 2.34KB
react (LazyPluginLoader.js) 4.47KB 1.63KB
react (SchemaRenderer.js) 120.63KB 39.56KB
react (data-invalidation.js) 5.05KB 2.08KB
react (index.js) 4.50KB 2.06KB
react (schema-input.js) 4.31KB 2.07KB
react (spec-input.js) 0.20KB 0.18KB
sdui-parser (body-dialect.js) 4.50KB 1.99KB
sdui-parser (codegen.js) 9.45KB 3.76KB
sdui-parser (dashboard-widget-options.js) 3.07KB 1.30KB
sdui-parser (index.js) 7.30KB 3.12KB
sdui-parser (input-type.js) 2.84KB 1.40KB
sdui-parser (parse.js) 25.28KB 7.81KB
sdui-parser (provenance.js) 3.84KB 1.90KB
sdui-parser (types.js) 0.29KB 0.24KB
sdui-parser (validate.js) 23.87KB 7.83KB
types (ai.js) 4.39KB 2.17KB
types (api-types.js) 0.20KB 0.18KB
types (app.js) 4.12KB 1.61KB
types (authoring-nodes.js) 0.20KB 0.19KB
types (base.js) 0.20KB 0.18KB
types (blocks.js) 0.20KB 0.18KB
types (cloud.js) 0.20KB 0.18KB
types (complex.js) 4.44KB 2.07KB
types (crud.js) 0.20KB 0.18KB
types (dashboard-filter-alias.js) 6.23KB 2.74KB
types (dashboard-widget-layout.js) 2.06KB 0.96KB
types (data-display.js) 3.75KB 1.85KB
types (data-protocol.js) 0.20KB 0.19KB
types (data.js) 0.20KB 0.18KB
types (designer.js) 1.85KB 0.85KB
types (disclosure.js) 0.20KB 0.18KB
types (error-code.js) 1.54KB 0.88KB
types (expression.js) 0.20KB 0.18KB
types (feedback.js) 0.20KB 0.18KB
types (field-types.js) 1.13KB 0.65KB
types (form.js) 0.20KB 0.18KB
types (http-inflight.js) 8.87KB 3.73KB
types (http-retry.js) 4.32KB 2.02KB
types (icon-key-migration.js) 4.26KB 1.63KB
types (index.js) 5.78KB 2.70KB
types (layout.js) 0.20KB 0.18KB
types (managed-by.js) 0.19KB 0.18KB
types (mobile.js) 5.00KB 2.39KB
types (navigation.js) 0.20KB 0.18KB
types (node-slots.js) 7.18KB 2.34KB
types (objectql.js) 0.20KB 0.18KB
types (overlay.js) 0.20KB 0.18KB
types (permissions.js) 2.52KB 1.31KB
types (plugin-scope.js) 0.20KB 0.18KB
types (record-approval-decision.js) 0.20KB 0.20KB
types (record-components.js) 0.20KB 0.19KB
types (record-panels.js) 0.20KB 0.19KB
types (record-semantics.js) 1.28KB 0.67KB
types (registry.js) 0.20KB 0.18KB
types (reports.js) 0.20KB 0.18KB
types (select-option.js) 0.20KB 0.19KB
types (spec-report.js) 4.99KB 1.96KB
types (spec-ui-namespace.js) 0.20KB 0.19KB
types (strict-authoring-face.js) 19.93KB 7.26KB
types (system-fields.js) 3.33KB 1.54KB
types (theme.js) 6.28KB 2.87KB
types (ui-action.js) 8.48KB 3.50KB
types (views.js) 0.20KB 0.18KB
types (widget.js) 0.20KB 0.18KB

Size Limits

  • ✅ Core packages should be < 50KB gzipped
  • ✅ Component packages should be < 100KB gzipped
  • ⚠️ Plugin packages should be < 150KB gzipped

@objectstack-fleet

Copy link
Copy Markdown
Contributor Author

Contract review

Served-tier: TIER_DEFAULT
Head-sha: 73751001145265e05346ea693cf60568d1051479
Local-runs: none

Face: the Clause-②: yes declaration on claim 6212954349 (objectui#12602). The committed tree has no published schema and no governed path: check-governed-merges --pr reports 0 of 31 paths, NOT governed, +1441/−326. Head 7375100114 is the dev's reviewed 9bf4170 plus a relay merge of main f62b6ff4e1 (for Bundle Analysis's superseded ceiling); the PR's own change lines against main are identical before and after that merge (measured). Inputs: the diff, the card, the cloud dev's report (on the card), and this head's check-runs (32 success, 3 skipped by design, Live E2E (informational) base-red with a matching signature, 6214488000).

① Derived judgments

  • @object-ui/i18n. Keys added in all ten packs: home.myWork.title, .openInbox, .viewAll, .approvals, .approvalsEmpty, .notifications, .notificationsEmpty, and home.pendingDrafts.title (a count family), .inPackage, .waiting, .nameSeparator. Keys removed: home.actionCenter.title, home.actionCenter.empty and the home.pendingDrafts.message count family. The exported en pack is typed by its literal content, so its type gains the first set and loses the second. The removed keys' only readers were the retired card and banner: check:i18n-keys and check:i18n-dead-keys exit 0 at the dev's head, and Type Check and all 16 test shards pass on this head. A widening and a narrowing, both declared in the i18n changeset. Correct.
  • @object-ui/app-shell. HomePage is the only exported symbol among the touched files (index.ts:297), and its props are unchanged. HomeActionCenter, useHomeInbox, sharedUserFeeds and its new PendingApprovalRequest / useSharedPendingApprovalRequests are package-internal; none is reachable from the entry. useSharedPendingApprovals keeps its shape ({ value: number, status }). No public-surface change. Correct.
  • The one-read rule. The approvals feed still makes one request; it now keeps the deduped rows, and every count is that list's length, so the bell, the greeting line and the column agree by construction. sharedInboxFeed.twoSurfaces.test.tsx pins the column pill equal to the bell badge over the real store and the real AppHeader bell. Correct.
  • No classification of a free-text field. The added code reads no topic or title to infer a kind or a due date (diff grep: no match, regex or comparison on either). The two-column form is the card's own Target 5 rule for a record with no declared kind. Correct.

② Semver level

@object-ui/app-shell minor and @object-ui/i18n minor: a visible home redesign, keys added and removed. Under objectui's no-major policy in pre mode (next), a key removal ships as minor and is declared in the changeset, as on PRs #12638 and #12640. Changeset Bump Policy and Changeset Fixed Group Check pass on this head. Consistent.

③ Boundary flags

The dev's three open questions:

  1. B now. The two-column form ships, and nothing derives a kind from topic. No objectstack card is filed for a declared kind and due_at: the live showcase emits only approval.requested, so no emitter is measured to pull for it. The fork and the field it needs are recorded on the card with the report, as Target 5 asks.
  2. A. The sharedUserFeeds.ts extension is accepted. It is the one place the rows exist; it adds no request and keeps the count's meaning. It sits outside the claim's file list, declared by the dev.
  3. A. Seat 1's claim 6212954349 is the claim of record. Seat 4 released its duplicate at 6213017945 before this branch was pushed.

.changeset/11659-console-record-ux.md (flagged by Changeset Claim Re-read) still reads true: its RecoveryPasswordReminder sentence is about a module this diff imports unchanged.

Implemented-by: session_015TchXBvZyEQx21tksAMaNv
Reviewed-by: session_011K9g23W67dy2zwnyzaoB6o

VERDICT: PASS


Generated by Claude Code

@objectstack-fleet

Copy link
Copy Markdown
Contributor Author

席位核对 · ACCEPT · domain:ui seat 1 · session_011K9g23W67dy2zwnyzaoB6o · 2026-10-16T11:42Z

What was reviewed:

  • Head 73751001145265e05346ea693cf60568d1051479: the cloud dev's 9bf4170 plus the relay's merge of main f62b6ff4e1. The PR's own change lines are identical across that merge.
  • The card objectui#12602, the claim 6212954349 (Clause-②: yes, mode:cloud, cloud session session_015TchXBvZyEQx21tksAMaNv), and the dev's report on the card.
  • The contract review of record, 6214717415 (TIER_DEFAULT, PASS, same head).
  1. Shape.
    • The seat opened this draft PR from the cloud session's final message; its provenance line is in the body.
    • Fixes #12602 is the first line and the only closing keyword. Clause-②: yes starts a line, and the assignee is os-tesla.
    • 31 files: HomeRail.tsx (HomeActionCenter), HomePage.tsx (the drafts row and the section order), useHomeInbox.ts, the ten locale packs, the home and hook tests, and two changesets, all inside the claim. One file sits outside it, declared by the dev and accepted in the contract review: hooks/sharedUserFeeds.ts, where the approvals feed now keeps its rows. HomeContinue / HomeActivity (objectui#12604) and HomeLayout.tsx (objectui#12639) are untouched.
    • The changesets were checked sentence by sentence against the diff. The surface is NOT governed, at 1767 changed lines.
  2. Premises measured by the seat.
    • HomePage's props are unchanged; every other touched symbol is package-internal.
    • The approvals feed makes one request; every count is the deduped list's length.
    • No added line reads topic or title to infer a kind or a due date.
  3. Gates (check-runs pinned to this head).
    • 32 success and 3 skipped by design, including Lint, Repo Gates, Type Check, Test (shard 1–16/16), Test (dist pins), Build & E2E, Bundle Analysis (eager closure 3116.2 KB of 3119.4 KB) and Changeset Bump Policy.
    • Live E2E (informational) is red before any spec runs, with the same npm crash as the base's own PR deps(v18): resolve @objectstack/* 18.0.0-next.2 and follow its contract (objectui#12626) #12648; objectui#12649 tracks it (6214488000).
    • The dev's eight ablations each go red.
  4. Accepted deviations.
    • Acceptance 1's "a past due date reads 逾期" is not implemented. The record has no due date, and Target 5 of the card rules the two-column form for that case. A pin holds the opposite: an assignment-like topic lands under Notifications, with no overdue text.
    • The dev's whole-package run was one commit behind its head; all 16 CI shards pass on this head.
    • Acceptance 3's pnpm check:i18n does not exist; its three halves exit 0.
    • Live readings at 1280 px, 0 / 2 / 18 items, light and dark, are in the PR body from claude/issue-12602-evidence 66d1f4f.
  5. Out of scope.
    • The published showcase at the next.1 tag refuses isDefault: true on a home-type page at boot; known, and worked around in a throwaway copy only.
    • A declared notification kind and due date (objectstack) wait for an emitter that needs them; see the contract review.
  6. Landing.
    • Ready, then auto-merge into the merge queue.
    • After the merge: verify by content, close the card through Fixes, strip pm:dispatched, and archive the cloud session.

Generated by Claude Code

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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Console home: a My work section with approvals first, then assigned to me, then reminders, and the pending-drafts row

2 participants