Skip to content

Commit aed9663

Browse files
test(qa-scenarios): add the leave_balances mid-tier scenario card (#30690)
<!-- claude-projects-attribution: {"github_login":"os-elon-musk"} --> _Requested by **Elon** · [project thread](https://claude.ai/code/project/chan_01WedDzV26nniwxv7jC88B9D?thread=cmsg_01WedDzV26nniwxv7jC88B9D5az28vj5D7FMGPRyuQEdi1)_ Fixes #30479 Clause-②: no Metadata-protocol: none ## 维护者速读 - **改了什么**:新增「请假与假期余额」中档场景卡:7 个对象(部门、员工、假期类型、假期余额、请假单、请假明细、审批步骤),3 天及以内只需经理审批、超过 3 天再加 HR 审批,批准后自动扣减余额;3 个角色其中 2 个按行限定;1 个请假天数报表;120 张请假单跨 7–10 月;10 道问数、6 个写操作、4 个 agent 动作。另配一份只属于这张卡的真值测试。 - **为什么改**:落实 cloud#3600 九个场景中的 HR 场景,让 AI 建应用、问数、代办写操作都有一张能用代码判分的请假与余额卡。 - **风险与回滚**:只加测试数据和测试,所在包私有、不发布,运行时零改动;回滚即删两个新文件。 - **先看**:① `docs/qa/scenarios/leave_balances.json` 的 `run.operations`(六个写操作及预期结果);② 同文件的 `run.questions` 与 `run.personas`;③ `packages/qa/scenarios/test/leave-balances.test.ts` 的 `EXPECTED_TRUTHS`。 - **两分钟验证**:`pnpm --filter @objectstack/scenarios test`,预期 5 个测试文件、73 个用例全绿。 - **需要你做的**:无,席位落地。 ## What changes - `docs/qa/scenarios/leave_balances.json` (new): the 请假与假期余额 leave-and-balances mid-tier card. - Seven objects: `department`, `employee`, `leave_type` (annual, sick, personal), `leave_balance` (one per employee, tracked type and leave year), `leave_request`, `leave_day` (one line per date, a full day or a half day) and `approval_step`. - The route follows the days: up to 3 days goes to the department manager only, more than 3 days to the manager and then HR (`e13`), and a manager's own request goes to the HR manager (`e14`) at step 1. On the last approval the balance's `used_days` (a roll-up of the approved requests) rises and `remaining_days` (entitlement + carry-over - used) falls. - Two validation rules: a request cannot be submitted for more days than its balance has left, and a sick request over 2 days needs a certificate. - Three personas: `employee` (own rows) and `dept_manager` (own department) carry a row scope; `hr_officer` sees everything except the medical note, which only the requester sees. - Seed: 120 requests starting July to October 2026, with 307 day lines, 141 approval steps and 28 balances. The 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 4 agent actions (one confirm-gated); `iterate` adds time off in lieu. - `packages/qa/scenarios/test/leave-balances.test.ts` (new): this card's own test file. - It pins all 10 computed truths and the 9 per-persona truths against hand-worked values, with the derivations beside them. - It asserts the mid-tier floor and checks the seed against the rules the card states: a request's days equal its weekday lines, a balance equals its approved requests and the tenure rule, each request's steps match its days and status, and both validation rules hold on every submitted request. It also checks that `LR-0091` really exceeds its balance, so the refused submission is a real refusal. - It checks that every `where` in an applied post-state matches no seeded row, so it can only name the row the write creates. - It shows that a wrong seed cell and a wrong truth spec in a fixture copy go red against those pins. ## Why #30479 is one of the six mid-tier cards of the open scenario library. This one covers HR: leave requests whose approval route depends on their length, and balances that move when a request is approved. ## Tests `pnpm --filter @objectstack/scenarios test`: 5 files, 73 tests passed. `pnpm --filter @objectstack/scenarios typecheck`: exit 0, after building the closure with `pnpm --filter '@objectstack/scenarios^...' build`. `eslint --no-inline-config` on the new test file: exit 0. ## Acceptance notes - **File names.** The card is `leave_balances.json`, not `leave-balances.json` as the issue spells it: a card's `id` is a snake_case machine name that must equal the file's basename. The test file follows the model's spelling, `leave-balances.test.ts`. - **No shared-file edit.** Since `travel_expense` landed, `library.test.ts` checks only that the three control cards are present, and the README's "Adding a card" step points at a per-card test file. So this PR touches neither, and the sibling cards no longer conflict on a shared line. - **No schema field for some floor items.** As with `travel_expense`, the approval flow, "declarative preferred" and a report as distinct from a dashboard have no field in the schema. The card states them in `prompt.detailed` (zh and en) and in `capabilities`, seeds `approval_step` as an expected object, and declares the report under `expect.dashboards`. Nothing in the loader grades them. - **Capability tags.** Where a tag in the closed tag table of the open scorer PR #30594 fits, the card uses that spelling (`approvals.approval-flow`, `access-security.row-scope`, `dashboards.widget-measures`, `records-forms.lookup`), so those tags are judged once the scorer lands. Tags outside that table read `unscored` there, not failed. - **Seven operation kinds, six operations.** `file_and_submit_from_text` covers two of them: entry from free text with lines, and the multi-step chain (file the request, add a full day and a morning, submit, route to the manager). - **Routed approval step not asserted.** The post-state of `file_and_submit_from_text` does not assert the routed step-1 row. A `where` cannot name the new request's id, and `approver e05 · pending` also matches seeded rows. - **Dates.** `asOf` is 2026-09-30, so October's requests are the upcoming ones and every draft or pending request is for future leave; "last month" is August. Balances belong to leave year 2026/27, which starts on 1 July, so the seed is the whole leave year so far. Days count Monday to Friday; public holidays are out of scope and the `$comment` says so. - **Reference.** `objectstack-ai/templates` is not attached to this session, so the domain is designed from the card text alone. ## Verification <details> <summary>scenarios test + typecheck</summary> ``` Test Files 5 passed (5) Tests 73 passed (73) os-verify-lock: VERDICT command-exit 0 > tsc --noEmit os-verify-lock: VERDICT command-exit 0 ``` </details> <details> <summary>one-time check: a wrong cell in the real card goes red</summary> `scripts/ablation-replace.mjs` set `LR-0098`'s `days` from 5 to 6 in `docs/qa/scenarios/leave_balances.json` and ran this card's test file: 4 of 9 tests failed (the pinned truths, the lines check, the balance check, and the fixture-copy pin, which reads the real card). It then restored the file: blob equal to HEAD, `git diff HEAD` empty. </details> <details> <summary>dispatch-gates --commands (50 commands, local, head 42b3e57)</summary> All 50 derived commands exit 0 on head `42b3e57a` (the commit before the `main` merge). The `--ran` reconciliation reads: 50 derived, 50 run, 0 NOT-MEASURED, 0 UNRUN, a derived zero because every line recorded its exit code. Four of them first exited 3 (PREREQUISITE NOT MET). Each exited 0 after the step it names: - `check-plugin-teardown-shape.mjs --self-test`, after `git fetch --unshallow origin main` (the clone was shallow); - `check:doc-formula-expressions`, `check:lean-entry-closure` and `check:dual-build-cjs-loads`, after a full `turbo run build` (119 of 119 tasks). The merge of `main` (9 commits) touches neither `docs/qa/scenarios/` nor `packages/qa/scenarios/`, and the derivation on the merged head `9bd3d3c9` names the same 50 commands. On that head the scenarios tests (5 files, 73 tests) and typecheck pass again. Changed lines: 1342 (+1342 / -0, 2 files), under the 3000 threshold. </details> ## Human Minimum - [x] 1. Schemas start as Zod; `packages/spec` holds no runtime logic. (Not touched.) - [x] 2. Every name I added uses the casing for its kind. - [x] 3. No formatter ran; `pnpm lint` passes. (eslint on the new test file locally; the repo-wide run is CI's.) - [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. (`@objectstack/scenarios` is `private: true` and publishes nothing, so no changeset, `skip-changeset`, as `travel_expense` landed.) - [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. - [x] The *Before Submitting* list in CONTRIBUTING.md is done. --- _Generated by [Claude Code](https://claude.ai/code/session_016WV4cw5kGUbtDLQqKwTH7E)_ Co-authored-by: Claude <noreply@anthropic.com>
1 parent 3da9a4c commit aed9663

2 files changed

Lines changed: 1342 additions & 0 deletions

File tree

0 commit comments

Comments
 (0)