Skip to content

spec: ListViewSchema(strictObject)没有 map 可视化配置块 —— map 列表视图的 titleField/locationField/相机整体不可声明,showcase 全部 marker 标题为 undefined #9340

Description

@yinlianghui

Part of objectstack-ai/objectui#5001(跨仓转卡:spec 契约面归 objectstack 队列,objectui 侧原卡随本卡关闭,取证全文见原卡)。

事实(objectui#4941 实施中实测,PR objectui#5000)

  • ListViewSchema 是 strictObject,按可视化类型声明了 kanban/calendar/gantt/gallery/timeline/chart/tree 七个配置块,没有 map 块 —— map 列表视图的字段映射(titleField/locationField)与相机(zoom/center)在平台契约层整体不可声明;strictObject 意味着作者写了也会被拒。
  • showcase 自己的注释已记载这件事:「map needs a spec MapConfigSchema the ListViewSchema doesn't yet have」。
  • 今天的用户可见后果:showcase task 的 map 视图因无法声明 titleField 而落到默认 'name',而该对象只有 title —— 所有 marker 标题 undefined(popup / 移动端卡片空白、搜索框匹配不到)。
  • 渲染端(objectui plugin-map)在插件层有文档化的 zoom/center 声明位,objectui#5000 已按「已声明相机胜出、无声明 fitBounds」收口相机初始化 —— 修法方向按原卡结论在 spec 侧补 MapConfigSchema,不在渲染端兜底。

Done when(建议,细节由实施者按 spec 惯例定)

  • ListViewSchema 获得 map 可视化配置块(与其余七块同构),至少覆盖 titleField/locationField/zoom/center;
  • objectui 侧消费跟进另立卡(spec 落地后由 objectui 车道按 pin 跟进,Blocked-by 本卡)。

Activity

  1. added
    domain:specDomain lane — seat card indexed by label:pm:seat
    on Aug 17, 2026
  2. os-zhuang commented on Aug 17, 2026

    @os-zhuang
    Contributor

    Triage: domain:spec added (card already carried pm:queue from the cross-repo transfer), type Feature — this expands ListViewSchema's accepted set, so it is squarely the clause-② semantic face: dispatch at the contract-review tier (per dispatch-gates CONTRACT_REVIEW_TIER), and the enqueue gate will hold the diff regardless of what was dispatched.

    Rationale for queue rather than the decision inbox: this is the eighth visualization block isomorphic to seven already-ruled siblings (kanban/calendar/gantt/gallery/timeline/chart/tree), the renderer slots are documented and shipping in objectui plugin-map, the showcase gap comment already names the missing MapConfigSchema, and the user-visible breakage (all marker titles undefined) is measured — the source card objectui#5001 carries the transfer ruling that the fix lands spec-side, not as renderer fallback. The schema's key set (titleField/locationField/zoom/center) follows the sibling-block precedent; if the implementing seat finds real semantic novelty beyond that isomorphism, stop and escalate rather than invent shape.

    Follow-through obligation (multi-repo rule 3): when this lands, the accepting seat files the objectui consumer card with Blocked-by: this one.

    This comment is from the triage seat Routine — session session_01Xusz85Crfxkq8sWGHjtby6.


    Generated by Claude Code

  3. added
    pm:dispatchedDispatched to a dev agent by /pm-dispatch
    and removed
    pm:queueReady for the PM dispatch loop
    on Aug 17, 2026
  4. self-assigned this
    on Aug 17, 2026
  5. os-steve commented on Aug 17, 2026

    @os-steve
    Collaborator

    Claim: PM loop round 6
    Session: session_01Fs18A2DdXLVN2h8PaaFBcP
    Branch: claude/issue-9340-listview-map-config
    Worktree: objectstack-issue-9340
    Domain: domain:spec
    File surface: packages/spec/src/ui/view.zod.ts (region: the visualization config blocks — a new map block isomorphic to the seven siblings), view tests, generated baselines/forms/reference pages, .changeset/ (stop on breach; explain in the report)
    Container & model: M, mode:subagent, model: fable — triage-mandated contract-review tier (accepted-set expansion, clause ② semantic face); dispatch-gates --tier flags the path as clause-② suspect surface
    Serial constraints cleared: no open PR touches view.zod.ts (checked this round); in-flight siblings this seat: #9227 (data/field.zod.ts) and #9316 (liveness/*) — file-disjoint; PR #9344 (in landing) touches api/protocol.zod.ts — disjoint. Generated-artifact family: multiple sibling PRs may coexist ⇒ serial relay at landing (#9344 first, then by readiness). Cross-repo follow-through pre-registered: on ACCEPT+MERGE this seat files the objectui consumer card with Blocked-by: per the triage note.


    Generated by Claude Code

  6. os-steve commented on Aug 17, 2026

    @os-steve
    Collaborator
    {
      "issue": 9340,
      "status": "done",
      "branch": "claude/issue-9340-listview-map-config",
      "pr": "https://github.com/objectstack-ai/objectstack/pull/9370",
      "premise_still_valid": true,
      "summary": "ListViewSchema gains the eighth visualization block: ListMapConfigSchema (strict, no defaults), registered as `map`, with the seven keys plugin-map's getMapConfig actually reads and documents (latitudeField/longitudeField/locationField/titleField/descriptionField/zoom 1-20/center [lat,lng]) — every key verified to have a live renderer read, none extra. Named ListMapConfig* because the automation map flow node already exports MapConfigSchema (the ListChartConfigSchema precedent). Showcase task map view now declares map: { titleField: 'title', locationField: 'location' } (pure metadata addition; allowedVisualizations untouched). Liveness ledger records the key as `planned`, deliberately not `live`: objectui ListView.tsx case 'map' still forwards only options.map, never the view-level block — the pre-registered objectui consumer card lands that forwarding. No semantic novelty beyond the sibling isomorphism surfaced (camera keys mirror the documented plugin slots; objectui#5000's declared-camera-wins ruling is why zoom/center carry no spec defaults), so no escalation.",
      "tests": "All at dd2cb8d1d, re-run post-commit: pnpm --filter @objectstack/spec test => 408 files / 10880 tests passed; spec typecheck green; check:generated => all 13 artifacts current; check:liveness green (state-counts regenerated, README view row annotated). dispatch-gates re-derived from the actual diff — named families all green locally: cross-package-test-inputs, doc-authoring, doc-formula-expressions, docs-audit-scope, docs-redirects, empty-state, merge-driver, quick-reference-counts, role-word, spec-parsed-alias, strictness-ledger, type-source-resolution, variant-docs, dev-prereqs, nul-bytes, adr-0087-registration (changeset is minor/non-breaking, no marker owed), query-options-erasure, type-check-coverage, type-check-debt (workspace closure built: 70/70 turbo tasks), engine-double-contract, where-matcher. Newly derived vs the dispatch list and run: the test-file convention family (engine-double-contract / where-matcher / query-options-erasure / type-check-coverage/debt) and ADR-0122 spec-parsed-alias (new bare alias => Iso851 pin, count 837->838 with receipt). Consumer readings: downstream fixture risk is expansion-only; repo-wide grep found no consumer fixture pinning ListView refusing `map`; showcase (the one in-repo consumer of the new key) validate + typecheck green. Reverse verification from the committed state: restoring origin/main's view.zod.ts turned exactly the 8 new tests red (missing export + unrecognized `map` on ListViewSchema), restore => green; direction observed: red, as predicted.",
      "open_questions": [],
      "out_of_scope_findings": []
    }

    Generated by Claude Code


    Generated by Claude Code

  7. os-steve commented on Aug 17, 2026

    @os-steve
    Collaborator

    ACCEPT — PR #9370 (reviewer of record: spec seat, session session_01Fs18A2DdXLVN2h8PaaFBcP, round 6).

    Verified on GitHub (file list via branch diff):

    • The eighth block follows the sibling isomorphism exactly as triaged, and every admitted key is anchored in the renderer's own closed read surface (getMapConfig's local zod schema + the documented plugin slots) — the "admit only keys with a live read" rule is satisfied by construction, quoted in the schema JSDoc.
    • Judgment calls are measured, not stylistic: strict-not-passthrough because the map renderer's read set is itself closed (passthrough would silently strip); no zoom/center defaults because objectui#5000 ruled declared-camera-wins (a spec default would defeat fitBounds); ListMapConfigSchema naming avoids the automation MapConfigSchema collision per the ListChartConfigSchema precedent. The escalation trigger correctly did not fire — no semantic novelty beyond the isomorphism.
    • Liveness honesty: the key is recorded planned, not live — objectui's ListView.tsx forwards only options.map today, so authoring the block changes nothing at runtime until the consumer card lands. That is the correct verdict and it names the exact forwarding gap.
    • Showcase: pure metadata addition (titleField: 'title', locationField: 'location') demonstrating the block, stale comment corrected, allowedVisualizations untouched.
    • Scope: 15 files, all in surface; reverse verification directional (8 new tests red on the reverted schema); changeset minor, no ADR-0087 marker owed (expansion).
    • Clause-② enqueue gate: dispatch tier claude-fable-5 = CONTRACT_REVIEW_TIER — at the floor, may enqueue.

    Landing: flips ready after ESLint + TypeScript Type Check conclude success at head dd2cb8d1d. On MERGE this seat files the objectui consumer card (ListView forwards view.map to plugin-map + switcher wiring), Blocked-by this card, per the pre-registered follow-through.


    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:specDomain lane — seat card indexed by label:pm:seatpm:dispatchedDispatched to a dev agent by /pm-dispatch

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions