Repository navigation
Commit 0e2ebce
docs(protocol): the batch cap is embedder-only, not “configurable via maxBatchSize” — the fourth carrier, plus the fifth-carrier enumeration (#18737)
Fixes #17183
## What this lands
`content/docs/protocol/kernel/http-protocol.mdx`, in the batch
endpoint's **Behavior** list, told the reader the 200-operation cap is
*"configurable via `maxBatchSize`"* with no statement of who may write
it. That claim was ruled false on 2026-09-07 (director seat, summon #17,
decision batch #2, maintainer verbatim 「同意」) and has already been
corrected on three carriers (#15543 / PR #16775; #16801; #16940). This
page was the fourth.
No fifth wording was invented. The landed vocabulary is **compressed**
into this page's terse bullet register rather than pasted from
`data-api.mdx`'s running prose — that compression is the one piece of
writing judgement the card asked for.
```
- Maximum batch size: **200** operations. The cap is `batch.maxBatchSize`, and it
is **embedder-only** (#15543): it is written only by a host that constructs the
`RestServerConfig` itself, never by `os serve` or the dev plugin, so a
CLI-started deployment always gets the default of 200. Over the cap is
`400 BATCH_TOO_LARGE`, carrying the `count` sent and the `max` allowed. ...
```
The `1..1000` range is deliberately not carried over: it is detail for
the embedding host, it lives on the generated reference page, and the
correction does not need it. Citing `(#15543)` matches this page's
existing convention (9 issue citations already).
## Zone-2 assumptions, re-taken on `objectstack-ai/objectstack` @
`080688b56`
| assumption | verdict |
|:--|:--|
| the sentence still reads verbatim as filed (located by **content**,
not line number) | **holds** — sole occurrence, at `:851` |
| `grep -rl maxBatchSize content/docs` reaches 9 files
(probe-reaches-the-tree control) | **holds** — 9 |
| the card body reads complete, not truncated | **holds** — ends at its
`## Refs` list |
## Triage's first question: does a fifth carrier exist?
**Yes — two, and one of them is a live source file that every previous
sweep walked past.**
Answered by enumeration, not impression. **Spellings used**, so the
coverage can be judged rather than taken on faith:
| # | spelling | population |
|:--|:--|:--|
| 1 | `max[._-]?batch[._-]?size`, case-insensitive | whole tracked tree
minus `content/**` |
| 2 | literal `deployment policy`, case-insensitive | whole tracked tree
|
| 3 | `` raise `batch.maxBatchSize` `` | whole tracked tree |
| 4 | proximity `batch.{0,40}configur` / `configur.{0,40}batch`,
case-insensitive | whole tracked tree |
Spelling 1 is deliberately wider than the census token that let the
fourth carrier survive three sweeps: the census positive token was
`batch.maxBatchSize` and this page spelled the key bare, so a probe
written over one spelling of a claim under-counted by exactly that
difference. Spellings 2 and 4 are there because a carrier need not name
the key at all — and spelling 2 is what actually found the fifth.
Spelling 1 reaches **29 files** outside `content/`. Adjudicated:
- **Not carriers, different key entirely** (9 files):
`packages/plugins/plugin-audit/**` (`readAudit.maxBatchSize`, the
read-audit flush buffer) · `packages/spec/src/system/tracing.*` (OTel
batch span processor) · `packages/spec/src/api/contract.*` (DataLoader)
· `docs/qa/platform-checklist/areas/access-security.json` (the audit
flush window).
- **Not carriers, already correct**:
`packages/spec/src/api/rest-server.zod.ts` (the `WHO CAN WRITE THIS
CONFIG` header) · `packages/rest/src/rest-server.ts#enforceBatchSize`
(corrected under #16801) · `packages/spec/liveness/batch_endpoints.json`
and `liveness/README.md` (per-key `REACHABILITY` sentences) ·
`docs/qa/platform-checklist/FOLLOW-UPS.md` row E2 and
`areas/api-backend.json` (which speak of *construction*: "harness:
construct with `{ batch: { maxBatchSize: 5 } }`").
- **Not carriers, no who-writes claim**: the six test files, the three
generated `authorable-surface` / `authorable-defaults` inventories, and
the migration registry entries — all name the key without asserting
anything about who may write it.
### Fifth carrier A — a live source file,
`packages/spec/src/api/batch.zod.ts:128`
```
// [#3939] No `.max()` here: the batch-size cap is DEPLOYMENT policy
// (`RestServerConfig.batch.maxBatchSize`, 1..1000, default 200), enforced at
// the route so one place decides it.
```
That is **the same phrase, verbatim**, that #16801 struck from
`packages/rest/src/rest-server.ts#enforceBatchSize`, whose docblock now
reads *"Reachability: EMBEDDER-ONLY (#15543, #16801). ⛔ It is NOT
deployment policy — this docblock said exactly that until #16801"*. The
twin survived in `batch.zod.ts`, in the same package whose file header
carries the corrected contract.
**Why every sweep missed it, measured:** the `deployment policy` probe
recorded in `FOLLOW-UPS.md` E2 was scoped to the single file
`packages/spec/src/api/rest-server.zod.ts` (with `maxBatchSize`'s 3 hits
there as its control), and the `maxBatchSize` censuses were scoped to
`content/`. `batch.zod.ts` is in neither population — a file-scoped
phrase probe and a tree-scoped token probe, and the carrier sat in the
gap between them.
⛔ **Not repaired here.** The dispatch fences the file surface to
`content/docs/protocol/kernel/http-protocol.mdx`, and editing
`packages/spec` opens the eight-artifact regeneration family — a new
verification surface, so the in-place-repair exemption does not hold. It
is reported for its own card, in `domain:spec`.
### Fifth carrier B — the published changelog text,
`packages/*/CHANGELOG.md`
The 17.0.0 entry carries the claim in its **strongest** form found
anywhere in the tree, and it carries it to npm:
- *"Batch size is deployment policy —
`RestServerConfig.batch.maxBatchSize`, 1..1000, default 200"* —
`packages/rest/CHANGELOG.md` ×2, `packages/spec/CHANGELOG.md` ×2
- *"Deployments that were quietly relying on unbounded batches should
raise `batch.maxBatchSize` (up to 1000) rather than discover the cap in
production."* — `packages/rest/CHANGELOG.md` ×2,
`packages/spec/CHANGELOG.md` ×2
That second sentence does not merely call the cap configurable; it
instructs deployments to raise it. AGENTS.md names
`packages/*/CHANGELOG.md` RELEASE-OWNED and says a factual error in a
released entry is amended in a **dedicated docs-only PR**, ⛔ never a
rider on code changes and ⛔ never an erratum in a later entry — and a
later entry is exactly what exists today:
`packages/spec/CHANGELOG.md:3581` already records the correction, while
the 17.0.0 entry an upgrading agent greps still carries the claim. ⛔
**Not repaired here**; reported for its own card.
### Where a fifth carrier is *not*
`examples/**` and root-level `*.md` were swept with all three spellings
and hold **zero** carriers — zero against the same probes that return 38
files tree-wide, so these are real zeros, not dead probes. The two
`deployment policy` hits under `examples/` are about flow scheduling, a
different subject.
## Triage's second question: could anything pin the claim to the actual
cap?
**One sentence: nothing today can, because the reachability fact exists
only as free prose — the `REACHABILITY` text inside the `note` string of
`packages/spec/liveness/*_endpoints.json` and the docblocks — with no
structured field and no gate that reads it, so a pin would first have to
promote `embedder-only` to a machine-readable per-key value and only
then could a prose gate hold every mention honest.**
Measured, not assumed: `REACHABILITY` appears in six liveness ledgers as
prose inside `note`; the three `scripts/**` hits for the word
(`check-dispatcher-error-vocabulary.mjs`, `check-half-states.mjs`,
`bare-root-worklist.mjs`) are unrelated uses in comments. Nothing
consumes it.
The shape such a pin would take already exists as a precedent:
`scripts/check-docs-spec-enumerations.mjs` (#17388) holds hand-written
prose equal to a derived set, and its own header states this card's
whole problem —
> Prose is where the class hides, because nothing reads it.
⛔ Not built here, per the dispatch.
## Report items, deliberately not in this diff
1. `content/docs/releases/v17/17-0.mdx:1734` — the claim once more, on
the RELEASE-OWNED tree. Named by the card; a dedicated docs-only PR or
its own card, never a rider.
2. Fifth carrier A — `packages/spec/src/api/batch.zod.ts:128`.
3. Fifth carrier B — `packages/rest/CHANGELOG.md` and
`packages/spec/CHANGELOG.md`.
4. `content/docs/references/api/**` is AUTO-GENERATED and untouched;
`rest-server.mdx:287` already carries the corrected wording.
## Verification
**Changeset: `skip-changeset`, measured.** `content/docs/**` appears in
no published package's `files[]`, and its only owner `@objectstack/docs`
is `private: true`. Positive control: `@objectstack/spec` and
`@objectstack/rest` are published and do declare `files[]` arrays,
neither of which lists `content/`. Nothing published moves.
**Gates: 39 derived, 39 run, 39 green.** Derived with `node
scripts/pm/dispatch-gates.mjs --commands --repo
objectstack-ai/objectstack` (three-dot change set vs merge base
`080688b56`), reconciled with `--ran`: *"39 derived, 39 run, 0
NOT-MEASURED, 0 UNRUN"*. Exit codes captured before any pipe.
Five refused on the first pass with **PREREQUISITE NOT MET** — not
findings, and nothing was measured by them:
`check:doc-formula-expressions` (3), `check:doc-security-posture` (3),
`check:docs-transcript-drift` (3), `check:docs` (1,
`packages/spec/json-schema` missing), `check:skill-examples` (1, no
`.d.ts` in `dist`). All five were re-run to a real verdict after
building `@objectstack/spec`, `@objectstack/lint`,
`@objectstack/formula`, `@objectstack/client` and
`@objectstack/client-react` under the shared verify lock (`VERDICT
command-exit 0`, two laps). Final reading on the built tree: **all 39
exit 0**, including `check:nul-bytes`, `check:doc-authoring`,
`check:doc-anchors`, `check:docs-single-h1` and
`check:docs-spec-enumerations`.
Note for the record: `check:cross-package-test-inputs` is carded as
reddening on a **built** worktree (#18348). It did **not** reproduce
here — exit 0 both before and after the build, with
`packages/spec/dist/*.d.ts` present on the second reading. Reported as a
non-reproduction, ⛔ not filed as anything new.
**Repo-wide scans** (`pnpm lint` and the artifact-roster /
wide-population families `dispatch-gates` prints outside the derived
total) are CI-owned and are not claimed here.
**Firing controls**, per the standing rule that a control must read 0
inside the diff and be present in the probed file:
| term | in diff | in file | role |
|:--|--:|--:|:--|
| `embedder-only` | 1 | 1 | firing |
| `batch.maxBatchSize` | 1 | 1 | firing |
| `BATCH_UNRESOLVED_REF` | 0 | 1 | control ✅ |
| `maxDepth` | 0 | 1 | control ✅ |
| `BATCH_NOT_ATOMIC` | 1 | 1 | ⛔ rejected — it appears in the diff's
context lines, so it is not a control |
**Control bytes:** `grep -naP` over the touched file for the C0 range
plus DEL returns no match.
## Acceptance notes
- noted, not filed: `content/docs/protocol/kernel/http-protocol.mdx:543`
carries a structurally identical sentence for a different knob —
*"Maximum expand depth: 3 levels by default (configurable via the query
adapter's `maxDepth`)"*. It is **not** in this card's defect class: no
ruling has been taken on `maxDepth`'s reachability, so calling it a
carrier would be inventing an adjudication rather than applying one.
Recorded because the next reader of this page will see the same shape
two screens up, and because it is the natural second subject for the pin
described above. Successor: whoever takes fifth carrier A, since
`maxDepth`'s reachability question is the same measurement on a
different key.
---
🤖 Generated with [Claude Code](https://claude.com/claude-code)
https://claude.ai/code/session_017ef78bLdybu3AffehKkhfk
---
_Generated by [Claude
Code](https://claude.ai/code/session_017ef78bLdybu3AffehKkhfk)_
Co-authored-by: Claude <noreply@anthropic.com>1 parent 0f10c65 commit 0e2ebce
1 file changed
Lines changed: 7 additions & 4 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
848 | 848 | | |
849 | 849 | | |
850 | 850 | | |
851 | | - | |
852 | | - | |
853 | | - | |
854 | | - | |
| 851 | + | |
| 852 | + | |
| 853 | + | |
| 854 | + | |
| 855 | + | |
| 856 | + | |
| 857 | + | |
855 | 858 | | |
856 | 859 | | |
857 | 860 | | |
| |||
0 commit comments