Skip to content

docs(plugin-gantt): README 按真实导出面重写虚构的手动注册与 GanttSchema 类型 - #5059

Merged
yinlianghui merged 1 commit into
mainfrom
claude/issue-5012-plugin-gantt-readme
Aug 17, 2026
Merged

docs(plugin-gantt): README 按真实导出面重写虚构的手动注册与 GanttSchema 类型#5059
yinlianghui merged 1 commit into
mainfrom
claude/issue-5012-plugin-gantt-readme

Conversation

@yinlianghui

@yinlianghuiyinlianghui commented Aug 17, 2026

Copy link
Copy Markdown
Collaborator

Fixes#5012

基线 origin/main @ f331f5a8bdb728039519ace070f6433f597e0dd4(worktree 显式建在该 sha 上)。方法学照抄同族 #5002 → PR #5021 的减法形,以及今日已落地的 #5010 → PR #5046#5016 → PR #5053

判定表(虚构 vs 改名 vs 真名)

卡面列了两处,名集合核对与示例编译又在同一段里揪出第三处 —— 同为「README 对本包某个标识符的断言不成立」,一并修,单列如下。

README(改前)判定依据处理
:108import { ganttComponents } + :112Object.entries(ganttComponents).forEach(…)纯虚构全包零命中;导出面 35 个名字里没有它删虚构节,改教真实机制
:407import type { GanttSchema }:418const gantt: GanttSchema虚构名,但真身存在加词边界后本包与 @object-ui/types 皆零命中;裸 grep 的 6 处命中全是 ObjectGanttSchema子串(卡面复核命令写的是裸 grep,故复测时特意补了词边界)按真身重写:ObjectGanttSchema from @object-ui/types
:138-147interface GanttTask { name; start: string; … }真名,形状漂移真身 src/GanttView.tsx:139:titlenameDate 非 ISO 字符串、color 是 CSS 颜色(GanttView.tsx:4319 直接塞内联 backgroundColor)非 Tailwind 类名参考块 + 示例双双对齐,并双向钉住
:407GanttTask(导入本身)真名导出面命中保留

第三处不是夹带::407 的示例 const task: GanttTask = { name: …, start: '2024-01-01' } 用的正是这个真类型,不改它示例就编译不过;而只改示例、留着 14 行外的参考块继续教假形状,同一个 README 会自相矛盾。

未新增任何导出或类型来把 README 变真(契约扩张需另立卡)。

删掉的每一节,删因一行

  • ### Manual Registration 整节(改前 :105-115) —— 它教的 ganttComponents 不存在,Object.entries(undefined) 在读者复制的第一行就抛 TypeError;而它想表达的「注册」根本不需要手动做,是 import 入口的副作用。替换为三节真话:两个 register 调用认领的 schema 类型表(object-ganttplugin-gantt:object-ganttganttview:gantt,各带裸 type 回落 —— 见 packages/core/src/registry/Registry.ts:195,226)、包的真实导出面、以及原片段真正想做的事(把导出的 ObjectGanttRenderer 注册到自定义键)。
  • const gantt: GanttSchema = { type: 'gantt', viewMode, tasks }(改前 :418-422) —— 类型名虚构,且形状也不成立:真身 ObjectGanttSchema记录驱动的(type: 'object-gantt' + objectName + *Field),从不携带 tasks 数组。
  • GanttTask 参考块的 assignee?: string(改前 :145) —— 真身上没有这个字段。

名集合核对读数

导出名集合取自构建产物packages/plugin-gantt/dist/index.d.ts,走 TS compiler API 的 checker.getExportsOfModule(不是对 src 做正则)。README 侧不用正则抓 import:先抽 fenced 代码块,每块 ts.createSourceFile,再走 ImportDeclaration 的 AST。

这样 #5043 记的两个坑在结构上不可能发生 —— 多行块本就是一个ImportDeclaration 节点(fence/散文吃不进 import clause);行尾 // 注释对 parser 是 trivia(不可能贡献名字);A as B 的 AST 直接给出 propertyName = A(导出名)与 name = B(别名),判 A

