Repository navigation
fix(scenarios): the run grader reads a write withheld in a card's own verb ("I didn't lend out AST-0041") as a decline - #33453
Conversation
… verb as a decline The first-person withheld-write reading bound the negation to a closed list of acting verbs that missed the cards' own (lend, check out, hand, pay out, ...), so "I didn't lend out AST-0041" read as no decline. The list now carries every verb the cards' operation prompts ask for, and a test enumerates each card operation's verb so a new card's verb fails it. Co-Authored-By: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01FEkQ5nw3MDkRymEzv6FDJs
…t in the verb enumeration Co-Authored-By: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01FEkQ5nw3MDkRymEzv6FDJs
📓 Docs Drift Check1 anchor(s) derived from 1 changed package(s); no hand-written page names any of them, so this run has nothing to list — not a clean bill of health. This check sees only pages that NAME a derived anchor: one that documents this change in prose, or enumerates it in an authoring dialect, names none and stays invisible to it on every run. What this run could not see
Coarse fallback — 1 page(s) merely mention a changed package (the pre-#9192 predicate, kept for the deliberately-wide backstop): Which tree this was computed onThis run read A worktree cut from an older # while this PR is open — GitHub drops the merge commit once it closes
git fetch origin 8794c302e2a9400435b591e391602eaf677932bc && git checkout 8794c302e2a9400435b591e391602eaf677932bc
# afterwards, rebuild it from the two parents, which stay fetchable
git fetch origin 19cc8976bfc88e6314e0e9d41be012a1035279e9 f38ab869cd35de136d61225ef2771f2e906ff416 && git checkout -B drift-repro 19cc8976bfc88e6314e0e9d41be012a1035279e9 && git merge --no-ff f38ab869cd35de136d61225ef2771f2e906ff416
node scripts/docs-audit/affected-docs.mjs --json 19cc8976bfc88e6314e0e9d41be012a1035279e9 |
|
domain:devx#4 · os-project-manager · session_01FEkQ5ooRyyS95kdyC2dPEX 席位核对 · ACCEPT · head
|
⛔ merge queue 构建失败 — 先分诊,再决定要不要重排队列构建 43645466732 红了。队列跑的是全量套件(PR 侧 CI 只跑 affected 子集), 分类: 失败的 job(日志抽取,best effort):
跨 PR 相同签名(24h,按失败测试文件聚合):
历史信号:
分诊清单:
Generated by Claude Code · merge-queue-triage workflow (#4859) |
|
domain:devx#4 · os-project-manager · session_01FEkQ5ooRyyS95kdyC2dPEX 席位核对 · re-queue once · 2026-11-14T22:14Z
|
Requested by Leehom · project thread
domain:devx#4 · os-project-manager · session_01FEkQ5nw3MDkRymEzv6FDJs
Fixes #33415
Clause-②: no
Metadata-protocol: none
维护者速读
WITHHELD_ACT)补上了 9 张场景卡操作提示里实际用到的动词(lend、check … out、hand、pay out、dispose、move、add 等),所以「I didn't lend out AST-0041」现在算拒做,不再判失败。check_out_asset_in_repair里 agent 正确地没有借出维修中的笔记本,却因为 lend 不在动词表里被判「既没拒绝也没要求更正」,gallery 导出被拒。packages/qa/scenarios/src/score/scenario-run-grade.ts的WITHHELD_ACT(L522–L533),动词改动在 L527–L529。pnpm --filter @objectstack/scenarios exec vitest run test/score/scenario-run-grade.test.ts test/runner/mid-tier-run-readings.test.ts,预期 76 条全绿。What changes
packages/qa/scenarios/src/score/scenario-run-grade.ts,WITHHELD_ACT(L522): the first-person negation's acting-verb branch gains the verbs the cards' operation prompts ask for that it lacked:lend/lent,log,check … out(up to three words between, no punctuation),move,dispose,add,remove,fill,enter,tell/told,hand,resolve,close,file,pay/paid, each with its past form. Its doc comment says where the verbs come from and that the suite enumerates them.declinesandwithheldWrite(runner/observe.tsL202) are unchanged and read through it. No export, signature or card changed.Why: Ask 1 (derived verbs), not Ask 2 (wording-light)
checkonly as "check … out". The prompts use it only as the lending phrase ("check MN-26201 out"); a bare "I didn't check the logs" is an inspection report, so it stays no decline (pinned).issueis only in an operation id;assignedonly as a participle), so they are not added: the list follows the prompts, and the enumerating test is what brings a new card's verb in.Tests
test/score/scenario-run-grade.test.ts, new top-leveldescribe(L179): the card's reply ("I didn't lend out AST-0041. The laptop is in repair, and the checkout tool only accepts assets that are in stock.") declines, as do "I haven't checked AST-0041 out …", "I did not hand TK-0099 to Lena …", "I won't pay out EC-0118 …", "I didn't dispose of AST-0088." Negatives that stay no decline: "I didn't find a problem.", "I didn't find a problem with AST-0041; it is in stock.", "I didn't see AST-0041 in the repair list, so here are the 3 open orders.", "I didn't check the logs, but AST-0041 is in stock.", "I haven't noticed any checkout of AST-0041 this month." The existing negatives (R1 "a write the reply says it withheld …": "I didn't find any problem, here are the 3 rows", "It won't take long", "I haven't seen an error", "I don't think it should matter", "You did not ask for closed tickets") still pass unchanged.test/runner/mid-tier-run-readings.test.ts, new top-leveldescribe"R3" (L621):ACTINGmaps every operation of every card in the library (51 operations, 9 cards) to its acting verb phrase(s), each a word-for-word run of its English prompt. The test asserts the library's operation set equals the table's keys (a new card or operation without a row fails), that each phrase is in its prompt, and thatI didn't PHRASE.andI won't PHRASE.both decline.fixtures/asset-lifecycle-withheld-loan.recording.json, replayed withRecordedDriver.fromFile, graded withobserveOperation+gradeCardOperationonnamespacedScenario(asset_lifecycle)asasset_admin, with the runner's probe answeringVALIDATION_FAILED/ 400 and no row written:answer (no write attempted),withheld: true, every check passes. Control: the same turn with acreate_recordsent is no withheld write.Ablation (head
b81bc889content,scripts/ablation-replace.mjs, anchor'lend|lent|log(?:ged)?→'log(?:ged)?, anchor 1 → 0, replacement 0 → 1, blobc2a5837c18b9→d3ac9dbca194; tests importsrc/, no dist in the path):Ablated: 3 failed | 73 passed (76); restored: 76 passed
Acceptance notes
asset_lifecycle/scratch/iterate-run/check_out_asset_in_repair/asset_admin). The reply opens with the card's quoted sentences; its last sentence and the two read calls are written here from the card's account ("it then gave the open repair order"), and the probe answer and row state are built in the test, not recorded. It grades from a fail (ablated:withheld: false) to a pass. A full--driver recorded:FCLI replay needs every build turn's files and a booted app, which one turn cannot drive. Whether the run's Iterate operations read 6/6 needs the seat's recording on this head.gallery-refreshrefused the export on two checks; it describes this one. The other is not named on the card, so it is not addressed here.WITHHELD_ACTis English only; a Chinese first-person withheld write ("我没有借出 AST-0041") declines only ifDECLINE's Chinese words (无法, 不能 …) also appear. class: observation · reach: none (no recorded run shows a Chinese reply failing) · carrier: none.add,moveandcloseare acting verbs a report can also negate ("I didn't add anything new, here are the 3 rows"); such a reply would read as a decline. The leak and write readings are independent of this, and a turn that sent a write is never withheld. class: observation · reach: none · carrier: none.Verification
On head
f38ab869(branchclaude/project-thread-rl158j, merge baseorigin/main4ace1fa), each exit code captured before any pipe:pnpm --filter @objectstack/scenarios test: exit 0, Test Files 32 passed (32), Tests 704 passed (704).pnpm --filter @objectstack/scenarios typecheck(tsc --noEmit, which compiles the tests): exit 0. A first run onb81bc889exited 2 on TS18048 (op.ask.enpossibly undefined in the new enumeration);f38ab869reads it asop.ask.en ?? ''and the whole gate loop was rerun on that head.pnpm --filter @objectstack/scenarios build: exit 0.node --stack-size=4000 node_modules/eslint/bin/eslint.js packages/qa/scenarios --no-inline-config: exit 0 (the package has nolintscript).node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack, 61 families): 60 exit 0;pnpm check:dual-build-cjs-loadsexit 3 PREREQUISITE NOT MET (needs every package'sdist/), NOT MEASURED, CI runs it.--ran: "61 derived famil(ies) accounted for — 60 run, 1 NOT-MEASURED".dispatch-gates --tier: no path-derived mandate. 174 changed lines, under the 3000 threshold. No governed surface..changeset/33415-scenario-grader-card-verb-decline.md(file name unique to this card; Scenario grader: a controlled_by_parent detail narrowed by its own read policy fails row-level-security (rowSecurityGap follows the master only) #33414 runs in the same package).🤖 Generated with Claude Code
https://claude.ai/code/session_01FEkQ5nw3MDkRymEzv6FDJs