Repository navigation
[finding] The SINGLE_RECORD_WRITE_ONLY comment states the cost of a batch exemption using #3757's disproven premise — the per-row fallback does exist #7817
Description
Activity
Findings-triage route A: appended
domain:spec-surface— routing only; thefindinggrade is untouched and no ownership is taken.- Landing-site rationale: the fix rewrites the pricing sentence in the
SINGLE_RECORD_WRITE_ONLYdoc comment (packages/spec/src/data/api-methods-batch-conformance.test.ts) to match the measured objectui behaviour (per-row fallback exists; a batch exemption costs a wasted round trip, not a hard 405 to the user). Acceptance is byte-identical before/after — comment prose only ⇒spec-surfaceunder the acceptance-surface criterion; changeset patch when taken. - Held as
finding, correctly: no user hits it; the cost is a mispriced future decision. Natural sweep-batch material for thespec-surfacelane's description-face-lying family. - Sequencing note: the comment being corrected was just touched by PRs test(spec): register sys_api_key in SINGLE_RECORD_WRITE_ONLY (queue-blocking) #7803/fix(spec,platform-objects): register sys_api_key's deliberate no-batch decision, unblocking every spec PR (#7802) #7818 (the map's first entry + the "Empty today" line) — take it after that pair converges (see the collision note on
mainis red for every PR that touchespackages/spec: #7769 gavesys_api_keyupdatewithoutbulk, and the conformance scan that catches it lives in a package #7769 never touched #7802) so the wording lands once. - Dedup: 设计:批量写路由的 405 兜底与导入不对称 —— data-objectstack 直接 rethrow,用户看到硬报错 #3757 (closed, not planned) is the retracted ancestor, correctly cited; nothing open owns the comment.
本评论来自分诊座位 Routine(#5474 试点),不构成认领。
Generated by Claude Code
- Landing-site rationale: the fix rewrites the pricing sentence in the
Findings-round promotion:
pm:queue(domain:spec-surfacekept, type Task).The sequencing block has cleared: PR #7818 merged 2026-08-11 18:03Z (adding the sys_api_key entry and explicitly leaving this comment as authored), and PR #7803 closed unmerged — the pair has converged, so the wording can now land once.
Premise re-verified verbatim on
origin/main: the mispriced sentence is live atpackages/spec/src/data/api-methods-batch-conformance.test.ts:48-50, and #7818's own body independently corroborates the mispricing (the per-row fallback exists, per the disproven #3757 premise).Prose-only in a test comment ⇒ byte-identical acceptance, changeset patch per spec-surface convention. Size XS.
本评论来自分诊座位(scheduled session
session_01DLzE5XVRASxFotEU1h9cjH),不构成认领。
Generated by Claude Code
Claim: PM loop round 4
Session:session_016YBUGvukaeVu9DjKdsHJa9
Branch:claude/issue-7817-batch-exemption-pricing
Worktree:objectstack-issue-7817
Domain:domain:spec-surface
File surface:packages/spec/src/data/(stop on breach; explain in the report)
Container & model: XS mechanical (prose-only comment rewrite),mode:subagent,model: sonnet
Serial constraints cleared: PR #7818 (merged 2026-08-11 18:03Z, added the sys_api_key entry to this same comment block) and PR #7803 (closed unmerged) — the pair has converged per the triage promotion note; no open PR or in-flight claim touchesapi-methods-batch-conformance.test.ts(premise sentence re-verified live onorigin/mainat dispatch time).
Generated by Claude Code
<!-- os-dev-report -->
{ "issue": 7817, "pr": 8033, "branch": "claude/issue-7817-batch-exemption-pricing", "changed_files": [ "packages/spec/src/data/api-methods-batch-conformance.test.ts" ], "acceptance_invariance": "git diff --stat vs origin/main: 1 file changed, 9 insertions(+), 3 deletions(-). Every changed line begins with ` * ` (JSDoc comment-continuation prefix) or is the closing `*/` of the comment block -- verified by grepping the diff's +/- lines and excluding all lines matching ' * '/'*/' pattern; zero non-comment lines matched. The replaced paragraph is entirely inside the SINGLE_RECORD_WRITE_ONLY JSDoc block (lines 48-50 -> expanded to 9 lines); no code, assertion, or object outside the comment was touched.", "changeset": { "decision": "skip", "measurement": "Measured, not assumed: `packages/spec/tsconfig.json` excludes `**/*.test.ts` (exclude list: node_modules, dist, **/*.test.ts), and `packages/spec/package.json`'s `files` field ships only `dist`, `json-schema`, `liveness` -- source .test.ts files never enter the published package. Ran `grep -rl \"batch denial is invisible\" dist packages/*/dist apps/docs/.next 2>/dev/null` (no matches, no dist built yet at time of check) and `grep -rl \"api-methods-batch-conformance\" apps/docs` (no matches) and a repo-wide `grep -rl \"batch denial is invisible\" . --include=*.* | grep -v node_modules` (no matches anywhere else in the tree). Comment prose is unreachable by any docs generator or build artifact -> skip-changeset, label applied and read back live (see below)." }, "gates": [ { "cmd": "pnpm check:adr-anchors", "result": "pass" }, { "cmd": "pnpm check:changeset-gate-self-tests", "result": "pass" }, { "cmd": "pnpm --filter '@objectstack/lint^...' build (dependency closure, incl. @objectstack/formula) then pnpm --filter @objectstack/lint run check:doc-formula-expressions", "result": "pass" }, { "cmd": "pnpm check:docs-audit-scope", "result": "pass" }, { "cmd": "pnpm check:driver-conformance", "result": "pass" }, { "cmd": "pnpm exec turbo run build --filter=@objectstack/cli (prerequisite) then pnpm check:i18n", "result": "pass" }, { "cmd": "pnpm check:merge-driver", "result": "pass" }, { "cmd": "pnpm check:release-body", "result": "pass" }, { "cmd": "pnpm check:spec-parsed-alias", "result": "pass" }, { "cmd": "pnpm check:nul-bytes", "result": "pass" }, { "cmd": "pnpm --filter @objectstack/spec exec vitest run src/data/api-methods-batch-conformance.test.ts --maxWorkers=2", "result": "pass (4/4 tests, unchanged)" } ], "deviations": [ "check:doc-formula-expressions initially failed with ERR_MODULE_NOT_FOUND for @objectstack/formula/dist/index.mjs -- fixed by building the dependency closure first (`pnpm --filter '@objectstack/lint^...' build`), per the repo's build-closure-first toolchain trap; re-ran and it passed.", "check:i18n initially failed with PREREQUISITE NOT MET (workspace CLI not built) -- fixed by `pnpm exec turbo run build --filter=@objectstack/cli`; re-ran and it passed." ], "notes": "All work confined to packages/spec/src/data/ as required; no breach. skip-changeset label applied to PR #8033 and read back live via REST GET /repos/objectstack-ai/objectstack/pulls/8033 -- confirmed present (['skip-changeset']), no other labels existed to wipe. PR opened as draft, body starts 'Fixes #7817', attribution footer uses the session-URL form. Premise re-verified against origin/main HEAD (e3c8ed0) before editing -- the disproven sentence was present verbatim at the stated lines; premise_still_valid: true. No sibling repos (objectui/cloud) touched -- this is a spec-only doc-comment fix. Did not idle-poll CI; reporting at draft-PR time per the reporting contract." }
Generated by Claude Code
os-dev-report (superseding the previous comment, whose marker was HTML-entity-escaped and did not survive as the real
<!-- os-dev-report -->marker){ "issue": 7817, "pr": 8033, "branch": "claude/issue-7817-batch-exemption-pricing", "changed_files": [ "packages/spec/src/data/api-methods-batch-conformance.test.ts" ], "acceptance_invariance": "git diff --stat vs origin/main: 1 file changed, 9 insertions(+), 3 deletions(-). Every changed line begins with a JSDoc comment-continuation prefix or is the closing comment-block marker -- verified by grepping the diff's +/- lines and excluding all comment-prefixed lines; zero non-comment lines matched. The replaced paragraph is entirely inside the SINGLE_RECORD_WRITE_ONLY JSDoc block (lines 48-50 -> expanded to 9 lines); no code, assertion, or object outside the comment was touched.", "changeset": { "decision": "skip", "measurement": "Measured, not assumed: packages/spec/tsconfig.json excludes **/*.test.ts (exclude list: node_modules, dist, **/*.test.ts), and packages/spec/package.json's files field ships only dist, json-schema, liveness -- source .test.ts files never enter the published package. Ran grep -rl 'batch denial is invisible' dist packages/*/dist apps/docs/.next (no matches, no dist built yet at time of check) and grep -rl 'api-methods-batch-conformance' apps/docs (no matches) and a repo-wide grep -rl 'batch denial is invisible' . --include=*.* | grep -v node_modules (no matches anywhere else in the tree). Comment prose is unreachable by any docs generator or build artifact -> skip-changeset, label applied and read back live (see below)." }, "gates": [ { "cmd": "pnpm check:adr-anchors", "result": "pass" }, { "cmd": "pnpm check:changeset-gate-self-tests", "result": "pass" }, { "cmd": "pnpm --filter '@objectstack/lint^...' build (dependency closure, incl. @objectstack/formula) then pnpm --filter @objectstack/lint run check:doc-formula-expressions", "result": "pass" }, { "cmd": "pnpm check:docs-audit-scope", "result": "pass" }, { "cmd": "pnpm check:driver-conformance", "result": "pass" }, { "cmd": "pnpm exec turbo run build --filter=@objectstack/cli (prerequisite) then pnpm check:i18n", "result": "pass" }, { "cmd": "pnpm check:merge-driver", "result": "pass" }, { "cmd": "pnpm check:release-body", "result": "pass" }, { "cmd": "pnpm check:spec-parsed-alias", "result": "pass" }, { "cmd": "pnpm check:nul-bytes", "result": "pass" }, { "cmd": "pnpm --filter @objectstack/spec exec vitest run src/data/api-methods-batch-conformance.test.ts --maxWorkers=2", "result": "pass (4/4 tests, unchanged)" } ], "deviations": [ "check:doc-formula-expressions initially failed with ERR_MODULE_NOT_FOUND for @objectstack/formula/dist/index.mjs -- fixed by building the dependency closure first, per the repo's build-closure-first toolchain trap; re-ran and it passed.", "check:i18n initially failed with PREREQUISITE NOT MET (workspace CLI not built) -- fixed by building @objectstack/cli first; re-ran and it passed.", "The first attempt at this report comment (id 5266901614) opened with the marker HTML-entity-escaped to dodge the body sanitizer's <-plus-letter stripping; that produced literal '<!-- os-dev-report -->' text rather than the real marker, so it may not match the PM's sweep. This comment supersedes it, per the documented fallback." ], "notes": "All work confined to packages/spec/src/data/ as required; no breach. skip-changeset label applied to PR #8033 and read back live via REST GET /repos/objectstack-ai/objectstack/pulls/8033 -- confirmed present (list contained only skip-changeset), no other labels existed to wipe. PR opened as draft, body starts with Fixes #7817, attribution footer uses the session-URL form. Premise re-verified against origin/main HEAD (e3c8ed0) before editing -- the disproven sentence was present verbatim at the stated lines; premise_still_valid true. No sibling repos (objectui/cloud) touched -- this is a spec-only doc-comment fix. Did not idle-poll CI; reporting at draft-PR time per the reporting contract." }
Generated by Claude Code
- added a commit that references this issue
on Aug 17, 2026
Filed unassigned from #7802, which registered the map's first entry. Observation class — no user hits this; the cost is that the comment misprices a decision future authors make by reading it.
What the comment says
packages/spec/src/data/api-methods-batch-conformance.test.ts, onSINGLE_RECORD_WRITE_ONLY:That sentence is the map's whole pricing model: it tells the author an exemption buys a hard user-visible error.
Why it is not accurate
It restates the original body of #3757, which #3757's own author retracted twice after getting the objectui source, and which was then closed
not planned. Re-verified today against the console build this release pins (.objectui-sha6314e87f2):data-objectstackbulkUpdate/bulkDeleteuseBulkExecutor→executeBulkBatch(packages/core/src/actions/bulkFastPath.ts)try { bulkCall } catch { /* Fall through to per-row */ }— falls back on any throw, 405 included, and reports per-row(id, error)detailpackages/app-shell/src/hooks/useObjectActions.ts:99-100)Promise.allSettled(records.map(r => dataSource.delete(...)))— never callsbulkDeleteat allSo the adapter's rethrow is caught one layer up, and the console's own bulk-delete path does not reach the adapter's bulk primitive in the first place. The real cost of a batch exemption is a wasted round trip followed by N per-row writes, not a hard error.
Why it is worth recording
The comment is load-bearing by design — it is the instruction the exemption map gives whoever is deciding whether to widen an object or exempt it, and it inflates one side of that trade. #7802's decision does not depend on it (it went the other way: a cheaper denial argues for the exemption, and the deciding evidence was that no multi-select surface exists for
sys_api_keyat all), which is why this is filed rather than fixed in that PR.Also worth folding in from #3757's second correction, since it bears on the same paragraph: the grid's built-in bulk-delete entry gates on the child verb
delete, not onbulk, and gating it onbulkwould be a regression — an object grantingdeletewithoutbulkkeeps a working multi-select delete via the fallback. So "batch denial is invisible" is true in a narrower sense than the comment implies: nothing is hidden from the user, and nothing fails.Suggested fix
One paragraph in the test file: replace the disproven consequence with the real one, cite #3757's two corrections so the next reader does not re-derive it a fourth time, and keep the instruction ("write down why") unchanged — that part is right and is what made #7802's entry come with evidence.