From 8b209863445f5a779b7f31155a726a4c39cf1940 Mon Sep 17 00:00:00 2001 From: Claude Date: Wed, 9 Sep 2026 00:04:20 +0000 Subject: [PATCH 1/2] test(plugin-charts): pin what the site-2 refusal settles to, not what it is not MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit `ObjectChart.contractEnvelope-6839`'s site-2 refusal arm asserted `.not.toBe('Apollo')` — a negation over an open codomain. Every value except that one literal satisfied it, including `String(undefined)`, `''` and `'null'` — i.e. every value a resolver emits once it has stopped resolving anything. Ablation on this file: deleting the `|| rawValue` fallback in `resolveGroupByLabels`, so an unresolved foreign key reaches the axis as the literal string `undefined`, left all six cases GREEN under the old pin. The file blessed an implementation strictly worse than the bug it was written to catch. The arm now names the one value a correct refusal settles on: `'p1'`, the foreign key verbatim, which is the raw-FK axis the module docblock already describes. Measured, not assumed — the lookup branch ends `idToName[rawValue] || rawValue`, so `humanizeLabel` is NOT on this path and never uppercases the key. The helper docstring claimed `'P1'`; that claim is corrected here, since a pin written for it would redden on a correct refusal. Test-only. No production code changes. Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_01YBWFb5YgMU5dw8p2VKj16S --- ...ObjectChart.contractEnvelope-6839.test.tsx | 21 +++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/packages/plugin-charts/src/ObjectChart.contractEnvelope-6839.test.tsx b/packages/plugin-charts/src/ObjectChart.contractEnvelope-6839.test.tsx index c3d2540f8d..13ce0ff147 100644 --- a/packages/plugin-charts/src/ObjectChart.contractEnvelope-6839.test.tsx +++ b/packages/plugin-charts/src/ObjectChart.contractEnvelope-6839.test.tsx @@ -135,8 +135,11 @@ async function settledOn(envelope: Envelope): Promise { * Run site 2 directly: resolve one `lookup` dimension's labels over a `find()` * answering `envelope`, and hand back the axis label the row ended up with. * - * `'Apollo'` means the domain was read; `'P1'` is what `humanizeLabel` makes of - * the unresolved foreign key, i.e. the silent-looking failure. + * `'Apollo'` means the domain was read; `'p1'` — the raw foreign key, verbatim + * — is the silent-looking failure. MEASURED, not assumed: the lookup branch + * ends `[groupByField]: idToName[rawValue] || rawValue`, so an unresolved key + * falls through UNTOUCHED. `humanizeLabel` is not on this path and never + * uppercases it; a pin written for `'P1'` reddens on a correct refusal. */ async function labelThrough(envelope: Envelope): Promise { const ds: any = { find: vi.fn(async () => envelope(PROJECTS)) }; @@ -185,10 +188,20 @@ describe('ObjectChart — the find() envelopes it reads (objectui#6839)', () => // The sharp half. The bar count is identical either way; what changes is // that the axis now carries the raw foreign key. A rows-only pin would // have called this module green. + // + // ⭐ ASSERT THE POSITIVE (objectui#8708). This arm read `.not.toBe( + // 'Apollo')` — a negation over an OPEN codomain, so it also accepted + // `String(undefined)`, `''`, `'null'` and every other value a resolver + // emits once it has stopped resolving anything. ABLATION, on this file: + // deleting the `|| rawValue` fallback in `resolveGroupByLabels` — so an + // unresolved key reaches the axis as the literal string `undefined` — + // left ALL SIX cases green under the old pin. Naming the one value a + // correct refusal settles on closes that: `'p1'` is the FK verbatim, the + // raw-foreign-key axis the docblock above describes. expect( await labelThrough(asRecords), - 'a `records` envelope must not resolve the referenced domain', - ).not.toBe('Apollo'); + 'a `records` envelope must leave the axis on the raw foreign key, unresolved', + ).toBe('p1'); }); }); }); From 5f18ba86151db1344527fac266dbc95f02659b9d Mon Sep 17 00:00:00 2001 From: Claude Date: Wed, 9 Sep 2026 00:08:24 +0000 Subject: [PATCH 2/2] chore(changeset): declare the plugin-charts pin repair as releasing nothing MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Empty frontmatter — the explicit exemption for a test-only change, not a workaround. `scripts/check-changeset-presence.mjs` goes green on it. Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_01YBWFb5YgMU5dw8p2VKj16S --- .changeset/chart-refusal-assertion-strength.md | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 .changeset/chart-refusal-assertion-strength.md diff --git a/.changeset/chart-refusal-assertion-strength.md b/.changeset/chart-refusal-assertion-strength.md new file mode 100644 index 0000000000..3a85f37869 --- /dev/null +++ b/.changeset/chart-refusal-assertion-strength.md @@ -0,0 +1,4 @@ +--- +--- + +Test-only change to `@object-ui/plugin-charts`: the `contractEnvelope-6839` site-2 refusal arm now pins the value a correct refusal settles on (`'p1'`, the raw foreign key) instead of negating the one value it must not produce. No published behaviour changes.