Skip to content

docs(plugin-dashboard): teach the adapter as renderer context, not a schema key (objectui#8468) - #8857

Merged
os-zhuang merged 2 commits into
mainfrom
claude/issue-8468-readme-datasource-shorthand
Sep 9, 2026
Merged

docs(plugin-dashboard): teach the adapter as renderer context, not a schema key (objectui#8468)#8857
os-zhuang merged 2 commits into
mainfrom
claude/issue-8468-readme-datasource-shorthand

Conversation

@claude

@claude claude Bot commented Sep 9, 2026

Copy link
Copy Markdown
Contributor

Part of #8468 — repairs one of the three sites the card names. The other two
are measured not to be instances of the defect, and that measurement is the
other half of this delivery. What #8468 has left is a triage decision, not a file
edit, so this PR does not close it.

What changed

packages/plugin-dashboard/README.md, section "Integration with Data Sources".
The example authored the live adapter returned by createObjectStackAdapter as a
shorthand property inside the dashboard schema literal. It is repaired to the
form already landed in plugin-form, plugin-grid, plugin-gantt and
plugin-view:

  • the literal is annotated with its own schema type, DashboardComponentSchema;
  • the prose states where the adapter actually goes — React context, installed once
    by SchemaRendererProvider above the tree, read at
    packages/plugin-dashboard/src/ObjectMetricWidget.tsx:159
    (const dataSource = propDataSource || context?.dataSource;), with an explicit
    dataSource prop taking precedence when the host renders the widget directly;
  • a closing note keeps the name collision explicit: a dataSource key on a
    schema node is the spec's element binding ({ object, view?, filter?, sort?, limit? }, a strict object in @objectstack/spec), a declarative reference
    resolved against the host — not an adapter instance.

No packages/*/src/** file is touched. No gate was added (issue ruling 2).

Premise check — two of the card's three sites are NOT the defect

Verified on origin/main fd9bf26df. All three coordinates are real grep hits and
none had drifted, but the probe ^ dataSource,$ is a syntactic pattern and it
matches three different constructs:

site construct verdict
plugin-dashboard/README.md:284 shorthand property inside const schema = { type: 'dashboard', … } the defect — repaired here
react/README.md:234 destructured React prop in function ObjectSomething({ schema, dataSource }: { schema: { objectName?: string }; dataSource: DataSource }) correct — a prop is exactly where the adapter belongs
plugin-report/README.md:523 second positional argument of createScheduleTrigger(report, dataSource, 'orders', cb) correct — matches plugin-report/src/LiveReportExporter.ts:245-249

plugin-report:523 is confirmed twice over: the ReportComponentSchema literal
directly above it (lines 508-519) carries no dataSource at all, and the type
tombstones the key — packages/types/src/reports.ts:407 declares
dataSource?: never.

Editing either of those two would replace correct documentation with wrong
documentation, so neither was touched. The card's acceptance reading (3 down to 0)
is therefore not the reading this PR delivers; the class reading below is.

Readings

Subject — the pattern. 3 hits down to 2, and the 2 that remain are the two
correct constructs above:

origin/main (fd9bf26df):        HEAD (3f455b8e7):
  plugin-dashboard/README.md:284  (gone)
  plugin-report/README.md:523     plugin-report/README.md:523
  react/README.md:234             react/README.md:234

Subject — the class. After this commit, no packages/*/README.md authors a
live adapter into a schema object literal. Measured in both spellings, shorthand
and explicit, over packages/*/README.md, the root README.md and
content/docs/**:

$ git grep -n '^\s*dataSource,\s*$' HEAD -- 'packages/*/README.md'
  plugin-report/README.md:523   -> call argument (correct)
  react/README.md:234           -> destructured prop (correct)
$ git grep -n '^\s*dataSource: ' HEAD -- 'packages/*/README.md' 'README.md' 'content/docs/**/*.md'
  content/docs/guide/building-crud-app.md:336  dataSource: { object: 'task', view: activeView },   -> the spec binding (correct)
  content/docs/guide/public-forms.md:168       dataSource: DataSource;                             -> a type annotation
  plugin-grid/README.md:669                    dataSource: NonNullable of the prop type                        -> a type annotation
  plugin-report/README.md:453                  dataSource: myAdapter,                              -> LiveExportOptions bag (correct)
  react/README.md:237                          dataSource: DataSource                              -> a type annotation

Zero members of the class remain. The corridor the card describes has an end.

Lit control — the probe runs. In the same sweep, the already-repaired wording
the card names is still present on HEAD, so this is not "every dataSource
mention was purged":

HEAD:packages/plugin-gantt/README.md:728:renderer context (or as an explicit `dataSource` prop), while the schema names
HEAD:packages/plugin-form/README.md:886:`ObjectForm` its `dataSource` prop.
HEAD:packages/plugin-view/README.md:402:All four operations are built in and run against the `dataSource` prop.

Third reading — the new passage says where the adapter goes, not merely that it
does not belong in the literal:

HEAD:packages/plugin-dashboard/README.md:276:widget reads its adapter from React context — `useContext(SchemaRendererContext)`
HEAD:packages/plugin-dashboard/README.md:305:  (JSX open tag) SchemaRendererProvider dataSource={dataSource}

Gates

Run in a dedicated worktree at 3f455b8e7, after
turbo run build $(node scripts/check-doc-snippet-types.mjs --build-filter):

gate verdict line
pnpm check:doc-snippets Semantic phase: 637 of 637 block(s) judged, 0 failed. (exit 0)
pnpm check:doc-fences every TypeScript block in 227 document(s) is fenced ts/tsx/typescript (exit 0)
pnpm check:readme-exports OK (43 tracked README(s) …, 538 self-imports judged (538 real, 0 wrong-path, 0 fabricated) (exit 0)
pnpm check:control-bytes OK (scanned 7057 tracked text file(s); skipped 85 binary) (exit 0)
node scripts/check-changeset-presence.mjs 1 file(s) changed, 0 of them published source …; no changeset is owed (exit 0)
node scripts/check-governed-queue-guard.mjs --test packages/plugin-dashboard/README.md NOT GOVERNED — 1 path(s) checked against 5 governed surface(s); none matched. (exit 0)
the same guard, lit control AGENTS.md GOVERNED — 1 of 1 path(s) are on a governed surface (exit 3) — the guard's probe runs

Ablation — proof the snippet gate actually judges the new block. The block is
new, so its green is worth nothing until it can be made red. From the committed
state, SchemaRendererProvider was renamed to SchemaRendererProviderZ in the new
fence only; the mutation was proved on disk (marker count 0 to 1, blob
09b920f81 to 5bcfff8f7) before the gate ran:

MUTATED-RUN-EXIT=1
  [semantic]  packages/plugin-dashboard/README.md:282:10  TS2724: '"@object-ui/react"' has no exported member named 'SchemaRendererProviderZ'.
  Semantic phase: 637 of 637 block(s) judged, 1 failed.

Restored with git checkout HEAD -- PATH; git diff HEAD empty and the blob
back to 09b920f81. A first attempt at this ablation wrote nothing (its anchor
was not unique) and the gate stayed green — that no-op is why the on-disk proof is
reported rather than the exit code alone.

No changeset: check-changeset-presence measured it, per the dispatch, rather than
assuming it — a README is documentation, not published source, on this gate's
derived surface.

Clause-2: no
Contract-text: packages/plugin-gantt/README.md:726-728 — published inside that
package's files[] — already states the contract this PR restates for
plugin-dashboard: "The adapter is not a schema key — it reaches the renderer
through the renderer context (or as an explicit dataSource prop), while the
schema names the object and the fields". The binding it distinguishes is
@objectstack/spec's own dataSource: { object, view?, filter?, sort?, limit? }.
This PR adds no exported symbol and no key on any published payload, and moves no
operator or contract semantics; check-changeset-presence measured 0 published
source files in the range.

Patch round — dequeued from the merge queue at 15:26:15Z (CI_FAILURE)

Test (shard 1/4) in run 34368473519 (merge_group, head 97f388f31d) failed:

Test Files  1 failed | 712 passed | 1 skipped (714)
     Tests  1 failed | 9542 passed | 2 skipped (9545)
SyntaxError: Unexpected token 'export'
 at packages/plugin-dashboard/src/__tests__/readme-dashboard-examples-spec-valid.test.ts:128:28

Why this PR page was green while the queue was not. ci.yml:183-195 — on
pull_request the "Decide whether this change needs a full run" step diffs with
':(exclude,glob)**/*.md', so a markdown-only PR skips the test shards: they
completed in ~10 seconds and reported success. On merge_group the same step
short-circuits to should_run=true ("a merge_group build is the last validation
before main. Running everything."), and there the shard ran 907s and failed.
⇒ a green Test (shard N/4) on this PR was never evidence the tests ran, so every
reading below was taken locally, from real output, not from a check mark.

Root cause. readme-dashboard-examples-spec-valid.test.ts extracts every fence
of this README matching BOTH /const\s+schema\b/ and /type:\s*'dashboard'/,
strips imports and annotations, and evaluates the rest with new Function. The
fence added by the first round carried the schema literal AND the provider wiring —
and new Function compiles neither a top-level export nor JSX. Two independent
breakages in one fence.

Fix — split the fence; the harness is not widened. toEvaluable() is untouched:
that test's own docblock states the deliberate remedy is adding a name to AMBIENT,
not swallowing arbitrary syntax, and an evaluator that skips what it cannot read is
the false-green shape objectui#4846 exists to prevent. So the section now carries
two fences, split along the extractor predicate's own semantic line:

fence language carries extractor selects it?
1 typescript the document alone — const schema: DashboardComponentSchema = { type: 'dashboard', … } yes — both halves of the predicate
2 tsx its own imports, declare const schema, the adapter construction, and the provider wiring no — carries no type: 'dashboard'

The provider example is kept (it is the substance of this PR), the closing note on
the dataSource name collision is unchanged, and react/README.md and
plugin-report/README.md are still untouched.

Readings — this round, at 223100735

Block count: 6 before, 6 after, and the same documents selected. The floor the
harness guards is blocks.length >= 6, so this number is what makes the pass
meaningful. Taken from the test's own verbose run, not from the brief:

before (3f455b8e7)                          after (223100735)
  :48  Automatic Registration      PASS       :48  Automatic Registration      PASS
  :129 Dashboard                   PASS       :129 Dashboard                   PASS
  :178 Basic Dashboard             PASS       :178 Basic Dashboard             PASS
  :217 Dashboard with Charts       PASS       :217 Dashboard with Charts       PASS
  :257 Responsive Dashboard        PASS       :257 Responsive Dashboard        PASS
  :282 Integration with Data ...   FAIL       :283 Integration with Data ...   PASS
  Test Files  1 failed (1)                    Test Files  1 passed (1)
       Tests  1 failed | 6 passed (7)              Tests  7 passed (7)

The split did not change which fences are selected: the same six documents, the
Integration one moved by one line (282 to 283) because the prose above it grew. The
new tsx fence is not selected — the count stayed at 6 rather than becoming 7,
which is the observation that proves it. ⇒ nothing was hidden from the extractor to
buy this green.

The whole plugin-dashboard suite, run from the repo root the way this repo's
vitest guard prescribes:

$ pnpm exec vitest run packages/plugin-dashboard/
Test Files  100 passed (100)
     Tests  890 passed (890)

check:doc-snippets — exit 0, and BOTH fences are judged. The count moved
637 of 637 to 638 of 638 precisely because one fence became two, so the second
fence is not a silent skip:

Semantic phase: 638 of 638 block(s) judged, 0 failed.
Every covered documentation snippet compiles against the built types.

Proved rather than inferred: injecting ThisNameIsDefinitelyNotExported into
each fence (on-disk proof first — blob fab0a7bc6 to ed0a263f5, sentinel
count 0 to 2) makes the gate report exactly two failures, one per fence:

  [semantic]  packages/plugin-dashboard/README.md:283:10  TS2305: ... has no exported member 'ThisNameIsDefinitelyNotExported'.
  [semantic]  packages/plugin-dashboard/README.md:306:10  TS2305: ... has no exported member 'ThisNameIsDefinitelyNotExported'.
  Semantic phase: 638 of 638 block(s) judged, 2 failed.

Line 283 is inside fence 1, line 306 inside fence 2. Restored by state:
git diff HEAD empty and blob back to fab0a7bc6.

Ablation — the test really catches this, and the mutation really landed. From
the committed tree at 223100735, the export/JSX was re-introduced into the
schema fence only (fence 2 left in place, so the export/JSX is the single
isolated variable). On-disk proof taken BEFORE the run:

HEAD blob      : fab0a7bc6fa04f94f34ba20b98ed1e587ce49eb3
post-mutation  : blob=094a1ff1729a93c6a5e989029674d3ed09d7370b  'export const App' count 1 -> 2
ON-DISK PROOF OK: blob moved, markers 1 -> 2

and the test went red, by test-case name:

FAIL  plugin-dashboard README dashboard examples >
      :283 Integration with Data Sources validates against the shipped DashboardComponentSchema
SyntaxError: Unexpected token 'export'
Test Files  1 failed (1)   Tests  1 failed | 6 passed (7)

Restore verified by state, not by an exit code: git checkout HEAD -- PATH, then
blob back to fab0a7bc6fa04f94f34ba20b98ed1e587ce49eb3 and git diff HEAD empty.
Both mutation scripts carried a trap ... EXIT INT TERM restore with absolute
paths, and both refuse to report a result if the edit's anchor count is not exactly
1 — the previous round's ablation attempt wrote nothing and stayed green at exit 0,
which is the failure this guard exists to make impossible.

Clause-2: no — measured this round, not inherited:

$ node scripts/check-governed-queue-guard.mjs --test packages/plugin-dashboard/README.md
NOT GOVERNED — 1 path(s) checked against 5 governed surface(s); none matched.

check:control-bytes (exit 0, 7057 files), check:doc-fences (exit 0),
check:readme-exports (exit 0) and check-changeset-presence (exit 0, "no
changeset is owed") were re-run and stay green; per the dispatch they are blind to
this failure and are reported only as unchanged, never as evidence about it.

验收备注

  • noted, not filed: the card's acceptance probe ^ dataSource,$ is a pattern, not
    a class predicate — it counts two correct constructs as members. Anyone taking up
    the gate question (deferred by ruling 2 behind objectui#7912's any-typed
    SchemaRendererProvider prop) inherits this: a text gate built on that pattern
    would redden react/README.md and plugin-report/README.md on day one.

  • noted, not filed: the triage comment warned that plugin-gantt/README.md does not
    carry "the repaired wording". Both readings are true and they are about different
    sentences — gantt:726-731 carries the repaired form the dispatch cites, while
    the exact sentence triage searched for ("The adapter is the dataSource prop,
    not part of the schema:") lives only at plugin-view/README.md:509. Recorded so
    the next reader does not re-litigate it.

  • noted, not filed: AMBIENT in readme-dashboard-examples-spec-valid.test.ts has one
    entry, createObjectStackAdapter, and after this split no selected block uses it —
    the schema fence is now pure data needing no ambient name. Harmless (unused
    new Function parameters), and the entry is the harness's documented extension
    point rather than dead weight, so it is left alone. 承接者: whoever next adds a
    dashboard document fence to this README, who reads that list before adding to it.


🤖 Generated with Claude Code

https://claude.ai/code/session_01611D6ZaRaMmwTNQmSbk8MH


Generated by Claude Code


Generated by Claude Code

…schema key (objectui#8468)

The "Integration with Data Sources" example authored the live adapter
returned by `createObjectStackAdapter` as a shorthand property inside the
`dashboard` schema literal. Nothing reads it there: `ObjectMetricWidget`
takes its adapter from `useContext(SchemaRendererContext)` (src/ObjectMetricWidget.tsx:159),
falling back to an explicit `dataSource` prop.

The slot is not merely redundant, it is a NAME COLLISION: a `dataSource`
key on a schema node is the spec's element binding
(`{ object, view?, filter?, sort?, limit? }`), a declarative reference
resolved against the host — not an adapter instance.

Repaired to the form already landed in `plugin-form`, `plugin-grid`,
`plugin-gantt` and `plugin-view`: the literal is annotated with its own
schema type (`DashboardComponentSchema`), and the prose says where the
adapter actually goes — `SchemaRendererProvider`, above the tree.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01611D6ZaRaMmwTNQmSbk8MH
@github-actions github-actions Bot added documentation Improvements or additions to documentation plugin labels Sep 9, 2026
@github-actions

github-actions Bot commented Sep 9, 2026

Copy link
Copy Markdown
Contributor

✅ Console Performance Budget

Metric Value Budget
Eager closure (gzip, 50 chunks) 3485.7 KB 3512.7 KB
Main entry chunk (gzip) 144.1 KB 350 KB
Entry file index-DT4PnhI-.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.69KB 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) 25.05KB 9.16KB
auth (AuthContext.js) 0.31KB 0.24KB
auth (AuthGuard.js) 2.07KB 1.00KB
auth (AuthProvider.js) 40.18KB 10.59KB
auth (AuthShell.js) 3.49KB 1.40KB
auth (ForgotPasswordForm.js) 12.21KB 3.45KB
auth (LoginForm.js) 18.15KB 5.39KB
auth (PreviewBanner.js) 0.90KB 0.50KB
auth (RegisterForm.js) 6.65KB 2.22KB
auth (SocialSignInButtons.js) 9.61KB 3.89KB
auth (UserMenu.js) 3.41KB 1.23KB
auth (auth-gate-events.js) 1.29KB 0.66KB
auth (authStyles.js) 5.04KB 1.72KB
auth (createAuthClient.js) 40.21KB 10.80KB
auth (createAuthenticatedFetch.js) 8.46KB 3.43KB
auth (index.js) 3.19KB 1.44KB
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) 26.08KB 7.56KB
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) 500.00KB 114.54KB
core (index.js) 7.48KB 2.96KB
create-plugin (index.js) 26.68KB 8.94KB
data-objectstack (index.js) 198.39KB 55.29KB
fields (index.js) 246.35KB 62.12KB
i18n (LocalizationContext.js) 1.76KB 0.96KB
i18n (builtinAggregateLabels.js) 0.86KB 0.49KB
i18n (currency.js) 1.22KB 0.64KB
i18n (fallbackInterpolation.js) 6.25KB 2.77KB
i18n (i18n.js) 6.57KB 2.76KB
i18n (index.js) 3.65KB 1.47KB
i18n (pickLocalized.js) 7.62KB 3.26KB
i18n (provider.js) 26.89KB 9.04KB
i18n (useDisplayLocale.js) 2.85KB 1.45KB
i18n (useObjectLabel.js) 34.34KB 9.17KB
i18n (useSafeTranslation.js) 5.60KB 2.33KB
layout (index.js) 38.84KB 10.94KB
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) 2.53KB 0.85KB
mobile (useResponsive.js) 0.72KB 0.42KB
mobile (useSpecGesture.js) 4.39KB 1.66KB
mobile (useTouchTarget.js) 1.01KB 0.54KB
permissions (MePermissionsProvider.js) 13.52KB 4.88KB
permissions (PermissionContext.js) 0.31KB 0.25KB
permissions (PermissionGuard.js) 0.89KB 0.45KB
permissions (PermissionProvider.js) 6.24KB 2.16KB
permissions (discardProofCache.js) 1.04KB 0.55KB
permissions (evaluator.js) 8.39KB 3.10KB
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) 14.81KB 3.63KB
plugin-calendar (index.js) 49.03KB 13.93KB
plugin-charts (index.js) 71.39KB 19.92KB
plugin-chatbot (index.js) 194.54KB 46.34KB
plugin-dashboard (index.js) 131.43KB 34.44KB
plugin-designer (index.js) 215.51KB 44.29KB
plugin-detail (index.js) 252.45KB 65.33KB
plugin-editor (index.js) 2.23KB 1.05KB
plugin-form (index.js) 134.69KB 33.72KB
plugin-gantt (index.js) 167.16KB 40.99KB
plugin-grid (index.js) 210.86KB 57.28KB
plugin-kanban (index.js) 57.03KB 16.26KB
plugin-list (index.js) 112.73KB 27.69KB
plugin-map (index.js) 20.49KB 6.83KB
plugin-markdown (index.js) 13.88KB 4.80KB
plugin-report (index.js) 43.42KB 11.92KB
plugin-timeline (index.js) 30.10KB 8.74KB
plugin-tree (index.js) 9.55KB 3.32KB
plugin-view (index.js) 84.54KB 20.84KB
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.66KB 3.50KB
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) 81.07KB 26.86KB
react (data-invalidation.js) 5.05KB 2.08KB
react (index.js) 4.63KB 2.18KB
react (schema-input.js) 2.32KB 1.24KB
react (spec-input.js) 0.20KB 0.18KB
sdui-parser (codegen.js) 6.58KB 2.74KB
sdui-parser (dashboard-widget-options.js) 3.08KB 1.30KB
sdui-parser (index.js) 5.55KB 2.45KB
sdui-parser (input-type.js) 2.84KB 1.40KB
sdui-parser (parse.js) 20.57KB 5.88KB
sdui-parser (provenance.js) 3.66KB 1.82KB
sdui-parser (types.js) 0.28KB 0.23KB
sdui-parser (validate.js) 13.64KB 4.59KB
types (ai.js) 0.20KB 0.17KB
types (api-types.js) 0.20KB 0.18KB
types (app.js) 2.87KB 1.00KB
types (base.js) 0.20KB 0.18KB
types (blocks.js) 0.20KB 0.18KB
types (complex.js) 2.93KB 1.49KB
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.25KB
types (layout.js) 0.20KB 0.18KB
types (managed-by.js) 0.19KB 0.18KB
types (mobile.js) 4.73KB 2.28KB
types (navigation.js) 0.20KB 0.18KB
types (objectql.js) 0.20KB 0.18KB
types (overlay.js) 0.20KB 0.18KB
types (permissions.js) 0.20KB 0.18KB
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) 14.27KB 5.47KB
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

@os-zhuang
os-zhuang marked this pull request as ready for review September 9, 2026 15:10
@os-zhuang
os-zhuang added this pull request to the merge queue Sep 9, 2026

Copy link
Copy Markdown
Contributor

PM 评审 — PR #8857(卡 #8468

结论:通过。 已翻 ready、auto-merge 已武装(squash)——两个调用都已返回成功再写这句。

⛔ 先记我自己的错:验收标准是错的

我的派发写的是:

Subjectgit grep -n '^ dataSource,$' -- 'packages/*/README.md'3 降到 0

这个数字是错的,而且错法正是这一班反复在教的那一种:我把卡片给的 grep pattern 直接升格成了验收数字,没有问每一个命中「是什么」。 卡片正文自己也断言三处「Each reads, in shape: const schema = { type, dataSource, … }」——这句话对其中两处为假,我继承了它而没有复测。

三处我独立复测过(在 origin/main 42df92809 上,不是 dev 报告里的 fd9bf26df,结论一致):

坐标 实际构造 判定
plugin-dashboard/README.md:284 const schema = { type: 'dashboard', dataSource, … } 里的简写属性 缺陷,本 PR 修复
react/README.md:234 function ObjectSomething({ schema, dataSource }: { …; dataSource: DataSource })解构 prop 正确
plugin-report/README.md:523 createScheduleTrigger(report, dataSource, 'orders', cb)第二位置实参 正确

后两处我验到了消费端,不是只对着文档自证:

  • packages/plugin-report/src/LiveReportExporter.ts:245-249 的签名逐字是 (report, dataSource, resource, onComplete)
  • packages/types/src/reports.ts:407 给这个 key 立了碑 —— dataSource?: never,注释还指回 objectstack#5576 / objectui#6121,同一场命名碰撞早已判过;
  • packages/plugin-dashboard/src/ObjectMetricWidget.tsx:159 逐字是 const dataSource = propDataSource || context?.dataSource;,新散文引的就是它。

照我原来的验收数字去改,会把两处正确文档改成错误文档。 dev 拒绝执行、并把这份测量当作交付的另一半送回来,是对的。

采纳 dev 的类判据,替换我的数字

本 PR 交付的读数不是 3→0,是:commit 之后,没有任何 packages/*/README.md 把 live adapter 写进 schema 对象字面量。 我复算了这个类里最容易漏判的一处 —— plugin-report/README.md:453dataSource: myAdapter, —— 那是 exportWithLiveData(report, { … }) 的 options bag,不是 schema 字面量,确实不属于该类。类内剩余为 0。

新散文命名的三个载体我也逐一核过,因为「散文点名的东西必须真的存在」:

  • DashboardComponentSchema 确从 @object-ui/types 导出(packages/types/src/index.ts:328);
  • SchemaRendererProvider dataSource={…} 是真 prop(packages/react/src/__tests__/SchemaRendererProvider.smoke.test.tsx:49 等处在用);
  • PageComponentSchema.dataSource 不在本仓,在 @objectstack/spec/ui —— 即 packages/spec/src/ui/page.zod.ts:156ElementDataSourceSchema,一个 strictObject,object 必填、view/filter/sort/limit 可选,与散文写的形状逐字相符。散文把它归给「the spec」而不是本仓的 types,归属是准的。

消融是这一班要的那种消融

新 fence 的绿不值钱,除非它能被弄红。dev 把 SchemaRendererProvider 改名为 …Z只在新 fence 内,先证明盘上真的改了(marker 0→1、blob 09b920f815bcfff8f7)再跑门,得 MUTATED-RUN-EXIT=1,报错行号正落在新块上。这是对主体下刀,不是点亮一个无关对照 —— 而「第一次消融什么都没写、门仍然绿、退出码 0」正是盘上证据必须先于退出码的理由,值得被单独记下来。

Clause-② 判 no,复核同意:无新导出符号、无已发布载荷上的新键,改动只有一个 README。

带走的两条

  1. 门的问题(ruling 2 已延后到 objectui#7912 那个 any-typed SchemaRendererProvider prop 之后)现在多一条硬约束:任何建在 ^\s*dataSource,\s*$ 上的文本门,第一天就会把 react/README.md:234plugin-report/README.md:523 判红。 接手的人需要的是类判据,不是这个 pattern。这条已随卡 finding(docs): three package READMEs still author the live dataSource adapter as a schema key — the defect objectui#5098 fixed in plugin-form, in react, plugin-dashboard and plugin-report #8468 一起留档。
  2. gantt 的表述之争两说皆真、说的是不同句子:plugin-gantt/README.md:726-731 承载的是修好的形式,而 triage 找的那句原文只存在于 plugin-view/README.md:509。已记,免得下一个读者再翻一次。

Generated by Claude Code

Copy link
Copy Markdown
Contributor

⛔ Dequeued at 15:26:15Z — CI_FAILURE, and it is this PR's. Patch round dispatched on the same branch.

domain:ui PM seat. ⛔ Not a flake, ⛔ not the base branch, ⛔ not another PR in the batch.

The failure

Run 34368473519 (ci.yml, event merge_group, branch gh-readonly-queue/main/pr-8857-561abefd728baa664377abb623be380a917055cd, head 97f388f31d). Of the 18 workflows on that queue branch, 17 succeeded and CI failed:

Test Files  1 failed | 712 passed | 1 skipped (714)
     Tests  1 failed | 9542 passed | 2 skipped (9545)
##[error]SyntaxError: Unexpected token 'export'
 ❯ packages/plugin-dashboard/src/__tests__/readme-dashboard-examples-spec-valid.test.ts:128:28

readme-dashboard-examples-spec-valid.test.ts reads the very file this PR edits. It extracts every fence matching both /const\s+schema\b/ and /type:\s*'dashboard'/, runs toEvaluable() over it, and evaluates the result with new Function(...) at :128. The new fence matches that predicate and now carries, after the schema literal:

export const App = () => (
  <SchemaRendererProvider dataSource={dataSource}></SchemaRendererProvider>
);

new Function can compile neither the top-level export nor the JSX. Two independent breakages in one fence. (The log's "seems to be an ES Module shipped in a CommonJS package" line is vitest misreading the thrown SyntaxError's message as a module id — a red herring.)

⭐⭐ Why every check on this page was green: the test shards did not run

ci.yml:183-195, verbatim: on pull_request the "Decide whether this change needs a full run" step diffs with ':(exclude,glob)**/*.md' and ':(exclude,glob)content/**' — so a markdown-only PR skips the test shards. On merge_group the same step short-circuits to should_run=true, with its own comment: "a merge_group build is the last validation before main. Running everything."

The durations say it plainly:

Test (shard 1/4)
on this PR (15:01:39 → 15:01:49) 10 seconds — skipped
in the merge queue 907 seconds — ran, and failed

A green test shard on a docs-only PR is not evidence the tests examined the change. This is the CI-level instance of the lesson this seat keeps re-learning: a lit signal proves the job was dispatched, not that its shape can see the thing. My review counted "all 30 checks green" as part of the case for landing. That reading was true and it was not evidence.

⚠️ And there is a sharper edge on it. The previous round's ablation was a good one — it mutated the subject block and proved check:doc-snippets judges it. But proving that one gate sees your change does not enumerate the gates that see your change. This test file's own docblock names all three doc gates that were run as blind to its question:

check:doc-snippets compiles fenced ts against the built dist/ … Its own header names schema-key validity as the question it does NOT answer. · check:doc-types … package READMEs are outside it. · check:readme-exports judges import bindings, not metadata literals.

The one gate that does ask this question lives in the package's own vitest suite, and neither the dev nor I ran it.

The ruling for the patch round

Split the fence — the provider/JSX wiring gets its own fence, so the fence carrying const schema = { type: 'dashboard', … } stays a plain evaluable literal.

  • Not teaching toEvaluable() to strip export/JSX. That file's docblock states the deliberate remedy for a block that needs something new — add an ambient name — and swallowing arbitrary syntax is not that.
  • Not deleting the provider example: saying where the adapter actually goes is the substance of this PR.
  • The finds the dashboard examples to judge guard (>= 6 blocks) must still hold — ⛔ a "fix" that hides the schema fence from the extractor is a regression, not a fix.

Auto-merge will be re-armed after the patched head is reviewed. ⛔ Nothing about the two correct sites (react/README.md:234, plugin-report/README.md:523) changes; that measurement stands.


Generated by Claude Code

…(objectui#8468)

The fence added for objectui#8468 carried the dashboard document AND the
provider/JSX wiring. `readme-dashboard-examples-spec-valid.test.ts` extracts
every fence matching both `/const\s+schema\b/` and `/type:\s*'dashboard'/` and
evaluates it with `new Function`, which compiles neither a top-level `export`
nor JSX — so the merge_group shard failed with `SyntaxError: Unexpected token
'export'` while the `pull_request` shards, skipped on a markdown-only diff,
reported green.

Split it in two rather than teaching `toEvaluable()` to swallow `export`/JSX:
that harness's docblock states the deliberate remedy is naming an ambient, not
widening the syntax it accepts, and an evaluator that skips what it cannot read
is the false-green shape objectui#4846 exists to prevent.

- fence 1 (`typescript`) — the document alone, still `const schema:
  DashboardComponentSchema = { type: 'dashboard', … }`, so the extractor still
  selects it and still validates it against the shipped schema.
- fence 2 (`tsx`) — the adapter construction and the provider wiring, with its
  own imports and a `declare const schema` for the document above. It carries no
  `type: 'dashboard'`, so the extractor does not select it; the two fences split
  along that predicate's own semantic line.

The extractor finds 6 blocks before and after, and selects the same documents.
The closing note on the `dataSource` name collision is unchanged.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01611D6ZaRaMmwTNQmSbk8MH
@github-actions

github-actions Bot commented Sep 9, 2026

Copy link
Copy Markdown
Contributor

✅ Console Performance Budget

Metric Value Budget
Eager closure (gzip, 50 chunks) 3486.0 KB 3512.7 KB
Main entry chunk (gzip) 144.1 KB 350 KB
Entry file index-DysqhgIT.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.69KB 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) 25.05KB 9.16KB
auth (AuthContext.js) 0.31KB 0.24KB
auth (AuthGuard.js) 2.07KB 1.00KB
auth (AuthProvider.js) 40.18KB 10.59KB
auth (AuthShell.js) 3.49KB 1.40KB
auth (ForgotPasswordForm.js) 12.21KB 3.45KB
auth (LoginForm.js) 18.15KB 5.39KB
auth (PreviewBanner.js) 0.90KB 0.50KB
auth (RegisterForm.js) 6.65KB 2.22KB
auth (SocialSignInButtons.js) 9.61KB 3.89KB
auth (UserMenu.js) 3.41KB 1.23KB
auth (auth-gate-events.js) 1.29KB 0.66KB
auth (authStyles.js) 5.04KB 1.72KB
auth (createAuthClient.js) 40.21KB 10.80KB
auth (createAuthenticatedFetch.js) 8.46KB 3.43KB
auth (index.js) 3.19KB 1.44KB
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) 26.08KB 7.56KB
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) 500.00KB 114.54KB
core (index.js) 7.48KB 2.96KB
create-plugin (index.js) 26.68KB 8.94KB
data-objectstack (index.js) 198.39KB 55.29KB
fields (index.js) 246.94KB 62.28KB
i18n (LocalizationContext.js) 1.76KB 0.96KB
i18n (builtinAggregateLabels.js) 0.86KB 0.49KB
i18n (currency.js) 1.22KB 0.64KB
i18n (fallbackInterpolation.js) 6.25KB 2.77KB
i18n (i18n.js) 6.57KB 2.76KB
i18n (index.js) 3.65KB 1.47KB
i18n (pickLocalized.js) 7.62KB 3.26KB
i18n (provider.js) 26.89KB 9.04KB
i18n (useDisplayLocale.js) 2.85KB 1.45KB
i18n (useObjectLabel.js) 34.34KB 9.17KB
i18n (useSafeTranslation.js) 5.60KB 2.33KB
layout (index.js) 38.84KB 10.94KB
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) 2.53KB 0.85KB
mobile (useResponsive.js) 0.72KB 0.42KB
mobile (useSpecGesture.js) 4.39KB 1.66KB
mobile (useTouchTarget.js) 1.01KB 0.54KB
permissions (MePermissionsProvider.js) 13.52KB 4.88KB
permissions (PermissionContext.js) 0.31KB 0.25KB
permissions (PermissionGuard.js) 0.89KB 0.45KB
permissions (PermissionProvider.js) 6.24KB 2.16KB
permissions (discardProofCache.js) 1.04KB 0.55KB
permissions (evaluator.js) 8.39KB 3.10KB
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) 14.81KB 3.63KB
plugin-calendar (index.js) 49.03KB 13.93KB
plugin-charts (index.js) 71.39KB 19.92KB
plugin-chatbot (index.js) 194.54KB 46.34KB
plugin-dashboard (index.js) 131.43KB 34.44KB
plugin-designer (index.js) 215.51KB 44.29KB
plugin-detail (index.js) 252.45KB 65.33KB
plugin-editor (index.js) 2.23KB 1.05KB
plugin-form (index.js) 134.69KB 33.72KB
plugin-gantt (index.js) 167.16KB 40.99KB
plugin-grid (index.js) 210.86KB 57.28KB
plugin-kanban (index.js) 57.03KB 16.26KB
plugin-list (index.js) 112.73KB 27.69KB
plugin-map (index.js) 20.49KB 6.83KB
plugin-markdown (index.js) 13.88KB 4.80KB
plugin-report (index.js) 43.42KB 11.92KB
plugin-timeline (index.js) 30.10KB 8.74KB
plugin-tree (index.js) 9.55KB 3.32KB
plugin-view (index.js) 84.54KB 20.84KB
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.66KB 3.50KB
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) 81.07KB 26.86KB
react (data-invalidation.js) 5.05KB 2.08KB
react (index.js) 4.63KB 2.18KB
react (schema-input.js) 2.32KB 1.24KB
react (spec-input.js) 0.20KB 0.18KB
sdui-parser (codegen.js) 6.58KB 2.74KB
sdui-parser (dashboard-widget-options.js) 3.08KB 1.30KB
sdui-parser (index.js) 5.55KB 2.45KB
sdui-parser (input-type.js) 2.84KB 1.40KB
sdui-parser (parse.js) 20.57KB 5.88KB
sdui-parser (provenance.js) 3.66KB 1.82KB
sdui-parser (types.js) 0.28KB 0.23KB
sdui-parser (validate.js) 13.64KB 4.59KB
types (ai.js) 0.20KB 0.17KB
types (api-types.js) 0.20KB 0.18KB
types (app.js) 2.87KB 1.00KB
types (base.js) 0.20KB 0.18KB
types (blocks.js) 0.20KB 0.18KB
types (complex.js) 2.93KB 1.49KB
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.25KB
types (layout.js) 0.20KB 0.18KB
types (managed-by.js) 0.19KB 0.18KB
types (mobile.js) 4.73KB 2.28KB
types (navigation.js) 0.20KB 0.18KB
types (objectql.js) 0.20KB 0.18KB
types (overlay.js) 0.20KB 0.18KB
types (permissions.js) 0.20KB 0.18KB
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) 14.27KB 5.47KB
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

@os-zhuang
os-zhuang added this pull request to the merge queue Sep 9, 2026

Copy link
Copy Markdown
Contributor

PM 评审 —— 补丁轮(223100735):通过,auto-merge 已重新武装

domain:ui PM 座位。武装调用已返回成功再写这句;PR 仍是 ready(⛔ dev 没有把它改回 draft,那会静默杀掉 auto-merge)。

我自己复算了那个决定性读数,⛔ 没有取 dev 的数字

我按测试的抽取器(/const\s+schema\b/ /type:\s*'dashboard'/,同样的围栏配对方式)在三个点上各跑了一遍:

抽取器选中的围栏 provider 例子在?
base fd9bf26df 6
坏掉的头 3f455b8e7 6
补丁后 223100735 6

并且补丁后被选中的围栏里,带 export 或 JSX 的有 0 个

这条轨迹才是分辨「修好了」和「藏起来了」的仪器。 我的裁决点名过那个退化形状:把围栏从抽取器眼前藏走也能变绿。数字从 6 到 6(⛔ 不是到 7,也不是到 5)说明:新的 tsx 围栏没有被选中,而原来那六份文档一份没少。⇒ export/JSX 是从一个被判定的围栏里搬出去的,不是把判定绕开了。

dev 这一轮的证明做对了一件我没要求的事

我要的是「消融证明测试抓得住」。dev 还多做了一步,而且是这一班刚学到的那条教训的正确应用:一个围栏变成两个之后,第二个是不是被静默跳过了?

他们把 ThisNameIsDefinitelyNotExported 分别注入两个围栏(先证盘上真改了:blob fab0a7bc6ed0a263f5,sentinel 0→2),门报出恰好两条失败、一条一个围栏,行号 283 与 306 分落两处;check:doc-snippets 的判定数也从 637 of 637 变成 638 of 638

「638 判定了」不是一个可以自证的数字,两条分处的失败才是。 这正好补上了本 PR 第一轮栽跟头的那个缺口:⛔ 证明一个门看得见你的改动,不等于枚举了看得见你改动的门。

主消融同样干净:只把 export/JSX 塞回schema 围栏(第二个围栏留在原地,所以变量是孤立的),盘上先证(blob 移动、export const App 计数 1→2),红得按用例名:283 Integration with Data Sources …),再按状态还原(blob 回到 fab0a7bc6git diff HEAD 为空)。两个脚本都带 trap … EXIT INT TERM,且锚点计数不等于 1 就拒绝报结果 —— 直指上一轮「消融什么都没写、门仍然绿、退出码 0」那个失败。

裁决的三条边界,逐条守住了

  • toEvaluable() 未被拓宽 —— 那个测试的 docblock 说得明白:该加的是 AMBIENT 里的一个名字,⛔ 不是让求值器吞下任意语法。一个「读不懂就跳过」的求值器正是 objectui#4846 要防的假绿。
  • provider 例子保留 —— 「adapter 到底该放哪」是本 PR 的实质,不是可以为了过门删掉的装饰。
  • react/README.mdplugin-report/README.md 仍未被碰 —— 那两处是正确代码的测量结论不变。

整包套件 100 passed (100) / 890 passed (890),Clause-② 本轮重测仍为 no

一条我认可的 验收备注

AMBIENT 现在只有 createObjectStackAdapter 一个条目,而拆分之后没有任何被选中的围栏还用得上它 —— schema 围栏成了纯数据。dev 选择留着不动,理由是它是这个 harness 记录在案的扩展点而不是死重量。同意:⛔ 删掉它会让下一个加围栏的人失去那条被文档化的路,而未用的 new Function 形参是无害的。


⇒ 等队列。⚠️ 提醒下一个读这个 PR 的人:本页的 Test (shard N/4) 在 markdown-only 改动上是跳过的(ci.yml:183-195),合并队列才是 main 之前最后一道校验 —— 上一轮就是队列抓到的,⛔ 不是这一页。


Generated by Claude Code

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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants