Skip to content

test(dogfood): packaged-action-disabled-dispatch-live picks a not-done task and reads its own ledger row - #27066

Merged
os-zhuang merged 1 commit into
mainfrom
claude/issue-26952-dogfood-not-done-task
Oct 28, 2026
Merged

os-zhuang merged 1 commit into
mainfrom
claude/issue-26952-dogfood-not-done-task

Conversation

@objectstack-fleet

Copy link
Copy Markdown
Contributor

Fixes #26952

Clause-②: no
Metadata-protocol: none

维护者速读

  • 改了什么:只改一个 dogfood 测试文件,让「禁用打包动作」测试挑一个确定未完成的任务,并让 acceptance[5] 自己读取账本行。
  • 为什么改:原来不加过滤和排序地取第一条任务,种子数据里有已完成的任务,取到它时 acceptance[0] 失败并连带 acceptance[5],main 已连续变红六次。
  • 风险与回滚:纯测试改动,不动产品代码,产品断言(409 ACTION_DISABLED、零写入)原样保留;回滚即 revert 本 PR。
  • 先看:packages/qa/dogfood/test/packaged-action-disabled-dispatch-live.dogfood.test.ts 的 beforeAll 取任务一段和 acceptance[5] 开头。
  • 两分钟验证:pnpm --filter @objectstack/dogfood exec vitest run test/packaged-action-disabled-dispatch-live.dogfood.test.ts,预期 8/8 通过。
  • 需要你做的:无,席位落地。

What changes

packages/qa/dogfood/test/packaged-action-disabled-dispatch-live.dogfood.test.ts, test-only:

  1. A provably not-done pick. beforeAll took GET /data/showcase_task?$top=1 with no filter and no order. The showcase seed carries done: true tasks (examples/app-showcase/src/data/seed/index.ts, the first seeded task is one), so the first row could already be done. It now reads $filter={"done":false}&$orderby=id&$top=1. That is the JSON $filter and $orderby spelling other dogfood files already use against this data door, for example activity-withheld-update.dogfood.test.ts. The setup then asserts done === false on the picked row before any switch flips, so a bad pick fails beforeAll with the sentence setup: task ID was picked as not done, not as acceptance[0].
  2. acceptance[5] no longer depends on acceptance[0]'s variable. The file-level markDoneRowId is gone. acceptance[5] reads the showcase_mark_done ledger row itself before the reboot, asserting it exists with the message acceptance[0] disables showcase_mark_done; this clause re-reads the ledger row it wrote, and then pins that the same row id survives the cold boot and the re-enable. acceptance[0] still asserts that exactly one ledger row exists.

Unchanged: both 409 ACTION_DISABLED answers, the engine sentence, the {done, progress, updated_at} before/after equality, and after.done === false. No skip, no retry, no quarantine.

Why

Six main push reds since 21:56Z on Dogfood Regression Gate (3/3) were this file, with the same two clauses each time: acceptance[0] expected true to be false and the acceptance[5] cascade expected '…' to be undefined.

Acceptance notes

Siblings that take ?$top=1 from a seeded object (read on origin/main cb8988ee14). None asserts on the picked row's state, so none has this defect, and none is changed:

  • api-key-owner-revoke: /data/showcase_task?$top=1 is an auth probe. Only the status (200, or 403 API_KEY_REVOKED) is read.
  • bearer-lane-password-change: two auth probes (403 PASSWORD_RESET_REQUIRED, then 200). Status only.
  • data-request-shape-live: the row is a handle. It PATCHes title and reads updated_at as a version token. The task's only validation is the status state machine, which a title PATCH never touches, so a done row behaves the same.
  • identity-admin-fields-org-peer: no $top=1. The seat's grep matched $top=100.
  • internal-field-data-door-positions: an api-key auth probe. Status 200 only.
  • permission-set-assignment-window: door() returns the status only.
  • rest-config-contract-live: the row id is a mount probe handle. expectMounted reads the routing answer, not the row.
  • Also matched by the substring grep, all harmless: comment-thread-parent-pair and activity-withheld-row-predicate read .total under a filter. activity-withheld-update pages with a filter and $orderby=timestamp asc. master-detail-batch-atomic and related-list-server-paging-and-gate use $top=10 or more.

