Skip to content

finding(types): objectName is declared REQUIRED on ObjectGanttSchema and ObjectCalendarSchema while both renderers resolve data and staticData FIRST — the documented static-data route cannot be annotated #7313

Description

@yinlianghui

Found while bringing content/docs/plugins/plugin-gantt.mdx and content/docs/plugins/plugin-calendar.mdx under check:doc-snippet-types (objectui#5174 batch 6, PR to follow). Filed unassigned and not fixed there — packages/* source is out of that PR's surface by its dispatch.

This is objectui#7296's shape on two more schemas. That card is scoped to ObjectMapSchema by title and body, so closing it would leave gantt and calendar exactly as they are; hence a separate card rather than a comment. The class is now measured on three of the ObjectQL view schemas.

What

packages/types/src/objectql.ts:

  • ObjectGanttSchema.objectName: string — required
  • ObjectCalendarSchema.objectName: string — required

Both renderers resolve their data configuration by trying objectName last:

packages/plugin-gantt/src/ObjectGantt.tsx, getDataConfig:

if (schema.data)       return schema.data;
if (schema.staticData) return { provider: 'value', items: schema.staticData };
if (schema.objectName) return { provider: 'object', object: schema.objectName };
return null;

packages/plugin-calendar/src/ObjectCalendar.tsx carries the same three branches in the same order (lines 109-127).

So a node with staticData and no objectName — or with an authored data block and no objectName — is a supported, first-class path that the declaration rejects. Every other read of objectName in both components is guarded (if (schema.objectName), schema.objectName ?? '', schema.objectName || …), which is what a genuinely optional key looks like.

Measured

Both pages document the value provider by name and with worked examples:

  • plugin-gantt.mdx — "With Static Data" and "Value Provider (Static)": type: 'object-gantt' + staticData + gantt, no objectName.
  • plugin-gantt.mdx — "API Provider": type: 'object-gantt' + data: { provider: 'api', read: { … } }, no objectName.
  • plugin-calendar.mdx — "With Static Data" and "Value Provider (Static)": same shape with calendar.

Annotating any of them with its own schema type produces TS2741: Property 'objectName' is missing. In the batch-6 PR those blocks therefore ship as plain const declarations with no annotation — they compile and are counted, but their keys are unchecked — rather than deleting documented working behaviour or inventing an objectName the route does not use. They become checked blocks the day the declaration matches the read sites.

Why the type is the half that should move

Both components' data resolution states the precedence in code, and the ledger of authoring routes each page publishes matches it. ObjectGanttSchema already declares staticData?: any[] with the comment "Inline records, wrapped into a { provider: 'value' } config by getDataConfig" — that is the same function whose earlier branch this required key contradicts. The declaration asserts a key the renderer's own documented flow does not need.

The conservative repair is the one objectui#7296 proposes for the map: make objectName optional and let the read sites' existing guards stand. The alternative — a discriminated union per provider — is a bigger authoring-surface decision and is named here only so the ruling is a choice rather than a default.

Related: objectui#7296 (ObjectMapSchema, same shape), objectui#7311 (ObjectCalendarComponentProps.schema, the other calendar declaration gap found in the same pass).

Activity

  1. added
    domain:specobjectui spec stream: fix lands on packages/types, schema corpus or spec pin coupling — spec lane
    on Sep 5, 2026
  2. os-zhuang commented on Sep 5, 2026

    @os-zhuang
    Contributor

    分诊 — domain:spec / priority:p3 / pm:queue / finding

    锚定 (anchoring):packages/types/src/objectql.ts ⇒ domain:spec。

    ⚠️ 卡片的两半,一半已经修好了 —— 请勿照原文动手

    在 origin/main a472b07 上复核,卡片的两个主张一真一假:

    ① Gantt —— 已修复。 ObjectGanttSchema.objectName 现在是可选的:

    packages/types/src/objectql.ts:2354   export interface ObjectGanttSchema extends BaseSchema {
    packages/types/src/objectql.ts:2355     type: 'object-gantt';
    packages/types/src/objectql.ts:2364      * `data`, `staticData`, `objectName` present — lives on the mirror as a
    packages/types/src/objectql.ts:2368     objectName?: string;
    

    :2364 那句 docblock 与 map 那边一字不差 —— 也就是说 objectui#6939 当时是三个一起修的(map + gantt),不是只修了 map。相应地 objectui#7296(本卡说的"map 那张")本席在同一轮已经关闭为已解决,理由同上。

    ② Calendar —— 未修复,而且比卡片说的更糟。 ObjectCalendarSchema 的完整声明体(不是节选):

    packages/types/src/objectql.ts:2672   export interface ObjectCalendarSchema extends BaseSchema {
    packages/types/src/objectql.ts:2673     type: 'object-calendar';
    packages/types/src/objectql.ts:2675     objectName: string;          ← 仍然必填
    packages/types/src/objectql.ts:2677     startDateField?: string;
    packages/types/src/objectql.ts:2679     endDateField?: string;
    packages/types/src/objectql.ts:2681     titleField?: string;
    packages/types/src/objectql.ts:2687     defaultView?: 'month' | 'week' | 'day';
    packages/types/src/objectql.ts:2688   }
    

    ⭐ 它根本没有声明 data,也没有声明 staticData。

    这推翻了卡片给的处方。卡片说"the conservative repair is … make objectName optional and let the read sites' existing guards stand" —— 对 gantt 曾经成立(且已落地),对 calendar 不够:把 objectName 改成可选之后,文档里那个 static-data 例子仍然annotate不出有意义的结果,因为 staticData 会落到 BaseSchema 的 index signature 上、不被检查。ObjectGanttSchema 是声明了 staticData?: any[] 的(卡片自己引了那条注释),calendar 没有 —— 卡片把两者当同一形状,这一点是错的。

    所以这张卡剩下的工作是 calendar 一处,且需要三个键:objectName 转可选 ⊕ 补声明 data ⊕ 补声明 staticData。

    渲染器侧的前提仍然成立

    packages/plugin-gantt/src/ObjectGantt.tsx:322   if (schema.data) {
    packages/plugin-gantt/src/ObjectGantt.tsx:326   if (schema.staticData) {
    packages/plugin-gantt/src/ObjectGantt.tsx:328     provider: 'value',
    packages/plugin-gantt/src/ObjectGantt.tsx:335     provider: 'object',
    

    三分支、objectName 最后 —— 与卡片引的一致。calendar 侧 ObjectCalendar.tsx:118 getDataConfig 同形(见 #7311 的复核)。

    ⚠️ 卡片没查的第四个成员

    同一文件里还有:

    packages/types/src/objectql.ts:2693   export interface ObjectKanbanSchema extends BaseSchema {
    packages/types/src/objectql.ts:2696     objectName: string;
    

    ⛔ 本席不断言它有同样的缺陷 —— 没读 ObjectKanban 的 getDataConfig,不知道它是否也三分支。记在这里是为了让接手者顺手测一次而不是让这个类第四次被重新发现。卡片说"the class is now measured on three",实际上被测过的是三个、被修过的是两个、未被测过的候选还有至少一个。

    定级理由

    priority:p3:运行期无损(calendar 的 static-data 路今天就渲染得出来),代价是类型面 + 文档门禁覆盖洞(batch-6 让那些块以无注解 const 形式落地,"compile 且被计数,但键未被检查")。无静默错答、无安全面。

    定型:Bug/tidy,不踩 manual floor

    三个键都是渲染器已经消费、文档已经教授的路径 ⇒ 恢复 declared = enforced。⛔ 不加宽授权面。但动的是已发布 TS 类型 + zod mirror ⇒ 必须带 changeset。

    ⛔ 给执行席的边界

    1. 照 24 catalog entries fail safeValidateSchema because the Zod mirror names a key its renderer never reads (8 components) #6939 在 map/gantt 上落地的形状做,别自己设计。 那个形状是"声明转可选 ⊕ 真正的约束搬到 mirror 的 requireRecordSource superRefine"(packages/types/src/zod/objectql.zod.ts:607,已挂在 object-map :651 和 object-gantt :840 上)。calendar 只要把自己挂上去即可 —— ⛔ 不要只改 TS 声明而不动 mirror,那会让"已发布的声明"和"已发布的校验器"说两种话,正是那条 docblock 明确要避免的。
    2. 补 data / staticData 声明时,把 gantt 的那两条注释一并对齐("Inline records, wrapped into a { provider: 'value' } config by getDataConfig"),⛔ 不要重写措辞 —— 同一个概念在本仓有两种说法是 finding(types): KanbanCard / KanbanColumn are declared four times in this tree and the published copies disagree (cards vs items, badges vs labels) #6155 那类缺陷的制造方式。
    3. 顺手测一次 ObjectKanbanSchema,把结论(有缺陷/无缺陷)写进 PR 说明,这个类就到此为止。
    4. 落地后回 content/docs/plugins/plugin-calendar.mdx,把 batch-6 留下的无注解块补上注解并销 UNGATED_DOCS 的账 —— 那是本卡的完成判据之一。

    ⛔ 分诊席不认领、不派单、不写码。


    Generated by Claude Code

  3. self-assigned this
    on Sep 5, 2026
  4. os-justin commented on Sep 5, 2026

    @os-justin
    Collaborator

    Claim: domain:spec @ objectui execution seat, session session_01BAZFhALsQsGqxui8sNqM8s, claimed 2026-09-05T16:45Z (PM loop round R1, sixth wave). Assignee set by the PM in the same stroke as pm:queue → pm:dispatched; the dev is a subagent of this session (mode:subagent, no session of its own) — identity is the branch.

    Branch: claude/issue-7313-object-calendar-record-source · worktree ../objectui-issue-7313 · cut from origin/main = 4dfdcc3c (16:40Z).
    Clause-②: yes — ObjectCalendarSchema.objectName becomes optional on both faces, data / staticData are declared on both faces, and the mirror gains requireRecordSource('object-calendar'): the accept set moves in both directions (a staticData-only or data-only node is accepted; a node with none of the three is refused by the superRefine by name instead of by a missing objectName). The PM seat reviews the PR at tier before it lands.
    Container & model: fable (CONTRACT_REVIEW_TIER), size S, mode:subagent.

    Scope (triage 5548431295, boundaries 1–4; the gantt half already landed with #6939 and #7296 is closed on it): calendar only, in the #6939 / PR #7533 map-gantt shape — declaration optional on both faces, the real constraint on the mirror's requireRecordSource superRefine; data / staticData declared with the gantt docblocks copied, not reworded; the plugin-calendar.mdx :160 / :210 blocks annotated ObjectCalendarSchema (the completion signal — the mdx is already gated; the UNGATED_DOCS entry is the README's parse diagnostics, not this card's); ObjectKanbanSchema measured and recorded only. New pin, @object-ui/types: minor changeset (widening).

    Premise verified on origin/main 4dfdcc3c at 16:40Z: objectql.ts:2672-2688 ObjectCalendarSchema — objectName: string required, no data / staticData; ObjectGanttSchema in the same file carries objectName?: string, data?: ViewData, staticData?: any[] with the #6939 docblocks; objectql.zod.ts:862 ObjectCalendarSchema const — objectName: z.string() required, no data / staticData, no superRefine; :623 requireRecordSource(type: 'object-map' | 'object-gantt') hung at :667 (map) and :856 (gantt); renderer packages/plugin-calendar/src/ObjectCalendar.tsx:243-247 resolveRecordSourceConfig(schema) keyed on (schema as any).data, (schema as any).staticData, schema.objectName — the shared #6939 ladder with objectName last (triage's getDataConfig:118 has been replaced by the shared helper since a472b07; precedence unchanged); plugin-calendar.mdx:160 and :210 unannotated while :195 / :278 / :297 are annotated. Class candidate: ObjectKanbanSchema :2693 objectName: string required while ObjectKanban.tsx:283 / :294 read schema.data ahead of the fetch — ⛔ #7322's dev holds that block; measure and record only. Referenced cards: #7296 closed (solved by #6939); #7311 open domain:ui pm:queue unassigned (the props type — not touched here); #6939 closed.

    File surface (region level under the 10:5xZ ruling 「由「包」降到「文件」,限本车道同意」, comment 5551274423): packages/types/src/objectql.ts — the ObjectCalendarSchema block only; packages/types/src/zod/objectql.zod.ts — the ObjectCalendarSchema const and the requireRecordSource type parameter at :623; new pin object-calendar-record-source-7313.test.ts; content/docs/plugins/plugin-calendar.mdx :160 / :210 (+ the import line); changeset. ⛔ packages/plugin-calendar/** read-only (#7311 is domain:ui); ⛔ ObjectKanbanSchema / packages/plugin-kanban/** (#7322 in flight — the ADJACENT block at objectql.ts:2693 / objectql.zod.ts:892); ⛔ no discriminated union (triage boundary 1). Hot files: objectql.ts and objectql.zod.ts are shared with #7322 (in flight, adjacent region) — fold-or-serial answered: not folded (#7322 is mid-run; widening a running dev's scope is a re-dispatch), so parallel under the ruling's disciplines: merge main before opening and again after #7322 lands; a textual conflict on the adjacent block is expected and is resolved in that merge, never by rebase; the queue arbitrates. Half-state patrol anchor: none exists in objectui (#5986) — no H rows to work.


    Generated by Claude Code

  5. os-justin commented on Sep 5, 2026

    @os-justin
    Collaborator

    Claim: dev of the domain:spec @ objectui PM seat's dispatch (session session_01BAZFhALsQsGqxui8sNqM8s, R1 sixth wave, 2026-09-05T16:47Z).

    • Branch: claude/issue-7313-object-calendar-record-source (pushed empty first as the write-route probe, then with the work)
    • Worktree: ../objectui-issue-7313, cut from origin/main 91f92768 (the dispatch base 4dfdcc3c is byte-identical on objectql.ts, objectql.zod.ts and plugin-calendar.mdx)
    • Scope: the calendar half only — ObjectCalendarSchema on both faces in the objectui#6939 map/gantt shape, the two doc annotations, a pin; ObjectKanbanSchema measured and reported, not edited (objectui#7322 holds that block).

    Generated by Claude Code

  6. os-justin commented on Sep 5, 2026

    @os-justin
    Collaborator

    os-dev-report

    {
      "issue": 7313,
      "status": "done",
      "branch": "claude/issue-7313-object-calendar-record-source",
      "pr": "https://github.com/objectstack-ai/objectui/pull/7777",
      "head": "c458bfe36751fda6e4d5561d01f0ef3d0df089ad",
      "base_cut": "91f9276801bc3274a8325b08b0205fa6abcdce20 (origin/main at cut; the dispatch base 4dfdcc3c is byte-identical on objectql.ts, objectql.zod.ts, plugin-calendar.mdx — git diff --quiet 4dfdcc3c 91f92768 on the three paths is empty)",
      "merged_main": "16a725f9 merged before opening (clean; PRs 7761, 7768, 7769 touch none of the five files); PR 7774 (kanban block, adjacent) not yet landed at report time — a second merge plus gate re-run is owed when the seat notifies",
      "premise_still_valid": true,
      "premise_evidence": "objectql.ts:2672-2688 ObjectCalendarSchema had objectName: string required and no data / staticData; objectql.zod.ts:861 const had objectName required, no data / staticData, no superRefine; requireRecordSource at :623 typed object-map | object-gantt; ObjectCalendar.tsx:242-246 useMemo(() => resolveRecordSourceConfig(schema), [(schema as any).data, (schema as any).staticData, schema.objectName]); the shared ladder packages/core/src/utils/record-source.ts:146-171 reads data (:151), staticData (:155), objectName (:162), null otherwise; plugin-calendar.mdx bare object-calendar blocks at :210 and :310 (not :160, which is the calendar-view fragment); no catalog entries and no test outside packages/types consume ObjectCalendarSchema",
      "clause_2": true,
      "tier": "CONTRACT_REVIEW_TIER — needs:contract-review attached by union (read set [package: types, tests] + target; read-back [package: types, tests, needs:contract-review]); PR left draft",
      "line_budget": "n/a",
      "summary": "ObjectCalendarSchema now declares data / staticData / objectName (the last optional) on both faces in the objectui#6939 map/gantt shape: TS face carries the gantt docblocks (identifiers substituted; one factual substitution noted under deviations), zod face widens requireRecordSource to object-calendar and ends the const in superRefine(requireRecordSource('object-calendar')) with data / staticData spelled as the gantt const spells them. The two static-data blocks on plugin-calendar.mdx are annotated ObjectCalendarSchema. New pin object-calendar-record-source-7313.test.ts (15 tests) with type-level Equal / IsOptionalKey pins, the four-document verdict table on safeParse and safeValidateSchema, verdict-for-verdict gantt parity with a non-vacuity assertion, BaseSchema controls, off-disk reads of the renderer, the ladder order and the doc annotations, and a ts-expect-error control that ObjectKanbanSchema still requires objectName. Changeset @object-ui/types minor. Kanban measured only, not edited.",
      "verdict_table": {
        "documents": ["staticData only", "data only { provider: value, items }", "none of the three", "objectName only"],
        "calendar_before_91f92768": ["refused at objectName (invalid_type)", "refused at objectName (invalid_type)", "refused at objectName (invalid_type)", "accepted"],
        "calendar_after": ["accepted", "accepted", "refused on the refinement: one root-level issue, code custom, params.code RECORD_SOURCE_REQUIRED, message `object-calendar` has no record source: declare one of `data`, `staticData` or `objectName`", "accepted"],
        "gantt_before_and_after": ["accepted", "accepted", "refused on the refinement (same issue, object-gantt)", "accepted"],
        "base_schema_control": ["accepted", "accepted", "accepted", "accepted"],
        "channels": "measured through ObjectCalendarSchema.safeParse AND safeValidateSchema (both pinned); objectName: '' still accepted (presence is !== undefined)"
      },
      "kanban_reading": "ObjectKanbanSchema carries the same defect class in a different ladder shape: objectName: string REQUIRED on both faces (objectql.ts:2696, objectql.zod.ts kanban const) while ObjectKanban.tsx:283 gates the fetch on schema.objectName && !boundData && !schema.data and :294 reads rawData = external || boundData || schema.data || fetchedData — data (an inline any[] on this schema, not ViewData) is read ahead of the fetch and UNDECLARED on ObjectKanbanSchema; every objectName read is guarded (:185 ?? '', :205, :247, :283, :601, :630, :723, :768, :976); no staticData rung; the plugin's own KanbanSchema (plugin-kanban/src/types.ts:89) already spells objectName?: string and data?: any[]. Ladder is external, bind, data, fetch — a card for it is not a copy of this one. NOT edited (objectui#7322 / PR 7774 hold the block); left to the seat to file. The pin's ts-expect-error control records the boundary and is the line that card deletes.",
      "tests": "All on merged head c458bfe3 unless stated; exit codes captured before any pipe; heavy runs under scripts/pm/os-verify-lock.sh (VERDICT command-exit 0 each). turbo run build --filter=@object-ui/plugin-calendar^... --filter=@object-ui/types --concurrency=2: Tasks 13 successful, 13 total, exit 0. pnpm exec vitest run --maxWorkers=2 packages/types/: Test Files 125 passed (125), Tests 2209 passed (2209), exit 0 (pre-merge run on adc43700: 122 files / 2102 tests, exit 0). New file alone, verbose: 15 passed (15), exit 0. pnpm --filter @object-ui/types type-check: exit 0, 0 error TS (script echoed; tsconfig.test.json compiles the new test, so the ts-expect-error control is checked). pnpm --filter @object-ui/plugin-calendar type-check: exit 0, 0 errors against the rebuilt dist (script echoed). dist proof: packages/types/dist/objectql.d.ts calendar block shows objectName?, data?: ViewData, staticData?; dist/zod/objectql.zod.js contains requireRecordSource('object-calendar') once. Ablation (red-first, both faces git checkout 4dfdcc3c, trap restore with absolute paths): mutated blobs 2714449218737b56d050bce3353123062e0e7283 / b20e082ba338dc430f3348912308652f3c9cb9fd differ from HEAD's 19b4419062770e3ceee8cf112d6c3172abec8d38 / f0e00a94b1ca93297a4f7c5ddf37a59849f1216f; on-disk: marker 0 in zod src, objectName: string; back, staticData 0 in the calendar block; rebuilt, dist marker 0 (absent preflight); vitest 9 failed / 6 passed of 15, exit 1; type-check exit 2 with 10 errors (8 x TS2344 on the Equal / IsOptionalKey pins, 2 x TS2741 on the document annotations); narrowed doc compile exit 2 with 2 x TS2741; restore: blobs equal HEAD's, git diff HEAD empty, git status --porcelain empty, rebuilt, dist marker 1, vitest 15 passed (15). Narrowed doc-snippet substitute: the two annotated blocks extracted verbatim, tsc --strict --noEmit moduleResolution Bundler, @object-ui/types mapped to the rebuilt dist/index.d.ts (traceResolution printed that path): exit 0, 0 diagnostics; control block staticData: 'nope' refused TS2322.",
      "gates": [
        {"command": "pnpm exec turbo run build --filter=@object-ui/plugin-calendar^... --filter=@object-ui/types --concurrency=2", "exit": 0, "head": "c458bfe3", "verdict": "Tasks: 13 successful, 13 total"},
        {"command": "pnpm exec vitest run --maxWorkers=2 packages/types/", "exit": 0, "head": "c458bfe3", "verdict": "Test Files 125 passed (125); Tests 2209 passed (2209)"},
        {"command": "pnpm --filter @object-ui/types type-check", "exit": 0, "head": "c458bfe3", "verdict": "0 error TS"},
        {"command": "pnpm --filter @object-ui/plugin-calendar type-check", "exit": 0, "head": "c458bfe3", "verdict": "0 error TS (read-only package)"},
        {"command": "pnpm --filter @object-ui/types lint", "exit": 0, "head": "c458bfe3", "verdict": "272 problems (0 errors, 272 warnings); 270 before — the 2 new are no-explicit-any on staticData?: any[] (objectql.ts:2700, same rule the gantt/map lines 2277/2662 carry) and the test's any[] pin"},
        {"command": "node scripts/check-changeset-presence.mjs", "exit": 0, "head": "c458bfe3", "verdict": "3 source file(s) of 1 released package(s) changed, and this change declares 1 changeset(s)"},
        {"command": "node scripts/check-changeset-fixed.mjs", "exit": 0, "head": "c458bfe3", "verdict": "privatePackages declared"},
        {"command": "node scripts/check-changeset-no-major.mjs", "exit": 0, "head": "c458bfe3", "verdict": "No changeset declares a major bump"},
        {"command": "node scripts/check-changeset-overwrite.mjs", "exit": 0, "head": "c458bfe3", "verdict": "No pre-existing changeset was modified or deleted"},
        {"command": "node scripts/check-control-bytes.mjs", "exit": 0, "head": "c458bfe3", "verdict": "OK (scanned 6339 tracked text files)"},
        {"command": "pnpm check:doc-fences", "exit": 0, "head": "c458bfe3", "verdict": "every TypeScript block in 227 document(s) is fenced ts/tsx/typescript"},
        {"command": "node scripts/check-doc-links.mjs", "exit": 0, "head": "c458bfe3", "verdict": "Links are valid across 17 scan roots"},
        {"command": "pnpm check:spec-symbols", "exit": 0, "head": "c458bfe3", "verdict": "no comment cites a key its spec symbol does not declare"},
        {"command": "pnpm check:doc-types", "exit": 0, "head": "c458bfe3", "verdict": "Every documented component type is registered"},
        {"command": "pnpm check:doc-snippets", "exit": null, "head": "c458bfe3", "verdict": "NOT MEASURED locally — --build-filter closure is 26 packages plus dependencies; narrowed tsc --strict compile of the two annotated blocks against the rebuilt dist: exit 0, 0 diagnostics, control TS2322; CI Doc Snippet Type Check is the measurement"},
        {"command": "node /home/user/objectstack/scripts/pm/check-governed-merges.mjs --test (five paths)", "exit": 0, "head": "c458bfe3", "verdict": "0 of 5 path(s) hit the register — NOT governed"},
        {"command": "CI on PR 7777", "exit": null, "head": "c458bfe3", "verdict": "in_progress at report time (mergeable_state blocked = draft); not awaited"}
      ],
      "files_changed": [
        "packages/types/src/objectql.ts (ObjectCalendarSchema block only: +27 -2)",
        "packages/types/src/zod/objectql.zod.ts (requireRecordSource type param; ObjectCalendarSchema const: +19 -3)",
        "packages/types/src/__tests__/object-calendar-record-source-7313.test.ts (new, 305 lines)",
        "content/docs/plugins/plugin-calendar.mdx (two blocks annotated: +6 -2)",
        ".changeset/7313-object-calendar-record-source.md (new, @object-ui/types minor)"
      ],
      "deviations": [
        "Dispatch names PR 7533 as the map/gantt shape; on main 7533 (777e5c6f) is the tree-view group, the map/gantt shape is PR 7471 (77cb489b). Both pins read; member shape follows 7471, type-level pin form follows 7533.",
        "Dispatch doc lines :160 / :210 predate the allowCreate section: :160 is the calendar-view fragment; the bare object-calendar blocks are :210 and :310 (the two sections the issue names) — those were annotated.",
        "objectName docblock copied from the gantt with identifiers, renderer path, card number substituted and one factual substitution: 'refused the two documented static-data examples' replaces 'refused three catalog entries' (the calendar has no catalog entries). data / staticData docblocks verbatim with the card number substituted. The getDataConfig wording is kept as the contract spells it (core header quotes it) although the calendar and gantt now read through resolveRecordSourceConfig — a wording sweep is a separate card.",
        "Changeset is minor per the dispatch; the objectui#6939 precedent changeset used patch for the same widening class and argues 'patch, not minor' — flagged for the reviewer, not decided here.",
        "check:doc-snippets not run locally (closure too heavy for the shared box); narrowed substitute declared above.",
        "The calendar page's Schema API plaintext block untouched (no prose rewrite per scope); the gantt page's got read-order comments in PR 7471.",
        "IsOptionalKey helper spelled Partial of Pick extends Pick (the {} extends Pick idiom trips no-empty-object-type in this repo's eslint).",
        "Claim comment was posted after the worktree and branch existed (5553433680), later than the CLAUDE.md claim-first wording; the PM's claim already stood.",
        "Worktree ../objectui-issue-7313 removed after the PR opened (rule); it will be recreated for the merge round after PR 7774 lands.",
        "The PR body's out-of-scope line says three bare gantt static-data blocks; the filed finding counts four (the :255 api-provider block is data-authored, not staticData) — the finding's count is the measured one."
      ],
      "open_questions": [],
      "out_of_scope_findings": [
        "filed as #7778 (sub-issue of #7313, label finding): four object-gantt blocks on plugin-gantt.mdx (:79, :238, :255, :354) are still bare const literals although ObjectGanttSchema has admitted them since PR 7471 — same completion-signal hole this card closed for the calendar",
        "not filed (dispatch: the seat files the card): ObjectKanbanSchema carries the same defect class — see kanban_reading; objectui#7322 / PR 7774 hold the block"
      ],
      "mcp_calls": "10 at posting time (claim comment, create PR, one failed issue_read get_labels on the PR number, pull_request_read get x2, pull_request_read get_files x1 (a mis-aimed read-back), issue_write labels, search_issues x1 for dedupe, issue_write create #7778, this comment); one read-back of this comment follows — final count in the terminal message. Zero-quota reads: five issue pages via the embedded payload tier; REST probe answered 403 for reads in this session."
    }

    Generated by Claude Code

  7. os-justin commented on Sep 5, 2026

    @os-justin
    Collaborator

    Contract review — PASS at CONTRACT_REVIEW_TIER (in-seat, 2026-09-05T17:21Z) — PR #7777, head c458bfe3

    Implemented-by: dev subagent of this session's dispatch, branch claude/issue-7313-object-calendar-record-source (mode:subagent, no session of its own); dev report 5553458585
    Reviewed-by: session_01BAZFhALsQsGqxui8sNqM8s (domain:spec @ objectui seat; served tier read via get_session at 17:19Z: session_context.model and last_served_model both claude-fable-5-1)

    Diff read by ref against origin/main 16a725f9 (five files, +393 / −7; the two contract hunks, the docs hunk and the changeset re-read off the branch tip with git diff origin/main... at 17:19Z; the dev's premise re-measured on 91f92768 with the three touched paths byte-identical to the dispatch base 4dfdcc3c).

    ① Derived judgments — each accept-set and public-surface change named and judged

    • packages/types/src/objectql.ts, ObjectCalendarSchema block only: objectName?: string (the gantt docblock with the identifiers substituted and one factual substitution — "the two documented static-data examples" for "three catalog entries" — accepted: the calendar has no catalog entries), data?: ViewData and staticData?: any[] with the gantt docblocks verbatim. The getDataConfig wording kept as the family spells it although the calendar and gantt now read through resolveRecordSourceConfig — accepted, one concept one wording; a wording sweep is a separate card.
    • packages/types/src/zod/objectql.zod.ts: requireRecordSource's type parameter widened to 'object-calendar' (its body does not branch on the type); the const declares objectName optional, data: ViewDataSchema.optional(), staticData: z.array(z.any()).optional() — spelled exactly as the gantt const — and ends in .superRefine(requireRecordSource('object-calendar')). Accept set: WIDENS by the two documented routes (staticData-only, data-only — both always rendered: the shared ladder packages/core/src/utils/record-source.ts:151 / :155 / :162 reads data, staticData, objectName in that order, cited by line); the one refused shape (none of the three) was refused before at objectName and is refused now by name with params.code = RECORD_SOURCE_REQUIRED and the map/gantt message; objectName-only accepted both sides (an empty string included — presence is !== undefined, as on map/gantt). Verdict-for-verdict parity with ObjectGanttSchema measured and pinned with a non-vacuity assertion; BaseSchema control accepts all four. Exactly ruling-shape 24 catalog entries fail safeValidateSchema because the Zod mirror names a key its renderer never reads (8 components) #6939 / PR fix(types): object-map / object-gantt — objectName optional behind a record-source refinement (objectui#6939, group 6 of 8) #7471 (the dispatch cited PR fix(types): tree-view mirror stops requiring the limb it reads third (group 2 of objectui#6939) #7533 for that shape — the dev found the right precedent and used fix(types): tree-view mirror stops requiring the limb it reads third (group 2 of objectui#6939) #7533 only for the type-level pin form; the seat's citation error, recorded). nodes-style refinement NOT added beyond the family's; no discriminated union (triage boundary 1 held).
    • Docs: the two bare object-calendar blocks (:210, :310 on this tree — the dispatch's :160 / :210 predated the allowCreate section; :160 is a declared calendar-view fragment) annotated ObjectCalendarSchema with the type import in the neighbouring blocks' style; Doc Snippet Type Check is green on the farm (17:15Z), which is triage's completion signal; the narrowed local compile agreed (0 diagnostics, a staticData: 'nope' control refused TS2322).
    • Kanban (triage boundary 3): measured, not edited — recorded in the PR body and filed by this seat as finding(types): ObjectKanbanSchema requires objectName on both faces while the renderer reads an undeclared inline data ahead of the fetch — the record-source ladder class (#7313) on a fourth view schema #7780 (the fourth member of the class, a different ladder shape: external → bind → inline data → fetch). The pin's @ts-expect-error control that ObjectKanbanSchema still requires objectName records the boundary; finding(types): ObjectKanbanSchema requires objectName on both faces while the renderer reads an undeclared inline data ahead of the fetch — the record-source ladder class (#7313) on a fourth view schema #7780's fix deletes that line.
    • Pin object-calendar-record-source-7313.test.ts (15 tests): type-level Equal / IsOptionalKey legs and parity with the gantt's types; the two documents as compile-time annotations; the four-document verdict table on both entry paths with the refusal message verbatim; gantt parity; BaseSchema control; data / staticData refused AT the key with the base as control; the renderer read and the ladder order off disk; the doc annotations off disk. Ablation: both faces reverted to 4dfdcc3c by blob hash → 9 / 15 red (the four-document, parity and declared-key groups; off-disk reads green as expected), tsc 10 errors (8 × TS2344 on the type pins, 2 × TS2741 on the annotated documents), the narrowed doc compile 2 × TS2741; restore proven; dist marker 0 → 1 across the cycle. Red-first, adequate.
    • Parity: both faces move together; zod-mirror-parity.test.ts green with no ledger row. packages/types/ 125 files / 2209 tests green on the merged head; @object-ui/plugin-calendar type-check green read-only against the rebuilt dist; lint 0 errors (the two new no-explicit-any warnings are on staticData?: any[], the rule the map/gantt lines already carry).

    ② semver — .changeset/7313-object-calendar-record-source.md: @object-ui/types: minor, a widening declared as such (what now validates, what still validates, the one refused shape unchanged). The dev flags that the #6939 precedent (.changeset/6939-objectql-record-source-refinement.md) graded the same class patch. Judged: minor stands — objectName losing its non-optional guarantee is a compile-visible change for TypeScript consumers of the interface, which is the "widening, not a replacement" class this seat has graded minor all shift (#7455, #7081); #6939's patch was the lenient reading and, inside the fixed group, the two grades differ only in the group's next version number. Not blocking; the precedent divergence is recorded here for the release seat.

    ③ Boundary flags — open_questions: none. Deviations reviewed and accepted (the precedent-PR citation; the doc line drift; the docblock substitution; check:doc-snippets NOT MEASURED locally with the narrowed compile and the farm green; the IsOptionalKey helper spelling; claim-comment timing after the seat's own claim; worktree removed after opening — to be recreated for the post-#7774 merge). Out-of-scope finding filed by the dev as #7778 (four bare object-gantt blocks on plugin-gantt.mdx — the gantt half of the same completion signal, unlabelled for triage); the PR body's "three" is superseded by the finding's measured four. Nothing touches content/docs/releases/; packages/plugin-calendar/** untouched (#7311 stays domain:ui).

    Verdict: PASS for PR #7777 on c458bfe3. Landing is sequenced behind PR #7774 (#7322 ①, in the merge queue since 17:08Z): it rewrites the ADJACENT ObjectKanbanSchema block on both faces, so once it lands the dev merges origin/main into this branch (the expected textual merge on the neighbour, resolved in the merge, never by rebase) and re-runs the gates on the merged head; the seat then re-reads the delta of the two contract files between c458bfe3 and the merged head (expected: exactly #7774's kanban block), clears needs:contract-review with provenance, and flips. ⛔ The carrier stays on until that delta is read.


    Generated by Claude Code

  8. os-justin commented on Sep 5, 2026

    @os-justin
    Collaborator

    Contract review — delta PASS (in-seat, 2026-09-05T17:33Z) — PR #7777 head moved c458bfe3 → d130a4f7 (the post-#7774 merge round; dev report on the PR, comment 5553548422).

    Reviewed-by: session_01BAZFhALsQsGqxui8sNqM8s (domain:spec @ objectui seat; served tier read at 17:19Z, claude-fable-5-1 on both readings).

    Delta read by ref at 17:31Z: the hunk bodies of git diff c458bfe3..d130a4f7 on packages/types/src/objectql.ts + packages/types/src/zod/objectql.zod.ts are byte-identical (md5) to git diff 16a725f9..669d71bf on the same two files — i.e. exactly PR #7774's kanban block, nothing else; the ObjectKanbanSchema block on the tip equals origin/main's (diff IDENTICAL); the calendar block, the requireRecordSource('object-calendar') superRefine and the three declared members are all present on the tip. The merge produced no textual conflict (three-way merge kept the adjacent hunks apart), so no manual resolution happened. One follow-on change in the dev's own pin (object-calendar-record-source-7313.test.ts, +6 −1): the @ts-expect-error class-boundary control literal now supplies groupBy: 'status' (PR #7774 made groupBy the required lane key and tombstoned groupField), so objectName is again the ONE member that literal is missing — correct, and it keeps the control meaningful rather than satisfied by an unrelated omission. Gates re-run on d130a4f7: packages/types/ 126 files / 2238 tests green (the #7322 pin now in the set), three tsc projects green, plugin-calendar type-check read-only green, lint 0 errors, four changeset scripts, control bytes, spec-symbols, doc-fences, doc-links, doc-types green, governed predicate 0 of 5.

    Verdict: the PASS of 5553491248 carries to d130a4f7. Same stroke: needs:contract-review cleared on PR #7777 with provenance; landing follows once every check run on d130a4f7 is completed: success (farm started 17:30Z; Type Check, four shards, Build Docs, Bundle Analysis, Skill Example Check, README Export Check in progress at 17:32Z) — flip re-check armed. Head moves ⇒ the label is re-hung and the delta re-reviewed.


    Generated by Claude Code

  9. os-justin commented on Sep 5, 2026

    @os-justin
    Collaborator

    Landing — PR #7777 (2026-09-05T17:46Z). Pre-landing three: ① flipped ready at 17:46Z after the PASS (comment 5553491248) and the delta PASS (comment 5553558086) with the carrier cleared on the PR with provenance (PR comment 5553561141); every check run on d130a4f7 was completed: success or skipped at 17:45Z (32 runs), branch tip unchanged since the delta review; ② auto-merge enabled, method SQUASH (the API echoes an empty method string — known platform reading); ③ queue probe running against refs/heads/gh-readonly-queue/main/* (the queue was empty at 17:45Z; origin/main = 1b69ca58). This PR carries Fixes #7313: the card closes on its squash; pm:dispatched is stripped once MERGED is read twice (PR merged: true + origin/main containing the squash). Follow-ups: #7778 (gantt doc blocks, dev-filed), #7780 (the kanban member of this class, seat-filed).


    Generated by Claude Code

  10. os-justin commented on Sep 5, 2026

    @os-justin
    Collaborator

    MERGED (2026-09-05T18:00Z) — PR #7777 landed through the merge queue as squash 554f2b6b on main. Three readings: PR merged: true (merged_at 17:59:53Z); this card's closed_by_pull_requests reference to PR #7777 reads MERGED and the card closed at 17:59:54Z; git log origin/main at 18:00:14Z shows 554f2b6b fix(types): ObjectCalendarSchema declares the record-source ladder its renderer reads (objectui#7313) (#7777) at the tip. pm:dispatched stripped in this stroke (remaining: finding, priority:p3, domain:spec). The gantt half landed earlier with #6939; the calendar half is on main now in the same shape. Follow-ups: #7778 (the gantt page's four bare object-gantt blocks — a sub-issue of this card, unlabelled for triage), #7780 (the kanban member of the class, seat-filed). Session session_01BAZFhALsQsGqxui8sNqM8s.


    Generated by Claude Code

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

Metadata

Metadata

Assignees

Labels

domain:specobjectui spec stream: fix lands on packages/types, schema corpus or spec pin coupling — spec lanefindingpriority:p3

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions