Skip to content

fix(plugin-calendar): a month-grid move keeps the wall-clock time across a DST change (objectui#11005) - #11036

Merged
objectstack-fleet[bot] merged 2 commits into
mainfrom
claude/issue-11005-month-grid-calendar-days
Sep 29, 2026
Merged

objectstack-fleet[bot] merged 2 commits into
mainfrom
claude/issue-11005-month-grid-calendar-days

Conversation

@objectstack-fleet

Copy link
Copy Markdown
Contributor

Fixes #11005
Clause-②: no

Ruling 5881826705 (letter B), PM claim 5882077455, branch claude/issue-11005-month-grid-calendar-days, dispatched from session https://claude.ai/code/session_011p7ikEivgXefNDaE5S5Uec. The month grid now moves a value by calendar days and keeps its wall-clock time. This holds for every value, for a move and for a drag of the span's end.

What changes

  1. CalendarView, MonthView.handleDrop. The move used to count deltaMs, the milliseconds between the grab cell's local midnight and the drop cell's, and add it to the start and the end. It now counts the calendar days between the two cells from their local year, month and day (calendarDaysBetween). The difference is taken on the UTC calendar, so it is a whole number with no rounding. It then moves a local copy of the start and of the end with setDate (moveByCalendarDays), leaving hours, minutes, seconds and milliseconds untouched. The drag of a span's end (resize-end) moves the end the same way, and its guards still compare day cells.
  2. ObjectCalendar: the objectui#10866 slice-4 day repair is removed (toMovedDateValue, isStoredDay, DAY_MS). It was measured redundant (see below). The default drop handler writes each field through toStoredDateValue again, as it did before that slice: a date field as the local day of the value the grid hands back, and a datetime field as its instant.
  3. Pins. A new zone pin, CalendarView.monthMoveCalendarDays-11005, sits at the grid. It covers Los Angeles and Shanghai, plus two suite-zone cases, and is registered in the driver's PINS (scripts/__tests__/date-only-zone-pins-10183.test.ts). In ObjectCalendar.dstDayMove-10866:
    • The four datetime controls are renamed from "keeps the grid's instants" to "keeps its wall-clock time".
    • The first Los Angeles control's end moves from 2026-11-02T17:00:00.000Z (09:00 PST) to 2026-11-02T18:00:00.000Z (10:00 PST). This is the ruled instant change.
    • Its header prose says what changed. Its ten date day moves are untouched.
  4. Docs. The plugin README's month-view drag table and the two month-view bullets in content/docs/plugins/plugin-calendar.mdx now say that a move and an end drag keep the time of day (AGENTS.md commandment Add automated testing infrastructure and CI/CD workflows #2).
  5. Changesets. .changeset/11005-month-grid-calendar-days.md declares @object-ui/plugin-calendar: patch. The pending slice-4 changeset is reconciled in the dated-note form (see mechanism assumption 4).

The ruled zone pins

These run under TZ=America/Los_Angeles, where the clocks fall back on November 1st and spring forward on March 8th, 2026, and under TZ=Asia/Shanghai. Base is a33cf7e.

Ruled pin Where On base On head
A datetime moved across a DST change keeps its wall-clock time New pin, four Los Angeles moves A 10:00 event on Nov 1 moved two days wrote 11:00. One moved back onto Nov 1 wrote 09:00. A 10:00 event on Mar 8 moved two days wrote 09:00. A span whose end crosses Nov 1 wrote its end at 09:00. 10:00 each
A local-midnight instant lands on the dropped day New pin, two Los Angeles spans The card's case: a start of 2026-11-01T07:00:00.000Z, grabbed on Nov 2 and dropped on Nov 3, wrote 2026-11-02T07:00:00.000Z (Nov 1, 23:00). A span ending at midnight on Mar 9, moved back one day, started at 2026-03-06T09:00:00.000Z (01:00). Midnight of the dropped day
A date-only value is unchanged Slice 4's ten day moves through ObjectCalendar, Los Angeles and Shanghai Written by the repair The same ten days, with the repair removed
A zone without DST behaves as before New pin, four Shanghai drags Exactly N times 24 hours The same instants
resize-end follows the same rule New pin, two Los Angeles end drags Hours, minutes and seconds already kept; milliseconds dropped (19:30:15.000Z for 19:30:15.250Z) The whole time of day

Mechanism assumptions (Zone 2), measured

  1. Partly held. The move derived one deltaMs from local-midnight cells. resize-end did not: it set the drop day's clock from the old end with setHours(h, m, s, 0), so it already kept hours, minutes and seconds across a DST change. On base, the March 8th end drag passed and the November 2nd one differed only in milliseconds. The resize guards compare day cells, as assumed.
  2. Held: the week and day views do not ride. The time grid places a moved event at its snapped minutes on the drop day's own clock (setHours(0, snapped) on the drop column's day). A throwaway probe in a forked child under Los Angeles (not committed) moved a 10:00 event off November 1st and onto it in the week view. It wrote 10:00 both ways: 2026-11-03T18:00:00.000Z and 2026-11-01T18:00:00.000Z.
  3. Held: the repair is redundant, and B is what makes it so. With B in the grid and the repair removed, slice 4's ten day moves pass in both zones. Ablation: put the base grid back under the committed head (repair still removed), and four of those ten go red in Los Angeles. They are exactly the four that slice 4 named (see Evidence).
  4. The named file does not describe the repair. .changeset/10866-calendar-gantt-date-only-days.md (slice 1) does not describe the repair. Its calendar sentence "A datetime field keeps its instant" is about the stored type, so it stays true under the ruling's own reading, and the file is untouched. The repair is described in slice 4's .changeset/10866-calendar-dst-day-moves.md. Two phrases there go false at this change: "The month grid moves each date…" and "…the grid's own arithmetic does not change". Both are now scoped "at this change", followed by a dated note naming this card. The front matter is byte-identical (the md5 of the first six lines matches the base). Its gantt and core bullets are untouched. check-changeset-overwrite reports the modification (report-only, exit 0), and that is expected.

Evidence

