Skip to content

ci(dogfood): carry the shard slice in a task env so the dogfood test hash sees its upstream closure - #21074

Merged
objectstack-fleet[bot] merged 3 commits into
mainfrom
claude/issue-20820-dogfood-shard-honest-hash
Oct 1, 2026
Merged

objectstack-fleet[bot] merged 3 commits into
mainfrom
claude/issue-20820-dogfood-shard-honest-hash

Conversation

@objectstack-fleet

Copy link
Copy Markdown
Contributor

Fixes #20820

Clause-②: no

What

The required Dogfood Regression Gate (k/3) leg ran turbo run test --filter=@objectstack/dogfood --only -- --shard=k/3. --only drops the ^build closure out of the dogfood#test hash, so a PR that changed only an upstream package could match a main-seeded cache entry and be replayed green. This ports #19278's shape to the dogfood leg:

  • turbo.json: @objectstack/dogfood#test now declares OS_TEST_SHARD in its env. The shared test task already declares it (ci(test-core): carry the shard slice in a task env so the slice leg's hash sees its upstream closure (#19278) #20824), but a per-package task entry REPLACES the shared entry's env instead of extending it, so the shared declaration did not cover dogfood: measured, the pre-change plan listed only OS_TEST_TIERS for that task.
  • packages/qa/dogfood/vitest.config.ts: reads process.env.OS_TEST_SHARD into the root test.shard (same spelling as packages/cli/vitest.config.ts).
  • .github/workflows/ci.yml: the leg exports OS_TEST_SHARD="k/3" and runs pnpm turbo run test --filter=@objectstack/dogfood --log-order=stream: no --, no --only, no --force. Stall guard, dogfood.log tee, NODE_OPTIONS / --report-dir, cache restore/save are untouched. The step's comment states the new mechanism.

