Repository navigation
test(qa-scenarios): add the order_to_cash mid-tier scenario card - #30706
Conversation
Adds docs/qa/scenarios/order_to_cash.json, the 订单到收款 order-to-cash mid-tier card: eight objects (employee, account, product, sales_order, order_line, invoice, payment, activity), a discount approval routed to the owner's sales manager, a time-triggered collection-call automation, three personas (two row-scoped), a receivables aging report, 120 orders across July-October 2026, 10 questions, 6 operations and 5 agent actions. Adds packages/qa/scenarios/test/order-to-cash.test.ts, the card's own truth pins: every computed truth over all rows and per persona against hand-worked values, the mid-tier floor, the seed's consistency with the rule in $comment, and two fixture copies (a wrong seed cell, a wrong truth spec) that go red against the pins. Claude-Session: https://claude.ai/code/session_016WV4d1Exmm9uiWTdqYBhqM Co-authored-by: Claude <noreply@anthropic.com>
Both writes target SO-0110. Listed first, the refused self-approval leaves the seed unchanged, so its outcome and the manager's applied approval hold whether a runner grades each write against the seed or applies them in order. Claude-Session: https://claude.ai/code/session_016WV4d1Exmm9uiWTdqYBhqM 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): |
|
domain:devx#3 · os-elon-musk · session_016WV4cz3RTQjLh7hZBLzgtZ 席位核对 · ACCEPT ·
|
⛔ merge queue 构建失败 — 先分诊,再决定要不要重排队列构建 42160085799 红了。队列跑的是全量套件(PR 侧 CI 只跑 affected 子集), 分类: 失败的 job(日志抽取,best effort):
跨 PR 相同签名(24h,按失败测试文件聚合):
历史信号:
分诊清单:
Generated by Claude Code · merge-queue-triage workflow (#4859) |
|
domain:devx#3 · os-elon-musk · session_016WV4d1Exmm9uiWTdqYBhqM Merge-queue triage: run 42160085799 is red from #30716, not from this PR
Generated by Claude Code |
⛔ merge queue 构建失败 — 先分诊,再决定要不要重排队列构建 42161971792 红了。队列跑的是全量套件(PR 侧 CI 只跑 affected 子集), 分类: 失败的 job(日志抽取,best effort):
跨 PR 相同签名(24h,按失败测试文件聚合):
历史信号:
分诊清单:
Generated by Claude Code · merge-queue-triage workflow (#4859) |
Requested by Elon · project thread
Fixes #30477
Clause-②: no
Metadata-protocol: none
维护者速读
docs/qa/scenarios/order_to_cash.json的run.questions与run.operations;②packages/qa/scenarios/test/order-to-cash.test.ts的EXPECTED_TRUTHS与EXPECTED_PERSONA_TRUTHS;③ 同文件的种子一致性用例(发票、收款、账龄与催收规则)。pnpm --filter @objectstack/scenarios test,预期 5 个测试文件、70 个用例全绿。What changes
docs/qa/scenarios/order_to_cash.json(new): the 订单到收款 order-to-cash mid-tier card.employee,account,product,sales_order,order_line,invoice,paymentandactivity(the account's follow-up stream, its own records with lookups to the account, the invoice and the owner, never typed into the account).approver,approved_on), and an invoice 15 days past due and not fully paid gets a collection call for the AR clerk.sales_rep(e03, own accounts; no payment object, no product cost) andsales_manager(e01, team east; no payment bank reference) carry a row scope;ar_clerk(e09) sees everything but product cost.$comment, so every truth can be worked by hand. Receivables are as ofasOf2026-10-31: one account has paid nothing, one pays half on the due date, one pays 20 days late.iterateadds credit notes.packages/qa/scenarios/test/order-to-cash.test.ts(new): this card's own test file.Tests
pnpm --filter @objectstack/scenarios test: 5 files, 70 tests passed (64 before this card, 6 new).pnpm --filter @objectstack/scenarios typecheck: exit 0, after building the closure withpnpm --filter '@objectstack/scenarios^...' build.The pinned values were worked from the seed rule by a script that implements the business rule directly (it never reads the card's truth specs or calls the loader), then matched against the loader's computed truths: every pin agreed on the first run. The ranking, aging, subscription and per-persona derivations are written out by hand beside their pins.
Acceptance notes
order_to_cash.json, notorder-to-cash.jsonas the issue spells it. A card'sidmust be a snake_case machine name and equal the file's basename, so a hyphenated basename cannot load. The test file follows the merged sibling's spelling,order-to-cash.test.ts.test/library.test.tsassert only the three control cards and moved per-card pins to each card's own file, so this PR edits neitherlibrary.test.tsnor the README. Sibling cards no longer conflict with it.docs/qa/scenarios/README.md"Adding a card" step 3 names the pin filetest/ID.test.ts, while its model and this card use a hyphenated basename. An observation only; the README is unchanged here.prompt.detailed(zh and en) and incapabilities, seeds the approval onsales_order(approver,approved_on) and the automation's collection calls asactivityrows, and declares the report underexpect.dashboards. Nothing in the loader grades them.order_from_textcovers two of them: entry from free text with lines, and the multi-step chain (create the order, add two lines, submit it, route it to the manager). The workflow step isapprove_discount; its progress query is the questionso_0120_waiting_on.rep_approves_own_discount(refused) is listed beforeapprove_discount(applied). A refused write changes nothing, so both outcomes hold whether a runner grades each write against the seed or applies the writes in order.where. Awherecannot name the new order's id, soorder_from_textlocates the order by account and today's date and each line by product, quantity and discount; no seeded row matches any of them. The lines are therefore not tied to the new order in the post-state.invoice.aging_bucketis a formula on today in the built app; the seed stores its value as ofasOf, and the test holds every bucket to the due date.approvals.dynamic-approver-routingandautomation.time-relative-triggerare checklist items; the other tags follow the existing cards' wording. The loader checks the area half only.@objectstack/scenariosisprivate: trueand nothing else moves, so this PR carriesskip-changeset, as the travel-expense card's PR did.Verification
scenarios test + typecheck (head e44efca)
dispatch-gates --commands (50 commands, local, head e44efca)
All 50 derived commands exit 0 on this head (the merge of
mainat e44efca), and on the pre-merge head 5d751a9 before it. The--ranreconciliation reads: 50 derived, 50 run, 0 NOT-MEASURED, 0 UNRUN, a derived zero because every line recorded its exit code.On the first run two of them exited 3 (PREREQUISITE NOT MET) and exited 0 once the prerequisite was met:
check-plugin-teardown-shape.mjs --self-test, after fetching its pinned positive-control commit into the shallow clone;check:dual-build-cjs-loads, after a fullturbo run build(119 of 119 tasks).After the merge of
main(which movedpackages/spec):pnpm --filter @objectstack/spec buildthencheck:generatedreported all 14 generated artifacts up to date.Changed lines: 1379 (+1379 / -0, 2 files), under the 3000 threshold.
Generated by Claude Code