All counts are read from vitest's own summary lines.

  • New pin, red on base. Before the fix, in a forked child with OBJECTUI_DATE_ZONE_CHILD=1: Tests 8 failed | 9 passed (17). The eight red cases:

    • the six Los Angeles moves;
    • the Los Angeles November end drag (milliseconds only);
    • the suite-zone end drag (milliseconds only).

    The Los Angeles March end drag, the rigs, the fixture case and every Shanghai case passed on base.

  • Head, all calendar zone pins driven. CalendarView.monthMoveCalendarDays-11005, ObjectCalendar.dstDayMove-10866, ObjectCalendar.endDateNoSchemaZone-10866, ObjectCalendar.dateOnlyZone-10866 and calendarViewRenderer.dateOnlyZone-10866, forked with the flag: Test Files 5 passed (5), Tests 104 passed (104).

  • Ablation. Run on committed head 55d7add. The base blob of CalendarView.tsx was checked out on its own, with ObjectCalendar.tsx staying at head (repair removed).

    • Landing proof: after the mutation the file hashed to the base blob 0fbcb72b, and the deltaMs count went from 0 to 4 while the moveByCalendarDays count went from 5 to 0.
    • Result, forked, driven: Tests 13 failed | 32 passed (45). The red cases are the eight new-pin cases, slice 4's four Los Angeles day moves (Oct 29 to 31 moved two days, Nov 1 to 3 grabbed on the 2nd, Oct 31 to Nov 2 moved back one, Mar 5 to 9 moved back one), and the first Los Angeles datetime control.
    • Restore, from a trap on EXIT/INT/TERM with absolute paths: git checkout HEAD -- brought the file back to the HEAD blob 29701d6f, and git diff HEAD came back empty.
  • Package suite at 600e84c. pnpm exec vitest run packages/plugin-calendar/: Test Files 55 passed (55), Tests 365 passed | 85 skipped (450). The skipped cases are zone pins, which run in the driver's child.

  • Zone-pin driver at 600e84c. scripts/__tests__/date-only-zone-pins-10183.test.ts: Tests 24 passed (24), which is every registered pin plus the child-exit case.

  • Tests outside the package that name an edited file, derived with git grep over test files for the edited paths and symbols. The zone pins are excluded because the driver ran them. 14 files: Test Files 14 passed (14), Tests 1067 passed (1067). The 16 test files that read .changeset/: Test Files 16 passed (16), Tests 618 passed (618).

  • Type-check. The dependency closure was built with turbo run build --filter='@object-ui/plugin-calendar^...' --concurrency=2: 13 tasks, all restored from turbo's shared worktree cache, none of them in this diff. Then pnpm --filter @object-ui/plugin-calendar type-check, which echoed tsc --noEmit && tsc -p tsconfig.test.json, exited 0. tsc -p tsconfig.test.json --listFiles lists both edited pins.

  • Gates, all exit 0:

    • check-changeset-presence: "4 source file(s) of 1 released package(s) changed, and this change declares 1 changeset(s)".
    • check-changeset-no-major, -fixed, -overwrite (report-only, see above) and -claims (report-only). For -claims, five pending changesets name ObjectCalendar.tsx, the README or the plugin page. Each was re-read: they concern the record source, filter, sort and the colour and all-day fields, and none is falsified.
    • check-pending-changeset-literals, check-control-bytes and check-new-cross-file-line-citations ("0 new citation(s)").
    • check-test-path-roots, the three check-vi-mock-* gates and check-unreferenced-sources.
    • check-doc-fence-languages, check-doc-component-types and check-doc-example-ids.
    • check-governed-queue-guard --test over the nine paths: NOT GOVERNED.
  • NOT MEASURED: check-doc-snippet-types (exit 2), check-doc-example-types (exit 2) and check-readme-exports (exit 1). All three stopped on their prerequisite: packages outside this closure are unbuilt, reported as [unbuilt-package] and "not on disk — run the build first". That means the runs never reached a verdict, not that the gates failed. The README and doc edits here change table rows and bullets only, with no fenced block. These gates belong to CI.

  • Lint, narrowed and declared as a narrowing.

    • Population: the root config lints **/*.{ts,tsx}, and this diff has five such files.
    • Count: eslint --no-inline-config --format json returned 5 results with no "ignored" message: 0 errors in total. Warnings equal each modified file's base blob (CalendarView.tsx 24, ObjectCalendar.tsx 31), and the three test files have 0.
    • Invariance: eslint.config.js sets no parserOptions, project or projectService, so linting is not type-aware and this diff cannot move the verdict for any untouched file.

    Repo-wide lint is CI's.

Acceptance notes

The dev records these here and files nothing; the seat decides.

  • A week or day view move of an overnight timed event shortens it (class (a): reproduced, pre-existing, unrelated to DST).
    • The time grid clips a timed event into one piece per day it touches. A move takes the grabbed piece's duration (durationMin = entry.endMin - entry.startMin), not the event's.
    • Measured with a throwaway jsdom probe (not committed): a 4-hour event from January 12th 22:00 to January 13th 02:00, dragged by its first-day piece to January 14th at 10:00, reached onEventDrop as 10:00 to 12:00, which is 120 minutes. ObjectCalendar's default drop handler writes the newEnd it is handed (read, not driven through an app).
    • Reach: the calendar's week and day view drag.
    • Dedupe words: week view drag overnight event duration, TimeGridView move durationMin clipped piece, calendar time grid move shortens event.
  • objectui#10866 slice 5, which is serial behind this card. Its ObjectCalendar mixed-event half (a date start with a datetime end) was not measured here. With the grid moving by calendar days, a date start now comes back at local midnight of the dropped day. Re-price that half against this head.
  • Observation, not measured, and out of this card's scope. When a gantt summary bar is dragged, GanttView shifts it and its descendants by one deltaMs (the group move and its live preview). Its axis is continuous time, so it is not known to be the same defect. It is not touched here. Carrier: none.

Commits carry only the model-free trailer pair.


Generated by Claude Code

…nd keeps its wall-clock time (objectui#11005)

Ruled B. MonthView.handleDrop counts the calendar days between the grab
cell and the drop cell from their local year/month/day and moves a local
copy of the start and the end with setDate, for a move and for a drag of
the span's end alike. ObjectCalendar's day-event repair from objectui#10866
slice 4 is removed: with the grid moving by calendar days its answer equals
the plain local-day write, measured by that slice's ten day moves under
America/Los_Angeles and Asia/Shanghai.

Claude-Session: https://claude.ai/code/session_011p7ikEivgXefNDaE5S5Uec
Co-authored-by: Claude <noreply@anthropic.com>
…ME, the plugin page and the changesets (objectui#11005)

The README and the plugin page say a month-grid move and an end drag keep
each value's time of day. The patch changeset declares the change. The
pending objectui#10866 slice-4 changeset keeps its reading of that change,
scoped "at this change", with a dated note naming this card; its front
matter and its gantt and core bullets are untouched.

Claude-Session: https://claude.ai/code/session_011p7ikEivgXefNDaE5S5Uec
Co-authored-by: Claude <noreply@anthropic.com>
@github-actions github-actions Bot added documentation Improvements or additions to documentation plugin tests labels Sep 29, 2026
@github-actions

Copy link
Copy Markdown
Contributor

changeset-claim-re-read

⚠️ 5 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/7313-object-calendar-record-source.md

  • names plugin-calendar/src/ObjectCalendar.tsx → packages/plugin-calendar/src/ObjectCalendar.tsx — edited by this change

    ObjectCalendar resolves its records through the shared ladder (resolveRecordSourceConfig in @object-ui/core, called from plugin-calendar/src/ObjectCalendar.tsx): data first, then staticData, then objectName. The published TypeScript interface REQUIRED objectName and declared neither data nor staticData; the published Zod mirror did the same. So an object-calendar node authored on staticData — the route the plugin page documents twice — rendered correctly and was refused by safeValidateSchema, and could not be annotated with its own type (TS2741: Property 'objectName' is missing).

  • names content/docs/plugins/plugin-calendar.mdx → content/docs/plugins/plugin-calendar.mdx — edited by this change

    A widening. A node authoring staticData or data without objectName now validates (it always rendered — the read is resolveRecordSourceConfig(schema), keyed on the three). Every document that validated before still validates: objectName alone still parses, an empty one included, because presence is !== undefined. The one shape the refinement refuses (none of the three) was refused before too, at objectName. The two static-data examples in content/docs/plugins/plugin-calendar.mdx are now annotated ObjectCalendarSchema and compile under the doc-snippet gate.

.changeset/7712-kanban-calendar-filter-input.md

  • names ObjectCalendar.tsx → packages/plugin-calendar/src/ObjectCalendar.tsx — edited by this change

    ObjectKanban.tsx sends the authored key to the query as $filter: schema.filter and ObjectCalendar.tsx does the same, and @objectstack/spec's ComponentPropsMap declares filter on both blocks (measured: safeParse accepts it, and refuses an undeclared key by name on the same call). But none of the four registrations that publish those two renderers listed filter in inputs, and sdui-parser's validateTree reports unknown-prop for every key no inputs entry claims. So an author writing the one spelling that WORKS was told it was unknown — objectui#6678's shape, where a correct write draws the same diagnostic as a write that does nothing. That is worse than an inert key: it actively punishes the correct behaviour, and the honest response to it is to delete working metadata.

.changeset/8171-calendar-sort-input.md

  • names ObjectCalendar.tsx → packages/plugin-calendar/src/ObjectCalendar.tsx — edited by this change

    objectui#7712's defect, one key over. ObjectCalendar.tsx lowers the authored key onto its own query as $orderby: convertSortToQueryParams(schema.sort), and @objectstack/spec's ComponentPropsMap['object-calendar'] declares sort (measured on 17.2.0: safeParse({ objectName, sort }) returns success: true, while the same strict schema on the same call refuses bogusProp by name — that control is what makes the acceptance a verdict). But neither of the two registrations that publish this renderer — plugin-calendar:object-calendar and view:calendar — listed sort in inputs, and sdui-parser's validateTree reports unknown-prop for every key no inputs entry claims. So an author writing the one spelling that WORKS was told it was unknown — objectui#6678's shape, where a correct write draws the same diagnostic as a write that does nothing.

.changeset/8174-kanban-calendar-filter-sort.md

  • names ObjectCalendar.tsx → packages/plugin-calendar/src/ObjectCalendar.tsx — edited by this change

    filter had four declaration faces and only three of them named it: @objectstack/spec declares it (ComponentPropsMap['object-kanban'] and ['object-calendar']), both plugins' registration inputs publish it, and both renderers read it — ObjectKanban.tsx lowers schema.filter onto $filter, ObjectCalendar.tsx lowers schema.filter onto $filter and schema.sort onto $orderby through convertSortToQueryParams. This package's own published faces (the TypeScript interface and its zod mirror) named none of them, so an authored value reached the renderer only through BaseSchema's index signature and the mirror's .passthrough() — admitted, never examined. That is the same reasoning finding(types,plugin-kanban): ObjectKanbanSchema requires groupField (zero read sites) and declares neither groupBy nor limit — no working object-kanban node is assignable to any declared type #7322 used to move groupBy and limit into this same interface.

.changeset/8466-calendar-color-allday-fields.md

  • names ObjectCalendar.tsx → packages/plugin-calendar/src/ObjectCalendar.tsx — edited by this change

    ObjectCalendar.tsx's getCalendarConfig reads FIVE flat keys off the node, and packages/plugin-calendar/README.md teaches all five in one sentence — "point titleField / startDateField / endDateField / allDayField / colorField at your own fields when they differ." Only three of the five were declared. The other two reached the renderer through BaseSchema's [key: string]: any on the TypeScript face and its .passthrough() on the zod mirror: admitted, never examined. A misspelling therefore left the calendar silently colourless while every published gate passed.

  • names packages/plugin-calendar/README.md → packages/plugin-calendar/README.md — edited by this change

    ObjectCalendar.tsx's getCalendarConfig reads FIVE flat keys off the node, and packages/plugin-calendar/README.md teaches all five in one sentence — "point titleField / startDateField / endDateField / allDayField / colorField at your own fields when they differ." Only three of the five were declared. The other two reached the renderer through BaseSchema's [key: string]: any on the TypeScript face and its .passthrough() on the zod mirror: admitted, never examined. A misspelling therefore left the calendar silently colourless while every published gate passed.

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 e327c8998 (merge-base with origin/main): 7 file(s) changed outside .changeset/, read against 1714 pending declaration(s) that publish a body (2318 pending in total). · run

@github-actions

Copy link
Copy Markdown
Contributor

✅ Console Performance Budget

Metric Value Budget
Eager closure (gzip, 330 chunks) 3105.2 KB 3149.4 KB
Main entry chunk (gzip) 149.4 KB 350 KB
Entry file index-CDN106Dg.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) 16.72KB 6.21KB
app-shell (runtime-config.js) 20.68KB 7.36KB
app-shell (types.js) 0.01KB 0.04KB
app-shell (urlParams.js) 10.06KB 3.86KB
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) 18.17KB 5.40KB
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.29KB 0.66KB
auth (authStyles.js) 5.04KB 1.72KB
auth (createAuthClient.js) 40.70KB 10.94KB
auth (createAuthenticatedFetch.js) 8.52KB 3.45KB
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.13KB 7.95KB
collaboration (LiveCursors.js) 3.17KB 1.27KB
collaboration (PresenceAvatars.js) 6.49KB 2.64KB
collaboration (PresenceProvider.js) 2.79KB 1.13KB
collaboration (index.js) 1.68KB 0.73KB
collaboration (useCollaborationTranslation.js) 6.05KB 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) 558.92KB 133.97KB
core (index.js) 9.93KB 3.94KB
create-plugin (index.js) 27.94KB 9.51KB
data-objectstack (index.js) 227.62KB 63.16KB
fields (index.js) 261.01KB 66.28KB
i18n (LocalizationContext.js) 1.76KB 0.96KB
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.24KB 2.27KB
i18n (pickLocalized.js) 9.86KB 3.95KB
i18n (provider.js) 39.40KB 12.91KB
i18n (translateFn.js) 0.20KB 0.18KB
i18n (useDisplayLocale.js) 3.52KB 1.76KB
i18n (useObjectLabel.js) 34.35KB 9.18KB
i18n (useSafeTranslation.js) 5.60KB 2.33KB
layout (index.js) 39.32KB 11.09KB
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) 13.53KB 4.89KB
permissions (PermissionContext.js) 0.31KB 0.25KB
permissions (PermissionGuard.js) 0.89KB 0.45KB
permissions (PermissionProvider.js) 6.25KB 2.17KB
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.01KB 3.93KB
plugin-calendar (index.js) 52.02KB 14.87KB
plugin-charts (index.js) 84.09KB 22.93KB
plugin-chatbot (index.js) 198.22KB 46.97KB
plugin-dashboard (index.js) 137.56KB 36.67KB
plugin-designer (index.js) 215.78KB 44.42KB
plugin-detail (index.js) 233.49KB 61.79KB
plugin-editor (index.js) 2.23KB 1.05KB
plugin-form (index.js) 162.67KB 41.95KB
plugin-gantt (index.js) 170.35KB 42.19KB
plugin-grid (index.js) 228.33KB 62.59KB
plugin-kanban (index.js) 48.43KB 15.11KB
plugin-list (index.js) 115.86KB 28.64KB
plugin-map (index.js) 22.90KB 7.62KB
plugin-markdown (index.js) 13.88KB 4.80KB
plugin-report (index.js) 44.17KB 12.20KB
plugin-timeline (index.js) 31.07KB 9.15KB
plugin-tree (index.js) 11.21KB 3.89KB
plugin-view (index.js) 89.54KB 22.44KB
providers (DataSourceProvider.js) 0.75KB 0.39KB
providers (MetadataProvider.js) 1.37KB 0.59KB
providers (ThemeProvider.js) 1.90KB 0.85KB
providers (UploadProvider.js) 11.81KB 3.58KB
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) 119.16KB 39.05KB
react (data-invalidation.js) 5.05KB 2.08KB
react (index.js) 4.03KB 1.86KB
react (schema-input.js) 4.25KB 2.04KB
react (spec-input.js) 0.20KB 0.18KB
sdui-parser (body-dialect.js) 4.78KB 2.09KB
sdui-parser (codegen.js) 7.50KB 3.05KB
sdui-parser (dashboard-widget-options.js) 3.08KB 1.30KB
sdui-parser (index.js) 6.16KB 2.71KB
sdui-parser (input-type.js) 2.84KB 1.40KB
sdui-parser (kanban-quick-add.js) 3.89KB 1.87KB
sdui-parser (parse.js) 25.28KB 7.80KB
sdui-parser (provenance.js) 3.84KB 1.90KB
sdui-parser (types.js) 0.28KB 0.23KB
sdui-parser (validate.js) 18.27KB 6.22KB
types (ai.js) 4.39KB 2.17KB
types (api-types.js) 0.20KB 0.18KB
types (app.js) 3.83KB 1.49KB
types (base.js) 0.20KB 0.18KB
types (blocks.js) 0.20KB 0.18KB
types (complex.js) 3.19KB 1.62KB
types (crud.js) 0.20KB 0.18KB
types (dashboard-filter-alias.js) 6.23KB 2.74KB
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) 0.20KB 0.18KB
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) 4.74KB 2.26KB
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 (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-components.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) 5.05KB 1.93KB
types (spec-ui-namespace.js) 0.20KB 0.19KB
types (strict-authoring-face.js) 19.30KB 6.99KB
types (system-fields.js) 3.33KB 1.54KB
types (theme.js) 6.28KB 2.87KB
types (ui-action.js) 8.11KB 3.32KB
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: CONTRACT_REVIEW_TIER
Head-sha: 600e84cb52cab4b9e59d956a86e3c3ed0421233a
Local-runs: none

① Derived judgments

Inputs read: card #11005 (body; comments 5874661711 decision-box, 5881826705 ruling B, 5882077455 claim, 5882783174 os-dev-report), PR #11036 (body, nine-file list, net diff against main), the 43 check-runs on the head (40 success; 3 skipped conditional lanes: coverage, coverage shard, dependabot; none failed, none pending), plus contents reads at the head for context only: CalendarView.tsx, ObjectCalendar.tsx, .changeset/10866-calendar-gantt-date-only-days.md, vitest.config.mts, the root listing. Nothing built, run or re-run.

  1. Month-grid move — RIGHT. MonthView.handleDrop now counts calendarDaysBetween(anchorDay, newTargetDay) (difference of local Y/M/D taken on the UTC calendar, so always a whole number) and applies moveByCalendarDays (setDate on a copy) to the start and to the end. That is the ruled form in 5881826705: the calendar days between the grab cell and the drop cell, applied with setDate on a local copy, hours / minutes / seconds untouched. Public surface: the instants CalendarViewProps.onEventDrop receives from a month-view drag change across a DST change (10:00 stays 10:00; a local-midnight start lands at midnight of the dropped day). Ruled, deliberate, and stated in the changeset. The legacy no-sourceDay fallback (anchor at the event's start day) is preserved.
  2. Month-grid resize-end — RIGHT. The end moves by calendarDaysBetween(oldEnd, newTargetDay) through moveByCalendarDays; the start is handed back unchanged; the two guards (same cell, drop before the start day) are kept. Read at the head: the handle renders only where isSpanEnd, and eventsByDate puts that on the end's own local day (a midnight end included), so the grabbed cell is the end's day and the ruling's grab-cell-to-drop-cell wording holds for the end drag. Milliseconds are now kept where the old setHours(h, m, s, 0) zeroed them: a consequence of the ruled setDate-on-a-copy form, not an addition.
  3. ObjectCalendar day repair removed — RIGHT. toMovedDateValue, isStoredDay and DAY_MS are deleted (all module-private; no export touched) and the default drop handler writes through toStoredDateValue again. A date read at local midnight (toDisplayDate) and moved by setDate stays at local midnight of the dropped day, and toStoredDateValue writes its local day: the same day the repair wrote. The ruling's condition ("removed once measured redundant") is met: slice 4's ten day moves in ObjectCalendar.dstDayMove-10866 are untouched and green on the head, and the dev's ablation (base grid put back with the repair still gone: four Los Angeles day moves red) shows B is what makes it redundant.
  4. Week and day views unchanged — RIGHT. The ruling has them ride only if their drop arithmetic is the same elapsed-time form. Read at the head: TimeGridView's move places the start with setHours(0, snapped) on the drop column's own day, and its two resizes with setHours(0, minutes) on that day; there is no two-midnights deltaMs. Not the ruled form, so not riding is the correct reading. (Its end is newStart plus durationMin in milliseconds, a same-day duration form; see ③.)
  5. Ruled zone pins — RIGHT and complete. New CalendarView.monthMoveCalendarDays-11005: Los Angeles six moves and two end drags, including the card's exact case (Nov 1 00:00 PDT, grabbed on the 2nd, dropped on the 3rd, now Nov 2 00:00 PST); Shanghai four drags at exactly N x 24 h; two suite-zone cases; a rig case and a fixture-validity case per zone so a child whose zone did not move goes red. Registered in the driver's PINS; scripts/**/*.test.ts is in the root unit project, so the driver (which fails unless every pin ran and passed in a forks child) runs inside CI's Test shards, all success. The ruling's five pins map one to one: DST wall-clock kept; local-midnight instant lands on the dropped day; date-only unchanged (the ten day moves); zone without DST as before; resize-end under the same rule. The single changed expectation in dstDayMove-10866 (first Los Angeles datetime control's end, 09:00 to 10:00 PST on Nov 2) is exactly the ruled instant change; every other expectation there is untouched.
  6. Docs (README gesture table, plugin mdx month-view bullets) — RIGHT. Prose only; each states the ruled behaviour (time of day kept for a move and for an end drag).
  7. No other public-surface movement. export { CalendarView } and the test-only export are unchanged; no prop, type or config accept set moves. README Export Check success.

② Semver level

  • .changeset/11005-month-grid-calendar-days.md: '@object-ui/plugin-calendar': patch — RIGHT. The diff publishes a behaviour fix inside one released package with no API added, removed or re-signed; the ruling prices it patch. Its prose matches the diff (move; end drag including milliseconds; date fields through the repair's removal; week and day views unchanged). Changeset Declaration, Changeset Bump Policy, Changeset Fixed Group Check, Changeset Claim Re-read and Changeset Overwrite Report: all success on the head.
  • Reconciliation — RIGHT. .changeset/10866-calendar-dst-day-moves.md (slice 4) carried two sentences this diff falsifies ("The month grid moves each date of an event by the milliseconds…" and "the grid's own arithmetic does not change"); both are now scoped "at this change" with a dated note naming objectui#11005; the front matter is untouched (the hunk starts at line 7) and the gantt and core bullets are untouched. The order's named file, .changeset/10866-calendar-gantt-date-only-days.md (slice 1), read at the head: its "A datetime field keeps its instant" sits under Writes and describes the type split (instant, not day), which the ruling itself says still governs the binding; no sentence there is falsified, so leaving it untouched is right.
  • Clause-②: no on the PR body — RIGHT; it matches the ruling's execution parameter and the claim's reading: the written instant changes by ruling, and no declared field shape, schema or accept set moves.

③ Boundary flags

Dev flags (deviations in os-dev-report 5882783174), each answered:

  1. File-surface additions (driver PINS entry; packages/plugin-calendar/README.md; content/docs/plugins/plugin-calendar.mdx) — ACCEPTED. The PINS entry is the only way the runIf(DRIVEN) zone cases run at all, so it is part of "zone pins under Los Angeles and Shanghai"; the two docs are prose under the repo's docs-driven rule. Neither plugin-gantt nor an objectui#10866 slice-5 item is touched: both of the claim's ⛔ bounds hold.
  2. Reconciled slice 4's changeset rather than the named slice-1 file — ACCEPTED (see ②): the named file is not falsified and the slice-4 file was; the conditional's purpose, that no false pending sentence ships, is served.
  3. resize-end now keeps milliseconds — ACCEPTED. The ruled setDate-on-a-copy form keeps every sub-day component; "hours / minutes / seconds untouched" is a floor, not an instruction to zero milliseconds. Pinned, and stated in the changeset.
  4. Commit-trailer form — NOT A CONTRACT ITEM. No gate reads it; the repo's AGENTS.md governs trailers.
  5. Lint narrowed locally; check-doc-snippet-types, check-doc-example-types, check-readme-exports NOT MEASURED locally — ANSWERED BY THE HEAD'S CHECK-RUNS: Lint, Doc Snippet Type Check, Doc Component Type Check, Doc Example Id Check and README Export Check are all success.

open_questions: empty — nothing to answer.

For the seat, from the report's out-of-scope notes; none bears on this verdict: (a) a week or day view move of an overnight timed event shortens it to the grabbed piece's duration — pre-existing and DST-independent, and readable in the head source (durationMin: entry.endMin - entry.startMin, newEnd = newStart + durationMin); the same line also means a time-grid event spanning the transition hour itself gets an elapsed-duration end, a same-day form outside this ruling; carrier to be chosen. (b) objectui#10866 slice 5's mixed-event half is to be re-priced against this head, since a date start now comes back at local midnight of the dropped day. (c) GanttView moves a summary bar and its descendants by one deltaMs on a continuous axis: observation only, out of scope. The PR is still a draft.

Implemented-by: claude/issue-11005-month-grid-calendar-days
Reviewed-by: session_011p7ikEivgXefNDaE5S5Uec

VERDICT: PASS


Generated by Claude Code

@objectstack-fleet
objectstack-fleet Bot marked this pull request as ready for review September 29, 2026 03:23
@objectstack-fleet
objectstack-fleet Bot added this pull request to the merge queue Sep 29, 2026
Merged via the queue into main with commit f9b6dfe Sep 29, 2026
45 checks passed
@objectstack-fleet
objectstack-fleet Bot deleted the claude/issue-11005-month-grid-calendar-days branch September 29, 2026 03:38
akarma-synetal pushed a commit to akarma-synetal/objectui that referenced this pull request Oct 7, 2026
…s repository; the RETIRED_ACTION_KEYS.execute pointer among them (objectui#11016) (objectstack-ai#11041)

Fixes objectstack-ai#11016
Clause-②: no

Dispatched implementation of the `domain:ui` seat 2 claim (comment
`5882822760`) on objectui#11016, triage direction `5876435318`, session
`https://claude.ai/code/session_011p7ikEivgXefNDaE5S5Uec`. Citations
only: a bare number whose sentence means an objectstack card now names
its repository as `objectstack-ai/objectstack#N`, as triage direction 2
spells it. No key, accept set, refusal decision or code path moves.

In this body a census number is written in a code span, so GitHub links
it to nothing.

## What changed, by class (one commit each)

1. **Runtime strings (2 sites, `patch`).**
- `@object-ui/core` `RETIRED_ACTION_KEYS.execute`, the dev warning for
an action still carrying the retired `execute` key, now reads "`execute`
was removed in @objectstack/spec 17 (objectstack-ai/objectstack#3855) —
rename the key to `target`. …". The card is live, so the pointer is
qualified rather than dropped (triage item 1; ruling `5860244997` Q1 = A
covers dead cards only). The rest of the message is byte-identical, and
the one test that pins its text (`actionKeys.pin.test.ts`, "rename the
key to `target`") still reads it.
- `@object-ui/app-shell` metadata-admin `default-schemas.ts`, the Studio
skill form's `triggerConditions` help text: its two bare numbers mean
objectstack cards `1878` and `1895` and now name them.
2. **Source comments.** Every other in-class site is a `//`, `/* */`,
JSX or doc comment in non-test `packages/*/src`: 350 bare numbers on 337
lines in 143 files across 24 packages, requalified in place. One more is
held (**Held** below).
3. **Pending changesets.** The 10 in-class sites in 9 pending entries
get a dated note each, in the form objectui#10877 used (`⚠️ **Dated
note, 2026-09-29 — … — objectui#11016.**`, what the number means, then
"The text above is kept as the reading of this change."). The note names
the card and never repeats the bare token. The frontmatter block is
md5-identical at the branch point and this head in all nine.
4. **Patch round 1: the qualified form of the same defect (claim
amendment `5883408510`, bounded in-place fix, commit `ba91ecf76`).** Two
`PackageFormDialog.tsx` comments (the `readEnvelopeUserMessage` docblock
and the objectui#8051 catch-arm comment) wrote `objectui#3821` for the
generic-substitution card and now write
`objectstack-ai/objectstack#3821`. The pending
`.changeset/violet-donkeys-brake.md`, which would publish that spelling
at the next release, gets a dated note in the form of the other nine: it
names objectstack-ai/objectstack#3821, the sharing-rule dialog card. Its
frontmatter md5 is `4e8ce550` at both `29d0e9ae2` and `ba91ecf76`. The
test file's doc comment is untouched, because tests are outside the
class. Evidence on `ba91ecf76`: the comment-stripping print of
`PackageFormDialog.tsx` is identical to `29d0e9ae2`, with 0 parse
diagnostics; `pnpm exec vitest run` over the five
`PackageFormDialog.*.test.tsx` files gives `Test Files 5 passed (5)`,
`Tests 67 passed (67)`; `pnpm exec eslint` on the file gives 0 errors;
`check:changeset-claims`, `check:pending-changeset-literals`,
`check:control-bytes` and `check:new-line-citations` all exit 0; trial
merges are unchanged.

Plus `.changeset/11016-cross-repo-bare-citations.md`: `patch` for
`@object-ui/core` and `@object-ui/app-shell`, the two packages whose
shipped runtime text moves; the comment-only packages need no entry of
their own, as in the objectui#10803 batches: every package here versions
as one group.

## Census (read before editing)

**Population.** The instrument is the one objectui#10803's batches used.
Its primary form is below; the blind-spot form swaps the lookbehind for
`(?<=[/.\-])`:

```
git grep -nP '(?:^|(?<=[^\w#&/.\-]))#\d+(?![0-9A-Za-z_])' REF -- '.changeset/*.md' 'packages/*/src/**' ':!**/__tests__/**' ':!**/*.test.*' ':!**/*.spec.*' ':!**/test/**' ':!**/tests/**'
```

At the branch point `e327c8998` it finds 3880 bare occurrences: 3694 in
the primary form and 186 after `/`, `.` or `-`, with 1005 distinct
values. A number written after an already-qualified one
(`objectui#9469/objectstack-ai#8649`, `framework#1878/objectstack-ai#1891`) inherits that qualifier
and is out of the bare class.

**Titles.** Both repositories' full issue and pull-request title lists
were read over REST: `issues?state=all`, cursor pagination. objectui
gives 10653 items (max `11037`); objectstack gives 18394 (max `20567`).
A number absent from a list answers 404 there.

**Reading.**
- Every distinct number between 100 and 25000 (952 of them, hex colours
excluded) was read with both titles beside every sentence that cites it,
grouped by number.
- Where a title did not settle it, the card or the landing commit was
read. For example, objectstack `1890`'s comment `4708800480` carries the
form-layout note two ObjectView/ModalForm comments cite. objectui PR
`2078`, not objectstack's same-numbered release PR, is the spec 11.2.0
bump a clientValidation comment cites.
- The 668 occurrences below 100 were read too: commandment numbers,
decision-batch numbers, React error codes and colours, none of them a
card. Above 25000 there are only hex colours.

**Verdicts.**
- **objectstack**: 105 numbers, 364 occurrences, 350 lines, 153 files
(144 source files, 9 pending changesets). The table below lists them.
- **objectui**: every other card citation, left bare. That includes the
sentences in mixed numbers that mean the objectui card: for `2212`, only
the six pagination lines mean objectstack's `findData` card, and the
`visibleOn` lines stay.
- **neither repository**: 10 numbers (**Acceptance notes** 2).
- **not a card**: decision batches, React errors, and one changeset's
GitHub Actions run numbers.

**Lit controls.**
- The review's floor is found in full: all 10 numbers on its 18 lines,
plus a third `8955` site the review did not list (plugin-detail
`buildDefaultPageSchema.ts`).
- The known hit `actionKeys.ts` `3855` is found.
- The negative control holds: `2078` sits beside "spec 11.2.0" and means
objectui's bump PR, and it stays bare.

**After, reconciled at this head.** Re-running the instrument, every
(file, number) count dropped by exactly the number of sites edited in
that file (0 mismatches), and no new bare occurrence appeared anywhere
in the classes (0 added). Of the 364, 11 remain: the 10 changeset sites,
now carrying their notes, and the 1 held site. The census verdicts come
from reading, and nothing re-derives them mechanically; the instrument
above re-derives the population.

## Special cases

- **Quotations of objectstack's own text** keep their words, and the
card name sits in square brackets, objectui#10803's editorial mark for a
substituted word. There are five:
- `apiErrorEnvelope.ts`, the `(objectstack-ai#3821)` in the quoted envelope-writer
sentence.
  - `widget.ts`, a quoted `RETIRED_DEFS_BY_MAJOR` entry.
  - `data-protocol.ts`, a quoted spec comment.
- `ValueDataSource.ts` and `filter-converter.ts`, a quoted refusal
message each.
- **The quoted `(objectstack-ai#3821)` is named, and triage's premise about it did not
hold.** Triage item 4 says neither `3821` is the card. Measured:
objectstack `3821` is the sharing-rule dialog card, and the objectui
change that repaired it, objectui#2920 (`53642d4fe`), is the change that
first replaced a refused write's raw server text with localized copy,
the generic substitution the sentence names. The comment now says that.
The three sibling "… holds by construction" comments in `form.tsx`,
`ObjectCalendar.tsx` and `ObjectKanban.tsx` mean the same card and are
qualified the same way.
- **The paraphrased spec tag `@deprecated [objectstack-ai#2578 -> size]`** (calendar,
gantt, kanban) is corrected inside its code span, with no extra
brackets: the tag's own syntax already uses them.
- **Words folded into the name.** "framework #N" (objectstack's former
name), "ObjectStack #N", "ObjectStack framework #N" and "objectstack #N"
become the one qualified name. "issue", "PR", "pre-" and "upstream"
stay.

## Held (serial rule)

The census hit in `plugin-grid` `ObjectGrid.tsx`, the server-side
pagination comment ending "reachable at all (framework `2212`).", is not
edited. Open draft objectui#10278 inserts lines directly beneath it.
Qualifying it here added a conflict hunk: 3 conflict markers in that
file against objectui#10278's head, versus 2 without this change. With
it held, the count is 2 either way. The line waits for objectui#10278 to
land or close.

## Proof of prose-only (C4), against current `main` `2eaf5be27`

- Each of the 144 touched `.ts`/`.tsx` files was parsed on both sides
with TypeScript's `createSourceFile` and re-printed by `createPrinter({
removeComments: true })`. 142 prints are identical and 2 differ, exactly
the two runtime-string files (`actionKeys.ts`, `default-schemas.ts`),
with 0 parse diagnostics.
- Lit controls on the same instrument: re-spacing a comment in
`actionKeys.ts` leaves the print unchanged, and editing its string
literal moves it. Both anchors were confirmed on disk, one each.
- Both changed literals are values in string-keyed `Record` types whose
values are typed `string` and `unknown`, so no type moves.

## Serial and trial merges

`main` was merged in before opening (`29d0e9ae2`). objectui#11038,
objectstack-ai#11036, objectstack-ai#11034 and objectstack-ai#11032 had landed in the meantime; the auto-merges in
`RecordDetailView.tsx`, `en.ts`, `ObjectCalendar.tsx` and plugin-view
`ObjectView.tsx` were clean. Re-reading the instrument on the merged
tree finds nothing new.

`git merge-tree --write-tree` of this head with each open pull request's
head, fetched into named refs:
- objectui#11033 (it holds `ActionRunner.ts` and `en.ts`, both of which
carry census edits here): clean.
- objectui#10930 (`dashboard-filters.ts`): clean.
- objectui#10278: conflicts in `plugin-grid.mdx`, plugin-grid
`README.md` and `ObjectGrid.tsx`, the same three files as against `main`
alone, with the same 2 conflict markers in `ObjectGrid.tsx` (see
**Held**).
- objectui#5400 (release): it deletes the pending changesets it
consumes, so the 9 noted entries show modify/delete conflicts, as every
edit of a pending entry does. It regenerates, and it is not a hold. If
it lands first, those notes have no file to land in.

## Gates and tests

Each line gives the gate's own verdict and its exit code, captured by
redirect-then-`$?`. On this head `29d0e9ae2`:
- `node scripts/check-changeset-presence.mjs --base 2eaf5be`, exit 0:
"143 source file(s) of 23 released package(s) changed, and this change
declares 1 changeset(s): .changeset/11016-cross-repo-bare-citations.md."
- `pnpm changeset:check`, exit 0: fixed group complete; "No changeset
declares a `major` bump."
- `pnpm check:changeset-claims` (report-only), exit 0. Its standing
notice lists pending entries that name a touched file. A pending entry
quoting a replaced spelling would carry a bare number the census sees,
and the census found exactly the nine entries noted here.
- `pnpm check:pending-changeset-literals`, exit 0: "No test source names
a pending changeset."
- `pnpm check:control-bytes`, exit 0: "OK (scanned 9331 tracked text
file(s); skipped 85 binary)."
- `pnpm check:new-line-citations`, exit 0: "VERDICT
new-cross-file-line-citations: 0 new citation(s), enforcement
report-only -> exit 0".
- `pnpm check:spec-symbols`, exit 0. `pnpm check:action-forward-parity`,
exit 0; it reads `RETIRED_ACTION_KEYS` off `actionKeys.ts`. `node
scripts/check-doc-links.mjs`, exit 0: "Links are valid across 17 scan
roots."
- `pnpm exec vitest run packages/core/` through the shared verify lock:
`Test Files 184 passed (184)`, `Tests 3658 passed | 27 skipped (3685)`,
`VERDICT command-exit 0`.
- `@object-ui/core` type-check, after building its dependency closure
(`@object-ui/types`): exit 0.

On `5d8eefd71`, the pre-merge head with the same diff over the older
base:
- `pnpm exec vitest run scripts/__tests__/`, the whole-tree scanner
suite: `Test Files 177 passed | 2 skipped (179)`, `Tests 5350 passed | 2
skipped (5352)`, `VERDICT command-exit 0`.
- `pnpm exec eslint` on the 144 touched source files: 0 errors. The
config enables no type-aware linting and no rule reads comments, and C4
shows no code token moved, so no untouched file's verdict can move
either.
- `pnpm check:installed-pin-claims` "OK". `pnpm
check:comment-mask-corpus` exit 0 (1 disagreeing file, within
objectui#7882's ceiling). `node
scripts/check-hand-rolled-comment-mask.mjs` "OK every carrier is a DEBT
entry". `pnpm check:handler-key-reads` exit 0.
- `node scripts/check-governed-queue-guard.mjs --test` over the 154
paths: "NOT GOVERNED".

**Declared narrowing.**
- Type-check ran for `@object-ui/core` only. The other 23 packages
change comments only, and `@object-ui/app-shell` changes one string
value typed `unknown` (C4). Their type-check is CI's.
- Package test suites ran for `packages/core/` only. No test pins the
app-shell help text: a search of tests, e2e and apps for its wording
finds nothing. The rest is CI's.

## Census table

`sites` counts this change's in-class occurrences of the number. "(k
stay objectui)" counts sentences citing the same number that mean the
objectui card, left bare. Titles are trimmed.

| number | objectstack title (what the sentence means) | objectui title
(what the bare number resolved to) | sites | files |
|:--|:--|:--|:--|:--|
| `1319` | [P2] i18n: zh-CN ↔ English switch occasionally garbled —
requires page… | chore: release packages | 4 |
app-shell/console/ConsoleShell.tsx, auth/createAuthenticatedFetch.ts,
data-objectstack/index.ts, i18n/provider.tsx |
| `1479` | Implement structured control-flow constructs (ADR-0031): loop
containe… | feat(auth): standalone shell-less /set-password page fo… | 1
| app-shell/views/metadata-admin/previews/FlowRunsPanel.tsx |
| `1505` | Surface per-iteration / per-region step logs in run
observability (ADR… | refactor: unify runtime dashboard editor onto
studio's … | 5 |
app-shell/views/metadata-admin/previews/FlowRunsPanel.tsx |
| `1604` | Cross-object atomic batch write (master-detail
parent+children in one … | chore(deps): upgrade @objectstack/spec from
^7.8.0 to ^… | 3 | core/adapters/batchTransaction.ts,
data-objectstack/index.ts, types/data.ts |
| `1752` | Report drill-down: date-granularity dimensions need a range
filter, no… | chore(deps): bump @sentry/react from 10.56.0 to 10.57.0 |
13 | changeset 9137-dataset-drill-conjoin-widget-filter.md,
app-shell/views/drillUrlFilters.ts, app-shell/views/ObjectDataPage.tsx,
app-shell/views/useOpenRecordList.ts, +4 more · changeset note |
| `1753` | Matrix reports: server-side totals row/column (subtotals +
grand total… | chore(deps): bump lucide-react from 1.17.0 to 1.18.0 | 1
| plugin-dashboard/DatasetWidget.tsx |
| `1874` | [P2] Provide a declarative time-relative trigger (avoid
fragile date-e… | chore(home): remove redundant "Make this home yours"
em… | 1 | app-shell/views/metadata-admin/inspectors/flow-node-config.ts
|
| `1878` | [P0] Metadata property liveness audit: ~half of all spec
properties ar… | fix(console-ai): actually render the "Proposed plan"
ca… | 1 | app-shell/views/metadata-admin/default-schemas.ts · runtime
string |
| `1885` | [P0][security] Action disabled (CEL form) silently ignored |
Add a tree / tree-grid object view type for self-refere… | 7 |
app-shell/views/DeclaredActionsBar.tsx,
components/renderers/action/action-button.tsx,
components/renderers/action/action-group.tsx,
components/renderers/action/action-icon.tsx, +2 more |
| `1890` | [P1] Finish ADR-0021 analytics migration (chart view /
dashboard+Studi… | feat(app-shell): testability ratchet — ban
synthetic-ev… | 14 | app-shell/console/AppContent.tsx,
app-shell/views/ObjectView.tsx, app-shell/views/RecordFormPage.tsx,
plugin-charts/ObjectChart.tsx, +5 more |
| `1895` | [P2] Designer authoring gaps (live prop, no Studio editor) |
chore(deps): bump the patch-updates group with 32 updat… | 1 (1 stay
objectui) | app-shell/views/metadata-admin/default-schemas.ts · runtime
string |
| `2169` | fix(showcase): register Mark Done action handler via inline
body | feat(studio): Data rail search + inline new-object (dra… | 4 |
app-shell/views/metadata-admin/anchors.ts, core/actions/actionKeys.ts,
core/actions/ActionRunner.ts |
| `2183` | fix(showcase): hide Mark Done once the task is complete |
fix(app-shell): don't show recovery-password reminder o… | 2 |
components/renderers/layout/containers.tsx, core/actions/ActionEngine.ts
|
| `2212` | findData 列表分页失效:total 永远等于本页条数、hasMore 恒为 false | Form-view
FormField.visibleOn (CEL) is never evaluated … | 6 (12 stay objectui) |
data-objectstack/index.ts, plugin-grid/ObjectGrid.tsx,
plugin-list/ListView.tsx · 1 held |
| `2552` | objectql: write pipeline accepts scalar values for
multi-value fields … | fix(spec-bridge/form): stop dropping spec
FormViewSchem… | 1 | plugin-grid/hooks/multiValueFields.ts |
| `2555` | Runtime view overlay drops viewKind/object — one grid sort
permanently… | Studio package-create UX dogfood follow-ups (2026-07 br…
| 1 (2 stay objectui) | data-objectstack/index.ts |
| `2578` | 字段多的对象:自适应呈现表面 + 语义 field span(auto/full)+ 表单布局防呆
lint(AI-authored,ADR… | Dashboard-level filters follow-ups: showcase,
more exam… | 20 (3 stay objectui) | changeset
gantt-navconfig-comment-once.md, changeset
kanban-calendar-nav-width-converge.md, app-shell/views/ObjectView.tsx,
plugin-calendar/ObjectCalendar.tsx, +10 more · changeset note |
| `2604` | Design: record create/edit/subtable surface + return-flow
model (follo… | feat(detail+fields+components+app-shell): record inline…
| 15 | app-shell/console/AppContent.tsx, app-shell/urlParams.ts,
app-shell/utils/recordFormNavigation.ts,
app-shell/views/RelatedRecordActionsBridge.tsx, +2 more |
| `2611` | defineMapping artifacts are registered but never consumed —
wire named… | fix(actions): defuse the three action-visibility traps … |
7 | data-objectstack/index.ts, plugin-grid/ImportWizard.tsx,
plugin-grid/savedMapping.ts, types/data.ts |
| `2670` | 记录页头审批决策按钮(Approve/Reject)被 app 动作挤进溢出菜单;建议审批动作可优先渲染 + Action
增加显式排序 | Flow designer: render loop / parallel / try_catch as ne… | 1
(23 stay objectui) | components/renderers/action/action-bar.tsx |
| `2675` | flow notify 节点无法给通知附带点击跳转目标(source_object/source_id)——inbox
通知点不进对应记录 | feat(studio): visualize loop/parallel/try_catch nested … | 1
| app-shell/views/metadata-admin/inspectors/flow-node-config.ts |
| `2707` | [spec/cli] 对象 enable.files/trackHistory/activities/feeds 为
dead proper… | fix(app-shell): guard ActionParamDialog submit during f…
| 4 | app-shell/utils/pageSchemaIntrospect.ts,
app-shell/views/RecordDetailView.tsx |
| `2727` | [objectui/framework] enable.files: generic Attachments
related-list (S… | fix(plugin-charts): draw dashboard bars on first
paint … | 5 (3 stay objectui) |
app-shell/views/RecordAttachmentsPanel.tsx,
app-shell/views/RecordDetailView.tsx,
plugin-detail/synth/buildDefaultPageSchema.ts |
| `2755` | [attachments] v1 follow-ups: sys_file orphan lifecycle +
non-admin per… | feat(data-objectstack): gate non-atomic batch fallback
… | 3 | app-shell/views/RecordAttachmentsPanel.tsx |
| `2782` | feat(console/auth): 复用 objectui ImportWizard 接入 sys_user
身份导入(替代原 acti… | fix(app-shell): map raw sys_activity rows in the inbox
… | 1 | auth/types.ts |
| `2926` | app-showcase 权限模型复测清单(07-15 对照 main 重评):1 项回归级重大缺陷(N 锚点写护栏被
A4 词表打穿)+ … | feat(setup): the datasource list shows the real connect… |
5 | fields/index.tsx, permissions/MePermissionsProvider.tsx |
| `2948` | security: 服务端 readonly 字段在 UPDATE 时未强制(可被用户上下文覆盖) |
feat(views): the list toolbar speaks one vocabulary — u… | 1 |
data-objectstack/userState.ts |
| `2970` | [attachments] v2 tracking: parent-visibility inheritance,
authed downl… | fix(app-shell)!: the server-action URL identifies an ac…
| 3 | app-shell/views/RecordAttachmentsPanel.tsx |
| `2998` | spec: structured form button/defaults config on
FormViewSchema + enrol… | fix(plugin-form): block page unload while a
modal/drawe… | 6 | app-shell/views/RecordFormPage.tsx,
plugin-form/ObjectForm.tsx, plugin-view/ObjectView.tsx,
types/objectql.ts |
| `3165` | enhancement: state_machine 校验规则在 INSERT 上是 no-op ——
无法强制记录的初始状态(declar… | record:activity 的 feed 结构上不可能有内容——11 个声明的输入全是空
feed 上的过… | 1 (3 stay objectui) |
core/validation/validators/object-validation-engine.ts |
| `3266` | [P1] approvals: quorum (M-of-N) + grouped per-group sign-off
(会签) + de… | console preview-samples: 除 tool 外还有 11 个样例过不了对应的 spec s… |
1 | app-shell/views/metadata-admin/inspectors/flow-node-config.ts |
| `3271` | feat(client): 类型化 data.batchTransaction() —— master-detail
保存统一走原子跨对象批… | fix(components): translate the built-in select branch's…
| 2 | data-objectstack/index.ts |
| `3298` | discovery 广播「跨对象原子 batch」能力位(让客户端声明式协商,取代 404/405/501 运行时探测)
| fix(components): deliver aria-required to field control… | 9 (1 stay
objectui) | data-objectstack/index.ts |
| `3371` | Console command palette (⌘K) doesn't surface record search
hits though… | fix(app-shell): flow 设计器不再给 wait 种子写入 spec 17 已退役的 wait…
| 5 | app-shell/chrome/CommandPalette.tsx,
app-shell/views/SearchResultsPage.tsx, data-objectstack/index.ts,
react/hooks/useRecordSearch.ts |
| `3405` | 动作参数弹窗:内联 lookup 参数无法声明引用目标(配置被静默剥离 + 文案谎报「即将上线」) |
fix(fields): 注册路径的全屏长文本对话框接上 i18n(N) | 10 |
app-shell/utils/paramToField.ts, app-shell/utils/resolveActionParams.ts,
app-shell/views/ActionParamDialog.tsx,
app-shell/views/metadata-admin/previews/ActionPreview.tsx, +1 more |
| `3407` | service-automation: update_record reports success when
written fields … | record:highlights block 的 inputs 声明 readonly,使其进入
sdui.… | 3 | app-shell/views/metadata-admin/previews/FlowRunsPanel.tsx |
| `3424` | Approval routed to an empty position permanently locks the
record (no … | [i18n] @object-ui/collaboration 整包接入 i18n:CommentThread…
| 3 | app-shell/hooks/useRecordApprovals.ts,
app-shell/views/DeclaredActionsBar.tsx, react/hooks/useExpression.ts |
| `3427` | record_change flow start node binds to a single lifecycle
event — no c… | fix(app-shell): 把 Save as view 的 URL 下钻条件折成 spec ViewFi…
| 1 | app-shell/views/metadata-admin/inspectors/flow-scope.ts |
| `3431` | rest: PATCH /data 对被静默剥离的写入字段无任何回传 — onFieldsDropped
通道未接线(follow-up N… | [finding] 已保存视图的 ViewFilterRule[] 被原样当 FilterNode
送进 $f… | 9 (1 stay objectui) | app-shell/providers/AdapterProvider.tsx,
app-shell/providers/writeWarningToast.ts, data-objectstack/index.ts,
data-objectstack/metadata-client.ts, +1 more |
| `3447` | 审批流无法在「运行中」动态确定审批人——审批人在提交时即被 $trigger 快照锁定(动态路由 / 动态会签受阻) |
[finding] PresenceAvatars 的状态圆点对联合类型外的 status 无颜色兜底(sta… | 13 |
app-shell/hooks/useConsoleActionRuntime.tsx,
app-shell/views/DeclaredActionsBar.tsx,
app-shell/views/metadata-admin/inspectors/flow-node-config.ts,
app-shell/views/metadata-admin/inspectors/flow-scope.ts, +3 more |
| `3455` | rest/protocol: 把 droppedFields 写路径观测扩展到 bulk / GraphQL /
client SDK(N … | fix(components,i18n): Sheet/Dialog 关闭按钮接入
common.close,… | 8 | app-shell/providers/AdapterProvider.tsx,
app-shell/providers/writeWarningToast.ts, data-objectstack/index.ts,
data-objectstack/metadata-client.ts |
| `3479` | data import: mid-lifecycle rows rejected by
state_machine.initialState… | content/docs 有 16 个失效的相对链接,且
check-doc-links.mjs 对相对链接一… | 2 | plugin-grid/ImportWizard.tsx,
types/data.ts |
| `3493` | data import: a "historical" import can't preserve original
timestamps … | feat(app-shell,plugin-detail): read-gated Approvals tab…
| 1 | types/data.ts |
| `3494` | [P2] Aspirational-config disposition: reconcile-or-prune the
still-dea… | [ci] scripts/ 在零 tsconfig 覆盖内:turbo type-check 从不检查 scr… |
1 | react/context/ThemeContext.tsx |
| `3508` | 审批节点「处理人 Value」应改为记录 lookup(现查 metadata 端点→只能手填);附 approver
value 语义核实… | docs(ci): live-e2e allowlist 改为指向 package.json,不再手抄 spe… |
18 | app-shell/views/metadata-admin/inspectors/flow-node-config.ts,
app-shell/views/metadata-admin/inspectors/FlowReferenceField.tsx,
app-shell/views/metadata-admin/inspectors/json-schema-to-fields.ts,
fields/widgets/LookupField.tsx, +1 more |
| `3528` | Console: screen-flow Submit never calls the resume endpoint —
every sc… | console-starter 的 vite 别名表漏了 5 个源码实际 import 的工作区包,未先构建就… | 3
| app-shell/views/FlowRunner.tsx, app-shell/views/ScreenView.tsx |
| `3574` | Dashboard widget filters do not interpolate {current_user_id}
— user-s… | fix(tsconfig): 根 tsconfig.node.json 加 noEmit,堵住全仓排放 | 12 |
app-shell/console/AppContent.tsx, app-shell/views/ObjectDataPage.tsx,
app-shell/views/ObjectView.tsx, app-shell/views/useOpenRecordList.ts, +6
more |
| `3689` | service-storage success bodies are three shapes, none
carrying success… | 站点文档 content/docs/utilities/cli.mdx
的兼容表有两行失真:@objectst… | 1 |
app-shell/views/metadata-admin/MetadataTypeActions.tsx |
| `3697` | ADR-0105 D8: the scope-bounded issuance path has no caller —
every pri… | 观察记录:文档散文里的版本宣称无门禁可守 —— N + N 把它清到零之后,没有任何东西阻止下一个作者写回去… | 2
| app-shell/console/organizations/manage/InviteMemberDialog.tsx,
app-shell/console/organizations/manage/MembersPage.tsx |
| `3713` | [P2] action execute vs target: spec and objectui resolve the
precedenc… | docs(skills): console-development.md 指路的 7 个 console 页面… |
2 | core/actions/ActionRunner.ts, types/ui-action.ts |
| `3723` | sys_member.role app-role channel reverses ADR-0057 D4 ("never
as the a… | ci.yml's Build Docs path gate fails CLOSED: a failed gi… | 1
| app-shell/console/organizations/orgRoleLabel.ts |
| `3794` | 审批场景下记录可写性的反馈全线失真:能改的显示「已锁定」,改不了的提示「更新成功」 | ADR-0056 的
Consequences 自相矛盾:「Capabilities 在 Setup 里作者化… | 3 |
app-shell/providers/writeWarningToast.ts, data-objectstack/index.ts,
data-objectstack/userState.ts |
| `3821` | fix(sharing): 共享规则新建页 — 自定义 widget 未国际化,且「接收方」永远无可选项 |
fix(scripts): check-i18n-en-drift 的显式 base 提为权威,解析不出即失败… | 4 |
app-shell/utils/apiErrorEnvelope.ts, components/renderers/form/form.tsx,
plugin-calendar/ObjectCalendar.tsx, plugin-kanban/ObjectKanban.tsx |
| `3842` | The dispatcher puts the HTTP status in error.code and parks
the real c… | 动作 disabled 的「已声明」判定用 != null,disabled: '' 把按钮永久置灰(N 同族… |
1 (4 stay objectui) | app-shell/preview/commitHistory.ts |
| `3843` | Envelope drift is not just service-storage: four more route
modules em… | fix(app-shell,components): 服务端声明动作的 visible 门按「已声明」判定,v… |
2 |
app-shell/views/metadata-admin/datasource/DatasourceResourcePage.tsx,
app-shell/views/metadata-admin/MetadataTypeActions.tsx |
| `3855` | [P3] Retire the three deprecated aliases — via the ADR-0087
D2 convers… | content/docs/guide/plugins.md 的示例 package.json 里 vite ^… |
7 | app-shell/views/metadata-admin/previews/ActionPreview.tsx,
core/actions/actionKeys.ts, core/actions/ActionRunner.ts,
test-support/spec-tombstones.ts, +1 more · runtime string |
| `3856` | [P3] objectui ActionRunner: the execute || target fallback is
dead cod… | docs(skills): console-development.md 顶部注记的搬家归因改成 04-21→… | 4
| app-shell/views/metadata-admin/previews/ActionPreview.tsx,
core/actions/ActionRunner.ts, types/ui-action.ts |
| `3896` | POST /data/sharing/rules 绕过 SharingRuleSchema:criteria
缺失或拼错静默变成"共享该对象… | AiChatPage 发给 agent 的四条确认文本仍按 UI 语言取值:zh 控制台 +
英文会话把「确认… | 7 (1 stay objectui) | changeset
dashboard-aria-member-retired-5830.md,
app-shell/views/metadata-admin/previews/AgentPreview.tsx,
app-shell/views/metadata-admin/previews/ToolPreview.tsx,
fields/widgets/FilterConditionField.tsx, +3 more · changeset note |
| `3903` | [P2] The spec contract stops at authored source — stored
metadata is r… | apps/site: Schema Catalog 索引页把每个缩略图包在 button 里,85 个含
bu… | 4 (1 stay objectui) | core/actions/ActionRunner.ts |
| `3916` | [17.0.0-rc.0] Matrix report date columns are unordered — no
server-sid… | fix(core): ActionRunner 的 condition 门改问「有没有声明」,conditio… |
2 | plugin-report/DatasetReportRenderer.tsx |
| `3923` | Action.requiredPermissions 在 Console 端形同虚设:会话不下发
systemPermissions + 客… | fix(app-shell): SchemaForm 读取归一化后的
visibleWhen,让 metada… | 1 | plugin-grid/components/RowActionMenu.tsx |
| `3948` | A filter with an operator outside VALID_AST_OPERATORS is
silently drop… | fix(plugin-list): UserFilters buttons declare
type="but… | 1 | fields/widgets/RecordPickerDialog.tsx |
| `3959` | A type: 'modal' action's server-side handler is unreachable:
objectui … | fix(fields): BooleanField 使用 host 下发的控件 id,可见 label 不再悬… |
2 (1 stay objectui) | app-shell/hooks/useActionModal.tsx,
app-shell/views/RecordDetailView.tsx |
| `3962` | [17.0.0-rc] /actions reports business failures as HTTP 200
inside a do… | [app-shell] ActionParamDialog 的 boolean 分支不下发 id,于是同一个控…
| 3 | app-shell/utils/flowResponse.ts, core/actions/actionResponse.ts |
| `4001` | 未知键静默剥离仍是全仓默认:把 N 的 strict 收紧从一个 schema 推广到整个可授权面(ADR-0078
完整性闸门) | examples/schema-catalog: 13 个 grid 示例用了未声明的 cols 键,列数被静… | 4 |
app-shell/views/metadata-admin/clientValidation.ts,
plugin-detail/index.tsx |
| `4019` | feat(runtime): /analytics 路由按能力条件挂载——没装 service-analytics 连
405 都不再有(N… | Studio Part A quick wins: wire the already-registered a… |
1 | data-objectstack/index.ts |
| `4074` | [P2] objectui @object-ui/types hand-declares five action
vocabularies … | [console] Four remaining inbox/activity entries still
h… | 5 | types/ui-action.ts |
| `4075` | [P3] objectui ActionDef's [key: string]: any absorbs every
retired and… | console: action:button / action:icon / action:menu bind…
| 2 (1 stay objectui) | core/actions/ActionRunner.ts,
types/data-protocol.ts |
| `4115` | [P2] objectui: a spec-named symbol must be an import, not a
declaratio… | test(plugin-charts): serve ObjectChart's option-color p… |
1 | types/widget.ts |
| `4171` | [P2] spec: four exported types resolve to any, so "bind the
spec-named… | docs(ci): stop the Merge Queue section keeping its own … |
2 | types/index.ts |
| `4463` | [runtime/metadata] 作者时规则只存在于 CLI:Studio/REST/MCP
的运行时授权面是第四扇门,26 条规则一条… | "Set as Default" is dead on every saved view —
handleSe… | 1 | data-objectstack/metadata-client.ts |
| `4610` | spec 双源清账 C3:通知语汇 Notification(Schema)(./api ≠ ./ui)+
NotificationConf… | finding(tooling): rule 2's citation window still
reads … | 1 | types/index.ts |
| `4614` | spec: dashboard date filter 的 defaultValue 没有作者时校验 ——
拼错的预设名要到浏览器控制台才被… | [plugin-dashboard] DashboardGridLayout has no
dataset p… | 1 (1 stay objectui) | core/utils/dashboard-filters.ts |
| `4616` | spec/system 通知模板语汇在 C3
后成为零消费方孤儿:EmailTemplate/SMSTemplate/PushNotific… | Docs gallery: 35
catalog entries render the red "Unknow… | 1 |
app-shell/views/metadata-admin/clientValidation.ts |
| `4649` | Script validation rules are silently skipped when their
predicate fail… | Unwind the objectstackN striped/bordered/virtualScroll
… | 1 | app-shell/views/metadata-admin/clientValidation.ts |
| `4709` | app.homePageId 退役的前提写错了 —— objectui 的 resolveLandingRoute()
一直在读它,现在成了… | finding: objectui still declares @objectstack/spec/clie… |
2 | app-shell/console/AppContent.tsx,
app-shell/views/metadata-admin/previews/AppPreview.tsx |
| `4717` | [P2/P3] 运行时授权门的 advisory findings 要进响应并被 Studio 渲染 + docs「the
gate」补第四… | test(data-objectstack): re-point v3-compat's vacuous Pa… | 2
| changeset render-publish-advisory-findings-5026.md,
data-objectstack/metadata-client.ts · changeset note |
| `4829` | rest: filterAppForUser treats app hidden flag as builder-only
access g… | docs(layout): app-shell.mdx 的 AppShellProps 声明块补齐到 7 个 … | 3
| app-shell/console/AppContent.tsx, app-shell/layout/AppSwitcher.tsx,
app-shell/utils/appRoute.ts |
| `5021` | 主题引擎发出的 9 组 CSS 变量零消费方(--font-size-* / --z-* / --duration-*
…):ADR-004… | docs(plugin-map): README 按现码重写,不再教包里不存在的那套 API (N) | 1 |
core/theme/ThemeEngine.ts |
| `5074` | ViewItemSchema 同时是授权形状和 Studio 往返的 wire 成员 —— 拆成两个 schema
还是保持宽松?(挡住 N… | plugin-gantt: schema 上的 viewMode 只被 ResourceWorkload 分支…
| 1 | app-shell/views/metadata-admin/clientValidation.ts |
| `5134` | SqlDriver.applyFilterCondition 丢弃编译成空的 $and/$or
子过滤器,而不是套用布尔单位元 —— 与同仓… | finding: the spec's nested aria.ariaLabel
admits an inl… | 1 | core/utils/filter-converter.ts |
| `5149` | Conditional-visibility predicates (visibleWhen / visibleOn)
fail OPEN … | governance: agent-instruction files are human-merge onl… |
7 | components/renderers/form/form.tsx,
core/evaluator/ExpressionEvaluator.ts, core/evaluator/fieldRules.ts,
core/evaluator/listConditional.ts |
| `5154` | fix(spec): 重开 ViewFilterRuleSchema —— 控制台盖的 UI 行 id 让保存筛选条件
422(N 热修)… | fix(app-shell,core): 对象列表工具栏 Import 消费 importPredicates… |
1 | app-shell/views/viewFilterFold.ts |
| `5240` | { field: {} }(零个操作符的字段约束)在同仓有三个答案:driver-sql 组合子内 TRUE、顶层抛
INVALID_FIL… | schema.userActions is a sixth grid key read but undecla…
| 2 | core/adapters/ValueDataSource.ts, core/utils/filter-converter.ts |
| `5316` | objectui 的 metadata-admin 用「授权 schema」校验一份 STORED view —— N
收紧后,给已保存视图… | docs(fields): tombstone MasterDetailField as a form-unr… |
1 | app-shell/views/metadata-admin/clientValidation.ts |
| `5322` | 空组合子在同仓有两个对立答案:五个后端归约成布尔单位元,service-analytics 的两个编译器
fail-closed 抛错 ——… | A field:-prefixed password / email field renders
type=&… | 4 | core/utils/filter-converter.ts |
| `5576` | PageComponentSchema.dataSource.view 是声明了但无人消费的绑定:objectui
resolveEleme… | holdsStudioAccess is unreachable from @object-ui/app-sh…
| 2 | core/data-scope/element-data-source.ts,
core/data-scope/ViewDataProvider.ts |
| `5777` | InlineActionSchema.params 声明为参数定义数组,但 type:'api' 的活消费者(与
showcase 页)用的… | purgeSignedOutClientCaches's try wraps the whole loop,
… | 2 | core/actions/ActionRunner.ts |
| `5811` | /analytics/query 仍把 RLS 策略字段名回显给调用方 —— read-scope
拒收的泄漏在姐妹面上没堵,N 只堵了 d… | test(app-shell): pin hollow view +
personalization over… | 1 | app-shell/preview/commitHistory.ts |
| `6761` | [决策] dataset 的 dimension/measure 声明成内联 locale map 的 label
被生产端整个丢弃 —— … | finding(react): five spellings of one "is this a real c…
| 1 | types/base.ts |
| `6776` | [移交自 objectui] ComponentPropsMap 未声明 objectui 渲染器实读的 5 个顶层
prop(page:h… | finding(console): metadata-admin's 172,651 B eager clos…
| 1 | layout/PageHeader.tsx |
| `6953` | PageComponentSchema.dataSource 在 list-view
之外仍无人消费:element:record_pick… | [finding]
ObjectGantt.referenceArms-6837.test.tsx races… | 1 |
plugin-detail/renderers/record-related-list.tsx |
| `7034` | fix(spec): the page-component conversion walk reaches nested
container… | finding(gate): the version-claim ledger's ci-cd-pipelin… |
2 | layout/index.ts, layout/PageHeader.tsx |
| `7127` | FieldSchema.defaultValue has the same z.unknown() acceptance
hole as t… | finding(plugin-detail): the record:details registration… |
1 | plugin-form/schemaDefaults.ts |
| `7137` | object-timeline / record:line_items 的查询没有 filter/sort
读点:dataSource.vi… | finding(app-shell): InterfacesPillar's block
selection … | 3 | core/utils/sort-query.ts, plugin-timeline/index.tsx |
| `7233` | [approvals][console] Bell badge sums unread notifications +
pending ap… | Handover for the next domain:ui execution-seat PM — wha… |
2 | app-shell/layout/InboxPopover.tsx, i18n/locales/en.ts |
| `7388` | feat(objectql): enforce the select idiom — the option marked
default: … | plugin-chatbot: the build-progress panel cannot express… |
2 | app-shell/views/metadata-admin/form-spec.ts,
components/renderers/basic/metadata-viewer.tsx |
| `7496` | spec: rule the submitBehavior.url semantics — objectuiN
dead-ends on i… | fix(skills): teach the honest test-double idiom in
test… | 2 | changeset 7122-spec-17-3-0-pin-repointing.md · changeset
note |
| `8010` | spec: ListView.exportOptions is typed as a bare array, but
the only re… | test(scripts): check-shell-escape-residue reds on an ag…
| 2 | changeset 6956-listview-export-options-spec-mirror.md,
types/zod/objectql.zod.ts · changeset note |
| `8135` | fix(rest): meta app by-name answers a permission-denied
envelope, not … | test(i18n): pin that the two defaults-population walks
… | 1 | data-objectstack/index.ts |
| `8270` | [finding] workspace owner lacks manage_metadata in the EE
multi-org de… | finding(plugin-map): the legacy filter.map warning name…
| 2 | app-shell/views/metadata-admin/PackageFormDialog.tsx |
| `8424` | N lands five new public exports in @objectstack/spec/shared —
should t… | finding(docs): the VS Code page's keybinding example re… | 1
| app-shell/preview/DraftChangesPanel.tsx |
| `8955` | feat(spec): field-level relatedListFilter — declarative
default filter… | test(console): pin the four object-metric query
members… | 3 | changeset 4664-related-list-declared-filter.md,
app-shell/utils/deriveRelatedLists.ts,
plugin-detail/synth/buildDefaultPageSchema.ts · changeset note |
| `9612` | runtime gate: full runtime-safe rule snapshot for the publish
door — t… | docs(plugins): author the listViews filter operator in … | 3
| changeset designer-publish-package-binding.md,
app-shell/views/metadata-admin/ResourceEditPage.tsx,
data-objectstack/metadata-client.ts · changeset note |
| `10235` | Shipped grids display formula columns the platform cannot
sort — a con… | The console drops an app translation bundle with no obj…
| 1 | plugin-grid/ObjectGrid.tsx |

## Acceptance notes

1. **Outside the card's two classes (recorded, not carried):**
- apps/console `AgentConnectSection.tsx` still says "the `9934`
channel", a dead objectstack number.
- The `recordDetailsInputs.spec-parity.test.ts` doc comment writes
`objectui#3546` for objectstack's card.
- Tests' own bare citations were not censused, since tests are outside
the class. The describe titles naming `2604`, `3405`, `3508` or `7233`
mean objectstack cards. NOT MEASURED as a population.
   - Published `CHANGELOG` history is untouched.
2. **Numbers that mean neither repository (10):** `432`, `586`, `772`,
`787`, `844`, `1238`, `1491`, `1852`, `1970`, and one `2150` sentence
(an intermittent CI failure).
   - Three say "cloud PR" outright (`1238`, `1852`, `1970`).
- `772` and `787` pair with objectui#2362, whose title cites cloud's
`772`.
   - The rest fit neither title.
- `objectstack-ai/cloud` answers 403 through this container's proxy, so
their cloud reading is NOT MEASURED. They are out of this card's
objectstack class and are left as written.
3. **Same family, not bare, not carried here:**
- 294 `framework#N` citations (83 distinct), qualified by objectstack's
former name, including the ones after a slash such as
`framework#1878/objectstack-ai#1891`.
- The three `objectui#3821` citations that meant objectstack's card were
carried in patch round 1 (item 4 above).
   - Measured, not edited.
4. **Held:** the `ObjectGrid.tsx` pagination comment (see **Held**).

---
_Generated by [Claude
Code](https://claude.ai/code/session_011p7ikEivgXefNDaE5S5Uec)_

---------

Co-authored-by: Claude <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentation Improvements or additions to documentation plugin tests

Projects

None yet

2 participants