Also touched (comment only, one deviation from the card's file surface, flagged): the comment of the preceding closure-build step said it exists "so that the sharded run in the next step can be --only", which is now false; it now says so. The step itself is unchanged.

No second shard mechanism. scripts/measure-test-shard-timings.mjs / partition-test-shards.mjs / report-test-timings.mjs are untouched: the dogfood leg passes no --summarize and has no timings consumer, so there is nothing to reuse or change.

Measurements

turbo 2.10.10 dry-runs (--dry=json) and real vitest runs, in this worktree at head 55bd9e0.

Pin 1, hash moves (shard 1/3, edit = append a comment line to the file, restored from HEAD after):

leg clean + packages/objectql/src/index.ts
old (--only -- --shard=1/3) a963b53363c79e20 a963b53363c79e20 (unchanged: the defect)
new, pre-build tree d6f169ed1431553e 2ee13c0afd852c96 (moves)
new, post-build tree bd114335fad78510 55dc2dd1da35f8e0 (moves)

The pre-build and post-build clean hashes differ (d6f169ed vs bd114335); I did not isolate why (suspect built output under the examples/app-showcase/** input). Each row's before/after is on one tree.

Pin 2, lit control (post-build tree, shard 1/3, clean bd114335fad78510):

  • packages/client-react/src/index.tsx (a workspace package NOT in the dogfood closure, checked against the plan): bd114335fad78510, unchanged.
  • packages/qa/dogfood/test/action-params-contract.dogfood.test.ts (dogfood-internal): a5dc81d7aadebe29, moves.

Pin 3, shards differ: post-build 1/3 bd114335fad78510, 2/3 0387e6b5b568a93c, 3/3 d3b158ab11f62582; pre-build d6f169ed1431553e / fd1f57f4bbe9537f / bc48cac953e838cc. Pins 1 to 3 are dry-run hash readings, not executions.

Pin 4, the shard is honoured: vitest 4.1.11 (lockfile). Real OS_TEST_SHARD=k/3 vitest run in packages/qa/dogfood ran 50 / 49 / 49 test files (148 in total, 148 in the union, 0 overlap between any two shards), 0 failed in each. vitest list --filesOnly is NOT a valid measure of this: it prints all 148 files for any shard, even with --shard=1/3 on the command line. #21032's vitest 5.0.2 is NOT MEASURED; the env-read shape is the one packages/cli/vitest.config.ts already uses, so the dogfood read breaks together with it if a vitest line stops honouring test.shard.

Plan cost of dropping --only (OS_TEST_SHARD=1/3 turbo run test --filter=@objectstack/dogfood --dry=json): 66 tasks. Against the cache the step above fills: 63 HIT / 3 MISS (the test, plus two #build nodes of packages with no build script, which never execute); cold cache: 66 MISS. The leg's 65 build hashes are identical to turbo run build --filter=@objectstack/dogfood's plan (65 same, 0 differ, 0 missing), so the closure replays rather than rebuilds. The old leg planned 1 task.

Pin 5, nothing is replayed green: a replay needs an equal dogfood#test hash. That hash now carries the shard value (pin 3), the upstream closure (pin 1) and the package's own files (pin 2), the control shows it is not moving on everything, and pin 4 shows the shard value is what selects the files that execute. NOT MEASURED: an end-to-end executed replay across an upstream edit on the new leg.

Gates

node scripts/pm/dispatch-gates.mjs --commands: 79 derived; 78 run, all exit 0, recorded with --ran. pnpm check:dual-build-cjs-loads exited 3 (PREREQUISITE NOT MET: Run pnpm build first, nothing measured), so it is NOT MEASURED; the diff changes no built output. pnpm --filter @objectstack/dogfood typecheck exit 0, but that program does not compile vitest.config.ts (0 hits in tsc --listFiles), so the satisfies clause is checked only by vitest loading the file. actionlint is not installed here: NOT MEASURED; ci.yml parses as YAML and turbo.json as JSON.

Changeset

None. @objectstack/dogfood is "private": true, and ci.yml / turbo.json ship in no package's files[].

Acceptance notes

None beyond the above.


🤖 Generated with Claude Code

https://claude.ai/code/session_01VDtqoecgES7ScQYGbFVDRv

@github-actions

github-actions Bot commented Oct 1, 2026

Copy link
Copy Markdown
Contributor

📓 Docs Drift Check

⚠️ 1 changed file(s) yielded no anchor (packages/qa/dogfood/vitest.config.ts), so the pages documenting them are NOT COVERED by this run — this is not a clean bill of health for those files. Nothing else in this diff resolved to a documentable surface (no symbol, route or SDK anchor derived from 1 changed package(s)).

What this run could not see
  • 1 changed file(s) yielded no anchor (packages/qa/dogfood/vitest.config.ts) — pages documenting those are invisible to this run
  • a page that states a rule by its inputs shares no identifier with the emitter that implements the rule, so an emitter-only diff cannot list it — not on this run and not on any run. Measured on fix(driver-sql): emit varchar(maxLength) for a text field a declared index keys on #11430: content/docs/protocol/objectql/types.mdx documents the text-family column mapping by the ObjectQL type names it maps FROM (text / textarea / html) while the diff changed createColumn; it went unlisted, and it was the page that diff falsified, in four places. No shared token exists to detect this on, so a rule your change carries has to be re-read by hand in the pages that restate it.
  • a key NAME is not a key, so the hand re-read the line above prescribes can land on the wrong schema. The same spelling is authorable on one governed type and a [REMOVED] tombstone on another for each of active, aria, joins, objects, template, tools and version (censused on [finding] tools is a key on BOTH AgentSchema (tombstoned, dead) and SkillSchema (live, cloud-attested), so a name-based search attributes skill examples to the agent key — it produced a false stop-the-line alarm on PR #19059 #19093 over the liveness ledger's governed types, top-level keys); nothing in a search result distinguishes the two, so a grep hit on a LIVE example reads as evidence about the DEAD key. Measured on fix(spec): the agent.tools liveness row says dead — it claimed live on a key the schema tombstoned #19059: content/docs/ai/agents.mdx was reported as contradicting the agent.tools tombstone over its tools: example at :161, which is inside the defineSkill({ block opened at :155 — the page was already correct. Settle ownership by PARSING the value against both schemas, never by the name: that literal PASSES SkillSchema, and as an AgentSchema it FAILS at tools with the tombstone prescription. ⛔ These names are not the whole class — a key retired through a .strict() guidance map leaves no tombstone in the walked shape and none of them here (tool.category, live as AIToolDefinition.category).

Coarse fallback — 2 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 5dbeb7d7b7e1deb7a64bd3178d2faada69c3097c → packageMentionDocs.

@objectstack-fleet
objectstack-fleet Bot marked this pull request as ready for review October 1, 2026 04:47
@objectstack-fleet
objectstack-fleet Bot enabled auto-merge October 1, 2026 04:47
@objectstack-fleet
objectstack-fleet Bot added this pull request to the merge queue Oct 1, 2026
Merged via the queue into main with commit e0c768f Oct 1, 2026
36 of 37 checks passed
@objectstack-fleet
objectstack-fleet Bot deleted the claude/issue-20820-dogfood-shard-honest-hash branch October 1, 2026 05:51
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

1 participant