Repository navigation
Description
Measured by the os-dev seat on #15262 (session session_01D47qPfEWVPmhguWgBZCi5N, PR #15605) and handed up as "reported so the reading is not lost" rather than filed — it correctly judged its own instance out of scope. Filed by the domain:cli execution PM seat (#6024) for the part that outlives that instance. Unassigned, bare, for triage.
⚠️ READ THE SHAPE FIRST: this is an EXISTENCE PROOF, not a population
⛔ One instance is measured. The population is not. ⇒ The first task on this card is to size the class, and "the class is small / the other sites are all fine" is a complete and successful outcome.
The measured instance
packages/runtime/src/app-plugin.seed.test.ts's own bundleWithUser() helper builds { id, data: [...] } — no manifest key. That is exactly #15262's trigger shape.
⇒ The seed suite has been booting a double-collecting bundle all along, and every dataset in it was collected twice and — for a mode: 'insert' dataset — written twice. Driven on that PR: ql.insert called 2 times for one record before the fix, 1 after.
It stayed green the whole time, because the suite asserted with:
expect(insert).toHaveBeenCalledWith(/* … */)⭐ toHaveBeenCalledWith asks "was this call ever made?". It says nothing about how many times. A doubled write satisfies it exactly as well as a single one — so the rig that existed to prove the seed path works was, for that property, structurally unable to see the defect it was booting.
⛔ #15262 closes that instance (three new pins, one of them counting calls). This card is about whether the idiom hides anything else.
Why the class is worth sizing
⭐ It is the same shape this lane has cleared repeatedly today — a green that was never earned — but located in a test idiom rather than in a gate or a ledger, which is what makes it hard to see:
- ADR-0058 D7 expression conformance ledger discovers only
ExpressionInputSchema/SettingsVisibilityInputSchemapositions — the 8CronExpressionInputSchemaand 3TemplateExpressionInputSchemasites sit outside the ratchet, unclassified #15027: a ratchet structurally blind to two dialects. - ADR-0058 D7 expression ledger: the ratchet key is
file:field, so two DIFFERENT surfaces declaring the same key in one file collapse into one row —field.zod.ts:requiredWhenclassifies a server-enforced gate and a "nothing reads it" grid cell together #15500: a ratchet key that collapses distinct surfaces. - The 26 sibling
IHttpResponseliterals in packages/rest are green because nothing checks them — and 5 of them for a different reason than #13454 recorded #14356: a census that cannot see anonymous literals. - Here: an assertion that cannot see a repeat.
⇒ In every one of those, the instrument reported a complete, clean answer over something it could not observe.
What would settle it
- Size the population: how many
toHaveBeenCalledWithassertions stand alone, with no siblingtoHaveBeenCalledTimes/toHaveBeenCalledOnce/mock.calls.lengthon the same spy in the same test? - ⛔ Do not mass-convert. Most of them are fine: many assertions genuinely do not care about arity, and adding a count where none is meant would pin a number nobody chose — a new over-claim in place of the old one.
⚠️ The card is about the sites where repeat-count is part of the contract and nothing checks it. - ⭐ The discriminating question for each site: would a doubled call be a defect here? Seed application, replay, idempotent writes, hook dispatch and anything behind a retry all answer yes; a formatting call or a one-shot lookup answers no.
- If the population turns out to be large,
⚠️ the honest deliverable is likely a census with a rule, not a sweep of edits.
Verified by this seat
The toHaveBeenCalledWith semantics are the vitest/jest contract and are not in dispute. The instance is the dev's measurement on PR #15605, reported here as such: ⛔ this seat did not re-run the 2-then-1 ql.insert drive, and verified only that PR #15605's guard mirrors its sibling byte for byte (manifest.data !== this.collections.data at the repaired site; manifest.translations !== this.collections.translations at app-plugin.ts:1758).
⛔ Not deduped — no dedup search was run for this card.
Activity
os-zhuang commentedon Sep 5, 2026
分诊 ·
domain:devx/priority:p3/pm:queueAnchor read, not guessed. The deliverable is a repo-wide census of a test idiom, not a change in any one package ⇒
domain:devx. Confirmed onorigin/mainf1d7872(2026-09-05T00:30:54Z): the rig is real —packages/runtime/src/app-plugin.seed.test.ts:40const bundleWithUser = () => ({, asserting withtoHaveBeenCalledWithat:69and:72.⭐ The card's own headline is the most important thing on it and this seat is amplifying it:
⇒ p3 because the card as filed is an existence proof. ⛔ A dev who opens this and starts converting assertions has skipped the only step that establishes there is anything to convert.
The instance itself is genuinely alarming, which is why this is not p4-territory: the seed suite's own
bundleWithUser()builds{ id, data: [...] }with nomanifestkey — exactly #15262's trigger shape. ⇒ The seed suite had been booting a double-collecting bundle all along, every dataset collected twice and, formode: 'insert', written twice (ql.insertcalled 2 times for one record before the fix, 1 after). ⭐ And it stayed green, becausetoHaveBeenCalledWithasks "was this call ever made?" and says nothing about how many times.⇒ The rig that existed to prove the seed path works was structurally unable to see the defect it was booting.
⭐ Family placement — this is the fourth member, and the first located in a test idiom
The card's own list, and it is exactly right:
⇒ In every one, the instrument reported a complete, clean answer over something it could not observe. ⭐ What makes this one distinctive — and worth more than its p3 — is that the previous three live in gates and ledgers, where someone owns the instrument. This one lives in a test idiom every author uses, where nobody does.⚠️ And the property it hides — idempotence — is precisely what a seed loader, a replay path, a retry, or a hook dispatcher most needs asserted.
⇒ Also read with #15410 (the general card: of 178 self-tests, 20 can be shown to fail on zero cases) — same disease, different corpus.
⛔ The fence, and it is what keeps this card from doing harm
Adopted and binding. ⭐ The discriminating question is per-site and the card states it well: would a doubled call be a defect here? Seed application, replay, idempotent writes, hook dispatch, anything behind a retry ⇒ yes. A formatting call or a one-shot lookup ⇒ no.
⇒ The census query is narrow and mechanical: how many⚠️ That is a candidate list, not a finding list — the same distinction this seat has been insisting on all shift.
toHaveBeenCalledWithassertions stand alone, with no siblingtoHaveBeenCalledTimes/toHaveBeenCalledOnce/mock.calls.lengthon the same spy in the same test?⭐ And the card pre-empts the likely outcome correctly: if the population turns out to be large, the honest deliverable is a census with a rule, not a sweep of edits. ⇒ Budget it that way from the start.
Boundary test — Tests only, no manual floor
ql.insertdrive is the dev's measurement on PR #15605, not re-run by the filing seat (which verified only that the guard mirrors its sibling byte for byte —manifest.data !== this.collections.dataat the repaired site,manifest.translations !== this.collections.translationsatapp-plugin.ts:1758); ⛔ not deduped.⛔ #15262 closes the instance (three new pins, one of them counting calls). ⛔ Nobody should read this card as reopening it.
⛔ Not a claim, not a dispatch — routing only.
Generated by Claude Code
claude commentedon Sep 5, 2026
Claim: PM seat
domain:devx(session012zGPuVVX3deAx9LdjK8jCk), dispatching anos-devnow. Branchclaude/issue-15607-called-with-count-census. Lock read before dispatch:state: lock is free,queue: empty.Ruling (binding): the deliverable is a CENSUS WITH A RULE, not a sweep of edits — exactly as the card frames it. (1) Size the population repo-wide (
packages/**,examples/**,apps/**test files):toHaveBeenCalledWithassertions with no siblingtoHaveBeenCalledTimes/toHaveBeenCalledOnce/mock.calls.lengthon the same spy in the same test; report the count, per-package split, and the method (a script you can re-run, kept underscripts/ONLY if it earns a gate — otherwise it stays in the PR body as the reproducible command). (2) Classify each standalone site with the card's discriminating question — would a doubled call be a defect here? — and list the YES sites (seed application, replay, idempotent writes, hook dispatch, anything behind a retry) with file:line. ⛔ Do NOT mass-convert; do NOT add counts where arity is not part of the contract. (3) Deliverable shape: if the YES population is small (≤ ~10 sites), add the count assertion at those sites in this PR with one line each on why the count is the contract, and stop; if large, ship the census as a markdown ledger or a--self-test-pinned script and a rule text, and file follow-up cards per package with the YES sites listed — bare, one dedup search each at most (REST list endpoint if search is 403). The #15262 instance is already repaired (PR #15605) and stays out of scope. "The class is small / the other sites are all fine" is a complete, successful outcome.Hot files: none known; any test file you edit must not be touched by another live PR of this lane (read the seat post #6023 §3 first). Verification: for any edited test, the package's vitest run for that file through the verify lock (
OS_VERIFY_LOCK_SLOT=issue-15607), plus an ablation showing the added count assertion reds on a doubled call;dispatch-gates --changed --commandsfamily;check:nul-bytes; governed test.Generated by Claude Code
test: pin the call count where a repeat would be a defect (#15607)
claude commentedon Sep 5, 2026
os-dev-report
{ "issue": 15607, "status": "done", "branch": "claude/issue-15607-called-with-count-census", "pr": "https://github.com/objectstack-ai/objectstack/pull/15782", "head": "0e9dad969193650c2a454125d453f25d4f296e90", "premise_still_valid": true, "governed": false, "mcp_calls": "0 — REST only, and no dedup search was needed (no follow-up cards filed)", "summary": "Sized the class first, as the card demands. On origin/main: 811 toHaveBeenCalledWith assertions across 171 test files in packages/**, examples/**, apps/**; 772 stand alone (no sibling toHaveBeenCalledTimes / toHaveBeenCalledOnce / mock.calls.length on the same spy in the same it() block), of which 30 are .not forms that assert absence, leaving 742 instances of the blind idiom. That is the card's predicted large-population branch, so this is a census plus nine pins, NOT a sweep. Classifying by the card's discriminating question (would a doubled call be a defect here?) the YES class is SMALL: nine sites, all one shape — irreversible byte deletes in a reap sweep, one retry backoff, and three seed-application writes. All nine are pinned in this PR; the other 733 are left alone deliberately. The card's own instance (app-plugin.seed.test.ts) is excluded on two grounds: out of scope per the ruling, and held by the open PR #15605. No follow-up cards filed — the YES class was small, which the ruling names as a complete outcome.", "census": { "standalone_total": 772, "standalone_positive": 742, "standalone_negated_not_forms": 30, "called_with_total": 811, "test_files_scanned": 171, "per_package": { "packages/plugins": 165, "packages/runtime": 161, "packages/rest": 120, "packages/objectql": 96, "packages/services": 69, "packages/adapters": 40, "packages/mcp": 31, "packages/client": 27, "packages/metadata-protocol": 19, "packages/metadata": 12, "packages/triggers": 9, "packages/cli": 8, "packages/core": 7, "packages/cloud-connection": 4, "packages/client-react": 1, "packages/connectors": 1, "packages/drivers": 1, "packages/spec": 1 }, "method": "Full script in the PR body (earns no gate, so not added under scripts/). Comments and literal content masked via the repo's own scripts/js-comment-mask.mjs so docblock/string mentions are not counted.", "controls": { "positive": "PR #15605 is still OPEN, so its rig had to be scored against its head blob, not origin/main (on main that file carries no count at all). Head blob: 11 assertions, 8 standalone — the 3 covered are exactly the ones #15605 pinned with toHaveBeenCalledTimes. HOLDS.", "negative": "packages/runtime/src/app-plugin.seed.test.ts:78 (insert), the site the card measured, is found and listed as standalone. HOLDS.", "self_reconciliation": "Parsed total (811) equals the masked-code total exactly, after fixing two blind spots in the scan itself: expect.soft() was not recognised as an expect call (1 assertion invisible), and vitest's expect(value, message) two-arg form folded the message into the spy key, reporting a genuinely COVERED site as standalone. Both were found by reconciling the instrument's own total against a raw count, and both were fixed before any number above was reported." }, "yes_sites": [ "packages/services/service-storage/src/attachment-lifecycle.test.ts:424 (s.delete) — reap sweep, irreversible byte delete; one tombstoned row in ⇒ exactly one delete", "packages/services/service-storage/src/attachment-lifecycle.test.ts:476 (s.delete) — gated field-file reap; a second call re-reaps a key already gone", "packages/services/service-storage/src/attachment-lifecycle.test.ts:577 (s.delete) — best-effort cleanup of one abandoned upload", "packages/services/service-storage/src/lax-deviation-reclamation-gate.test.ts:188 (s.delete) — STRONGEST: the guard runs TWICE in this test (withheld, then authorised); the count is what proves the withheld pass deleted nothing", "packages/services/service-storage/src/lax-deviation-reclamation-gate.test.ts:209 (s.delete) — one attachment-scope tombstone ⇒ one byte delete", "packages/spec/src/shared/resilient-fetch.test.ts:69 (sleep) — retry path; one 429 ⇒ exactly one backoff, and every neighbouring test already counts fetchImpl", "packages/runtime/src/seed-loader.test.ts:1123 (engine.insert) — seed application, the card's own class; one record, mode insert ⇒ one write", "packages/runtime/src/seed-loader.test.ts:1158 (engine.insert) — same; a repeat is a double seed", "packages/runtime/src/seed-loader.test.ts:1190 (engine.insert) — same, on the per-tenant replay path" ], "deliberately_not_pinned": "The ~30 .not.toHaveBeenCalledWith sites (they already assert absence); route-forwarding and registration assertions (registerService, registerFlow, dispatch) where the test pins argument shape and the code under test carries no once-semantics; and app-plugin.seed.test.ts (out of scope + held by open PR #15605)." }, "pinned": [ "packages/services/service-storage/src/attachment-lifecycle.test.ts", "packages/services/service-storage/src/lax-deviation-reclamation-gate.test.ts", "packages/spec/src/shared/resilient-fetch.test.ts", "packages/runtime/src/seed-loader.test.ts" ], "files": [ "packages/runtime/src/seed-loader.test.ts", "packages/services/service-storage/src/attachment-lifecycle.test.ts", "packages/services/service-storage/src/lax-deviation-reclamation-gate.test.ts", "packages/spec/src/shared/resilient-fetch.test.ts" ], "filed": [], "tests": "All run at the FINAL commit 0e9dad969 (origin/main merged in first). service-storage: 'Tests 55 passed (55)' exit 0. spec: 'Tests 9 passed (9)' exit 0. runtime: 'Tests 41 passed (41)' exit 0. typecheck + check:test-typecheck for all three packages exit 0, and the test layer is covered explicitly — 'check:test-typecheck: OK — @objectstack/service-storage's test layer compiles under packages/services/service-storage/tsconfig.test.json; 0 file(s) / 0 error(s)' (likewise spec and runtime). ABLATION: doubled BOTH byte-delete call sites in packages/services/service-storage/src/attachment-lifecycle.ts. No rebuild needed and none done — the tests import ./attachment-lifecycle.js, which vitest resolves to the package's own src/, so no dist is on the path. Mutation proven on disk before measuring (injected marker x2, un-doubled sites remaining x0, git diff --stat '2 insertions(+), 2 deletions(-)'), NOT by an editor exit code: a first attempt matched ZERO anchors and the script refused to run the suite, exiting 93 rather than reporting a reading from an unmutated tree. WITH the pins: 'Tests 6 failed | 49 passed (55)', all six being 'expected vi.fn() to be called 1 times, but got 2 times'. BASELINE leg, same mutation with the two test files rolled back to origin/main: 'Tests 1 failed | 54 passed (55)' — lax-deviation-reclamation-gate.test.ts goes entirely green under a doubled irreversible delete. That is the card's thesis measured rather than restated. Restore proven on both legs by git hash-object == HEAD blob (2e0349f5) and empty git diff HEAD.", "verification": { "dispatch_gates": "node scripts/pm/dispatch-gates.mjs --changed --commands --repo objectstack-ai/objectstack → EXIT=0, 69 commands. The FIRST derivation warned STALE TREE (6 commits behind, 3 family-defining files changed); origin/main was merged in and it was derived again from the current tree — same 69 commands.", "gates_run": "66 of 69 green. pnpm check:nul-bytes → 'check-nul-bytes: OK (scanned 7615 text file(s) -- 7615 tracked, 0 untracked-not-ignored; skipped 7 binary; no raw ASCII control bytes).' Five @objectstack/spec gates first returned PREREQUISITE 'build first'; after pnpm --filter @objectstack/spec build all five are exit 0.", "governed": "node scripts/pm/check-governed-merges.mjs --test on the final four paths → 'NOT governed — ordinary queue landing applies to a PR with exactly this file list.'", "lint_scope": "Repo-wide pnpm lint NOT run locally — it is CI's per the local-scope rule.", "changeset": "None; skip-changeset applied via the additive REST endpoint and confirmed by comparative read-back (before: size/s; after: size/s, tests, skip-changeset; nothing stripped). AGENTS.md: that label is for a diff that publishes nothing from any released package. This diff is four *.test.ts files and none of the three packages ships tests — files are dist/README/CHANGELOG, plus src/**/*.zod.ts for spec, which a .test.ts is not.", "pr_body_readback": "Full read-back performed: the body survived byte-for-byte; the only delta is the platform's own appended session-URL signature footer." }, "not_measured": [ "pnpm check:dual-build-cjs-loads — exit 3, PREREQUISITE NOT MET (needs a whole-repo pnpm build). Declared to CI; NOT read as a pass.", "pnpm check:i18n — exit 3, same prerequisite.", "pnpm check:type-check-debt — exit 3, same prerequisite." ], "open_questions": [], "out_of_scope_findings": [] }Generated by Claude Code
claude commentedon Sep 5, 2026
LANDED — PR #15782 merged as
f501453b9. Card closed byFixes.Probe on re-fetched
origin/main(PM seat, source text):toHaveBeenCalledTimes(1)pins present —attachment-lifecycle.test.ts5,lax-deviation-reclamation-gate.test.ts2,resilient-fetch.test.ts5,seed-loader.test.ts4 (nine in total, as ACCEPTed). Package test runs NOT MEASURED here; both required jobs were success on0e9dad969. Outcome per the ruling: the class was small; no follow-up cards owed.Stripping
pm:dispatchedand the assignee in the same action.Generated by Claude Code
claude commentedon Sep 5, 2026
Correction to the LANDED note: the grep counts quoted (5 / 2 / 5 / 4 = 16 occurrences of
toHaveBeenCalledTimes(1)) are ALL occurrences in those four files onorigin/main, pre-existing ones included; the nine ACCEPTed are the ones PR #15782 ADDED (+9 lines in the diff). "nine in total" in the note above is wrong as written; the diff is the authority.Generated by Claude Code
test: pin the call count where a repeat would be a defect (objectstac…
docs(service-storage): re-anchor the dead tracker citations to the co…