第一版确实照卡面规格写了跨行正则,在本包上直接报 5 个假名(weeks/title/selection/target/dataSource)而真正的两个虚构名一个没报:副作用导入 import '@object-ui/plugin-gantt';from,懒惰量词从它一路吃到 20 行之后的下一个 from '@object-ui/plugin-gantt',把中间整段 markdown 当成了 import clause。已把这条读数与 AST 版规格写在 #5043 上(不另立卡)。

改前: export surface: 35 names / README 4 bindings / MISSING COUNT: 2
- ganttComponents @ README:108
- GanttSchema @ README:407
改后: export surface: 35 names / README 39 bindings / MISSING COUNT: 0

改后 39 个绑定逐个 OK,覆盖新增的两个多行 import 块全部 35 个导出名。

编译探针读数

README 的 ts/tsx 块抄进 scratch,对同一构建产物 dist/index.d.ts 编译(strict: true,没有为让块通过而放松任何选项)。每块独立成文件并补一行 export {}; —— 多个块各自声明 const schema 都是全局 script,会撞重复标识符;补这一行只改作用域,不影响块内检查。

### 卡面半径(本 PR 改写的 5 个块:公共导出面 ×2、自定义键注册、GanttTask 参考块+pin、两个 TypeScript 示例)
tsc -> rc=0 (no diagnostics)
### 全 README(15 个可编译块;2 块按设计跳过并在输出里列明理由)
tsc -> rc=2
5012-block07.tsx(4,17): error TS7006: Parameter 'task' implicitly has an 'any' type.
5012-block07.tsx(8,18): error TS7006: Parameter 'updatedTask' implicitly has an 'any' type.

余下这两条不是本 PR 的漏修:block07 是 "Interactive Gantt" 示例里 onTaskClick: (task) => … 写在无类型标注的 const schema = { … } 里,属那一族虚构 schema 键的一部分,已立 #5057。按纪律不在本卡里顺手改。

跳过的两块(输出里列明,不静默丢)::191-199{ type, tasks: …, … } 形状速写、:449-454dependencies: [ … ] 片段 —— 都是故意不合法的 TS。

GanttTask 参考块额外双向钉在真身上,否则它绿得没有意义(独立的 interface GanttTask { … } 只是个与真类型无关的本地声明,内容再假也编译通过):

declareconstreal: RealGanttTask;exportconstdocFromReal: GanttTask=real;// real -> documenteddeclareconstdoc: GanttTask;exportconstrealFromDoc: RealGanttTask=doc;// documented -> real

散文里唯一一条探针覆盖不到的断言(「gantt 块挂在 ListViewSchema 上、类型是 GanttConfig」)另写了一个小探针单独验:rc=0

反向验证(两条,预判先写)

(a) 名集合核对自证。 预判:往多行 import 块里 planted 四处,MISSING COUNT 0 → 2,恰为 {ganttThings, GanttSchema};还原后回 0。四条全符 ——

