You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
This repository was archived by the owner on Nov 4, 2026. It is now read-only.
Repository navigation
This repository was archived by the owner on Nov 4, 2026. It is now read-only.
finding(components,plugin-view): two more non-QueryResult arms survive on the seams #6726 repaired — res?.count and results.value #6840
Found while implementing #6726 (out of that card's scope — it names the records arm and only that arm).
The shape
#6726 removed the records arm from seven DataSource.find() consumers, after measuring that nothing produces it at that seam. Two arms reading other keys QueryResult does not declare were left standing in the same expressions, deliberately, because the card measured records and not them:
packages/components/src/hooks/related-count-store.ts — typeof res?.count === 'number' ? res.count : …, tried second, ahead of the contract's rows member. count is not a QueryResult member; the store already asks for the server count via $count: true and reads it back as total, which is one.
packages/plugin-view/src/ObjectView.tsx (~:935) — else if (Array.isArray((results as any).value)) { items = (results as any).value; }, the last branch of the unwrap ladder, after data. value is not a QueryResult member either — it is the OData spelling that ObjectStackAdapter.normalizeQueryResult and ApiDataSource.normalizeQueryResult both read on the raw payload, i.e. strictly below the adapter, exactly like records.
Both are dead rather than actively wrong on today's tree (each sits behind the contract's own member), which is the same standing six of #6726's seven had.
What is NOT measured here
⛔ No producer sweep was run for count or value — #6726's sweep asked about records. Recording the shape is not the same as measuring the arm, and this card should not be actioned on #6726's numbers. What a fix owes, per module:
does any producer emit count / value at that seam (repo-wide, with a control term that must hit and does);
only if none does — delete the arm and pin the contract read, one pin per module.
Note value also appears in extractRecords (packages/core/src/utils/extract-records.ts), which #6839 is about; whoever takes that card and this one should check they agree rather than landing two different answers for the same key.
Why it is worth recording
AGENTS.md #0.1: a tolerant arm is where a non-conforming producer keeps working unrejected. #6726's own history is the argument for not leaving the residue unnamed — the records/items confusion outlived two cards (#5458, #5945) precisely because each pass fixed the spellings it had been asked about and said nothing about the ones it had not.
⛔ Do not widen QueryResult to bless count or value — that is a published-type change and a maintainer decision, same hard floor as #6726.
卡写:⛔ Do not widen QueryResult to bless count or value — that is a published-type change and a maintainer decision, same hard floor as #6726.本席确认并加固:放宽已发布类型是契约面变更,落在人工底线,⛔ 执行席不得自决,本席也不代裁。执行者若在普查中发现确有生产者发 count/value,⛔ 停手回报,不要顺势把类型放宽 —— 那时的正解多半是修生产者。
{
"issue": 6840,
"status": "done",
"branch": "claude/issue-6840-queryresult-count-value-arms",
"pr": "https://github.com/objectstack-ai/objectui/pull/6916",
"premise_still_valid": true,
"summary": "Both arms were swept per module with this card's OWN producer sweep (never #6726's records numbers), then deleted on a measured zero, one refusal pin per module. count: 0 producers repo-wide across all 452 find() definition bodies / 331 files; value: 0 producers across the 25 bodies reachable by plugin-view's ObjectView. Deleted `typeof res?.count === 'number' ? res.count` from related-count-store.ts (it was tried second but AHEAD of the contract's data — a real precedence inversion) and the `results.value` branch from ObjectView.tsx (a pure fallback, data was already read first — no inversion existed, and the pin says so in prose instead of fabricating a case). HUMAN FLOOR NOT REACHED and packages/types/src/data.ts is untouched: QueryResult was not widened. The card's premise held exactly as written — both arms were present, both dead at their own seam, and both keys are consumed BELOW the adapter by the two normalizeQueryResult implementations, which is the mechanism that makes the zero make sense.",
"sweeps": {
"method": "Cell = the body of a `find` DEFINITION, delimited by a real bracket scanner over comment- and string-blanked source so a body cannot leak into the SIBLING properties of its enclosing object literal. Subject terms and control terms are extracted from the SAME cells in the SAME pass, so the control sits on the JOIN — the cell the zero lives in — not merely on the terms. This precision changed the answer: a first line-window pass reported 4 `count` hits, and all four were `count: async () => 0`, the fake adapter's own sibling count() METHOD, never an envelope key. The scanner was tightened until the zero was mechanical rather than a manual subtraction.",
"count_repo_wide": "SUBJECT `count` 0 hits / 0 files || CONTROL `total` 85 hits / 75 files || CONTROL `data` 135 hits / 103 files — over 452 find() definition bodies in 331 files. Repo-wide IS the seam here: containers.tsx hands RelatedCountStore an arbitrary `(object, query) => ds.find(object, query)`, so every DataSource implementation in the repo is a producer at this seam.",
"value_at_objectview_seam": "SUBJECT `value` 0 hits / 0 files || CONTROL `data` 6 hits / 6 files || CONTROL `total` 6 hits / 6 files — over the 25 find() definition bodies in the 24 files that mount plugin-view's ObjectView.",
"named_control_count": "HIT. Triage named `total`: hot at 85/75 in the same pass as the zero. The mechanism behind the zero also checks out — `count` is folded into `total` BELOW the seam at data-objectstack/src/index.ts:3382 (`resultObj.total ?? resultObj.count ?? records.length`) and core/src/adapters/ApiDataSource.ts:402 (`raw.total ?? raw.totalCount ?? raw.count ?? ...`).",
"named_control_value": "HIT, both implementations triage named. ObjectStackAdapter.normalizeQueryResult at data-objectstack/src/index.ts:3381 — `const records = resultObj.records || resultObj.value || [];`. ApiDataSource.normalizeQueryResult at core/src/adapters/ApiDataSource.ts:398 — `for (const key of ['data', 'items', 'results', 'records', 'value'])`. Both read `value` on the RAW payload and return only data/total/page/pageSize/hasMore/cursor, so the query demonstrably reached the seam.",
"both_halves_stated": "A hot control proves the query RAN. The second half — that the question was RIGHT — is that the controls were extracted by the same pass, from the same cells, in the same units as the zero: `total` and `data` counted as emitted envelope keys inside find() bodies, exactly what `count` and `value` were counted as. Had the question been wrong (e.g. scanning read positions rather than emit positions), the controls would have moved WITH the subjects instead of separating 85-to-0. Both halves are stated in the PR.",
"value_is_NOT_zero_repo_wide": "Repo-wide the same pass finds `value` emitted 5 times — every one a live TEST DOUBLE feeding extractRecords (2 in plugin-calendar, 3 in plugin-kanban: ObjectCalendar.markedRefusalToast:113, ObjectCalendar.expandGate-6453:180, ObjectKanban.markedRefusalToast:164, ObjectKanban.rejectedMoveRollback:128, ObjectKanban.requiredWhenPrompt:139). NONE reaches ObjectView or RelatedCountStore. That is why the deletion is safe here and would NOT be at #6839's seam."
},
"human_floor": "NOT REACHED, and packages/types/src/data.ts is untouched by this PR. Both sweeps returned zero AT THEIR OWN SEAM, so the stop-and-report branch never triggered. QueryResult was not widened to bless `count` or `value`. Note for the record: the 5 `value` emitters that DO exist repo-wide are test doubles at a different seam (#6839's), not production producers at mine — so they are not a floor trigger for this card, and the correct handling was to hand them to #6839 as evidence rather than to act on them here.",
"cross_card_consistency_6839": "DISCHARGED, and the answer is the non-obvious one. Per 谁先动谁负责对齐, this PR lands first on `value` and states in its description: the reading is that `value`'s status is SEAM-LOCAL, and #6839 must NOT delete on this card's zero. The same single pass returned 0 producers at ObjectView's seam and 5 LIVE producers at extractRecords' seam. So the two cards treating `value` differently is the CORRECT result, not an inconsistency — and deleting extractRecords' `value` arm on this PR's numbers would break five tests. The evidence is handed over, not a verdict; #6839 owes its own sweep. The same warning is written into the source comment at ObjectView.tsx's deletion site so a later reader cannot pick the zero up and carry it.",
"pin_form_for_6837": "SET, and stated in the PR as the form for #6837 to copy, extending #6726's: (1) a header carrying the MEASUREMENT — cell, subject count and control counts side by side — so the pin carries its own evidence and a later reader can tell a measured zero from an assumed one; (2) the LIVE arms pinned in the same file as the dead one, because live and dead is the whole distinction and without them a module that simply stopped working would pass the refusals too; (3) one named refusal case per deleted key, asserting the honest zero; (4) a precedence-inversion case WHERE AND ONLY WHERE one exists — `count` was tried ahead of `data` so `{count:7, data:[a,b]}` is pinned to 2, while `value` in ObjectView was the ladder's LAST branch so no inversion exists and the pin says so in PROSE rather than fabricating a case that would pass before and after and measure nothing; (5) the human floor restated at the pin, so re-widening is refused where someone would try it.",
"deliberately_left_out": "(a) QueryResult itself — human floor. (b) The `records` arm anywhere — #6726's territory, already done. (c) extractRecords' `value` arm — #6839's, and measured LIVE, so touching it would have been the exact error triage warned about. (d) The six sibling read sites in plugin-detail / plugin-list / fields / app-shell / apps/console — outside the fence, filed as #6917 rather than swept up; app-shell and apps/console are also inside unlanded PR #6913's fence. (e) plugin-grid's data-table.tsx (unlanded PR #6912) and everything else in packages/components beyond related-count-store.ts — untouched. (f) Awaiting CI convergence — per dispatch that is the PM's, not mine. (g) A full-console build to satisfy check:sdui-registration-pins — reported as NOT MEASURED instead.",
"tests": "All results on a tree byte-identical to commit 6163cf9 (proven by the ablation's restore: `git diff HEAD` empty AND `git hash-object` equal to the HEAD blob for both mutated paths), re-confirmed post-ablation. RED FIRST (pins vs unmodified source): `vitest run` both new pins -> 'Tests 3 failed | 7 passed (10)', failures exactly the three refusals ('expected 7 to be +0', 'expected 7 to be 2', 'expected [ { id: r1 ... } ] to have a length of +0 but got 2') with all 7 live-arm controls green. GREEN AFTER: both new pins + both #6726 pins + store suite + tab-strip memo -> 'Test Files 6 passed (6) / Tests 29 passed (29)'. FULL SUITES: plugin-view 'Test Files 29 passed (29) / Tests 268 passed (268)'; components 'Test Files 218 passed (218) / Tests 2007 passed (2007)'. TYPE-CHECK: exit 0, 'Scope: 2 of 47 workspace projects', script echoed as `tsc --noEmit && tsc -p tsconfig.test.json` (zero-match filter trap guarded). NEW PINS ARE PROGRAM INPUTS: `tsc -p tsconfig.test.json --listFiles` -> 1 match each, measured not assumed. LINT (the real gate is `turbo run lint`, per package): exit 0, 'Scope: 2 of 47', 0 errors in the diff. GATES, each read from its own printed verdict line, exit codes captured before any pipe: check:control-bytes OK (5762 files), check:vi-mock-specifiers OK, check:vi-mock-inherit OK (109 @object-ui/react call sites judged, 109 inherit), check:self-import OK, check:esm-specifiers OK, check:phantom-deps OK, check:element-data-source-declaration OK, check:side-effects-array OK. ABLATION (mutated the FACT, not the assertion): resolution path stated first — both pins import the mutated module by RELATIVE source path ('../hooks/related-count-store', '../ObjectView'), no package exports hop, so no dist/ and no rebuild leg exists; both deleted arms reinserted on the committed tree; mutation PROVEN ON DISK by anchored counts (res?.count 0->1, '(results as any).value' 0->2) AND git hash-object diverging from the HEAD blob on both files, never by the editor's exit code; result 'Tests 3 failed | 7 passed (10)' — same three refusals, seven live-arm controls still green; restore proven BOTH ways scoped to the mutated paths only (`git diff HEAD` empty AND hash-object equal to HEAD blobs b114e864 / ae4d44cd), with `trap` on EXIT/INT/TERM using absolute paths from `git rev-parse --show-toplevel` and restore pinned to `git checkout HEAD -- path` rather than the bare form that restores from a mutated index. NOT MEASURED (reported as such, not as a colour): check:sdui-registration-pins exits 2 with PREREQUISITE NOT MET — its own message is 'a run with nothing to read has measured nothing. Build the console first'; it needs a built console bundle this diff does not affect, left to CI. DECLARED NARROWING: the repo-wide flat `eslint .` was ALSO run — 4013 files in scope (read from eslint's own --format json output, not guessed), 90 errors, 11644 warnings, ALL pre-existing with 0 of the 90 in this diff's four files; type-aware linting is not enabled (no projectService/project: in eslint.config.js) so this diff cannot move any untouched file's verdict. CI gate status at report time: in_progress (not awaited, per dispatch).",
"mcp_calls": "2 — issue_read on #6840 (1) and one targeted search_issues for the pre-filing duplicate check (1). Everything else went over repo-scoped REST, which probed 200 on this seat; the global /search/issues path is blocked here ('sessions are bound to their configured repositories'), which is why the duplicate check switched channels to MCP — declared.",
"open_questions": [],
"out_of_scope_findings": [
"filed as #6917: six MORE non-QueryResult count/value arms survive in four packages outside this fence (plugin-detail/record-reference-rail.tsx:196, plugin-list/ListView.tsx:1816, fields/index.tsx:250, app-shell/AppHeader.tsx:182, console/PublicFormsPage.tsx:134, console/FlowRunsPage.tsx:155) — and fields/index.tsx:250 reads `result?.value || result?.data`, i.e. value AHEAD of data: an ACTIVE precedence inversion, not a dead arm. Filed unassigned and unlabelled for PM triage (it is a concrete defect, not an observation). Explicitly carries the warning that #6840's zero is seam-local and must not be reused.",
"recorded inside #6917: core/src/data-scope/ViewDataProvider.ts:128 declares a second, private `extractRecords` reading records|data|items — a DIFFERENT tolerance set from @object-ui/core's exported extractRecords (records|data|value), under the same name.",
"recorded inside #6917: plugin-grid __tests__/columnIdentity.test.tsx:31 and recordIdFieldProjection.test.tsx:48 return { value: [], '@odata.count': 0 } from their find doubles while ObjectGrid reads result.data only — fixtures that read as though they supply rows and supply none. Inert today only because the arrays are empty."
]
}
Activity
os-project-manager commentedon Aug 30, 2026
Triage 审计 · R+34
定级:
domain:ui·priority:p3·pm:queue· typeTask(
finding已摘除 = 已完成首次定级)refactor/tech-debt族,而打bug会撒谎 —— 两条臂在今天的树上都是死的(各自坐在契约自己的成员后面),不是活错。为什么 p3
两臂今天都不可达 ⇒ 无在飞损害。但它们是 AGENTS.md #0.1 意义上的静默吸收点,并且这条历史线本身就是不清残留会付利息的证据:卡自己指出
records/items的混乱熬过了两张卡(#5458、#5945),原因正是每一遍只修被问到的拼写,对没被问到的一言不发。#6726 是第三遍,这张卡就是它没被问到的部分。⇒ 值得留在队列里,不值得插队。✅ 本席采信卡的自我克制,并把它升格为派发口径
卡写:⛔ No producer sweep was run for
countorvalue— this card should not be actioned on #6726's numbers. 完全正确,而且这是这张卡最值钱的一句。 钉成执行者的强制顺序:count/value";records-before-datatolerant reader survives in ~7 morefind()consumers that #5945 did not name #6726 关于records的数字去覆盖count/value。记录形状 ≠ 度量该臂。零命中纪律(强制)
每一条普查的零,必须与一个必然命中的对照词在同一条查询里:
count:对照 =total(该 store 已经用$count: true请求服务端计数并以total读回,total是QueryResult的成员,所以它必须命中);value:对照 = 适配器层下方那两个normalizeQueryResult(ObjectStackAdapter与ApiDataSource)对原始 payload 读value的位置 —— 它们必须命中,否则说明查询压根没覆盖到这条缝。⛔ 没有正对照的零不算读数。本仓最近四张卡(objectstack#13293 / #13304 / #13305 / #13306)连续四次栽在这上面。
⛔ 人工底线,原样保留
卡写:⛔ Do not widen
QueryResultto blesscountorvalue— that is a published-type change and a maintainer decision, same hard floor as #6726. 本席确认并加固:放宽已发布类型是契约面变更,落在人工底线,⛔ 执行席不得自决,本席也不代裁。执行者若在普查中发现确有生产者发count/value,⛔ 停手回报,不要顺势把类型放宽 —— 那时的正解多半是修生产者。value也出现在packages/core/src/utils/extract-records.ts的extractRecords里,那是 #6839 的地盘。⇒ 同一个键,两张卡,不得落两个不同的答案。处置:谁先动谁负责对齐 —— 先落地的一方必须在 PR 描述里点名另一张卡并写明它给
value定的是什么读法;后落地的一方以此为准或公开推翻,⛔ 不得沉默地做第二种。本席不设阻塞边(两处可以独立普查),只设这条一致性义务。同族
与 #6837 同类:容忍分支 = 静默吸收点。⭐ 两张卡的 refusal-pin 形制应当统一,谁先落地谁定形制。
Generated by Claude Code
claude commentedon Aug 30, 2026
os-dev-report
{ "issue": 6840, "status": "done", "branch": "claude/issue-6840-queryresult-count-value-arms", "pr": "https://github.com/objectstack-ai/objectui/pull/6916", "premise_still_valid": true, "summary": "Both arms were swept per module with this card's OWN producer sweep (never #6726's records numbers), then deleted on a measured zero, one refusal pin per module. count: 0 producers repo-wide across all 452 find() definition bodies / 331 files; value: 0 producers across the 25 bodies reachable by plugin-view's ObjectView. Deleted `typeof res?.count === 'number' ? res.count` from related-count-store.ts (it was tried second but AHEAD of the contract's data — a real precedence inversion) and the `results.value` branch from ObjectView.tsx (a pure fallback, data was already read first — no inversion existed, and the pin says so in prose instead of fabricating a case). HUMAN FLOOR NOT REACHED and packages/types/src/data.ts is untouched: QueryResult was not widened. The card's premise held exactly as written — both arms were present, both dead at their own seam, and both keys are consumed BELOW the adapter by the two normalizeQueryResult implementations, which is the mechanism that makes the zero make sense.", "sweeps": { "method": "Cell = the body of a `find` DEFINITION, delimited by a real bracket scanner over comment- and string-blanked source so a body cannot leak into the SIBLING properties of its enclosing object literal. Subject terms and control terms are extracted from the SAME cells in the SAME pass, so the control sits on the JOIN — the cell the zero lives in — not merely on the terms. This precision changed the answer: a first line-window pass reported 4 `count` hits, and all four were `count: async () => 0`, the fake adapter's own sibling count() METHOD, never an envelope key. The scanner was tightened until the zero was mechanical rather than a manual subtraction.", "count_repo_wide": "SUBJECT `count` 0 hits / 0 files || CONTROL `total` 85 hits / 75 files || CONTROL `data` 135 hits / 103 files — over 452 find() definition bodies in 331 files. Repo-wide IS the seam here: containers.tsx hands RelatedCountStore an arbitrary `(object, query) => ds.find(object, query)`, so every DataSource implementation in the repo is a producer at this seam.", "value_at_objectview_seam": "SUBJECT `value` 0 hits / 0 files || CONTROL `data` 6 hits / 6 files || CONTROL `total` 6 hits / 6 files — over the 25 find() definition bodies in the 24 files that mount plugin-view's ObjectView.", "named_control_count": "HIT. Triage named `total`: hot at 85/75 in the same pass as the zero. The mechanism behind the zero also checks out — `count` is folded into `total` BELOW the seam at data-objectstack/src/index.ts:3382 (`resultObj.total ?? resultObj.count ?? records.length`) and core/src/adapters/ApiDataSource.ts:402 (`raw.total ?? raw.totalCount ?? raw.count ?? ...`).", "named_control_value": "HIT, both implementations triage named. ObjectStackAdapter.normalizeQueryResult at data-objectstack/src/index.ts:3381 — `const records = resultObj.records || resultObj.value || [];`. ApiDataSource.normalizeQueryResult at core/src/adapters/ApiDataSource.ts:398 — `for (const key of ['data', 'items', 'results', 'records', 'value'])`. Both read `value` on the RAW payload and return only data/total/page/pageSize/hasMore/cursor, so the query demonstrably reached the seam.", "both_halves_stated": "A hot control proves the query RAN. The second half — that the question was RIGHT — is that the controls were extracted by the same pass, from the same cells, in the same units as the zero: `total` and `data` counted as emitted envelope keys inside find() bodies, exactly what `count` and `value` were counted as. Had the question been wrong (e.g. scanning read positions rather than emit positions), the controls would have moved WITH the subjects instead of separating 85-to-0. Both halves are stated in the PR.", "value_is_NOT_zero_repo_wide": "Repo-wide the same pass finds `value` emitted 5 times — every one a live TEST DOUBLE feeding extractRecords (2 in plugin-calendar, 3 in plugin-kanban: ObjectCalendar.markedRefusalToast:113, ObjectCalendar.expandGate-6453:180, ObjectKanban.markedRefusalToast:164, ObjectKanban.rejectedMoveRollback:128, ObjectKanban.requiredWhenPrompt:139). NONE reaches ObjectView or RelatedCountStore. That is why the deletion is safe here and would NOT be at #6839's seam." }, "human_floor": "NOT REACHED, and packages/types/src/data.ts is untouched by this PR. Both sweeps returned zero AT THEIR OWN SEAM, so the stop-and-report branch never triggered. QueryResult was not widened to bless `count` or `value`. Note for the record: the 5 `value` emitters that DO exist repo-wide are test doubles at a different seam (#6839's), not production producers at mine — so they are not a floor trigger for this card, and the correct handling was to hand them to #6839 as evidence rather than to act on them here.", "cross_card_consistency_6839": "DISCHARGED, and the answer is the non-obvious one. Per 谁先动谁负责对齐, this PR lands first on `value` and states in its description: the reading is that `value`'s status is SEAM-LOCAL, and #6839 must NOT delete on this card's zero. The same single pass returned 0 producers at ObjectView's seam and 5 LIVE producers at extractRecords' seam. So the two cards treating `value` differently is the CORRECT result, not an inconsistency — and deleting extractRecords' `value` arm on this PR's numbers would break five tests. The evidence is handed over, not a verdict; #6839 owes its own sweep. The same warning is written into the source comment at ObjectView.tsx's deletion site so a later reader cannot pick the zero up and carry it.", "pin_form_for_6837": "SET, and stated in the PR as the form for #6837 to copy, extending #6726's: (1) a header carrying the MEASUREMENT — cell, subject count and control counts side by side — so the pin carries its own evidence and a later reader can tell a measured zero from an assumed one; (2) the LIVE arms pinned in the same file as the dead one, because live and dead is the whole distinction and without them a module that simply stopped working would pass the refusals too; (3) one named refusal case per deleted key, asserting the honest zero; (4) a precedence-inversion case WHERE AND ONLY WHERE one exists — `count` was tried ahead of `data` so `{count:7, data:[a,b]}` is pinned to 2, while `value` in ObjectView was the ladder's LAST branch so no inversion exists and the pin says so in PROSE rather than fabricating a case that would pass before and after and measure nothing; (5) the human floor restated at the pin, so re-widening is refused where someone would try it.", "deliberately_left_out": "(a) QueryResult itself — human floor. (b) The `records` arm anywhere — #6726's territory, already done. (c) extractRecords' `value` arm — #6839's, and measured LIVE, so touching it would have been the exact error triage warned about. (d) The six sibling read sites in plugin-detail / plugin-list / fields / app-shell / apps/console — outside the fence, filed as #6917 rather than swept up; app-shell and apps/console are also inside unlanded PR #6913's fence. (e) plugin-grid's data-table.tsx (unlanded PR #6912) and everything else in packages/components beyond related-count-store.ts — untouched. (f) Awaiting CI convergence — per dispatch that is the PM's, not mine. (g) A full-console build to satisfy check:sdui-registration-pins — reported as NOT MEASURED instead.", "tests": "All results on a tree byte-identical to commit 6163cf9 (proven by the ablation's restore: `git diff HEAD` empty AND `git hash-object` equal to the HEAD blob for both mutated paths), re-confirmed post-ablation. RED FIRST (pins vs unmodified source): `vitest run` both new pins -> 'Tests 3 failed | 7 passed (10)', failures exactly the three refusals ('expected 7 to be +0', 'expected 7 to be 2', 'expected [ { id: r1 ... } ] to have a length of +0 but got 2') with all 7 live-arm controls green. GREEN AFTER: both new pins + both #6726 pins + store suite + tab-strip memo -> 'Test Files 6 passed (6) / Tests 29 passed (29)'. FULL SUITES: plugin-view 'Test Files 29 passed (29) / Tests 268 passed (268)'; components 'Test Files 218 passed (218) / Tests 2007 passed (2007)'. TYPE-CHECK: exit 0, 'Scope: 2 of 47 workspace projects', script echoed as `tsc --noEmit && tsc -p tsconfig.test.json` (zero-match filter trap guarded). NEW PINS ARE PROGRAM INPUTS: `tsc -p tsconfig.test.json --listFiles` -> 1 match each, measured not assumed. LINT (the real gate is `turbo run lint`, per package): exit 0, 'Scope: 2 of 47', 0 errors in the diff. GATES, each read from its own printed verdict line, exit codes captured before any pipe: check:control-bytes OK (5762 files), check:vi-mock-specifiers OK, check:vi-mock-inherit OK (109 @object-ui/react call sites judged, 109 inherit), check:self-import OK, check:esm-specifiers OK, check:phantom-deps OK, check:element-data-source-declaration OK, check:side-effects-array OK. ABLATION (mutated the FACT, not the assertion): resolution path stated first — both pins import the mutated module by RELATIVE source path ('../hooks/related-count-store', '../ObjectView'), no package exports hop, so no dist/ and no rebuild leg exists; both deleted arms reinserted on the committed tree; mutation PROVEN ON DISK by anchored counts (res?.count 0->1, '(results as any).value' 0->2) AND git hash-object diverging from the HEAD blob on both files, never by the editor's exit code; result 'Tests 3 failed | 7 passed (10)' — same three refusals, seven live-arm controls still green; restore proven BOTH ways scoped to the mutated paths only (`git diff HEAD` empty AND hash-object equal to HEAD blobs b114e864 / ae4d44cd), with `trap` on EXIT/INT/TERM using absolute paths from `git rev-parse --show-toplevel` and restore pinned to `git checkout HEAD -- path` rather than the bare form that restores from a mutated index. NOT MEASURED (reported as such, not as a colour): check:sdui-registration-pins exits 2 with PREREQUISITE NOT MET — its own message is 'a run with nothing to read has measured nothing. Build the console first'; it needs a built console bundle this diff does not affect, left to CI. DECLARED NARROWING: the repo-wide flat `eslint .` was ALSO run — 4013 files in scope (read from eslint's own --format json output, not guessed), 90 errors, 11644 warnings, ALL pre-existing with 0 of the 90 in this diff's four files; type-aware linting is not enabled (no projectService/project: in eslint.config.js) so this diff cannot move any untouched file's verdict. CI gate status at report time: in_progress (not awaited, per dispatch).", "mcp_calls": "2 — issue_read on #6840 (1) and one targeted search_issues for the pre-filing duplicate check (1). Everything else went over repo-scoped REST, which probed 200 on this seat; the global /search/issues path is blocked here ('sessions are bound to their configured repositories'), which is why the duplicate check switched channels to MCP — declared.", "open_questions": [], "out_of_scope_findings": [ "filed as #6917: six MORE non-QueryResult count/value arms survive in four packages outside this fence (plugin-detail/record-reference-rail.tsx:196, plugin-list/ListView.tsx:1816, fields/index.tsx:250, app-shell/AppHeader.tsx:182, console/PublicFormsPage.tsx:134, console/FlowRunsPage.tsx:155) — and fields/index.tsx:250 reads `result?.value || result?.data`, i.e. value AHEAD of data: an ACTIVE precedence inversion, not a dead arm. Filed unassigned and unlabelled for PM triage (it is a concrete defect, not an observation). Explicitly carries the warning that #6840's zero is seam-local and must not be reused.", "recorded inside #6917: core/src/data-scope/ViewDataProvider.ts:128 declares a second, private `extractRecords` reading records|data|items — a DIFFERENT tolerance set from @object-ui/core's exported extractRecords (records|data|value), under the same name.", "recorded inside #6917: plugin-grid __tests__/columnIdentity.test.tsx:31 and recordIdFieldProjection.test.tsx:48 return { value: [], '@odata.count': 0 } from their find doubles while ObjectGrid reads result.data only — fixtures that read as though they supply rows and supply none. Inert today only because the arrays are empty." ] }Generated by Claude Code
fix(fields,plugin-detail,plugin-list,app-shell,console): read count/v…
fix(fields,plugin-detail,plugin-list,app-shell,console): read count/v…