skip-changeset: @objectstack/dogfood (packages/qa/dogfood/package.json) is "private": true and declares no files[]. There is no packages/qa/package.json. Nothing under dogfood/test/** ships.

CI note: dispatch-gates reports that Dogfood Regression Gate does not run on pull_request or merge_group. Its first CI run on this change is the main push battery after the merge, so the local runs below are this PR's evidence for the file.

Verification

Head aaaa7f96, built with pnpm turbo run build --filter=@objectstack/dogfood (exit 0). Each run used the dogfood package's own vitest config (|isolated| project), the same config CI's shard uses, as a single file.

Reproduction on the ORIGINAL file: done-first state forced, acceptance[0] and [5] fail exactly as on main

A scratch copy, not committed, of the origin/main file PATCHes the unordered ?$top=1 task to { done: true, progress: 100 } right after sign-in:

SCRATCH done-first row G2I6Iw9nF_S2Pdv5 true
     × acceptance[0]: the REST door answers 409 ACTION_DISABLED with the engine's sentence and writes nothing 112ms
     × acceptance[5] / [2]: after a cold boot the switch holds; re-enabling updates the same row and re-arms dispatch 1911ms
AssertionError: expected true to be false // Object.is equality
 ❯ test/zz-scratch-26952.dogfood.test.ts:158:24
AssertionError: expected 'K_wXNbQ0V8WU76yh' to be undefined // Object.is equality
 ❯ test/zz-scratch-26952.dogfood.test.ts:249:29
      Tests  2 failed | 6 passed (8)
os-verify-lock: VERDICT command-exit 1
The FIXED file against the same done-first state: green

The same injection applied to this PR's file:

SCRATCH done-first row 4wyelL2XgkXDo2eH true
 Test Files  1 passed (1)
      Tests  8 passed (8)
os-verify-lock: VERDICT command-exit 0

The filter is really applied: a second variant forces the id-ordered first task ($orderby=id&$top=1, unfiltered) to done. The fixed pick still skips it and stays green:

SCRATCH done-first row -Pm8fzBxJ3PIse1h true
      Tests  8 passed (8)
os-verify-lock: VERDICT command-exit 0
The committed file, 3 consecutive runs
 Test Files  1 passed (1)
      Tests  8 passed (8)
 Test Files  1 passed (1)
      Tests  8 passed (8)
 Test Files  1 passed (1)
      Tests  8 passed (8)
Typecheck, lint, derived gates
  • pnpm --filter @objectstack/dogfood typecheck: exit 0. The tsconfig include: ["test/**/*"] covers the file.
  • eslint --no-inline-config on the file: exit 0.
  • node scripts/pm/dispatch-gates.mjs --commands: 51 commands derived and 51 run. 49 exited 0 and 2 exited 3 (PREREQUISITE NOT MET, so NOT MEASURED):
    • check-plugin-teardown-shape --self-test needs an unshallow clone for its pinned positive control, and grades only the checker.
    • check:dual-build-cjs-loads needs dist for packages outside the dogfood closure.
  • --ran reconciliation: 51 derived famil(ies) accounted for — 49 run, 2 NOT-MEASURED (2 DERIVED from a recorded exit 3).

Generated by Claude Code

…e task and reads its own ledger row

beforeAll took `showcase_task?$top=1` with no filter or order; the showcase
seed carries done tasks, so the first row could already be done and
acceptance[0]'s `after.done === false` failed while the door had refused
correctly. Pick `{ done: false }` ordered by id and assert the precondition
in setup, before any switch flips. acceptance[5] now reads the Mark Done
ledger row itself before the reboot instead of a variable acceptance[0]
assigns, so it no longer cascades as `undefined`.

Co-Authored-By: Claude <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QSeKYnxoqB6x8ynuZJhzXk
@objectstack-fleet objectstack-fleet Bot added the skip-changeset PR has no user-facing published change; bypasses the changeset gate label Oct 28, 2026
@github-actions

Copy link
Copy Markdown
Contributor

📓 Docs Drift Check

Nothing 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): node scripts/docs-audit/affected-docs.mjs --json 3230bdbf76844966623e21db5ac940e4b83fd1b9 → packageMentionDocs.

@objectstack-fleet

Copy link
Copy Markdown
Contributor Author

席位核对 — ACCEPT · domain:devx#2 · head aaaa7f9697 · 2026-10-28T04:11Z

席位意见:立即合入(p0,main 已红 6 次)。只改测试:改为取一个确定未完成的任务、先断言前提再动开关,验收 [5] 不再依赖验收 [0];产品断言(409 ACTION_DISABLED、什么都没写入)一字未放松。

Shape: draft → main. Fixes #26952. One file, packages/qa/dogfood/test/packaged-action-disabled-dispatch-live.dogfood.test.ts, +19/−7. skip-changeset, test-only. Not governed.

Seat's read of the diff:

  • beforeAll picks ?$filter={"done":false}&$orderby=id&$top=1 (the JSON filter spelling other dogfood files already use on /data). It asserts 200, a non-empty pick, and done === false before any switch flips.
  • The file-level markDoneRowId is gone. acceptance[5] reads the showcase_mark_done ledger row itself, with a message naming acceptance[0].
  • The product assertions are untouched. Nothing is skipped, retried or quarantined.

Reproduction (dev, on head): the ORIGINAL file plus a scratch patch forcing the unordered pick to a done task fails exactly main's two clauses: acceptance[0] expected true to be false, and acceptance[5] expected '…' to be undefined. The FIXED file under the same injection passes 8/8. A control that forces the id-ordered first task to done also passes 8/8. The committed file ran 3× in a row at 8/8.

Gates: at head aaaa7f9697: 32 success, 17 skipped, 0 failure. The Dogfood shard jobs are skipped on pull_request by design (aggregate success), so the first CI run of this file is the main push battery after merge, and the seat reads it there. The dev's local union is 51 derived: 49 exit 0, 2 NOT MEASURED (shallow clone; dist outside the closure).

Open question: answered A (the filtered pick stays). Every clause is indifferent to which not-done task it gets.

Siblings: none of the 7 ?$top=1 dogfood files has the defect; each is listed in the PR's Acceptance notes with its reason.

Landing: ready + auto-merge now. After merge, the seat reads the next main push run's Dogfood Regression Gate (3/3).


Generated by Claude Code

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

Labels

size/s skip-changeset PR has no user-facing published change; bypasses the changeset gate tests

Projects

None yet

3 participants