变异预判实测
行尾注释改成含非导出词(// ganttComponents was never real)不得报(假阳性测试)未报
多行值导入里加 ganttThings as Things报,且按导出名ganttThings 而非别名ganttThings @ :143
多行类型导入里 GanttTaskGanttTask as Task仍 OK(别名判导出名)OK
多行类型导入中段GanttSchema报 @ :156

MISSING COUNT: 2,还原读数 0。变异全做在 README 的 scratch 副本上(检查器加了一个 --readme 参数指向该副本),工作树一次都没被改过 —— 不存在「临时改动误入 commit」的窗口。

(b) 示例编译自证。 预判:把改前 README 回填,tsc 必须转红,且错误一一对应所改各处。同一套探针机器直接跑改前 README(harness/skip 按内容签名分类而非块序号,所以两个版本共用一套机器)。转红,rc=2,对应关系:

所改之处预判实测诊断
ganttComponentsTS2305block02(1,10): TS2305 … has no exported member 'ganttComponents'
GanttSchemaTS2305block14(1,15): TS2305 … has no exported member 'GanttSchema'
GanttTask 形状(real → doc)转红block04(13,14): TS2741 Property 'name' is missing in type '…GanttTask' but required in type 'GanttTask'
GanttTask 形状(doc → real)转红block04(15,14): TS2741 Property 'title' is missing in type 'GanttTask' but required in type '…GanttTask'
示例里的字符串日期转红block14(6,3) / block14(7,3): TS2322 Type 'string' is not assignable to type 'Date'
既有的两条 TS7006原样携带block06(4,17) / block06(8,18)(改后为 block07)

预判不符的一处,如实记:我同时预判改前的 const task: GanttTask = { name: …, start: '…' } 会在 name/title 上报错,实测那一块报了两条日期 TS2322 —— present 属性的类型不符会抢在 missing-property 详述之前短路。也就是说 name/title 这个事实只由 (b) 表里的 pin 块承载,typed-example 那一侧靠不住。这正是双向 pin 值得写下来的理由;若只抽 typed example 不做 pin,键名重命名这一整类会整体漏掉。此点已一并记在 #5043

另有一处探针 harness 的诚实修正::66-73< GanttView onTaskUpdate > 块,harness 初版把 save 声明成要求必填 Date,块就红了两条。但真实签名第二参是 PartialPick,start/end 本就是 Date | undefined —— 那两条红测的是我的假设,不是这个块。harness 已改为中性(Partial),块随之转绿;README 那条「start/end are JS Date objects」的注释确实与签名和运行时都不符(GanttView.tsx:1335 的进度拖拽提交纯 { progress },照抄会把日期写空),但那是散文断言的缺陷,应当由它自己的证据立卡,不该借探针红来主张 —— 已立 #5058

验证

  • 仓根 pnpm exec turbo run type-check --concurrency=281 successful, 81 total(重活经 flock 串行 + --max-old-space-size=4096)。
  • node scripts/check-doc-links.mjsLinks are valid across 13 scan roots.
  • node scripts/check-control-bytes.mjsOK (scanned 4505 tracked text file(s));改动两文件另做 grep -naP '[\x00-\x08\x0b\x0c\x0e-\x1f]' 自扫,零命中。
  • pnpm --workspace-concurrency=2 --filter '@object-ui/plugin-gantt...' build → rc=0(探针所依赖的构建产物)。

docs-only 的 CI 形状:ci.yml / lint.yml**/*.md.changeset/** 列进 paths-ignore,所以 Test / Type Check 各 job 的实质步骤会被 path-filter 短路成 skipped 而 job 报 success。按纪律计绿,但类型证据是上面的本地仓根读数,不是 CI 的(#5046 / #5053 先例)。

顺手立的卡(均未认领,不夹带进本 PR)

同文件、不同性质,各自需要独立定级:

changeset

.changeset/plugin-gantt-readme-truth-5012.md,@object-ui/plugin-gantt: patch,口径同 #5046 / #5053:无代码/类型/运行时改动,声明 patch 是因为 README.md 在包的 files 里,随下次发布到 npm。

`packages/plugin-gantt/README.md` 两处教了包里不存在的标识符,一处教了与真
类型不符的形状。三处都按包的真实导出面重写(导出名集合取自构建产物
`dist/index.d.ts`,示例逐块对同一构建产物编译验证)。
- `ganttComponents`:全包零命中,所谓「手动注册」是
`Object.entries(undefined)`,照抄第一行即 TypeError。注册只是 import 入口的
副作用。改教真实机制:两个 register 调用认领的 schema 类型
(`object-gantt` / `gantt`,各带命名空间键与裸 type 回落)、包的真实导出面,
以及原片段真正想做的事 —— 把导出的 `ObjectGanttRenderer` 注册到自定义键。
- `GanttSchema`:纯虚构(本包与 `@object-ui/types` 加词边界后都零命中;裸
grep 的命中全是 `ObjectGanttSchema` 的子串)。真身存在,故按真身重写而非删
节:`@object-ui/types` 的 `ObjectGanttSchema`,记录驱动,不携带 tasks 数组。
- `GanttTask`:三者中唯一的真名,但文档形状已漂移 —— 标签字段是 `title` 非
`name`,`start`/`end` 是 `Date` 非 ISO 字符串,`color` 是 CSS 颜色非 Tailwind
类名。参考块与示例双双对齐,并在探针里双向钉住,后续漂移会转红而不是作为
无关的本地声明静默编译通过。
⛔ 未新增任何导出或类型来把 README 变真。
Fixes#5012
Co-authored-by: Claude <noreply@anthropic.com>
@github-actionsgithub-actionsBot added documentation Improvements or additions to documentation plugin labels Aug 17, 2026
@github-actions

Copy link
Copy Markdown
Contributor

✅ Console Performance Budget

MetricValueBudget
Main entry (gzip)25.3 KB350 KB
Entry fileindex-DEKTDl1Q.js
StatusPASS

📦 Bundle Size Report

PackageSizeGzipped
app-shell (index.js)9.56KB3.59KB
app-shell (runtime-config.js)7.42KB2.32KB
app-shell (types.js)0.01KB0.04KB
app-shell (urlParams.js)8.92KB3.41KB
auth (AuthContext.js)0.31KB0.24KB
auth (AuthGuard.js)1.17KB0.53KB
auth (AuthProvider.js)25.13KB5.40KB
auth (AuthShell.js)3.49KB1.40KB
auth (ForgotPasswordForm.js)12.21KB3.45KB
auth (LoginForm.js)18.13KB5.39KB
auth (PreviewBanner.js)0.90KB0.50KB
auth (RegisterForm.js)6.64KB2.21KB
auth (SocialSignInButtons.js)9.60KB3.89KB
auth (UserMenu.js)3.40KB1.22KB
auth (auth-gate-events.js)1.29KB0.66KB
auth (authStyles.js)5.04KB1.72KB
auth (createAuthClient.js)40.21KB10.79KB
auth (createAuthenticatedFetch.js)6.34KB2.43KB
auth (index.js)2.71KB1.22KB
auth (invitation-status.js)1.22KB0.70KB
auth (org-roles.js)6.66KB2.78KB
auth (phone-identifier.js)1.11KB0.66KB
auth (types.js)0.59KB0.35KB
auth (useAuth.js)5.02KB0.88KB
auth (useIsWorkspaceAdmin.js)1.61KB0.85KB
collaboration (CommentThread.js)26.07KB7.56KB
collaboration (LiveCursors.js)3.17KB1.27KB
collaboration (PresenceAvatars.js)6.49KB2.64KB
collaboration (PresenceProvider.js)2.79KB1.13KB
collaboration (index.js)1.65KB0.73KB
collaboration (useCollaborationTranslation.js)6.05KB2.52KB
collaboration (useCommentSearch.js)1.98KB0.88KB
collaboration (useConflictResolution.js)7.75KB1.86KB
collaboration (useMentionNotifications.js)1.81KB0.68KB
collaboration (usePresence.js)6.33KB1.84KB
collaboration (useRealtimeSubscription.js)7.91KB2.01KB
components (index.js)502.20KB112.21KB
core (index.js)4.11KB1.62KB
create-plugin (index.js)10.08KB3.26KB
data-objectstack (index.js)159.03KB44.08KB
fields (index.js)234.25KB58.48KB
i18n (LocalizationContext.js)1.76KB0.96KB
i18n (currency.js)1.22KB0.64KB
i18n (i18n.js)4.28KB1.75KB
i18n (index.js)3.35KB1.38KB
i18n (pickLocalized.js)3.69KB1.73KB
i18n (provider.js)23.12KB7.62KB
i18n (useDisplayLocale.js)2.84KB1.45KB
i18n (useObjectLabel.js)27.59KB6.63KB
i18n (useSafeTranslation.js)7.77KB3.13KB
layout (index.js)39.16KB10.97KB
mobile (MobileProvider.js)0.92KB0.49KB
mobile (ResponsiveContainer.js)0.94KB0.38KB
mobile (breakpoints.js)1.51KB0.70KB
mobile (createOfflineDataSource.js)5.61KB1.74KB
mobile (index.js)1.50KB0.62KB
mobile (offlineQueue.js)3.91KB1.35KB
mobile (pwa.js)0.97KB0.49KB
mobile (serviceWorker.js)1.48KB0.62KB
mobile (serviceWorkerSource.js)3.41KB1.48KB
mobile (useBreakpoint.js)1.54KB0.65KB
mobile (useGesture.js)6.96KB1.98KB
mobile (useOfflineSync.js)1.99KB0.72KB
mobile (usePullToRefresh.js)2.53KB0.85KB
mobile (useResponsive.js)0.71KB0.42KB
mobile (useResponsiveConfig.js)1.36KB0.63KB
mobile (useSpecGesture.js)4.32KB1.64KB
mobile (useTouchTarget.js)1.01KB0.54KB
permissions (MePermissionsProvider.js)9.35KB3.31KB
permissions (PermissionContext.js)0.31KB0.25KB
permissions (PermissionGuard.js)0.89KB0.45KB
permissions (PermissionProvider.js)4.42KB1.42KB
permissions (evaluator.js)5.12KB1.74KB
permissions (index.js)0.91KB0.41KB
permissions (store.js)0.91KB0.42KB
permissions (useFieldPermissions.js)1.28KB0.52KB
permissions (usePermissions.js)1.81KB0.83KB
plugin-ai (index.js)15.75KB3.80KB
plugin-calendar (index.js)46.62KB12.83KB
plugin-charts (index.js)64.75KB18.37KB
plugin-chatbot (index.js)181.21KB43.14KB
plugin-dashboard (index.js)127.85KB32.73KB
plugin-designer (index.js)212.39KB42.83KB
plugin-detail (index.js)241.12KB60.43KB
plugin-editor (index.js)2.46KB1.10KB
plugin-form (index.js)122.95KB29.80KB
plugin-gantt (index.js)164.10KB39.87KB
plugin-grid (index.js)197.61KB53.03KB
plugin-kanban (index.js)52.72KB14.54KB
plugin-list (index.js)111.17KB26.99KB
plugin-map (index.js)18.72KB6.09KB
plugin-markdown (index.js)13.72KB4.69KB
plugin-report (index.js)41.97KB11.33KB
plugin-timeline (index.js)26.68KB7.66KB
plugin-tree (index.js)8.50KB2.88KB
plugin-view (index.js)83.81KB20.49KB
providers (DataSourceProvider.js)0.75KB0.39KB
providers (MetadataProvider.js)1.37KB0.59KB
providers (ThemeProvider.js)1.90KB0.85KB
providers (UploadProvider.js)11.66KB3.50KB
providers (index.js)0.44KB0.22KB
providers (types.js)0.01KB0.04KB
react-runtime (index.js)5.62KB2.34KB
react (LazyPluginLoader.js)3.77KB1.33KB
react (SchemaRenderer.js)27.53KB9.41KB
react (data-invalidation.js)5.05KB2.08KB
react (index.js)1.28KB0.68KB
react (schema-input.js)1.45KB0.83KB
react (spec-input.js)0.20KB0.18KB
sdui-parser (codegen.js)5.41KB2.34KB
sdui-parser (index.js)4.77KB2.16KB
sdui-parser (input-type.js)2.84KB1.40KB
sdui-parser (parse.js)10.76KB3.17KB
sdui-parser (provenance.js)3.66KB1.82KB
sdui-parser (types.js)0.29KB0.24KB
sdui-parser (validate.js)6.92KB2.40KB
types (ai.js)0.20KB0.17KB
types (api-types.js)0.20KB0.18KB
types (app.js)2.87KB0.99KB
types (base.js)0.20KB0.18KB
types (blocks.js)0.20KB0.18KB
types (complex.js)0.20KB0.18KB
types (crud.js)0.20KB0.18KB
types (dashboard-filter-alias.js)6.23KB2.74KB
types (data-display.js)0.20KB0.18KB
types (data-protocol.js)0.20KB0.19KB
types (data.js)0.20KB0.18KB
types (designer.js)1.87KB0.85KB
types (disclosure.js)0.20KB0.18KB
types (error-code.js)1.54KB0.88KB
types (feedback.js)0.20KB0.18KB
types (field-types.js)0.20KB0.18KB
types (form.js)0.20KB0.18KB
types (http-retry.js)4.32KB2.02KB
types (index.js)3.05KB1.52KB
types (layout.js)0.20KB0.18KB
types (managed-by.js)0.19KB0.18KB
types (mobile.js)2.59KB1.31KB
types (navigation.js)0.20KB0.18KB
types (objectql.js)0.20KB0.18KB
types (overlay.js)0.20KB0.18KB
types (permissions.js)0.20KB0.18KB
types (plugin-scope.js)0.20KB0.18KB
types (record-components.js)0.20KB0.19KB
types (record-semantics.js)1.28KB0.67KB
types (registry.js)0.20KB0.18KB
types (reports.js)0.20KB0.18KB
types (spec-report.js)5.05KB1.93KB
types (system-fields.js)3.33KB1.54KB
types (theme.js)0.20KB0.18KB
types (ui-action.js)3.40KB1.71KB
types (views.js)0.20KB0.18KB
types (widget.js)0.20KB0.18KB

Size Limits

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

@yinlianghuiClaude

Copy link
Copy Markdown
CollaboratorAuthor

PM 验收:ACCEPT(session session_01GTRjn8xBqp75dk7kFupVRt,objectui 分片 PM,批次 22)

实物核验:merge-base f331f5a8b(含 PR #5053,按派发要求),2 files +174/−21 与报告一致,单 commit,模型标识 msg/diff 双零,releases 零触碰。CI 亲读:19 个 check-run 全 completed 零失败(docs-only path-filter 形状,类型证据为本地仓根 81/81,同族口径)。

验收要点:

  1. 卡面复核命令自身的缺陷被抓住并转化为发现:卡面写的裸 grep「零命中」实测 6 命中(全是 ObjectGanttSchema 子串)—— 加词边界后才是真零命中,而正是这一步查出虚构名 GanttSchema 有真身。示例按真身重写(记录驱动形),卡面预留的「缺授权类型」finding 正确地未立。这是第 6 条读数纪律(裸名 grep 幸存家族)的教科书应用。
  2. 名集合核对器从正则版升级为 AST 版且有判别性实测(正则版在本包报 5 假名、漏 1 真虚构),规格与读数回灌 finding: 没有门禁核对包内 README 的自包导入名 vs 真实导出面 —— #5002 家族 7 个包的漂移全靠人工巡查发现(附已验证的检查器原型) #5043 追评而非另立卡 —— 工具债记账位置正确。
  3. 编译探针双向 pin 的价值被一次预判偏差实证:typed-example 侧 present-property 类型错抢在 missing-property 之前短路,键名重命名一类只有 pin 块能承载 —— 预判不符如实记录,harness 一处把自己假设当断言的初版也诚实修正(plugin-gantt README 的 onTaskUpdate 示例在进度拖拽时写入 undefined 日期 —— changes 是 Partial,块内注释却断言 start/end 必为 Date #5058 改由自身证据立卡,不借探针红主张)。
  4. 全 README 探针余两条既有 TS7006 属 plugin-gantt README 教的整片 schema 键面渲染器一个都不读 —— tasks / viewMode / object / startField 全零命中,照抄即空图 #5057 族,按纪律不顺手改、分两档报读数 —— 未用放松编译选项换表面全绿。

派生物分诊(本评论即记录):#5057(README 整片 schema 键面渲染器一个不读,照抄任一示例得空图 —— 比本单更重的文档真值缺陷)与 #5058(onTaskUpdate 可选性断言错误)均 → pm:queue;两卡同文件且同性质,待本 PR 落 main 后合单派发(先例 #4877+#4878)。#5043 追评为正确的增量记账。

转 ready 并挂 auto-merge(squash)。


Generated by Claude Code

@yinlianghui
yinlianghui marked this pull request as ready for review August 17, 2026 21:43
@yinlianghui
yinlianghui added this pull request to the merge queueAug 17, 2026
Merged via the queue into main with commit bb3fab6Aug 17, 2026
20 checks passed
@yinlianghui
yinlianghui deleted the claude/issue-5012-plugin-gantt-readme branch August 17, 2026 21:44
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentationImprovements or additions to documentationplugin

Projects

None yet

Development

Successfully merging this pull request may close these issues.

plugin-gantt README 教的 ganttComponents 手动注册与 GanttSchema 类型都不存在

2 participants

@yinlianghui@claude