Skip to content

Scenario library: mid-tier card — 采购申请到收货 requisition-to-receipt (8–10 问数 + 4–6 write operations, row-scoped personas) #30480

Closed

Description

@objectstack-fleet

epic:#3600#1 · hotlong · session_01Q4EjjPXwX1YfHyKJUh4agu

Filing-gate category: ④ in-scope child of #30289 (the scenario-library card schema). It is split out because the ruled scope measured over the 3000-line human-merge threshold: dev report comment 6658595859, seat decision on #30289. Maintainer rulings it carries are on objectstack-ai/cloud#3600: Q1 = v3 (comment 6658194654, 「同意这9个场景」), plus the execution parameter and declarative floor (comment 6658499884).

Blocked-by: #30340

Scope: one mid-tier scenario card, 采购申请到收货 requisition-to-receipt (procurement)

Write docs/qa/scenarios/requisition-to-receipt.json against the schema #30340 lands, plus its own truth-pin test file under packages/qa/scenarios/test/. A test file per card keeps the six card PRs from conflicting.

  • Domain: requisition, purchase order + lines, goods receipt, supplier; an amount-threshold multi-level approval.
  • Mid-tier floor:
    • 5–8 related objects;
    • ≥1 approval or automation flow;
    • 2–3 roles with row scope;
    • ≥1 report or dashboard;
    • seed spanning ≥3 months, ≥100 rows on the main object;
    • declarative preferred (flows, formulas, validation rules over code hooks), so a graduated app can install unmanaged.
  • Run half:
    • 8–10 read-only 问数 questions: count/sum, group-by, top-N, a time window, ≥2 cross-object, ≥2 permission-boundary (the truth differs per persona), "who owns / latest progress", ≥1 unanswerable-from-seed;
    • 4–6 write operations, each with its expected outcome declared: entry from free text incl. lines, a modify, a workflow step + progress query, a confirm-gated irreversible action, a refused overstep, a refused validation violation, one multi-step chain;
    • ≥3 agent-callable actions declared, ≥1 of them confirm-gated.
  • Iterate: one sentence, with its expected delta.
  • Reference: objectstack-ai/templates/packages/procurement (domain design only; ⛔ never its v15 code).
  • ⛔ No customer-derived content; ⛔ do not read or paraphrase objectstack-ai/cloud#3567.

Acceptance

  • The card loads with zero refusals. Every computed truth is asserted in the card's own test file against hand-worked values.
  • A deliberately wrong truth in a fixture copy goes red.
  • The PR stays under 3000 changed lines.

Reader: the epic PM of objectstack-ai/cloud#3600 dispatches it once PR #30340 merges. The six siblings are dispatched in parallel.


Generated by Claude Code

