Repository navigation
Commit fbb8bec
fix(spec): a count roll-up saves without summaryOperations.field (#27533)
domain:spec#3 · os-support-ai · session_01WGufzgbJhFoXYsLSe5WSPP
<!-- claude-projects-attribution: {"github_login":"os-support-ai"} -->
_Requested by **Yibo Wang** · [project
thread](https://claude.ai/code/project/chan_01BVUyyPie8gHwoPM18iABwB?thread=cmsg_01BVUyyPie8gHwoPM18iABwB6Ss4nCDVbpzX9zFKKXkNyU)_
Fixes #27462
Clause-②: yes (widening)
Metadata-protocol: added
Skills-docs: updated here.
`skills/objectstack-data/rules/field-types.md:125` spelled the `summary`
config row `({ object, field, function, relationshipField?, filter? })`,
teaching `field` as always required; it now reads `` ({ object, field?
(omit for `count`), function, relationshipField?, filter? }) ``. The
words are paid for in the same file: its `sum` example (:259) drops the
comment "(ignored for count)", which the row now states.
`skills/objectstack-data/rules/relationships.md:201` is a `sum` example
whose comment stays true; not edited.
**Seat ruling.** The spec follows its own describe.
`summaryOperations.field` becomes optional when `function` is `count`
and stays required for every other function, with the refusal for a
missing `field` on a non-count function naming the function and the fix.
Not "Studio fills an arbitrary field": that would store a value the
engine ignores.
## 维护者速读
- 改了什么:汇总字段(roll-up)用 `count` 时不再要求
`summaryOperations.field`;`sum`/`min`/`max`/`avg` 缺 `field`
仍被拒,报错指明函数和改法。Studio 汇总编辑器在 `count` 时不再显示「Child field to aggregate」。
- 为什么改:规范自己的说明写着 count 忽略该字段,但校验却要求它,Studio 里存 count 汇总会
422,作者只能随便选一个子字段。
- 风险与回滚:放宽接受集,原来能存的定义照旧能存(count 带 field 仍接受、仍忽略);引擎本来就不为 count
读字段。回滚即还原本 PR。
- 先看:`skills/objectstack-data/rules/field-types.md`(:125 与 :259
两行),`packages/spec/src/data/field.zod.ts`(`summaryFunctionReadsField` 与
`refuseSummaryWithoutField`),`ui/packages/app-shell/src/views/metadata-admin/inspectors/ObjectFieldInspector.tsx`(`SummaryConfigFields`
的条件渲染)。
- 两分钟验证:`pnpm --filter @objectstack/spec exec vitest run
src/data/field.test.ts -t "summaryOperations"`,应见 count 无 field
通过、sum/min/max/avg 无 field 各被拒共 5 个用例全绿。
- 需要你做的:席位 ACCEPT 后批准本 PR:它改了受管的
`skills/objectstack-data/rules/field-types.md`(一处表格行写明 count 可省略 field)。
## What changes
**Measured on `origin/main` `273137d2` (before).** Spec parse,
`FieldSchema.safeParse` of a `summary` with `summaryOperations: {
object: 'child', function: 'count' }`:
```
count false [{"expected":"string","code":"invalid_type","path":["summaryOperations","field"],"message":"Invalid input: expected string, received undefined"}]
sum false [{"expected":"string","code":"invalid_type","path":["summaryOperations","field"],"message":"Invalid input: expected string, received undefined"}]
count+field true {"object":"child","field":"amount","function":"count"}
```
The metadata write door, `saveMetaItem({ type: 'object', … })` on the
metadata-protocol stub engine (the #8783 harness), an object whose
`child_count` is that count roll-up:
```
count-no-field: 422 INVALID_METADATA [{"path":"fields.child_count.summaryOperations.field","message":"Invalid input: expected string, received undefined","code":"invalid_type"}] rows=0
sum-no-field: 422 INVALID_METADATA [{"path":"fields.child_count.summaryOperations.field","message":"Invalid input: expected string, received undefined","code":"invalid_type"}] rows=0
count-with-field: saved rows=1
```
That is the card's 422 ("fields.child_count.summaryOperations.field
expected string").
**After (head `023da3b2`), same probes:**
```
count-no-field: saved rows=1
sum-no-field: 422 INVALID_METADATA [{"path":"fields.child_count.summaryOperations.field","message":"`summaryOperations.function: 'sum'` needs `summaryOperations.field`, the child field the sum aggregates: name it (e.g. `field: 'amount'`), or use `function: 'count'`, which counts the child rows and reads no field.","code":"custom"}] rows=0
count-with-field: saved rows=1
```
### The spec (`packages/spec/src/data/field.zod.ts`)
- `summaryOperations.field` is `z.string().optional()`; its describe now
reads "Field on the child object to aggregate. Required for sum, min,
max and avg; count counts the child rows and reads no field, so a count
may omit it (ignored when given)."
- The rule lives once: `export function summaryFunctionReadsField(fn)`
answers `fn !== 'count'` (an unset function answers `true`). The
`summaryOperations` object carries
`.superRefine(refuseSummaryWithoutField)`, which reads that predicate
and adds a `custom` issue at `['field']`, so the error stays located at
`summaryOperations.field` and travels with the shape wherever it is
embedded (objectui's `form.zod.ts` takes
`SpecFieldSchema.shape.summaryOperations`). This follows the
`CurrencyConfigSchema` precedent (`refuseFixedCurrencyWithoutCode`,
#27157): a value-conditional requirement on an inner object.
- The rule is value-conditional ("required unless `function` is
`count`"), which no arm of the closed projectable list states
(`dependent-required` is presence-only and its docblock names this
`if`/`then` shape as staying dropped). So `summaryOperations` joins
`dropped-refinements.baseline.json` at each of the 14 schemas that embed
a field (`data/Field`, `data/Object`, `data/ObjectExtension`,
`system/AddFieldOperation`, …); `measured.droppedRefinementSites` 892 →
906. `publishedSchemasWithDroppedRefinements` stays 244: all 14 were
already in the ledger.
- The two metadata-form sub-rows (`field.form.ts` roll-up composite,
`object.form.ts` quick-add grid) drop `required: true`. Their help text
("ignored for count") is unchanged, so no translation bundle moves.
### Readers of `summaryOperations.field`, measured
| Reader | On an absent `field` for `count`, before | Change |
|:---|:---|:---|
| objectql `buildSummaryIndex` (`engine.ts`) | copies `so.field` into
`sourceField` (undefined) | none; `SummaryDescriptor.sourceField`
becomes optional to say so |
| objectql `aggregateSummaryValue` | already sends no `field` for
`count` | none |
| objectql `createBatchSummaryAccumulator` | reads `row[sourceField]`
only when `fn !== 'count'` | guard added for a non-count descriptor
without a field (reads no value, as an absent column) |
| lint `ROLLUP_NON_NUMERIC_AGGREGAND` (`data-model-rules.ts`) | scoped
to `min`/`max`, checks `typeof … === 'string'` | none |
| spec `checkFieldCompleteness` / lint functional completeness | reads
`summaryOperations` presence only | none |
| metadata-core FLS references | keeps `summaryOperations` as is | none
|
| Studio `SummaryConfigFields` (`ObjectFieldInspector.tsx`) | showed the
control for count with "still required — pick any child field" | reads
`summaryFunctionReadsField`: no control for count, the note "Count
counts the child rows, so it needs no child field." (en/zh) |
| ui `snapshotSummaryPlan.ts` (`sum` only) | indexes
`summarized.fields[sum.field]` | type guard for the now-optional key |
The hand-written `content/docs/data-modeling/field-types.mdx` table and
its count example move with the rule; `content/docs/references/**` is
regenerated (`gen:docs`), with `api-surface/data.json` and
`export-origins/data.json` (`gen:api-surface`, `gen:export-origins`).
`check:authorable-surface` is green and the base file does not move.
## Tests
- spec `src/data/field.test.ts`: a count with no `field` parses
unchanged; `sum`/`min`/`max`/`avg` with no `field` are each refused with
one `custom` issue at `['summaryOperations','field']` whose message
names the function and the `function: 'count'` alternative;
`summaryFunctionReadsField` answers.
- objectql `src/summary-rollup.test.ts`: the parent and child
definitions go through `ObjectSchema.parse` first; a count with no
`field` seeds 0, counts single and batch inserts (4), holds through an
update, and drops on delete (3).
- objectql `src/summary-batch-accumulation.test.ts`: a count descriptor
with no `sourceField` still adds one per admitted row.
- app-shell `ObjectFieldInspector.test.tsx`: no aggregate-field control
for count; picking "Count — child records" saves `{ object, function:
'count' }` and `FieldSchema` accepts the saved field; control: a sum
still offers the control and the spec still refuses it without a field.
<details><summary>Ablations (each restored, `git diff HEAD`
empty)</summary>
Run through `scripts/ablation-replace.mjs`.
- Refusal off (`if (false /* ablated-27462 */ && …)` in
`refuseSummaryWithoutField`): spec `field.test.ts` 4 failed | 281 passed
(the four refusal cases).
- Widening off (`field: z.string()` again): 5 failed | 280 passed (the
count case, plus the four refusal cases, whose issue becomes
`invalid_type`).
- Studio predicate off (`{true /* ablated-27462 */ ? (` in
`SummaryConfigFields`): `ObjectFieldInspector.test.tsx` 1 failed | 44
passed (the count control case).
</details>
## Acceptance notes
- A `count` that carries a `field` stays accepted and ignored, as
before. Studio does not clear it when the function switches to `count`,
so switching back to a `sum` keeps it.
- Stored rows: the change only widens the accept set, so every row that
loaded before loads the same. A non-count row saved without `field`
could only have reached `sys_metadata` around the parse; the engine
reads no value for it (the batch guard) instead of indexing
`row[undefined]`.
## Verification
**r2 (head `7533c782`).** Contract review 6496620533 (FAIL on
`023da3b2`): ②-1 was discharged by r1. ③-1:
`skills/objectstack-data/rules/field-types.md` spells `field?` with
"(omit for `count`)" in the `summary` row and drops the duplicate
"(ignored for count)" comment from its `sum` example; the changeset adds
`Skills-docs: updated here` and `'@objectstack/skills': minor`. No code
change. ③-2 (the QA checklist item) is a follow-up card; `docs/qa` is
untouched.
<details><summary>Skills readings (the token ratchet)</summary>
- `skills/objectstack-data/rules/field-types.md`: 12623 bytes / 322
lines before and after; 3156 tokens against a ceiling of 3158 both times
(`check-skills-token-ratchet.mjs`, exit 0). The ceiling does not move.
- Whole bundle: ratcheted (authored) 207935 / 217474 tokens, bundle
total 219187, unchanged; all `skills/*/SKILL.md` together 4614 lines,
unchanged (no SKILL.md moves).
</details>
<details><summary>Derived gates on head `7533c782`: 116 of 116 run,
every one exit 0</summary>
`dispatch-gates --commands` now derives 116 families (the 109 below plus
7 for the `skills/**` path: `check-skills-token-ratchet.mjs` and its
`--self-test`, `check:agent-test-spelling`, `check:pm-governed-merges`,
`check:pm-skill-id-lint`, `check:skill-compatibility`,
`check:skill-frame-sync`). All 116 were run serially on `7533c782`, with
the full build from r0 still on disk; `dispatch-gates --ran`: "116
derived famil(ies) accounted for — 116 run, 0 NOT-MEASURED".
`check-changeset-no-major` with this body as the event: exit 0.
```
node scripts/check-adr-0087-registration.mjs --base origin/main :: exit 0
node scripts/check-adr-0087-registration.mjs --self-test :: exit 0
node scripts/check-adr-links.mjs --self-test :: exit 0
node scripts/check-adr-links.mjs :: exit 0
node scripts/check-changeset-no-major.mjs --base origin/main :: exit 0
node scripts/check-closing-keyword-parity.mjs --self-test :: exit 0
node scripts/check-closing-keyword-parity.mjs :: exit 0
node scripts/check-comment-mask-adoption.mjs --self-test :: exit 0
node scripts/check-comment-mask-adoption.mjs :: exit 0
node scripts/check-comment-mask-corpus.mjs :: exit 0
node scripts/check-dev-prereqs.mjs --self-test :: exit 0
node scripts/check-doc-route-spelling.mjs --advisory :: exit 0
node scripts/check-doc-route-spelling.mjs --self-test :: exit 0
node scripts/check-docs-section-name.mjs --self-test :: exit 0
node scripts/check-docs-section-name.mjs :: exit 0
node scripts/check-dts-emitted.mjs --self-test :: exit 0
node scripts/check-empty-changeset.mjs --base origin/main :: exit 0
node scripts/check-empty-changeset.mjs --self-test :: exit 0
node scripts/check-engine-split-ratio.mjs --self-test :: exit 0
node scripts/check-issue-citations.mjs :: exit 0
node scripts/check-plugin-teardown-shape.mjs --self-test :: exit 0
node scripts/check-plugin-teardown-shape.mjs :: exit 0
node scripts/check-sdui-manifest.mjs --self-test :: exit 0
node scripts/check-sdui-manifest.mjs :: exit 0
node scripts/check-section-landing-index.mjs --self-test :: exit 0
node scripts/check-section-landing-index.mjs :: exit 0
node scripts/check-skills-token-ratchet.mjs --self-test :: exit 0
node scripts/check-skills-token-ratchet.mjs :: exit 0
node scripts/ci/assert-turbo-remote-cache.mjs --self-test :: exit 0
node scripts/ci/plan-test-core-shards.mjs --self-test :: exit 0
node scripts/ci/prune-turbo-cache.mjs --self-test :: exit 0
node scripts/docs-audit/check-affected-docs.mjs :: exit 0
node scripts/docs-audit/check-drift-comment.mjs :: exit 0
node scripts/pm/release-rehearsal-clone.mjs --self-test :: exit 0
node scripts/release-pending-publish.mjs --self-test :: exit 0
pnpm --dir ui exec vitest run scripts/ :: exit 0
pnpm --filter @objectstack/lint run check:doc-formula-expressions :: exit 0
pnpm --filter @objectstack/lint run check:doc-security-posture :: exit 0
pnpm --filter @objectstack/spec run check:api-surface :: exit 0
pnpm --filter @objectstack/spec run check:authorable-surface :: exit 0
pnpm --filter @objectstack/spec run check:browser-reachable-entries :: exit 0
pnpm --filter @objectstack/spec run check:docs :: exit 0
pnpm --filter @objectstack/spec run check:dual-source-exports :: exit 0
pnpm --filter @objectstack/spec run check:duration-unit-keys :: exit 0
pnpm --filter @objectstack/spec run check:empty-state :: exit 0
pnpm --filter @objectstack/spec run check:entry-nameability :: exit 0
pnpm --filter @objectstack/spec run check:export-origins :: exit 0
pnpm --filter @objectstack/spec run check:exported-any :: exit 0
pnpm --filter @objectstack/spec run check:generated :: exit 0
pnpm --filter @objectstack/spec run check:liveness :: exit 0
pnpm --filter @objectstack/spec run check:llms-txt :: exit 0
pnpm --filter @objectstack/spec run check:skill-examples :: exit 0
pnpm --filter @objectstack/spec run check:skill-refs :: exit 0
pnpm --filter @objectstack/spec run check:strictness-ledger :: exit 0
pnpm --filter @objectstack/spec run check:variant-docs :: exit 0
pnpm --filter @objectstack/spec run check:yaml-examples :: exit 0
pnpm check:agent-test-spelling :: exit 0
pnpm check:changeset-gate-self-tests :: exit 0
pnpm check:ci-filter-parity :: exit 0
pnpm check:closed-ceremony-text :: exit 0
pnpm check:corpus-claim-drift :: exit 0
pnpm check:cross-package-test-inputs :: exit 0
pnpm check:dispatcher-error-vocabulary :: exit 0
pnpm check:doc-anchors :: exit 0
pnpm check:doc-authoring :: exit 0
pnpm check:doc-frontmatter :: exit 0
pnpm check:docs-audit-scope :: exit 0
pnpm check:docs-redirects :: exit 0
pnpm check:docs-single-h1 :: exit 0
pnpm check:docs-spec-enumerations :: exit 0
pnpm check:docs-transcript-drift :: exit 0
pnpm check:driver-memory-census :: exit 0
pnpm check:dts-closure :: exit 0
pnpm check:dual-build-cjs-loads :: exit 0
pnpm check:durability-log-level :: exit 0
pnpm check:engine-double-contract :: exit 0
pnpm check:gitlink-declared :: exit 0
pnpm check:i18n :: exit 0
pnpm check:issue-citations :: exit 0
pnpm check:keyed-text-bounds :: exit 0
pnpm check:lean-entry-closure :: exit 0
pnpm check:logger-receiver-detach :: exit 0
pnpm check:merge-driver :: exit 0
pnpm check:nul-bytes :: exit 0
pnpm check:objectql-double-limit :: exit 0
pnpm check:org-identifier :: exit 0
pnpm check:page-declaration-shape :: exit 0
pnpm check:platform-object-tenancy-census :: exit 0
pnpm check:pm-changeset-deadline-census :: exit 0
pnpm check:pm-governed-merges :: exit 0
pnpm check:pm-prior-rulings :: exit 0
pnpm check:pm-skill-id-lint :: exit 0
pnpm check:published-files :: exit 0
pnpm check:published-readme-links :: exit 0
pnpm check:query-options-erasure :: exit 0
pnpm check:react-page-adapter-contract :: exit 0
pnpm check:refd-timer-probe :: exit 0
pnpm check:registry-log-declared :: exit 0
pnpm check:rest-log-spy-declared :: exit 0
pnpm check:role-word :: exit 0
pnpm check:skill-compatibility :: exit 0
pnpm check:skill-frame-sync :: exit 0
pnpm check:skill-identifier-liveness :: exit 0
pnpm check:slot-lookup :: exit 0
pnpm check:sourcemap-no-sources-content :: exit 0
pnpm check:spec-docblock-symbol-anchors :: exit 0
pnpm check:spec-parsed-alias :: exit 0
pnpm check:system-context-census :: exit 0
pnpm check:test-source-alias :: exit 0
pnpm check:tier-file-adoption :: exit 0
pnpm check:type-check-coverage :: exit 0
pnpm check:type-check-debt :: exit 0
pnpm check:undeclared-dep-imports :: exit 0
pnpm check:vendor-version-stamps :: exit 0
pnpm check:watch-hint-literal :: exit 0
pnpm check:where-matcher :: exit 0
```
</details>
**r1 (head `39742179`).** The declaration is `Metadata-protocol: added`:
a count roll-up with no `summaryOperations.field` is a newly accepted
value. The changeset declares the same and grades every package it names
`minor`; the commit moves only
`.changeset/27462-count-rollup-without-field.md`.
`check-changeset-no-major` with this body as the event and
`check-empty-changeset` were rerun on that head; the readings below are
from `023da3b2`, whose tree differs from it only in that changeset.
All on head `023da3b2`, under `os-verify-lock` (shared-box seconds; one
hold of 2390 s for the chain).
<details><summary>Package suites</summary>
- closure build `'@objectstack/objectql^...' '@objectstack/lint^...'
'@objectstack/platform-objects^...'`: exit 0
- `pnpm --filter @objectstack/spec test`: exit 0 · Test Files 750 passed
· Tests 22319 passed | 1 todo
- `pnpm --filter @objectstack/spec typecheck`: exit 0
- `pnpm --filter @objectstack/spec test:repo`: exit 0 · Test Files 86
passed · Tests 1419 passed
- `pnpm --filter @objectstack/objectql test`: exit 0 · Test Files 483
passed · Tests 9090 passed
- `pnpm --filter @objectstack/objectql typecheck`: exit 0
- `pnpm --filter @objectstack/metadata-protocol test`: exit 0 · Test
Files 279 passed | 4 skipped · Tests 21774 passed | 26 skipped
- `pnpm --filter @objectstack/lint test`: exit 0 · Test Files 177 passed
· Tests 7589 passed
- `pnpm --filter @objectstack/platform-objects test`: exit 0 · Test
Files 97 passed · Tests 1369 passed
- `'@object-ui/app-shell^...'` build, then `pnpm --filter
@object-ui/app-shell type-check`: exit 0
- `cd ui && vitest run packages/i18n/
packages/app-shell/src/views/approval-decision/ …/ObjectFieldInspector`:
exit 0 · Test Files 118 passed · Tests 1699 passed | 13 skipped
(narrowed to the files the diff moves and their importers; CI's Test UI
runs the rest)
</details>
<details><summary>Derived gates: 109 of 109 run, every one exit
0</summary>
`node scripts/pm/dispatch-gates.mjs --commands --repo
objectstack-ai/objectstack` derived 109 families against merge base
`273137d22`; each was run serially on head `023da3b2` and recorded as
`CMD :: exit N`. Three (`spec check:skill-examples`,
`check:dual-build-cjs-loads`, `check:i18n`) exited 3 (prerequisite:
built output) on the first pass and exit 0 after a full `turbo run build
--concurrency=2` (exit 0, 677 s held). `dispatch-gates --ran`: "109
derived famil(ies) accounted for — 109 run, 0 NOT-MEASURED".
```
node scripts/check-adr-0087-registration.mjs --base origin/main :: exit 0
node scripts/check-adr-0087-registration.mjs --self-test :: exit 0
node scripts/check-adr-links.mjs --self-test :: exit 0
node scripts/check-adr-links.mjs :: exit 0
node scripts/check-changeset-no-major.mjs --base origin/main :: exit 0
node scripts/check-closing-keyword-parity.mjs --self-test :: exit 0
node scripts/check-closing-keyword-parity.mjs :: exit 0
node scripts/check-comment-mask-adoption.mjs --self-test :: exit 0
node scripts/check-comment-mask-adoption.mjs :: exit 0
node scripts/check-comment-mask-corpus.mjs :: exit 0
node scripts/check-dev-prereqs.mjs --self-test :: exit 0
node scripts/check-doc-route-spelling.mjs --advisory :: exit 0
node scripts/check-doc-route-spelling.mjs --self-test :: exit 0
node scripts/check-docs-section-name.mjs --self-test :: exit 0
node scripts/check-docs-section-name.mjs :: exit 0
node scripts/check-dts-emitted.mjs --self-test :: exit 0
node scripts/check-empty-changeset.mjs --base origin/main :: exit 0
node scripts/check-empty-changeset.mjs --self-test :: exit 0
node scripts/check-engine-split-ratio.mjs --self-test :: exit 0
node scripts/check-issue-citations.mjs :: exit 0
node scripts/check-plugin-teardown-shape.mjs --self-test :: exit 0
node scripts/check-plugin-teardown-shape.mjs :: exit 0
node scripts/check-sdui-manifest.mjs --self-test :: exit 0
node scripts/check-sdui-manifest.mjs :: exit 0
node scripts/check-section-landing-index.mjs --self-test :: exit 0
node scripts/check-section-landing-index.mjs :: exit 0
node scripts/ci/assert-turbo-remote-cache.mjs --self-test :: exit 0
node scripts/ci/plan-test-core-shards.mjs --self-test :: exit 0
node scripts/ci/prune-turbo-cache.mjs --self-test :: exit 0
node scripts/docs-audit/check-affected-docs.mjs :: exit 0
node scripts/docs-audit/check-drift-comment.mjs :: exit 0
node scripts/pm/release-rehearsal-clone.mjs --self-test :: exit 0
node scripts/release-pending-publish.mjs --self-test :: exit 0
pnpm --dir ui exec vitest run scripts/ :: exit 0
pnpm --filter @objectstack/lint run check:doc-formula-expressions :: exit 0
pnpm --filter @objectstack/lint run check:doc-security-posture :: exit 0
pnpm --filter @objectstack/spec run check:api-surface :: exit 0
pnpm --filter @objectstack/spec run check:authorable-surface :: exit 0
pnpm --filter @objectstack/spec run check:browser-reachable-entries :: exit 0
pnpm --filter @objectstack/spec run check:docs :: exit 0
pnpm --filter @objectstack/spec run check:dual-source-exports :: exit 0
pnpm --filter @objectstack/spec run check:duration-unit-keys :: exit 0
pnpm --filter @objectstack/spec run check:empty-state :: exit 0
pnpm --filter @objectstack/spec run check:entry-nameability :: exit 0
pnpm --filter @objectstack/spec run check:export-origins :: exit 0
pnpm --filter @objectstack/spec run check:exported-any :: exit 0
pnpm --filter @objectstack/spec run check:generated :: exit 0
pnpm --filter @objectstack/spec run check:liveness :: exit 0
pnpm --filter @objectstack/spec run check:llms-txt :: exit 0
pnpm --filter @objectstack/spec run check:skill-examples :: exit 0
pnpm --filter @objectstack/spec run check:skill-refs :: exit 0
pnpm --filter @objectstack/spec run check:strictness-ledger :: exit 0
pnpm --filter @objectstack/spec run check:variant-docs :: exit 0
pnpm --filter @objectstack/spec run check:yaml-examples :: exit 0
pnpm check:changeset-gate-self-tests :: exit 0
pnpm check:ci-filter-parity :: exit 0
pnpm check:closed-ceremony-text :: exit 0
pnpm check:corpus-claim-drift :: exit 0
pnpm check:cross-package-test-inputs :: exit 0
pnpm check:dispatcher-error-vocabulary :: exit 0
pnpm check:doc-anchors :: exit 0
pnpm check:doc-authoring :: exit 0
pnpm check:doc-frontmatter :: exit 0
pnpm check:docs-audit-scope :: exit 0
pnpm check:docs-redirects :: exit 0
pnpm check:docs-single-h1 :: exit 0
pnpm check:docs-spec-enumerations :: exit 0
pnpm check:docs-transcript-drift :: exit 0
pnpm check:driver-memory-census :: exit 0
pnpm check:dts-closure :: exit 0
pnpm check:dual-build-cjs-loads :: exit 0
pnpm check:durability-log-level :: exit 0
pnpm check:engine-double-contract :: exit 0
pnpm check:gitlink-declared :: exit 0
pnpm check:i18n :: exit 0
pnpm check:issue-citations :: exit 0
pnpm check:keyed-text-bounds :: exit 0
pnpm check:lean-entry-closure :: exit 0
pnpm check:logger-receiver-detach :: exit 0
pnpm check:merge-driver :: exit 0
pnpm check:nul-bytes :: exit 0
pnpm check:objectql-double-limit :: exit 0
pnpm check:org-identifier :: exit 0
pnpm check:page-declaration-shape :: exit 0
pnpm check:platform-object-tenancy-census :: exit 0
pnpm check:pm-changeset-deadline-census :: exit 0
pnpm check:pm-prior-rulings :: exit 0
pnpm check:published-files :: exit 0
pnpm check:published-readme-links :: exit 0
pnpm check:query-options-erasure :: exit 0
pnpm check:react-page-adapter-contract :: exit 0
pnpm check:refd-timer-probe :: exit 0
pnpm check:registry-log-declared :: exit 0
pnpm check:rest-log-spy-declared :: exit 0
pnpm check:role-word :: exit 0
pnpm check:skill-identifier-liveness :: exit 0
pnpm check:slot-lookup :: exit 0
pnpm check:sourcemap-no-sources-content :: exit 0
pnpm check:spec-docblock-symbol-anchors :: exit 0
pnpm check:spec-parsed-alias :: exit 0
pnpm check:system-context-census :: exit 0
pnpm check:test-source-alias :: exit 0
pnpm check:tier-file-adoption :: exit 0
pnpm check:type-check-coverage :: exit 0
pnpm check:type-check-debt :: exit 0
pnpm check:undeclared-dep-imports :: exit 0
pnpm check:vendor-version-stamps :: exit 0
pnpm check:watch-hint-literal :: exit 0
pnpm check:where-matcher :: exit 0
```
</details>
Dogfood: not run — no `!` in the title and the `Clause-②:` arm is
`(widening)`, not `(narrowing)`.
---
_Generated by [Claude
Code](https://claude.ai/code/session_01WGufzh4Bxv1fXaUEeGaKDn)_
---------
Co-authored-by: Claude <noreply@anthropic.com>1 parent 7538f27 commit fbb8bec
23 files changed
Lines changed: 253 additions & 45 deletions
File tree
- .changeset
- content/docs
- data-modeling
- references
- data
- system
- ui
- packages
- objectql/src
- spec
- api-surface
- export-origins
- src/data
- skills/objectstack-data/rules
- ui/packages
- app-shell/src/views
- approval-decision
- metadata-admin/inspectors
- i18n/src/namespaces/studio
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
712 | 712 | | |
713 | 713 | | |
714 | 714 | | |
715 | | - | |
| 715 | + | |
716 | 716 | | |
717 | 717 | | |
718 | 718 | | |
| |||
729 | 729 | | |
730 | 730 | | |
731 | 731 | | |
732 | | - | |
733 | 732 | | |
734 | 733 | | |
735 | 734 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
87 | 87 | | |
88 | 88 | | |
89 | 89 | | |
90 | | - | |
| 90 | + | |
91 | 91 | | |
92 | 92 | | |
93 | 93 | | |
| |||
228 | 228 | | |
229 | 229 | | |
230 | 230 | | |
231 | | - | |
| 231 | + | |
232 | 232 | | |
233 | 233 | | |
234 | 234 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
265 | 265 | | |
266 | 266 | | |
267 | 267 | | |
268 | | - | |
| 268 | + | |
269 | 269 | | |
270 | 270 | | |
271 | 271 | | |
| |||
628 | 628 | | |
629 | 629 | | |
630 | 630 | | |
631 | | - | |
| 631 | + | |
632 | 632 | | |
633 | 633 | | |
634 | 634 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
99 | 99 | | |
100 | 100 | | |
101 | 101 | | |
102 | | - | |
| 102 | + | |
103 | 103 | | |
104 | 104 | | |
105 | 105 | | |
| |||
530 | 530 | | |
531 | 531 | | |
532 | 532 | | |
533 | | - | |
| 533 | + | |
534 | 534 | | |
535 | 535 | | |
536 | 536 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
618 | 618 | | |
619 | 619 | | |
620 | 620 | | |
621 | | - | |
| 621 | + | |
622 | 622 | | |
623 | 623 | | |
624 | 624 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
39 | 39 | | |
40 | 40 | | |
41 | 41 | | |
42 | | - | |
43 | | - | |
| 42 | + | |
| 43 | + | |
| 44 | + | |
| 45 | + | |
| 46 | + | |
| 47 | + | |
44 | 48 | | |
45 | 49 | | |
46 | 50 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
62 | 62 | | |
63 | 63 | | |
64 | 64 | | |
| 65 | + | |
| 66 | + | |
| 67 | + | |
| 68 | + | |
| 69 | + | |
| 70 | + | |
| 71 | + | |
65 | 72 | | |
66 | 73 | | |
67 | 74 | | |
| |||
0 commit comments