Repository navigation
test(dogfood): the persona matrix hangs its invoice lines off an unpaid invoice - #24832
objectstack-fleet[bot] merged 2 commits into
Conversation
…id invoice
The admin payload control created a showcase_invoice_line under
firstId('showcase_invoice'), whichever invoice a limit-1 read returned.
With random ids that is a different invoice on every boot, and several
seeded invoices are paid. Since the showcase locks a paid invoice's lines
(its showcase_guard_paid_invoice_line_* hooks), the control answered 400
"This invoice is paid, so its lines are locked" on some boots and not
others.
The seeded parent is now chosen by the state the lock reads (status not
paid), the way the account above it is chosen by its rule. Every line the
file creates under a seeded invoice hangs off this one parent. The lock is
unchanged.
Claude-Session: https://claude.ai/code/session_01LmjU2x1faLZ39DVTFyVca6
Co-authored-by: Claude <noreply@anthropic.com>
📓 Docs Drift CheckNothing in this diff resolved to a documentable surface (no symbol, route or SDK anchor derived from 0 changed package(s)), so this run has no opinion about the docs. What this run could not see
Coarse fallback — 0 page(s) merely mention a changed package (the pre-#9192 predicate, kept for the deliberately-wide backstop): |
席位核对 · ACCEPT
Accepted deviations:
Out-of-scope dispositions (one line each):
Landing: this is the main-red card's last row in this lane. It goes through the merge queue by this seat once every check on this head reads Generated by Claude Code |
Refs #24780
Clause-②: no
This is row 3 of #24780 (triage pointer
6286191020): the stale fixture inshowcase-crud-persona-matrix.dogfood.test.ts. Row 1 is PR #24805, which landed asc56115bf9. Row 2 belongs to #24749. #24780 remains open: the PM closes it once rows 1 and 3 have both landed.What changes
One fixture line in
packages/qa/dogfood/test/showcase-crud-persona-matrix.dogfood.test.ts, inbeforeAll:seed.invoiceId = await firstId('showcase_invoice'), which takes whichever invoice alimit: 1read returns first.statusis notpaid. That is the state the showcase's paid-invoice line lock reads (theshowcase_guard_paid_invoice_line_*hooks testheader.status === 'paid'). It follows the pattern of the[#18682]account choice directly above it, and the new comment explains why.The lock from PR #24731 is unchanged. This PR changes no case assertion, no other dogfood file, and nothing under
examples/app-showcase/**orpackages/spec/**.Why
showcase_invoice_lineunderseed.invoiceIdand asserts a status below 300. Since PR fix(showcase): a paid invoice's lines can no longer be added, removed or moved, so its total stays what was paid #24731, the showcase refuses a line insert under a paid invoice with a 400: "This invoice is paid, so its lines are locked: a line cannot be added to it."firstIddoes not pick the same invoice each time. Onab9890169I measured three boots. Thelimit: 1read returned INV-1012 (sent), then INV-1008 (sent), then INV-1005 (paid). The ids are random and differ on every boot. The unlimited read returned insertion order every time, with INV-1001 first. The seed holds 12 invoices, and 5 of them are paid. So the control fails on some boots and passes on others.74f78159afwas red in push run 39376439272 and green in schedule run 39378039597. Ona43405d596it was red in schedule run 39384364728. I also read fourmainruns from before576d0f3733, and shard 3/3 was green in all of them.Evidence
Every run used
pnpm --filter @objectstack/dogfood exec vitest run --maxWorkers=2 FILEunderos-verify-lock, after building the closure withturbo run build --filter='@objectstack/dogfood^...'. This file belongs only to theisolatedproject. The gate runsturbo run test --filter=@objectstack/dogfoodwithOS_TEST_SHARD=k/3.On an unmodified file, red or green comes down to which invoice the boot happens to draw. So the red/green comparison uses an uncommitted scratch copy whose only change forces the parent to a paid invoice (
where: { status: 'paid' }):4e0f5f50d(576d0f3733^)Tests 46 passed (46), VERDICT command-exit 0576d0f373(PR #24731)ab9890169(main, the base):369), VERDICT command-exit 18c65e505a(the fix)Tests 46 passed (46), VERDICT command-exit 00503d47c6(final head,mainmerged)Tests 46 passed (46)on each of two runsOnly
examples/app-showcase, a changeset and one docs file differ between the two bisect trees, and the dogfood suite loads the showcase from source. So a single built closure served both legs, and the matrix file is byte-identical across the pair.Which lines hang off a seeded invoice. I ran a probe on
8c65e505a: a scratch copy with one extra reporting case, not committed. Onlyshowcase_contributorcreates a line. That persona'sshowcase_invoicerow runs first, and its line hangs off its own invoice, whose status isdraft. The only line under a seeded invoice is the admin control's, so fixing this one parent fixes every place in the file with this cause.No ablation: product behaviour does not change.
Gates (final head
0503d47c6)node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstackderived 56 commands from 1 changed path. All 56 ran, each with its exit code captured before any pipe.--ran: "56 derived famil(ies) accounted for — 56 run, 0 NOT-MEASURED (a DERIVED zero — all 56 recorded an exit code and none of them is 3)."check:dual-build-cjs-loadsfirst exited 3 (PREREQUISITE NOT MET: 8 packages had nodist). I built those 8 and re-ran it: exit 0, "112 published require entry point(s) across 69 package(s) load".pnpm lint(eslint . --no-inline-config): exit 0, no findings.pnpm --filter @objectstack/dogfood run typecheck: exit 0.tsc --listFilesOnlylists the edited file.check-nul-bytes: OK (scanned 12537 text file(s) ...; no raw ASCII control bytes).Changeset
skip-changeset: the diff is one test file in@objectstack/dogfood, which isprivate: trueand publishes nothing.Acceptance notes
showcase_product,showcase_project,showcase_expense_report,showcase_team) still usefirstId, so they are also drawn at random on each boot. Today no rule makes any of those choices refuse a payload, and every pre-lock run I read was green. If a state rule is added to one of those objects, its parent should be chosen the same way.Generated by Claude Code