Skip to content

Commit 9b24f3c

Browse files
test(qa-scenarios): add the asset_lifecycle mid-tier scenario card (#30695)
<!-- claude-projects-attribution: {"github_login":"os-elon-musk"} --> _Requested by **Elon** · [project thread](https://claude.ai/code/project/chan_01WedDzV26nniwxv7jC88B9D?thread=cmsg_01WedDzV26nniwxv7jC88B9DUKRk5mV2mBg59GDjf3Z61H)_ Fixes #30481 Clause-②: no Metadata-protocol: none ## 维护者速读 - **改了什么**:新增「资产全生命周期」中档场景卡(8 个对象、报废审批、3 个角色其中 2 个按行限定、1 个按类别统计账面价值的报表、120 件资产跨 6–9 月采购、10 道问数、6 个写操作、6 个 agent 动作),并配一份只属于这张卡的真值测试。 - **为什么改**:落实 cloud#3600 九个场景中的资产场景,让 AI 建应用、问数、代办写操作都有一张能用代码判分的资产管理卡(领用与归还、维修、按月折旧、报废审批)。 - **风险与回滚**:只加测试数据和测试,所在包私有、不发布,运行时零改动,也没碰兄弟卡共用的文件;回滚即删两个新文件。 - **先看**:① `docs/qa/scenarios/asset_lifecycle.json` 的 `run.questions` 与 `run.operations`;② `packages/qa/scenarios/test/asset-lifecycle.test.ts` 的 `EXPECTED_TRUTHS` 及旁边的手算注释;③ 同一文件里「seed internally consistent」用例(折旧、账面价值、资产状态与单据对得上)。 - **两分钟验证**:`pnpm --filter @objectstack/scenarios test`,预期 5 个测试文件、70 个用例全绿。 - **需要你做的**:无,席位落地。 ## What changes - `docs/qa/scenarios/asset_lifecycle.json` (new): the 资产全生命周期 asset-lifecycle mid-tier card. - Eight objects: `department`, `employee`, `asset_category` (useful life, straight-line method), `asset` (the main object, with roll-up `accumulated_depreciation` and formula `book_value`), `checkout` (checkout and return, with the return condition), `repair_order`, `disposal_request` (the scrap approval, routed to the manager of the asset's department) and `depreciation_entry` (one per asset per month, posted by a scheduled flow). - Three personas: `employee` (the assets they hold, their own checkouts, repairs and scrap requests; no cost, book value, depreciation, budget or home address) and `dept_manager` (their department; no home address) carry a row scope; `asset_admin` sees every asset but no asset budget. - Seed: 120 assets bought June to September 2026, 92 checkouts (64 kits, re-issues after repair, 14 loaners), 19 repair orders, 7 scrap requests in all four states and 297 depreciation entries. The arithmetic rule that generated it is stated in the card's `$comment`, so every truth can be worked by hand. - Run half: 10 questions, 6 operations and 6 agent actions (one confirm-gated); `iterate` adds transfers between departments. - `packages/qa/scenarios/test/asset-lifecycle.test.ts` (new): this card's own test file. - It pins all 10 computed truths and the 10 per-persona truths against hand-worked values; each derivation is written next to its pin. - It asserts the mid-tier floor, and the seed's own consistency: each depreciation entry is cost over useful life, posted after the purchase month and never from the disposal month on; accumulated depreciation sums the entries and book value is cost minus it; each asset's status and custodian follow its checkouts, repairs and scrap request; each scrap request's approver is its department's manager. - It asserts each operation targets a row in the state its story needs (an overdue loaner, a submitted request the manager holds, an approved request, the employee's own request, an asset in repair, serials and a checkout key that do not exist yet). - It shows that a wrong seed cell and a wrong truth spec in fixture copies go red against those pins. ## Why The card is one of the six mid-tier scenarios ruled on objectstack-ai/cloud#3600 (Q1 = v3, 「同意这9个场景」). It gives the asset domain a scenario whose answers, permission boundaries and write outcomes are graded by code only. ## Tests `pnpm --filter @objectstack/scenarios test`: 5 files, 70 tests passed (64 before this PR). `pnpm --filter @objectstack/scenarios typecheck`: exit 0, after building the closure with `pnpm --filter '@objectstack/scenarios^...' build`; `tsc --listFiles` lists the new test file. Both read at head `0ffa47e2a6`. ## Acceptance notes - **File name.** The card is `asset_lifecycle.json`, not `asset-lifecycle.json` as the issue spells it: a card's `id` must be a snake_case machine name equal to the file's basename. #30600 made the same call. - **No shared file touched.** Since #30600, `test/library.test.ts` names only the three control cards and the README's "Adding a card" step already sends a mid-tier card's pins to its own file. So this PR adds two files and edits none, and it cannot conflict with the sibling cards. - **Seven operation kinds, six operations.** `receive_and_issue_from_text` covers two of them: entry from free text with lines (three monitors on one delivery) and the multi-step chain (register them, then check one out). The workflow step is `manager_approves_scrap`; its progress query is the question `dr_0005_waiting_on`, asked about a different request so its truth stays a fact of the seed. - **New rows in post-states.** A `where` cannot name a created row's id, so the new checkout is matched by `employee` plus `checked_out_on`; the test proves no seeded checkout has that pair, and that the three delivered serials are new. - **Overdue means due before `asOf`.** `overdue_loaners_by_department` filters `due_on lt "2026-10-31"`, the card's `asOf`; the window operators only name ranges that end on `asOf`. - **No schema field for some floor items.** An approval or automation flow, "declarative preferred" and a report as distinct from a dashboard have no field. The card states them in `prompt.detailed` (zh and en) and `capabilities`, seeds `disposal_request` as an expected object, and declares the report under `expect.dashboards`. Nothing in the loader grades them. - **Capability names.** The loader checks only the area half of a tag. `approvals.dynamic-approver-routing` is a checklist id; the rest follow the descriptive names `travel_expense.json` uses. - **Changeset.** `packages/qa/scenarios` is `"private": true` and the diff touches no published package, so this PR carries no changeset and asks for `skip-changeset`, as #30600 did. - **Sources.** The domain is designed from the card text and general business knowledge; the card's Reference line names no template. objectstack-ai/cloud#3567 was not read. ## Verification <details> <summary>scenarios test + typecheck (head 0ffa47e)</summary> ``` Test Files 5 passed (5) Tests 70 passed (70) > tsc --noEmit os-verify-lock: VERDICT command-exit 0 ``` Run after merging `main` and a whole-tree `pnpm build` (118 of 118 turbo tasks). </details> <details> <summary>dispatch-gates --commands (50 commands, local, head 0ffa47e)</summary> All 50 derived commands exit 0 on head `0ffa47e2a6`. The `--ran` reconciliation reads: 50 derived, 50 run, 0 NOT-MEASURED, 0 UNRUN, a derived zero because every line recorded its exit code. The first run, on the pre-merge head `11193506f5`, had 47 exit 0 and 3 exit 3 (PREREQUISITE NOT MET, nothing measured). Each cleared once its prerequisite was in place: - `check-plugin-teardown-shape.mjs --self-test`, after `git fetch --unshallow origin main` (its fixture is a pinned commit a shallow clone lacks); - `check:lean-entry-closure` and `check:dual-build-cjs-loads`, after the whole-tree build. </details> Changed lines: 1294 (+1294 / -0, 2 files), under the 3000 threshold (`dispatch-gates.mjs` reading). ## Human Minimum - [x] 1. Schemas start as Zod; `packages/spec` holds no runtime logic. (No schema touched.) - [x] 2. Every name I added uses the casing for its kind. - [ ] 3. No formatter ran; `pnpm lint` passes. (No formatter ran, and eslint on the new test file exits 0; the repo-wide `pnpm lint` is left to CI's `Lint & Repo Gates`.) - [x] 4. One issue, one branch off an up-to-date `main`, one pull request. - [x] 5. A change that publishes carries a changeset, and both declaration lines are filled in here and in the changeset. (Publishes nothing: private package.) - [x] 6. `packages/spec` touched: its generated artifacts are regenerated and committed. (Not touched.) - [x] 7. No hand edits to `content/docs/references/`, `packages/*/CHANGELOG.md` or `content/docs/releases/`. - [x] 8. Title, body and comments are in English. - [ ] The *Before Submitting* list in CONTRIBUTING.md is done. (Every item but the repo-wide `pnpm lint`, left to CI as in item 3.) --- _Generated by [Claude Code](https://claude.ai/code/session_016WV4czx7zatyA1s7R4yPhB)_ Co-authored-by: Claude <noreply@anthropic.com>
1 parent a599cc1 commit 9b24f3c

2 files changed

Lines changed: 1294 additions & 0 deletions

File tree

0 commit comments

Comments
 (0)