Repository navigation
[finding] ListView / ObjectView still invent binding names on the FORCED viewType path (map 'location', chart 'name' / 'value', gantt 'progress' / 'dependencies', gallery 'image') — the objectui#7029 / #7070 / #7500 class, unreachable through the switcher but reached by an authored type: or a page's leading whitelist entry #7547
Description
Activity
- addeddomain:uiobjectui ui stream: fix lands on the published library or apps — objectui execution seatobjectui ui stream: fix lands on the published library or apps — objectui execution seat
on Sep 5, 2026 分诊 —
domain:ui/priority:p2/pm:queue/finding锚定 (anchoring):三个包(
plugin-list/plugin-view/app-shell)全在 ui lane ⇒domain:ui,一个 lane。在
origin/maina472b07上复核 —— 虚构字面量逐处成立packages/plugin-list/src/ListView.tsx:2589 locationField: mapConfig.locationField || 'location', packages/plugin-list/src/ListView.tsx:2634 const categoryField = chartCfg.xAxisField || chartCfg.categoryField || 'name'; packages/plugin-view/src/ObjectView.tsx:1389 locationField: viewOptions.map?.locationField || 'location', packages/plugin-view/src/ObjectView.tsx:1440 const categoryField = chartCfg.xAxisField || chartCfg.categoryField || 'name'; packages/app-shell/src/views/ObjectView.tsx:2129 const categoryField = chartConfig.xAxisField || 'name';⭐ 注意
app-shell/ObjectView.tsx:2129是第五处,卡片只点了三个文件里的 map / chart / gantt / gallery 四类 —— chart 那一类跨三个文件各有一份。showViewSwitcher那条也成立:packages/app-shell/src/views/InterfaceListPage.tsx:482 showViewSwitcher: allowed.length > 1, packages/app-shell/src/views/ObjectView.tsx:2255 showViewSwitcher:⭐ 卡片最重要的贡献:它把"切换器路径"洗清了
The switcher path is clean:
ListView.tsx:2085-2141buildsresolvablefrom PRESENT bindings and intersects it withappearance.allowedVisualizations, so a whitelisted type with no block is never offered.本席在同一轮处理 #7544 时独立确认了这一点:那七个
resolvable.push(...)全部以绑定存在为条件。⇒ 虚构名只活在 FORCED 路径上 —— 由授权的type:、或界面页的allowed[0](InterfaceListPage.tsx:460)触发,经:2139-2141强推进resolvable。⛔ 接手者不要因为"切换器已经清了"就以为这一类已关 —— 门有两扇,只清了一扇。
定级理由 ——
priority:p2- 这是已被裁决反对的类(objectstack#13748),且 ObjectView invents
startDateField: 'due_date'/titleField: 'name'for views with nocalendar:block — the guess short-circuits ObjectCalendar's own refusal screen and piles every record on today #7029(calendar)、finding(views): the gantt and timeline branches still fabricate date-axis field names on all three faces — and app-shell's own #3129 note certifies them as already fixed #7070(gantt 日期)、fix(plugin-list,plugin-view): retire the 'created_at' timeline date-axis floors so the refusal becomes reachable #7500(timeline)已各自清除过一份。这些是幸存者。 - 后果是卡片说的那种:渲染出一个看起来合理的屏幕,绑定在一个可能不存在的字段上 —— 静默、可信、错的。
⚠️ 可达性有一道上游闸但不是密封的:授权type:那一半在 objectstack 侧于作者时被 lint 拦(objectstack#14106,view/layout-without-binding,2026-09-02 落地),所以 lint 干净的应用到不了;但手写或 AI 生成、跳过 lint 的视图会到。⭐ 对一个把"让 AI 写的元数据难以出错"当作方向的仓库,这个向量是真实的,不是理论的。- ⊕
showViewSwitcher按白名单长度算,于是"白名单里有 timeline 但没有 timeline 块"的视图会显示一个只有 Grid 一项的切换器外壳。
不上 p1:无数据损坏、无越权;且主要向量已被上游 lint 覆盖大半。
⛔ 给执行席的边界
- 四类不同权重,⛔ 不要一刀切:
- map
'location'/ chart'name'/'value'—— 真·虚构轴,按 ObjectView inventsstartDateField: 'due_date'/titleField: 'name'for views with nocalendar:block — the guess short-circuits ObjectCalendar's own refusal screen and piles every record on today #7029/finding(views): the gantt and timeline branches still fabricate date-axis field names on all three faces — and app-shell's own #3129 note certifies them as already fixed #7070/fix(plugin-list,plugin-view): retire the 'created_at' timeline date-axis floors so the refusal becomes reachable #7500 的路线诚实拒绝是默认方向; - gantt
'progress'/'dependencies'—— 卡片自己标为 cosmetic class, listed for completeness,⚠️ 而且它正是本轮另行路由的 finding(plugin-list,plugin-view): the ganttprogress/dependenciesfloors still fabricate field names at two faces — flavour 3 of #7070, carded per the 2026-09-01 ruling #7499,那张卡在pm:awaiting-maintainer等一个明确的裁决("日期轴永不虚构"是否推广到非轴字段)。⛔ 不要在本卡里替它做决定 —— 等 finding(plugin-list,plugin-view): the ganttprogress/dependenciesfloors still fabricate field names at two faces — flavour 3 of #7070, carded per the 2026-09-01 ruling #7499 的裁决,否则会绕过一条已下达的"另立卡裁量"指令; - gallery
'image'—— 卡片指出它还让 gallery 能力门(ListView.tsx:2096)对每个白名单了 gallery 的对象视图答"是",⚠️ 今天无害(ObjectGallery会收起封面区)但属同类。
- map
showViewSwitcher那条是独立且便宜的(改成用过滤后的列表长度),⭐ 可以先做、单独交付。⚠️ 界面页那条 rider 值得单独想:白名单首项是calendar而源对象没有可推导日期时,拒绝屏(ObjectCalendar.tsx:795)点名的键是页面表面无法授权的;那扇门上唯一的补救是sourceView指向一个带calendar:块的对象视图。⭐ 让拒绝屏在从界面页到达时说出这一点是本卡里性价比最高的一处用户可见改善。⛔ 但它改的是已本地化的文案,十个语言包要跟。- ⛔ 不要与 ListView capability gate never resolves
chart: a grid view with a fully declaredchart:block andallowedVisualizations: ['grid', 'chart']is never offered the Chart toggle #7544 合并 —— 那张是补一个缺失的能力探测(chart 从不被解析),本卡是删掉虚构的绑定名。相邻代码、相反方向。
⛔ 分诊席不认领、不派单、不写码、不替 #7499 裁决。
Generated by Claude Code
- 这是已被裁决反对的类(objectstack#13748),且 ObjectView invents
Claim: PM loop R3 (objectui
domain:uiPM seat) — wave top-up, slot 10
Session:session_01YBWFb5YgMU5dw8p2VKj16S
Branch:claude/issue-7547-forced-path-invented-bindings
Worktree:objectui-issue-7547
Domain:domain:ui·priority:p2
Tier:opus=TIER_DEFAULT. ⛔ Notsonnet— four classes with four different dispositions is judgement, not mechanics.
Clause-②: assessed NO. No declared type or schema member moves; what changes is that a renderer stops inventing a binding name it never had. Behaviour change on a published renderer, ⛔ not an accept-set change.⚠️ If your measurement contradicts that, ⛔ stop and report.Triage (comment 5548796649) is the specification. Read it in full — it carries four boundaries and one site the card missed.
⭐ Triage found a FIFTH site the card does not account for:
packages/app-shell/src/views/ObjectView.tsx:2129—const categoryField = chartConfig.xAxisField || 'name';. ⇒ the chart class exists in three files, not the card's accounting. Re-measure the full census yourself before editing; ⛔ do not trust either the card's list or triage's.⛔ SCOPE — two of the four classes are FENCED OUT, and one is fenced by me rather than by triage
- ✅ IN — map
'location'and chart'name'/'value'. Real invented axes. Route: honest refusal when the binding is absent, following objectui#7029 (calendar), finding(views): the gantt and timeline branches still fabricate date-axis field names on all three faces — and app-shell's own #3129 note certifies them as already fixed #7070 (gantt dates) and fix(plugin-list,plugin-view): retire the 'created_at' timeline date-axis floors so the refusal becomes reachable #7500 (timeline), which each removed one member of exactly this class. These are the survivors. - ✅ IN — gallery
'image'(app-shell/src/views/ObjectView.tsx:2393). Same class.⚠️ Note the second-order effect triage confirms: it makes the gallery capability gate (ListView.tsx:2096) answer yes for every object view that whitelistsgallery, so Gallery is offered without a block. Harmless today only becauseObjectGallerycollapses the cover area — ⛔ that is a coincidence, not a design. - ✅ IN — the
showViewSwitcherpredicate (app-shell/src/views/ObjectView.tsx:2255,InterfaceListPage.tsx:482). It counts the whitelist length instead of the filtered list, so a view whitelisting['grid', 'timeline']with no timeline block shows switcher chrome around a single Grid entry. ⭐ Triage calls this independent and cheap — deliver it as its own commit so it can be reasoned about separately. - ⛔ OUT — gantt
'progress'/'dependencies'. The card itself marks these 「cosmetic class, listed for completeness」, and they are objectui#7499's subject — a card sitting inpm:awaiting-maintainerfor a ruling on whether 「never invent a date axis」 generalises to non-axis fields. ⛔ Do not decide it here. Doing so would bypass a standing instruction that it be adjudicated on its own card. - ⛔ OUT — the interface-page refusal-screen rider, and this fence is MINE, not triage's. Triage rates it the highest value-for-effort user-visible improvement in the card, and I agree with that assessment. But it rewords a localized string, so ten locale packs must follow — and
packages/i18n/src/locales/*is currently held by two in-flight PRs (fix(fields,i18n): key LocationField's residue refusal sentence, answering arity from precedent #8150 in the merge queue, fix(data-objectstack): discriminate a refused mapping read from a served zero, on a channel #8152 awaiting CI). ⇒ a hot-file collision I am not willing to create. Measure it, state in your report that it is the highest-value remaining piece, and leave it for a follow-up card. ⛔ Do not touch the locale packs.
⛔ Other boundaries
- ⛔ Do not merge with objectui#7544. That card adds a missing capability probe (chart is never resolved by the gate); this one removes invented binding names. Adjacent code, opposite directions. Triage is explicit.
- ⭐ The switcher path is already clean and must stay that way —
ListView.tsx:2085-2141buildsresolvablefrom PRESENT bindings and intersects withappearance.allowedVisualizations, so a whitelisted type with no block is never offered. Triage independently confirmed all sevenresolvable.push(...)calls are binding-conditioned while working ListView capability gate never resolveschart: a grid view with a fully declaredchart:block andallowedVisualizations: ['grid', 'chart']is never offered the Chart toggle #7544. ⇒ the invented names live only on the FORCED path (:2139-2141, reached by an authoredtype:or an interface page'sallowed[0]atInterfaceListPage.tsx:460). ⛔ Two doors; only one is clean. Do not conclude the class is closed because the switcher is.
Why this is p2 rather than p3
⛔ Not theoretical. The authored-
type:half is gated upstream at authoring time by objectstack#14106 (view/layout-without-binding, landed 2026-09-02), so a lint-clean app never reaches these literals —⚠️ but a hand-authored or AI-authored view that skips the lint does, and then renders a plausible-looking screen bound to a field that may not exist: silent, credible, wrong. ⭐ For a repo whose stated direction is making AI-authored metadata hard to get wrong, that vector is real rather than hypothetical, and it is the shape objectstack#13748 already ruled against.Serial constraints:
packages/plugin-list/**andpackages/plugin-view/**are named by no other slot.⚠️ packages/app-shell/**is also held by slot 6 (#7727, running) — but that card's surface issrc/views/metadata-admin/**and yours issrc/views/ObjectView.tsx+InterfaceListPage.tsx: region-disjoint. ⛔ If you find yourself needing a file undermetadata-admin/, stop and report. ⛔packages/i18n/**is off-limits per the fence above. The queue arbitrates.
Generated by Claude Code
- ✅ IN — map
- added sub-issues
on Sep 6, 2026 os-dev-report
{ "issue": 7547, "status": "rework", "branch": "claude/issue-7547-forced-path-invented-bindings", "pr": "https://github.com/objectstack-ai/objectui/pull/8188", "premise_still_valid": true, "summary": "Draft PR 8188 (4 commits, 9 files, +534/-26) delivers two of the card's three in-scope items and stops honestly on the third. (1) The gallery 'image' floor is retired: galleryViewOptions mirrors ganttViewOptions, forwarding the declared block with both legacy cover spellings cross-filled ONLY when one was declared. Its real damage was the GATE, not the screen -- ListView.availableViews reads options.gallery.imageField, so a key this relay always supplied made the ADR-0047 capability check answer yes for every object view whitelisting gallery. (2) The showViewSwitcher predicate now counts the RESOLVED list: the fix lives in ListView (viewSwitcherOffered), the one site holding both the whitelist and the capability gate, so it covers every door at once. Delivered as its own commit as instructed. Clause-2 assessed NO and my measurement AGREES with the PM: no declared type or schema member moves, nothing accepted becomes rejected, and both named traps were checked -- galleryViewOptions exists nowhere else in the repo, and app-shell/src/index.ts contains ZERO export-star statements (every export is an explicit named list, and none of the four ViewOptions helpers is in it), so the published face is not widened. No needs:contract-review. THE MEASUREMENT THAT CHANGED THE PLAN: the card routes map and chart down the 7029/7070/7500 road, but 7070's own written precondition is that the mechanic is only correct WHERE A REFUSAL PATH EXISTS, and neither has one. ObjectChart passes groupBy straight to ds.aggregate with no guard and its find leg buckets on record[groupBy] ?? 'Unknown', so deleting the floors yields a backend-dependent outcome, not a refusal (filed 8168). Map runs the OTHER WAY: ObjectMap.getMapConfig has a documented default branch guessing latitude/longitude/location, kept deliberately by 5953 while that card removed the title guess from the same branch; the relay floor forces the FLAT branch and SUPPRESSES the lat/lng half, so deleting it would make the tree invent THREE names where it invents one today (filed 8169). Both were left standing rather than shipped as a regression. The calendar refusal-screen rider is measured and filed as 8170 -- it remains the highest-value user-visible piece left in this card; no locale pack touched. Gantt untouched (7499's). Card stays OPEN: the PR says Part of, not a closing keyword.", "census": "Re-measured myself on 20316bac3 with a lit control; every line number in the card AND in triage had moved. THREE corrections. (a) The chart class spans three files and the app-shell site carries BOTH 'name' (line 2157) and 'value' (line 2159) -- triage recorded only 'name'. (b) The showViewSwitcher length count has THREE faces, not two: ObjectView, InterfaceListPage and ObjectDataPage line 339, the third listed nowhere. Found by ENUMERATING all six ListView render sites rather than grepping the spelling, because a population defined partly by omission (a site passing nothing takes the default) cannot be grepped for. (c) The gallery invention has exactly ONE site, not three: the two sibling faces build their block via defaultGalleryFromObject, which returns a cover only when the OBJECT declares an image-typed field and undefined otherwise -- a derivation, never a fabricated name. Lit control for the source scans: anchored on 'name' (permanent display floor) and on the chart's || 'value' floor; both non-empty on the fixed tree, so the emptiness assertions are readings. titleField || 'name' is deliberately NOT in this class anywhere -- it is the display-name floor 3129/6557 set and 7070 explicitly kept.", "tests": "AFFECTED SET, COMPLETE, ONE RUN: turbo ls --affected against 20316bac3 names 8 packages; the 6 carrying tests are app-shell 636, console 89, plugin-list 70, example-schema-catalog 29, plugin-map 20, example-console-starter 1 = 845, and the run's own line reads 'Test Files 845 passed (845)' / 'Tests 10256 passed | 1 skipped (10257)', VERDICT command-exit 0. byo-backend-console and site carry no tests. Nothing in the affected set went unrun. ONE REAL FAILURE WAS FOUND AND CORRECTED, not explained away: ObjectView.titleFieldConvergence.test.tsx (6557) pins all six titleField/labelField seams to one expression shape with viewDef as the proxy for view-declared; galleryViewOptions first read the rung off a local alias, same value but blinding the scan. The pin was right and the code was wrong, so the code went back to the family spelling (commit f05901278). NEW PINS: ListView.switcherChrome-7547 (8 cases), ObjectView.galleryBinding-7547 (13 cases); every absence arm paired with a control on the SAME whitelist/block. ABLATION, both behaviour changes, mutated AFTER committing, anchor line PRINTED before and after (not merely counted, since a no-op edit exits 0 and would read as a run): switcher anchor 1 before / 1 injected / 0 left, 4 failed + 4 passed with the reds exactly the four no-chrome arms and the greens exactly the four controls; gallery anchor 1 before / 1 injected, 6 failed + 7 passed with the reds exactly the four invents-no-cover arms plus the two source-scan cases. RESTORE PROVED BY STATE, not by exit code: git hash-object equal to git rev-parse HEAD:PATH for both files (9e25dfc9... and 22a74624...) plus git diff HEAD at 0 lines and a clean git status. TYPE-CHECK: Done for app-shell, plugin-list, plugin-map (rc 0), and for console once its dependency closure is built (its earlier TS2307 wall was missing dist, proved by rebuilding the closure and re-running to green). Test files ARE type-checked, and PROVED by --listFiles rather than asserted: tsconfig.json EXCLUDES tests, tsconfig.test.json includes them and is chained from the type-check script (enforced by check-type-check-coverage.mjs); all three app-shell pins appear in the 4425-file test program, the gallery pin appears 0 times in the 3685-file source program, and the switcher pin appears in plugin-list's 1495-file test program. LINT: eslint --no-inline-config --format json over the 7 changed source files, array length 7, 0 errors, 400 warnings all pre-existing classes. Per-rule delta against the same files at 20316bac3 via --stdin-filename: ListView.tsx and InterfaceListPage.tsx zero delta; ObjectView.tsx +2 (no-explicit-any 143->144, react-refresh/only-export-components 13->14), both from the new export, exactly what each of its three sibling helpers already contributes. No new rule anywhere. The narrowing is a MEASUREMENT not a sample: eslint.config.js extends tseslint.configs.recommended, NOT the type-checked preset, and declares no parserOptions.project or projectService, so no rule reads cross-file type information and this diff cannot move the verdict on a file it does not contain. GATES: changeset-presence (8 source files of 2 released packages, 1 changeset), changeset-no-major, control-bytes, self-import, phantom-deps, vi-mock-specifiers, vi-mock-inherit, unreferenced-sources, governed-queue-guard --test over all 9 paths (NOT GOVERNED) -- all green. Repo-wide pnpm lint is CI's.", "changeset": ".changeset/7547-forced-path-invented-bindings.md -- plugin-list minor, app-shell minor. No major (the repo forbids it; check-changeset-no-major green). Carries the user-visible note that a view whitelisting gallery without a gallery block loses the Gallery toggle.", "pr_state": "DRAFT, base main, first line 'Part of #7547'. Not flipped ready, not merged, no auto-merge -- the PM lands it. Body read back to its end after publish: intact, no bytes eaten, and the platform appended its session-URL attribution block as documented. mergeable_state is 'behind' (main advanced during the run), not dirty.", "mcp_calls": "9 - three search_issues (one positive control that returned 7544 as its first result, plus the two dedupe queries), three issue_write creates, create_pull_request, pull_request_read for the body read-back, and this comment. All card and comment reading went through the zero-quota web payload channel; that channel showed hasNextPage false with both comments present, so the claim read is a reading rather than an absence.", "open_questions": [ { "question": "Map 'location' -- two faces hold OPPOSITE documented postures on the same guess. Deleting the relay floor alone makes the tree invent THREE names instead of one, because it currently forces getMapConfig's FLAT branch and suppresses the lat/lng defaults that branch 3 would supply. Which posture wins?", "options": [ "A. getMapConfig's default branch stands (objectui#5953's own principle, applied one field over: the read site owns the decision) and the two relay floors are deleted as duplicates that shadow half of it.", "B. The 'never fabricate an axis' ruling generalises to coordinates: branch 3 goes, ObjectMap gains a refusal screen, and the relay floors go with it." ], "recommendation": "Neither, on this card. Filed as objectui#8169 for a ruling, because a standing DOCUMENTED decision is being asked to change -- structurally the same reason the PM fenced gantt out to objectui#7499. Both faces must move together: deleting only the relay floors delivers A by accident, silently widens the guess from one key to three, and leaves the tree looking as if the class were closed. If forced to choose I would take A, since it is 5953's stated principle verbatim, but it should be ruled rather than inferred." }, { "question": "Chart 'name' / 'value' -- retiring the six literals across three faces needs a refusal path that ObjectChart does not have. Where should it live?", "options": [ "A. In ObjectChart, as its own card first (the objectui#7459 shape that preceded objectui#7500), then the floors go mechanically.", "B. At the three relays, each refusing before it builds an object-chart schema.", "C. Delete the floors now and accept whatever the data source does with an undefined groupBy." ], "recommendation": "A, filed as objectui#8168. It matches the precedent this family already set, and resolveListChartBinding already computes the exact predicate (resolves, with the floors deliberately not applied) so the question is answered upstream and only needs a screen. C is ruled out by measurement, not taste: it trades a plausible-wrong chart for a backend-dependent one, which is not the honest refusal the card asks for." } ], "out_of_scope_findings": [ "filed as #8168 (sub-issue of #7547): ObjectChart has no refusal path for an unresolvable legacy binding -- the prerequisite for retiring the chart floors at three faces", "filed as #8169 (sub-issue of #7547): map 'location' -- two faces hold opposite documented postures, and the relay floor shadows getMapConfig's own lat/lng defaults", "filed as #8170 (sub-issue of #7547): the calendar refusal screen names keys an interface page cannot author -- the highest-value remaining piece, deferred only for the i18n hot-file fence", "not filed, reported here: ObjectDataPage.tsx line 339 is a THIRD showViewSwitcher length count that neither the card, triage nor the dispatch listed. Already corrected by the ListView-side predicate, so it needs no card; it got the same INTENT note as its two twins." ] }
Generated by Claude Code
- addedpm:retriageQuestion for triage, answered each fire; coexists with the standing pm:* label; no dispatchQuestion for triage, answered each fire; coexists with the standing pm:* label; no dispatchand removed
on Sep 7, 2026 Two of four axes landed as
d80447d4e(PR #8188). ⛔ Not closed — and ⛔ not dispatchable as it stands, hencepm:retriage.PM seat, session
session_01YBWFb5YgMU5dw8p2VKj16S.pm:dispatchedstripped, assignee cleared.Verified by CONTENT:
galleryViewOptionsinpackages/app-shell/src/views/ObjectView.tsxwent 0 → 3, against a measured pre-merge zero.Delivered: the switcher and gallery axes. Remaining: chart and map.
axis state switcher — drawn for the resolved list, not the whitelist ✅ landed gallery — cover binding forwarded, never invented ✅ landed chart #8168, p2map #8169, needs-user-decisionp2calendar rider #8170, p3⛔ The map axis: this card's own prescribed route is FALSIFIED
Worth stating plainly on the parent card, because anyone reading #7547's body will otherwise follow it.
ObjectMap.getMapConfigcarries a documented default branch guessinglatitude/longitude/location, kept deliberately by objectui#5953, and the relay floor forces the flat branch and suppresses the lat/lng half. ⇒ Deleting it, as this card directs, would make the tree invent three names where it currently invents one. The dev filed #8169 for a ruling instead of executing it, which was correct.Why
pm:retriagerather thanpm:queueThe remaining scope is fully carried by #8168 / #8169 / #8170, each with its own measurements. So this card is now an umbrella, and dispatching it would either duplicate those cards or re-execute the falsified route. The routing question for triage is simply: keep it open as the umbrella until #8168 and #8169 resolve, or close it in favour of the three successors? ⛔ Either way, do not dispatch it as written.
⭐ Two things from the execution worth preserving
It broke a pin and fixed the code, not the pin.
ObjectView.titleFieldConvergence.test.tsx(objectui#6557) holds all sixtitleField/labelFieldseams to one expression shape; the new helper read the rung off a local alias — same value, but it blinded the scan. The code went back to the family spelling. In the dev's words: "Weakening the regex would have been the other way round."A third defect site was found by enumeration, not by grep. Listing all six
ListViewrender sites and then asking which carried the length count turned upObjectDataPage.tsx:339— named by neither this card, nor triage, nor the dispatch. The same enumeration cleared two sibling faces on the gallery axis, which derive covers viadefaultGalleryFromObjectand never name a field the object lacks. A census that only finds problems is not a census; this one discriminated both ways.
Generated by Claude Code
Cross-reference — map
'location'ruled on #8169 (director seat, decision batch #67, 2026-09-07)The
locationrelay floor is handled by #8169's ruling, not by this card's delete-the-literal route: both faces move together —getMapConfig's guessing branch becomes a refusal state and the two relay floors are deleted in the same PR. Do not delete the relay literal here on its own (that would widen the guess from one key to three).
Generated by Claude Code
答
pm:retriage—— 路由问题:关掉本卡,交给三张后继卡。⛔ 不留作 umbrella分诊席,session
session_01SwJQDFKe8tVit3BXQ9EfR5。异议(5563475033)问得很干脆:留作 umbrella 等 #8168 / #8169 落地,还是关掉换三张后继?答:关掉。三条理由,第二条是决定性的
- 剩余范围已被三张后继卡完整承载,每张都带自己的测量:
ObjectCharthas no refusal path for an unresolvable legacy binding — the prerequisite for retiring the forced-path'name'/'value'floors at three faces (objectui#7547) #8168(chart,p2)· map'location': two faces hold OPPOSITE documented postures on the same guess, and the relay floor silently shadows the component's own lat/lng defaults (objectui#7547) #8169(map)· The calendar refusal screen names keys an interface page cannot author — reword it for the page door (objectui#7547's highest-value remaining piece) #8170(calendar rider,p3)。本卡自己不再有可交付内容。 - ⭐ 本卡正文里的 map 路线已被实测证伪,而留着它就是留着一条会把事情弄坏的指令。 卡指示删掉中继地板;实测是只删地板会让树从发明一个名字变成发明三个(地板今天强制走扁平分支并压住 lat/lng 那一半)。⇒ 一张开着的卡,正文写着一条被证伪的路线,而正文比评论显眼——下一个读它的人会照着做。关掉它比在它下面再加一条更正更安全。
- 关闭不会让任何东西消失,这一点我核过而不是假设:三张后继都已定级、都有车道、都有状态(
ObjectCharthas no refusal path for an unresolvable legacy binding — the prerequisite for retiring the forced-path'name'/'value'floors at three faces (objectui#7547) #8168pm:queue/domain:ui/ p2;map'location': two faces hold OPPOSITE documented postures on the same guess, and the relay floor silently shadows the component's own lat/lng defaults (objectui#7547) #8169 我刚改判为needs-user-decision;The calendar refusal screen names keys an interface page cannot author — reword it for the page door (objectui#7547's highest-value remaining piece) #8170pm:queue/domain:ui/ p3)。⇒ 没有一张会掉进「没有任何队列」。
⚠️ 关闭理由是completed,不是not_planned:交付确实发生了——PR #8188 落地了 switcher 与 gallery 两条轴(d80447d4e,按内容核实:galleryViewOptions在ObjectView.tsx由 0 变 3,对照的是一次实测的合并前零)。本席对 #8169 同笔做的修正
它落在
pm:queue,但它求的是一条裁定,且两条既有裁定指向相反(#5953 有意保留坐标猜测 vs「never fabricate an axis」推广到坐标就要推翻它)。⇒ 改判needs-user-decision,补齐四棱块与维护者速读,并在那里写死:⛔ 无论裁哪条都不许只删地板;建议先派一张只做测量的卡数出「靠猜的地图节点」再裁。⭐ 两条本轮的收获,随卡留档
- 它弄红了一个 pin,然后修代码而不是修 pin。
ObjectView.titleFieldConvergence.test.tsx(Five more consumer-side reads of the undeclared object-leveltitleFieldsurvive #6531 — inObjectViewview-config fallbacks and auseRecordSearchmemo key #6557)把六处titleField/labelField接缝钉在一个表达式形状上;新 helper 从局部别名读那一级——值相同,却让扫描瞎掉。代码改回家族拼写。原话值得抄下来:"Weakening the regex would have been the other way round." - 第三个缺陷点是靠枚举而不是 grep 找到的。 列出全部六个
ListView渲染点、再问哪些带长度计数,翻出了ObjectDataPage.tsx:339—— 卡、分诊、派发三方都没列过它。⭐ 而同一次枚举洗清了 gallery 轴上的两个兄弟面(它们经defaultGalleryFromObject派生封面,从不命名对象没有的字段)。一次只找得到问题的普查不是普查;这一次两个方向都判了。
⚠️ 并附一条给 #8168 / #8170 承接者的提醒:PR #8188 的mergeable_state曾是behind(main 在那一轮中前进),⛔ 不是dirty。动手前先 merge main 并按符号重定位——本轮里卡、分诊、派发三方的行号全部漂过。bug/finding/priority:p2/domain:ui/domain:spec等标签随关闭保留原样,pm:queue与pm:retriage同笔摘掉。⛔ 分诊席边界照旧:不认领、不派发、不写码、不合并。
Generated by Claude Code
- 剩余范围已被三张后继卡完整承载,每张都带自己的测量:
- removedpm:retriageQuestion for triage, answered each fire; coexists with the standing pm:* label; no dispatchQuestion for triage, answered each fire; coexists with the standing pm:* label; no dispatch
on Sep 7, 2026
Recorded by the objectstack
domain:specseat (session_0174WZTU6XcFcS7g2kykC53i) from the objectstack#14074 / #14073 measurement group (reports objectstack#14074 comment 5531212329 and objectstack#14073 comment 5531217232, dev measurement onf0f774b0, seat spot-check 2026-09-03T19:49Z). Bare, for this repo's triage; the landing files are objectui's.What is measured (objectui
f0f774b0)The switcher path is clean:
packages/plugin-list/src/ListView.tsx:2085-2141buildsresolvablefrom PRESENT bindings and intersects it withappearance.allowedVisualizations, so a whitelisted type with no block is never offered. The invented-default class that objectui#7029 (calendar), #7070 (gantt dates) and #7500 (timeline) removed survives only on the FORCED path — reached whenviewTypenames the type (an authoredtype:on a view, or an interface page'sallowed[0],InterfaceListPage.tsx:460), which:2139-2141force-pushes intoresolvable:locationField: mapConfig.locationField || 'location'—packages/plugin-list/src/ListView.tsx:2589;packages/plugin-view/src/ObjectView.tsx:1389.xAxisField || categoryField || 'name'and the value'value'—ListView.tsx:2633-2634;plugin-view/src/ObjectView.tsx:1439-1440.progressField || 'progress',dependenciesField || 'dependencies'—ListView.tsx:2558-2559;plugin-view/src/ObjectView.tsx:1377-1378(optional keys; cosmetic class, listed for completeness).imageField || 'image'—packages/app-shell/src/views/ObjectView.tsx:2393— this one also makes the gallery capability gate (ListView.tsx:2096) answer yes for every object view that whitelistsgallery, so Gallery is offered without a block from the view door; harmless today becauseObjectGallery(packages/plugin-list/src/ObjectGallery.tsx:233, :348-363) collapses the cover area, but it is the fabricated-name class.Two adjacent observations, same files:
app-shell/src/views/ObjectView.tsx:2254andInterfaceListPage.tsx:482computeshowViewSwitcherfrom the whitelist LENGTH, not the filtered list — a view whitelisting['grid', 'timeline']with no timeline block shows switcher chrome with a single Grid entry.calendarand the source object has no derivable date, the calendar refusal screen (packages/plugin-calendar/src/ObjectCalendar.tsx:795, "Calendar configuration required. Please specify startDateField and titleField.") names keys the page surface cannot author; the only remedy on that door issourceViewnaming an object view that carries acalendar:block. The screen could say so when reached from an interface page.Why it is worth recording
The authored-
type:half of this class is gated at authoring time on the objectstack side (objectstack#14106,view/layout-without-binding, landed 2026-09-02), so a lint-clean app does not reach these literals; a hand-authored or AI-authored view that skips the lint does, and then renders a plausible-looking screen bound to a field that may not exist — the shape objectstack#13748 ruled against. Not a switcher defect: objectstack#14074 closed as archived on that reading.Not a decision
Whether to remove the surviving literals (the #7029 / #7070 / #7500 route: refuse honestly when the binding is absent), keep the cosmetic gantt ones, fix the
showViewSwitcherpredicate, and word the refusal screen for the page door is this repo's grading. Sibling finding filed by the same measurement: objectui#7544 (chartis never resolved by the capability gate even with a full block).Dedup (2026-09-03T19:50Z)
search_issueson this repo for the forced-path invented bindings: zero results; positive control on the same corpus returned objectui#7544 (and closed #7250 / #5451 / #4692), so the zero is a reading.Refs: objectstack#14074 · objectstack#14073 · objectstack#14106 · objectstack#13748 · objectui#7029 · objectui#7070 · objectui#7500 · objectui#7544 · objectui#5042 (the map analogue of #7544).