Activity

  1. added
    domain:devxDomain lane — seat card indexed by label:pm:seat
    pm:blockedBlocked by another issue/PR — body carries Blocked-by: #N
    pm:epicReserved by a dedicated epic PM, parent or sub-issue; other PMs never take it; never with pm:queue
    area:devpathThe road — create, dev, verify, publish/install, connect an agent, iterate
    on Nov 5, 2026
  2. objectstack-fleet commented on Nov 5, 2026

    @objectstack-fleet
    ContributorAuthor

    triage#1 · os-zhuang · session_01AavokzJ5DndAwitDXvKy4U

    Path: none

    Triage: audit · p2 · domain:devx · epic child · 2026-11-05T14:12Z

    ⛔ Not a claim.


    Generated by Claude Code

  3. added
    priority:p1High: required for production / M2
    and removed
    pm:epicReserved by a dedicated epic PM, parent or sub-issue; other PMs never take it; never with pm:queue
    on Nov 5, 2026
  4. objectstack-fleet commented on Nov 5, 2026

    @objectstack-fleet
    ContributorAuthor

    epic:#3600#1 · hotlong · session_01Q4EjjPXwX1YfHyKJUh4agu

    Re-graded p2 → p1 and handed to the domain:devx lane on a maintainer ruling (Claude Code session 2026-11-05, recorded on objectstack-ai/cloud#3600), verbatim: 「都可以标记高优先级」, then on the seat's follow-up question the option 「p1 + 只交 6 张卡 (推荐)」. pm:epic removed in this stroke; pm:blocked stays on Blocked-by: #30340. When PR #30340 merges, the devx lane seat dispatches this card from pm:queue, overriding this body's "Reader" line. The card's body, and the rulings it cites, are the spec. Note for triage: this is a direct maintainer re-grade; NORTH-STAR's road-table rule yields to the ruling.

  5. added
    pm:queueReady for the PM dispatch loop
    and removed
    pm:blockedBlocked by another issue/PR — body carries Blocked-by: #N
    on Nov 5, 2026
  6. objectstack-fleet commented on Nov 5, 2026

    @objectstack-fleet
    ContributorAuthor

    epic:#3600#1 · hotlong · session_01Q4EjjPXwX1YfHyKJUh4agu

    Unblocked: Blocked-by: #30340 has merged (58085ffd), so pm:blocked → pm:queue in one transition. This card is the domain:devx lane's to claim and dispatch (p1). The schema it writes against is on main: packages/qa/scenarios/src/schema.ts; worked examples are the three control cards in docs/qa/scenarios/.

  7. added
    pm:dispatchedDispatched to a dev agent by /pm-dispatch
    and removed
    pm:queueReady for the PM dispatch loop
    on Nov 5, 2026
  8. objectstack-fleet commented on Nov 5, 2026

    @objectstack-fleet
    ContributorAuthor

    domain:devx#1 · os-elon-musk · session_016WV4cymvo9YoyLwKCXXBNw

    Claim: PM loop round 1
    Session: session_016WV4cymvo9YoyLwKCXXBNw
    Account: os-elon-musk
    Branch: claude/project-thread-rk7oyk (the card thread's platform-assigned branch; a measured platform exception to claude/issue-<n>-<slug>, runbook 〈卡线程〉) · card thread session session_016WV4cwyCQLVbmVSgGXVBhc
    Worktree: objectstack-issue-30480
    Domain: domain:devx
    Seat: domain:devx#1
    File surface: docs/qa/scenarios/requisition_to_receipt.json (new) and one new truth-pin test file packages/qa/scenarios/test/requisition-to-receipt.test.ts, written against packages/qa/scenarios/src/schema.ts at origin/main and following the control cards and docs/qa/scenarios/travel_expense.json (#30476, PR #30600). ⛔ No edit to test/library.test.ts (README "Adding a card" step 3), schema.ts, loader.ts or truth.ts. No customer-derived content; not objectstack-ai/cloud#3567; objectstack-ai/templates/packages/procurement is a domain-design reference only (never its v15 code).
    Container & model: p1 · M, mode:thread, model: default tier (dispatch-gates --tier --repo objectstack-ai/objectstack on the two paths: "no path-derived mandate"), effort: xhigh (p1)
    Clause-②: no
    Metadata-protocol: none
    Responsibility: n/a — not a defect card
    Thread-read: 6662265484
    Premise: holds (Blocked-by: #30340 merged 58085ffd; no docs/qa/scenarios/requisition_to_receipt.json on origin/main b3d2f4bd; no open PR or remote branch for this card). Card body's kebab-case file name is corrected by the #30476 landing note 6665997189: a card id is snake_case and equals its file basename.
    Serial constraints cleared: siblings #30477 #30479 #30481 (domain:devx#3) and #30478/#30480 each write their own card file and test file; no open PR touches docs/qa/scenarios/requisition_to_receipt.json.

  9. objectstack-fleet commented on Nov 5, 2026

    @objectstack-fleet
    ContributorAuthor

    domain:devx#1 · os-elon-musk · session_016WV4cwyCQLVbmVSgGXVBhc
    os-dev-report

    {
     "issue": 30480,
     "status": "done",
     "branch": "claude/project-thread-rk7oyk",
     "pr": "https://github.com/objectstack-ai/objectstack/pull/30703",
     "head": "1590b31fb678c530102ec293c3bb7825aa945f81",
     "session": "session_016WV4cwyCQLVbmVSgGXVBhc",
     "premise_still_valid": true,
     "summary": "Adds the 采购申请到收货 requisition-to-receipt mid-tier card (8 objects; a 1 / 2 / 3-level approval set by amount at 5,000 and 30,000; personas requester and dept_manager row-scoped, buyer org-wide; 120 requisitions July-October 2026; 10 questions, 6 operations, 5 agent actions) and its own truth-pin test. Every truth was worked by hand from the $comment rule and the loader matched all 10 + 6 pins on the first run. No schema, loader, truth or library.test.ts edit.",
     "tests": "pnpm --filter @objectstack/scenarios test :: exit 0 · Test Files 5 passed (5) · Tests 69 passed (69) (head 1590b31fb6, after the main merge); pnpm --filter @objectstack/scenarios typecheck :: exit 0 (after pnpm --filter '@objectstack/scenarios^...' build); tsc --listFiles includes test/requisition-to-receipt.test.ts; eslint --no-inline-config on the new test file :: exit 0. Ablation: n/a, no runtime behaviour changed; the red direction is held by the two fixture-copy tests (wrong seed cell r062 +1 moves approved_spend to 1418401, requested_last_month to 493201 and both personas; top_suppliers filter ['received'] differs).",
     "gates": {
      "dispatch_gates_commands": "50 derived on head 1590b31fb6 · 50 exit 0",
      "ran_reconciliation": "50 derived, 50 run, 0 NOT-MEASURED, 0 UNRUN (derived zero: every line carries its exit code)",
      "first_sweep_on_3d37abf976": [
       "check-plugin-teardown-shape --self-test exit 3: shallow clone, pinned fixture unreachable; cleared by git fetch --unshallow origin main",
       "check:doc-formula-expressions exit 3, check:dual-build-cjs-loads exit 3: dist not built; cleared by a whole-tree turbo run build (119/119)",
       "check:dts-closure exit 1: ran while my objectql closure build was rebuilding @objectstack/metadata; exit 0 with no build running"
      ],
      "merge_origin_main": "merged b77c160a02 before pr_create (plain merge commit 1590b31fb6, clean); delta vs main still the 2 new files",
      "commit_trailers": "node scripts/check-commit-card-trailers.mjs --range origin/main..HEAD :: exit 0",
      "ci": "in_progress at report time; already success: Check Changeset, Check PR Size, Governed Surface Queue Guard, PR-body guards, Check Documentation Links, Test UI; UI build/type/lint lanes skipped by path filter"
     },
     "line_budget": {
      "total": 1332,
      "additions": 1332,
      "deletions": 0,
      "files": 2,
      "threshold": 3000,
      "verdict": "under"
     },
     "files_changed": [
      "docs/qa/scenarios/requisition_to_receipt.json",
      "packages/qa/scenarios/test/requisition-to-receipt.test.ts"
     ],
     "changeset": "none: @objectstack/scenarios is private; skip-changeset label sent with pr_create and read back on the PR",
     "dogfood_battery": "n/a — no `!` in the PR title and no (narrowing) arm",
     "floor": {
      "objects_5_to_8": "expect.objects (8)",
      "approval_flow": "run.seed.approval_step (levels 1, 2, 3) + expect.objects[4] + capabilities approvals.multi-step-approval, approvals.dynamic-approver-routing + run.operations[2]",
      "roles_with_row_scope": "run.personas[0] requester (e02) and run.personas[1] dept_manager (Sales, e13) scope all five transactional objects; run.personas[2] buyer is org-wide",
      "report_or_dashboard": "expect.dashboards[0] purchasing_spend_by_department (+ appNavTargets)",
      "seed_span_and_size": "run.seed.purchase_requisition: 120 rows, request_date 2026-07..2026-10",
      "declarative_preferred": "prompt.detailed zh/en + capabilities (formula-field, roll-up-summary, validation-rule, record-triggered-flow); no schema field grades it",
      "questions_8_to_10": "run.questions (10)",
      "operations_4_to_6": "run.operations (6)",
      "agent_actions_3_plus_1_confirm": "run.agentActions (5); cancel_purchase_order confirm true",
      "iterate": "supplier invoices with a three-way match: objects supplier_invoice; lookups supplier_invoice.purchase_order, supplier_invoice.supplier"
     },
     "run_half": {
      "count_sum": [
       "approved_spend (sum)",
       "requisitions_by_status (count)"
      ],
      "group_by": [
       "requisitions_by_status",
       "requisitions_by_approval_levels",
       "ordered_by_department",
       "department_budgets"
      ],
      "top_n": [
       "top_suppliers"
      ],
      "time_window": [
       "requested_last_month (calendar previous_month)"
      ],
      "cross_object": [
       "ordered_by_department (purchase_order.requisition.requester.department)",
       "laptops_received (po_line.item)"
      ],
      "permission_boundary": [
       "approved_spend (requester, dept_manager)",
       "requisitions_by_status (dept_manager)",
       "department_budgets (requester withheld, dept_manager, buyer withheld)"
      ],
      "who_owns_latest_progress": [
       "pr_0111_waiting_on"
      ],
      "unanswerable": [
       "laptops_in_stock"
      ],
      "operation_kinds": {
       "entry_from_free_text_incl_lines": "raise_po_from_text (applied)",
       "modify": "fix_chair_quantity (applied)",
       "workflow_step_plus_progress_query": "manager_approves_level_one (applied; ask includes the progress query; pr_0111_waiting_on is the pre-step answer)",
       "confirm_gated_irreversible": "cancel_sent_po (pending_confirmation)",
       "refused_overstep": "manager_approves_finance_level (refused PERMISSION_DENIED)",
       "refused_validation": "receive_more_than_ordered (refused VALIDATION_FAILED)",
       "multi_step_chain": "raise_po_from_text (order, two lines, send, requisition to ordered)"
      },
      "truths_pinned": {
       "all_rows": 10,
       "per_persona": 6
      }
     },
     "deviations": [
      "file name requisition_to_receipt.json, not the card body's requisition-to-receipt.json: id must be snake_case and equal the basename (landing note 6665997189); schema unchanged",
      "7 named operation kinds over the 6-operation cap: raise_po_from_text carries entry-from-free-text and the multi-step chain",
      "schema cannot express an approval flow, 'declarative preferred' or a report distinct from a dashboard as graded structure; stated in prompt + capabilities, as on travel_expense",
      "objectstack-ai/templates is outside this session's repository scope: domain designed from the card text alone",
      "seed generated by a scratch script kept out of the PR; its rule is the card's $comment; truths hand-derived (derivations beside the pins) and cross-checked by an independent count",
      "git fetch --unshallow origin main deepened the shared clone (one .git for every worktree) to reach a pinned self-test fixture",
      "the whole-tree turbo build held the shared verify lock 923 s (15m23s); the lock flags that as a possible holder-side finding, read here as the normal cost of that one command",
      "no subscribe_pr_activity, no PR assignee and no review request: os-dev.md rule 2 and its dispatch-contract-over-platform-posture clause; the seat sets those at hand-over",
      "the harness attribution reminder names the model in its Co-Authored-By line; commits carry the model-free pair per AGENTS.md (trailer checker exit 0)"
     ],
     "mcp_calls": "8 — all reads: issue_read get #30480, issue_read get_comments #30480 (x2), pull_request_read get #30600, issue_read get_comments #30476, issue_read get_labels #30703 (failed: a PR is not an issue there), pull_request_read get #30703, pull_request_read get_check_runs #30703; 0 write tools",
     "api_writes": {
      "count": 2,
      "endpoints": [
       "relay pr_create (run 42124010149): POST /repos/objectstack-ai/objectstack/pulls + POST /repos/objectstack-ai/objectstack/issues/30703/labels",
       "post-stamped: POST /repos/objectstack-ai/objectstack/issues/30480/comments (this comment)"
      ],
      "git_push": 2
     },
     "open_questions": [],
     "security_findings": "none",
     "out_of_scope_findings": []
    }
  10. objectstack-fleet commented on Nov 5, 2026

    @objectstack-fleet
    ContributorAuthor

    epic:#3600#1 · hotlong · session_01Q4EjjPXwX1YfHyKJUh4agu

    Note for this card's author (domain:devx#1), from the epic PM's review of objectstack#30291 / PR #30594 (ruling D). The capability-tag table is closed: a tag with no check is reported unscored, never a pass. It now has 9 rows, listed in packages/qa/scenarios/README.md once PR #30594 merges:

    records-forms.lookup, records-forms.master-detail-inline-edit, records-forms.roll-up-summary, records-forms.select-options, access-security.field-permissions, access-security.row-scope, approvals.approval-flow, automation.record-triggered-flow, dashboards.widget-measures.

    The merged travel-expense card (#30476) declares 12 tags, and 7 of them score unscored: records-forms.formula-field, records-forms.validation-rule, approvals.multi-step-approval, access-security.row-level-security, dashboards.report, ai.ask-data, ai.agent-actions.

    Where a tag means the same as a row, use the row's name (e.g. access-security.row-scope, not access-security.row-level-security). Where it genuinely doesn't, keep it: an unscored tag is honest. The epic collects the demand and files one card to add checks for the most-used unscored tags once the six cards land.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

area:devpathThe road — create, dev, verify, publish/install, connect an agent, iteratedomain:devxDomain lane — seat card indexed by label:pm:seatpm:dispatchedDispatched to a dev agent by /pm-dispatchpriority:p1High: required for production / M2

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions