Skip to content

chore(ci): refresh the Test Core shard-timings dataset - #20388

Merged
objectstack-fleet[bot] merged 2 commits into
mainfrom
claude/shard-timings-refresh-36380128221
Oct 4, 2026
Merged

objectstack-fleet[bot] merged 2 commits into
mainfrom
claude/shard-timings-refresh-36380128221

Conversation

@github-actions

Copy link
Copy Markdown
Contributor

Refreshes scripts/test-shard-timings.json, the balancing input for the Test Core
shard split. Opened automatically by .github/workflows/shard-timings-refresh.yml.
Every byte came out of scripts/measure-test-shard-timings.mjs; nothing here was
hand-edited, and no bound, timeout or matrix entry was touched.

Source

Measured across 1 accumulated run(s) of the HOURLY schedule run of CI on
main — the full-battery run (#16467). A push run on main is affected-only and
is not a measurement of the workspace, so no push run feeds this file.

No single green run measures the whole workspace either — turbo's cache is namespaced
per shard and only main pushes write it, so a
package whose inputs have not changed is a HIT and the generator refuses hits rather
than recording a replay as a duration. Runs are therefore accumulated, each fenced by
its own --run group, until every package the committed dataset holds is measured
again; a package seen in several of them gets the median of those observations.

  • https://github.com/objectstack-ai/objectstack/actions/runs/36380128221

  • Newest run in the set: 36380128221, commit eee0974236c87a7232f9805a19b6e53e3e36da59 — the date this refresh carries.

  • Every run above had all six Test Core (N/6) jobs conclude success with its six
    run-summary artifacts still retained; runs that were cancelled, failed or had lost
    their artifacts were rejected by name in the log before any of these were used.

All 72 package weights were measured in these runs; nothing was carried.

⚠️ This PR references #16173 and #16222 but does NOT carry a closing keyword for them,
because a weekly lane cannot know which cards a given run ought to retire. If this is
the first refresh to land, retire those two by hand as part of merging it.

Measured per-shard suite time on the newest run in the set

1: 1023s  |  2: 757s  |  3: 957s  |  4: 728s  |  5: 728s  |  6: 619s

Predicted bins, before and after

BEFORE  partition-test-shards: self-test OK (70 measured packages -> 71 shard items, 6 shards, max/mean 1.00x <= 1.3x, floor 404s, bins 666/666/666/667/666/666s)
AFTER   file:///home/runner/work/objectstack/objectstack/scripts/partition-test-shards.mjs:967
        throw new Error(
              ^

Error: slice derivation: UNSLICED, @objectstack/cli at 1231.52s is 1391s against a 1321s mean and now fits under 1.3x on its own, so the two cases above no longer prove the slicing is what satisfies the bound. Re-derive the slice count (or retire it) instead of leaving a pin that cannot fail.
    at file:///home/runner/work/objectstack/objectstack/scripts/partition-test-shards.mjs:967:15
    at check (file:///home/runner/work/objectstack/objectstack/scripts/partition-test-shards.mjs:694:5)
    at selfTest (file:///home/runner/work/objectstack/objectstack/scripts/partition-test-shards.mjs:965:5)
    at main (file:///home/runner/work/objectstack/objectstack/scripts/partition-test-shards.mjs:1513:9)
    at file:///home/runner/work/objectstack/objectstack/scripts/partition-test-shards.mjs:1579:3
    at ModuleJob.run (node:internal/modules/esm/module_job:343:25)
    at async onImport.tracePromise.__proto__ (node:internal/modules/esm/loader:681:26)
    at async asyncRunEntryPointWithESMLoader (node:internal/modules/run_main:117:5)

Node.js v22.23.2

The partitioner's own pins RED on this refresh — read this before merging

This is the designed behaviour, not a defect in the refresh: the acceptance bound is
a ratio, and a package that has grown past what any six-way split can bin makes the
pins fail with the arithmetic in the message. The remedy the partitioner names is to
raise the file-level slice count for that package — ⛔ never to raise the bound, and
⛔ never to hand-edit this dataset. This workflow deliberately does neither: it
reports and stops, because both are decisions.

No checks will start on this PR by themselves

It was opened with the Actions GITHUB_TOKEN, and GitHub's recursion guard means a
PR opened that way triggers no workflow runs. Push any commit to the branch, or close
and reopen the PR, to start CI.

Refs #16464, #16173, #16222.

Regenerated by .github/workflows/shard-timings-refresh.yml from the test-core-run-summary artifacts of 1 accumulated run(s) (36380128221), newest 36380128221 at eee0974. Generated, never hand-edited.
@objectstack-fleet

Copy link
Copy Markdown
Contributor

Claim: PM loop round 1
Session: session_01HRYqpqGcWpJuJkDmbRF75w
Account: os-sales
Branch: claude/issue-20388-cli-slice-pins
Worktree: objectstack-issue-20388
Domain: domain:devx
Seat: domain:devx#2
File surface: scripts/partition-test-shards.mjs only, i.e. its self-test slice pins and, if the re-derivation needs it, FILE_SHARDED_PACKAGES. ⛔ Not scripts/test-shard-timings.json (this PR's generated dataset stays byte-identical), ⛔ not .github/workflows/ci.yml (the drift-step wiring is #16465). Stop on breach and explain in the report.
Container & model: M, mode:subagent, model: opus (default tier; dispatch-gates --tier printed no path-derived mandate for this surface)
Clause-②: no
Thread-read: none
Serial constraints cleared: no open PR other than this one touches scripts/partition-test-shards.mjs, scripts/test-shard-timings.json or .github/workflows/ci.yml (4 open PRs, all file lists read); no in-flight claim in the lane; #16465 and #16468 wait behind this PR on the same files.

Why a seat claims a bot PR. The maintainer approved this PR and armed auto-merge on it (2026-09-30T05:51Z, os-zhuang); that state is theirs and this claim does not touch it. What has no owner is the remedy that lets it go green. This PR is the blocker named by Blocked-by: #20388 on #16465; #16468 waits on it too. It cannot land as it stands: by its own body, partition-test-shards.mjs --self-test reds on this dataset at the slice-derivation counterfactual ("UNSLICED, @objectstack/cli … now fits under 1.3x on its own … Re-derive the slice count (or retire it)"), and no CI has run on it (opened with GITHUB_TOKEN). No card or person owns that remedy, so the blocked lane seat takes it (execution-duties.md: an ownerless blocker is claimed and done by the seat it blocks).

How it lands. The dev opens a separate draft PR from the branch above that re-derives the pins so the self-test passes on both datasets: the one on main and this PR's. Once that merges, this seat reviews this PR's dataset diff, then merges main into it (update-branch). The merge also starts its CI, and on green the auto-merge the maintainer armed takes it into the queue. This PR's dataset is not edited by hand at any point.

Stamp: 2026-10-02T22:01Z · read against origin/main 49524f6906, this PR's head 8d60ae8676


Generated by Claude Code

@objectstack-fleet

Copy link
Copy Markdown
Contributor

os-dev-report
{
"issue": 20388,
"status": "done",
"branch": "claude/issue-20388-cli-slice-pins",
"pr": "#21487",
"session": "session_01HRYqpqGcWpJuJkDmbRF75w (subagent of the dispatching PM session; harness-stamped id in the commit's Claude-Session trailer)",
"premise_still_valid": true,
"summary": "Retired the CLI's file-level slicing (FILE_SHARDED_PACKAGES emptied, mechanism kept) because the partitioner's own derivation gives n = 1 on #20388's dataset: K / R / R-worst = 1.124x / 1.124x / 1.053x, all inside 1.3x, with spec (1391.38s) the heaviest item in every case. Pin 3c now refuses any slice count that n - 1 could replace (sliceCountProblems, 5 fixtures plus the live case), and pin 3b also grades a cut of the heaviest package, so it is not vacuous. The mechanism's pins read a fixture map through new optional sliced parameters on sliceCountFor, weighItems and driftReport. Pin 6's inversion pair, which had flipped in the refresh (example-todo 35.30s vs core 57.09s, a second red masked behind 3c's), is now plugin-pinyin-search over sdui-parser, with a guard on the dataset's order. The self-test passes on both datasets at c614a09. measure-test-shard-timings.mjs's live-map case was rewritten too, because its unedited self-test exits 1 under an empty map.",
"decision": {
"choice": "retire (empty map, mechanism kept)",
"readings_on_20388_dataset": {
"K_cli_sliced_2": "bins 1391/1208/1208/1207/1208/1208s, max/mean 1.124x, heaviest spec 1391s, meets",
"R_cli_whole_733.33s": "bins 1391/1208/1206/1208/1208/1208s, max/mean 1.124x, heaviest spec 1391s, meets",
"R_worst_cli_whole_1231.52s": "bins 1391/1308/1307/1307/1308/1307s, max/mean 1.053x, heaviest spec 1391s, meets",
"cli_whole_breach_point": "C ≤ (1.3/6)(6696.67 + C) holds until about 1852s, 1.5x the worst reading"
},
"readings_on_main_dataset": "K 1.000x; R 1.001x (heaviest cli 458s); R-worst 1.549x BREACH (the old bridge, only on the stale dataset)",
"four_axes": "need: slicing moves no bin maximum on the refreshed data and costs a duplicated closure build plus a sequential slice leg on two shards (run 36380128221: closure step 6m15s on 5/6 and 6m43s on 6/6; 5/6 was the longest job at 19m23s) / long-term: keeping 2 leaves a count no failing pin can justify / AI-error: the new 3c reds on an over-sliced count / startup focus: no new gate, and the retirement is immediate",
"interim_model": "between this merge and #20388's, main splits on stale weights with the CLI whole. Costed at #20388's weights, the heaviest bin stays spec's (1775s sliced vs 1773s whole); the CLI's bin is 1116s at 733.33s or 1614s at 1231.52s"
},
"premise_checks": {
"A1": "holds on aa46322 (map {cli:2}; 3b prose 1231.52s/800.7s; 3c CLI_MEASURED = 1231.52)",
"A2": "reproduced on aa46322 with #20388's blob 84342b45 overlaid: exit 1 at partitioner line 1075 (967 in the PR body), the same message. The message mislabels spec's 1391s as the CLI's",
"A3": "main 70 pkgs 3997.47s, cli 458.15, spec 403.65; #20388 72 pkgs 7430.00s, measuredAt 2026-09-28, runs [36380128221], spec 1391.38, cli 733.33; new packages are organizations and vitest-filter-preflight; the package set equals the workspace minus dogfood",
"A4": "well-formed: today's generator writes identical keys and byte-identical note/mergeRule/refresh strings, and accepts the file as --merge-into; skippedAsCached, skippedIncompleteSlices and carriedOver are empty; cli is a two-slice sum from one run; the 09-28 passthrough carrier is still read (sliceOfCliArguments). NOT MEASURED: byte-level regeneration, reason: the run's summary artifacts are no longer retained"
},
"files_changed": [
"scripts/partition-test-shards.mjs (+ map retired, sliceCountProblems/meetsBound, optional sliced params, pins 3b/3c/6 and the slice-items and wiring batteries rewritten, floors 21 to 25 and 9 to 11)",
"scripts/measure-test-shard-timings.mjs (live-map case rewritten for either map state; one stale comment parenthetical dropped) -- outside the claimed surface: the unedited file's self-test exits 1 under the empty map (measured)"
],
"gates": "head c614a09; dispatch-gates --commands (2 paths from git) derived 32 families; all 32 exit 0; --ran reconciliation: 32 derived, 32 run, 0 NOT-MEASURED, 0 UNRUN. Plus report-test-timings --self-test exit 0. The 32: check-ci-filter-parity 0, check-closing-keyword-parity 0 / --self-test 0, check-comment-mask-corpus 0, check-declaration-mirrors 0 / --self-test 0, check-scripts-symbol-anchors 0 / --self-test 0, check-self-test-wired 0 / --self-test 0, check-self-test-workflow-commands 0 / --self-test 0, check-whole-set-label-write 0 / --self-test 0, select-shard-timings-run --self-test 0, measure-test-shard-timings --self-test 0, partition-test-shards --self-test 0, bare-root-worklist --self-test 0, check:agent-test-spelling 0, check:bash32-floor 0, check:cli-command-ids 0, check:cross-package-test-inputs 0, check:driver-memory-census 0, check:entry-guard 0, check:gitlink-declared 0, check:nul-bytes 0, check:parse-guard 0, check:pm-dispatch-gates 0 (1976 cases, 1000.4s), check:pnpm-filter-targets 0, check:ratchet-remedy-authority 0, check:refd-timer-probe 0, check:watch-hint-literal 0. Lint narrowed and proven: eslint --format json reports 2 files, 0 errors / 0 warnings, none ignored; print-config shows 2 per-file rules and no parserOptions.project/projectService, so no untouched file's verdict can move. CI on the PR: in_progress at report time.",
"tests": "partition-test-shards --self-test at c614a09: main dataset exit 0 'self-test OK (70 measured packages -> 70 shard items, 6 shards, max/mean 1.00x ... floor 458s, bins 666/666/667/667/667/666s, file-level slices: none)'; #20388 dataset (blob 84342b45, unstaged overlay in a second worktree, never committed) exit 0 'self-test OK (72 measured packages -> 72 shard items ... max/mean 1.12x ... floor 1391s, bins 1391/1208/1206/1208/1208/1208s, file-level slices: none)'. BEFORE at aa46322: main exit 0, #20388 exit 1 (3c). Battery counts are measured equal to the floors on both datasets (balancing 25, slice items 20, wiring 11). Mutation proof: 20 committed-first mutations via scripts/ablation-replace.mjs, run on both datasets. Each leg: anchor x1, replacement 0 to 1, restored to the HEAD blob with git diff HEAD empty; a bash trap re-proved the hashes in both worktrees. All went red at the targeted case (M1 live 3c 'Retire the entry' at 458.15s / 733.33s; M2-M6 the five 3c fixtures; M7 3b cut; M8 old pin-6 pair green on main and red on #20388 at the new guard (35.3s vs 57.09s); M9 pin 6 weighing; M10-M17 slice-item cases; M18-M19 wiring live + tree fixture; M20 measure live-map case). Controls: measure generator on synthetic env-carried 1/2 + 2/2 CLI summaries gives aa46322 exit 0 cli 733.33, c614a09 exit 1 (the designed refusal); BASE with 3c muted on #20388's dataset reds pin 6 with a 'weighing test-file count again' misdiagnosis; nightly-tiers partition under the new map gives shard 1/2 '@objectstack/cli' whole and 2/2 empty.",
"deviations": [
"landing also in scripts/measure-test-shard-timings.mjs (outside the claim's surface), under the dispatch's File-surface clause (land where measurement shows the change must live): its self-test reds under the empty map (measured exit 1)",
"pin 6 (inversion pair) changed although it is not a slice pin: #20388's dataset reds it (a second red masked behind 3c), so the self-test could not pass on that dataset otherwise",
"optional sliced parameters added to three exported functions (sliceCountFor, weighItems, driftReport); defaults are the live map, so production behaviour is unchanged",
"commit trailers are the model-free pair AGENTS.md requires, not the harness reminder's model-named Co-Authored-By",
"the first gate-loop spelling (a bash -c over the derived list) was refused by the harness safety check and never ran; a static script ran the same list. Its 600s foreground cap moved the run to the background, and it was waited on in the foreground (tail --pid) until exit",
"consequences outside the diff, named in the PR body: the refresh lane's pull_request dry run is predicted to red on this PR (every candidate run predates the map change and is refused by design; the check is running at report time); nightly-tiers shard 2/2 is now empty"
],
"mcp_calls": "0 — no MCP tool used",
"api_writes": "3 relay dispatches (POST /repos/objectstack-ai/objectstack/dispatches): (1) pr_create, executed as POST /repos/objectstack-ai/objectstack/pulls (draft, #21487; body read back byte-identical); (2) label-write, executed as POST /repos//issues/21487/labels (skip-changeset) + POST /repos//issues/21487/assignees (os-sales), read back as matching; (3) this report, executed as POST /repos//issues/20388/comments. Plus 2 git pushes (not REST). No other writes.",
"open_questions": [],
"out_of_scope_findings": [
"carrier: #16468 · spec's 1391.38s is larger than every shard's measured test-step wall in run 36380128221 (max 1023s), consistent with the generator summing overlapping test + test:repo windows (its documented fold). Spec is now the floor at about 83% of its about-1670s breach point, and #16468's ceilings will read this number · noted in the PR's Acceptance notes, not filed",
"carrier: #16465 · ci.yml's slice-leg comments (shards 5/6 and 6/6 'carry a slice') and its drift-step note '(458.15s recorded, 1231.52s measured)' go stale with the retirement; #16465 edits that file · noted, not filed",
"carrier: 承接者:无 · test-nightly-tiers.yml's header says FILE_SHARDED_PACKAGES cuts the CLI in two, and its matrix is [1, 2]; under the empty map shard 2/2 is empty (measured locally) and 1/2 runs the CLI whole · Acceptance notes only",
"carrier: 承接者:无 · packages/cli/vitest.config.ts comment 'partition-test-shards.mjs slices this package (FILE_SHARDED_PACKAGES)' is now stale (the env read stays as dormant wiring, pinned by the tree fixture) · Acceptance notes only",
"carrier: 承接者:无 · shard-timings-refresh.yml: when the generator refuses every candidate, the final ::error:: blames a coverage shortfall ('a suite failed, a package was renamed ...') rather than the refusals. This is inferred from the step's code and predicted to show on this PR's dry run, not yet observed · not filed (no public door)"
]
}


Generated by Claude Code

@objectstack-fleet

Copy link
Copy Markdown
Contributor

os-dev-report
{
"issue": 20388,
"status": "done",
"branch": "claude/issue-20388-cli-slice-pins",
"pr": "#21487",
"session": "session_01HRYqpqGcWpJuJkDmbRF75w (subagent of the dispatching PM session; harness-stamped id in the commit's Claude-Session trailer)",
"premise_still_valid": true,
"summary": "Round 2 (the coordinator's red rehearsal): the retire route stands, and the refresh lane now survives it. At c614a09 the lane's pull_request rehearsal refused all ten eligible hourly runs on main, because every retained summary carries the CLI's 1/2 and 2/2 as OS_TEST_SHARD digests and the emptied map gave the matcher no candidate. d049d35 declares PREVIOUS_FILE_SHARDED_PACKAGES (the outgoing map, cli: 2) beside the map, and the generator's matcher decodes digests against both declared maps by hash equality. Per-run completeness and the refusal of undeclared digests are unchanged. The rehearsal at d049d35 is GREEN (run 37075730446, job 111065090886, first candidate accepted). Round 1 is unchanged: FILE_SHARDED_PACKAGES emptied by the derivation (K / R / R-worst 1.124x / 1.124x / 1.053x on #20388's dataset), pin 3c's minimality check, pin 3b's cut, the fixture-pointed mechanism pins, and pin 6's new inversion pair. The self-test passes on both datasets at d049d35.",
"decision": {
"choice": "retire (empty map, mechanism kept)",
"readings_on_20388_dataset": {
"K_cli_sliced_2": "bins 1391/1208/1208/1207/1208/1208s, max/mean 1.124x, heaviest spec 1391s, meets",
"R_cli_whole_733.33s": "bins 1391/1208/1206/1208/1208/1208s, max/mean 1.124x, heaviest spec 1391s, meets",
"R_worst_cli_whole_1231.52s": "bins 1391/1308/1307/1307/1308/1307s, max/mean 1.053x, heaviest spec 1391s, meets",
"cli_whole_breach_point": "C ≤ (1.3/6)(6696.67 + C) holds until about 1852s, 1.5x the worst reading"
},
"readings_on_main_dataset": "K 1.000x; R 1.001x (heaviest cli 458s); R-worst 1.549x BREACH (the old bridge, only on the stale dataset)",
"four_axes": "need: slicing moves no bin maximum on the refreshed data and costs a duplicated closure build plus a sequential slice leg on two shards (run 36380128221: closure step 6m15s on 5/6 and 6m43s on 6/6; 5/6 was the longest job at 19m23s) / long-term: keeping 2 leaves a count no failing pin can justify / AI-error: the new 3c reds on an over-sliced count / startup focus: no new gate, and the retirement is immediate",
"interim_model": "between this merge and #20388's, main splits on stale weights with the CLI whole. Costed at #20388's weights, the heaviest bin stays spec's (1775s sliced vs 1773s whole); the CLI's bin is 1116s at 733.33s or 1614s at 1231.52s",
"transition": {
"choice": "retire + decode the outgoing map (PREVIOUS_FILE_SHARDED_PACKAGES), not keep-2",
"why_four_axes": "need: every run summary that exists today carries the CLI's two slices, and that is the lane's only input until a day after the merge / long-term: the matcher stays a whitelist of two declared maps, decoded by hash; any later map change gets the same one-day bridge by setting one constant / AI-error: the refusal is unchanged for any digest neither map names (mutation N4), and completeness is still judged within a run / startup: no new gate, and no grace window beyond the artifacts' own one-day life (retention-days: 1). Keep-2 would bring back a count pin 3c refuses on both datasets, with no measured counterfactual (R-worst meets).",
"hypothesis": "CONFIRMED that the empty map caused it, and the rival is FALSIFIED. The 09-30 green rehearsals predate the env carrier, so they could not tell 'empty map refuses' from 'env carrier never decoded on real summaries'. The d049d35 rehearsal is green on main's real env-carried runs once the matcher knows the outgoing map. Local repro on synthetic summaries in the measured turbo 2.10.10 digest format, fed to the lane's generator + --check-coverage commands: aa46322 exit 0 / c614a09 exit 1 ('none: FILE_SHARDED_PACKAGES does not slice it') / d049d35 exit 0, packages identical to aa46322. The real run logs and artifacts are blocked by egress policy (blob host 403, summary_raw 403).",
"monday_refresh": "Mon 2026-10-05 05:30Z after merge: expected to succeed. With one-day retention, its candidates are post-change runs (whole CLI, no digest). Measured: a post-change run alone gives exit 0 (cli 740s); post + pre-change accumulated gives exit 0 (cli 599.08s). Still a prediction, as every refresh depends on an eligible full-battery run existing."
}
},
"premise_checks": {
"A1": "holds on aa46322 (map {cli:2}; 3b prose 1231.52s/800.7s; 3c CLI_MEASURED = 1231.52)",
"A2": "reproduced on aa46322 with #20388's blob 84342b45 overlaid: exit 1 at partitioner line 1075 (967 in the PR body), the same message. The message mislabels spec's 1391s as the CLI's",
"A3": "main 70 pkgs 3997.47s, cli 458.15, spec 403.65; #20388 72 pkgs 7430.00s, measuredAt 2026-09-28, runs [36380128221], spec 1391.38, cli 733.33; new packages are organizations and vitest-filter-preflight; the package set equals the workspace minus dogfood",
"A4": "well-formed: today's generator writes identical keys and byte-identical note/mergeRule/refresh strings, and accepts the file as --merge-into; skippedAsCached, skippedIncompleteSlices and carriedOver are empty; cli is a two-slice sum from one run; the 09-28 passthrough carrier is still read (sliceOfCliArguments). NOT MEASURED: byte-level regeneration, reason: the run's summary artifacts are no longer retained"
},
"files_changed": [
"scripts/partition-test-shards.mjs: map retired, PREVIOUS_FILE_SHARDED_PACKAGES declared, sliceCountProblems/meetsBound, optional sliced params; pins 3b/3c/6 and the slice-items and wiring batteries rewritten; floors 21 to 25 and 9 to 11",
"scripts/measure-test-shard-timings.mjs (outside the claimed surface): the digest matcher reads the previous map too; the live-maps case is rewritten and an across-change case added (env-carried floor 10 to 11); one stale parenthetical dropped"
],
"gates": "head d049d35 (final): dispatch-gates --commands derived the same 32 families as on c614a09; all 32 exit 0; --ran: 32 derived, 32 run, 0 NOT-MEASURED, 0 UNRUN; report-test-timings --self-test exit 0; check:pm-dispatch-gates 976.7s, 1976 cases. eslint --format json at d049d35: 2 files, 0 errors / 0 warnings; no type-aware linting (print-config: 2 per-file rules, no project). CI at d049d35 at report time: Regenerate the shard-timings dataset SUCCESS (rehearsal); Test Core x6 + aggregate SUCCESS (the closure step idle on all six); TypeScript Type Check SUCCESS; Dogfood Regression Gate SUCCESS; Governed Surface Queue Guard SUCCESS; Lint & Repo Gates in_progress. c614a09: rehearsal FAILURE (run 37074888579).",
"tests": "Self-test at d049d35: main dataset exit 0 and #20388 dataset (blob 84342b45 overlay) exit 0, lines identical to c614a09. measure / select-shard-timings-run / report-test-timings self-tests exit 0. Mutation proof re-run from committed d049d35 on both datasets: M1-M20 plus N1-N4 = 24 mutations x 2 trees = 48 legs, all landed (anchor x1, replacement 0 to 1) and restored (HEAD blob, git diff HEAD empty, trap re-proof in both trees). All red except M8 on main (by design). N1 (matcher ignores the previous map) and N2 (previous default not live) red at the live-maps case; N3 (explicit previous dropped) red at the across-change case; N4 (decodes a count neither map names) and M20 red at the live-maps refusal ('1/3 ... was not refused listing (1/2, 2/2)'). Lane repro on synthetic summaries: aa46322 gen 0 + coverage OK; c614a09 gen 1; d049d35 gen 0 + coverage OK, packages identical to aa46322; post-change-only exit 0; mixed exit 0 (cli 599.08). Round 1 measurements stand (K/R/R-worst, BEFORE red, masked pin-6 red, nightly partition).",
"deviations": [
"landing also in scripts/measure-test-shard-timings.mjs (outside the claim's surface), under the dispatch's File-surface clause (land where measurement shows the change must live): its self-test reds under the empty map (measured exit 1)",
"pin 6 (inversion pair) changed although it is not a slice pin: #20388's dataset reds it (a second red masked behind 3c), so the self-test could not pass on that dataset otherwise",
"optional sliced parameters added to three exported functions (sliceCountFor, weighItems, driftReport); defaults are the live map, so production behaviour is unchanged",
"commit trailers are the model-free pair AGENTS.md requires, not the harness reminder's model-named Co-Authored-By",
"the first gate-loop spelling (a bash -c over the derived list) was refused by the harness safety check and never ran; a static script ran the same list. Its 600s foreground cap moved the run to the background, and it was waited on in the foreground (tail --pid) until exit",
"PR body NOT patched: the coordinator asked for the Monday answer 'in the PR body', but the role file forbids a dev PATCH of the PR body (written once, at pr_create; later edits named in the report, written by the seat). The conflict is flagged here, not settled by choosing a side. The full replacement body (v2: the refresh-lane red-then-green section, the Monday answer, the transition choice, N1-N4, gates at d049d35) is at /tmp/claude-0/-home-user/0a250331-4d01-53c7-82d4-060195186652/scratchpad/issue-20388/pr-body-v2.md (18406 bytes, sha256 prefix 2a87f42199cb08ba), ready for the seat's issue_patch on #21487. The live body (v1) still says the rehearsal is 'predicted' to red, which d049d35 overtook.",
"the round-2 change extends the matcher with a declared second map; it is not a looser match. The refusal text names both maps, and the coordinator should judge whether this counts as weakening (mutation N4 proves an undeclared count is still refused)",
"the worktree was re-created for round 2 from the pushed branch; worktrees, node_modules and owned refs are removed again after this report"
],
"mcp_calls": "0 — no MCP tool used",
"api_writes": "round 1: 3 relay dispatches (pr_create to POST /repos/objectstack-ai/objectstack/pulls; label-write to POST .../issues/21487/labels + POST .../issues/21487/assignees; os-dev-report to POST .../issues/20388/comments, comment 5962771016). round 2: 1 relay dispatch, this os-dev-report, to POST /repos//issues/20388/comments. git pushes: 3 in total (empty branch, c614a09, d049d35), not REST. No PR body PATCH.",
"open_questions": [],
"out_of_scope_findings": [
"carrier: #16468 · spec's 1391.38s is larger than every shard's measured test-step wall in run 36380128221 (max 1023s), consistent with the generator summing overlapping test + test:repo windows (its documented fold). Spec is now the floor at about 83% of its about-1670s breach point, and #16468's ceilings will read this number · noted in the PR's Acceptance notes, not filed",
"carrier: #16465 · ci.yml's slice-leg comments (shards 5/6 and 6/6 'carry a slice') and its drift-step note '(458.15s recorded, 1231.52s measured)' go stale with the retirement; #16465 edits that file · noted, not filed",
"carrier: 承接者:无 · test-nightly-tiers.yml's header says FILE_SHARDED_PACKAGES cuts the CLI in two, and its matrix is [1, 2]; under the empty map shard 2/2 is empty (measured locally) and 1/2 runs the CLI whole · Acceptance notes only",
"carrier: 承接者:无 · packages/cli/vitest.config.ts comment 'partition-test-shards.mjs slices this package (FILE_SHARDED_PACKAGES)' is now stale (the env read stays as dormant wiring, pinned by the tree fixture) · Acceptance notes only",
"carrier: 承接者:无 · shard-timings-refresh.yml: when the generator refuses every candidate, the final ::error:: blames a coverage shortfall ('a suite failed, a package was renamed or removed, or its slices could not be assembled') rather than the refusals; OBSERVED on run 37074888579 ('The 0 eligible run(s) ...') · not filed (no public door)"
],
"round": 2
}


Generated by Claude Code

@objectstack-fleet

Copy link
Copy Markdown
Contributor

ACCEPT — PR #21487 (head d049d3539d) · domain:devx seat 2 (session_01HRYqpqGcWpJuJkDmbRF75w) · 2026-10-02T23:33Z

Reviewed against GitHub and the diff, not the report (os-dev-report comments 5962771016 and 5963093078).

Checklist

  • Shape. Draft, base main, first line Unblocks #20388 …. No closing keyword sits near chore(ci): refresh the Test Core shard-timings dataset #20388, ci: Test Core compares each shard's measured duration with its predicted weight — warning at 1.3x, red at 70% of the timeout (maintainer-directed, drift alarm) #16465 or ci: a per-package suite-duration ratchet — a PR that makes a suite exceed its measured ceiling is red; ceilings rise only by ruling (maintainer-directed, growth constraint) #16468: the body says they "remain open". The PR's assignee is os-sales, and it carries skip-changeset. Root scripts/ ships in no package.
  • Files. Exactly two: scripts/partition-test-shards.mjs (+308/−138) and scripts/measure-test-shard-timings.mjs (+120/−33), 599 changed lines in total.
    • ⛔ Not touched: the dataset, .github/workflows/ci.yml, MAX_SHARD_OVER_MEAN, MAX_MEASURED_OVER_PREDICTED and the shard count.
    • No governed path, and no contract-review face.
  • File surface amended (this seat, recorded here): the claim's surface now includes scripts/measure-test-shard-timings.mjs. The producer-side change was measured necessary in two places: its self-test exits 1 under the empty map, and its digest matcher refused every pre-change run.
  • Rulings held.
    • The pins can still fail: 3c judges minimality for every map entry and carries five fixtures. 3b grades a cut of the heaviest package. The undeclared-digest refusal is kept, and the diff spot-checked as matches no slice … or emitted under the map it replaced.
    • The dev reports 24 mutations × 2 datasets, red-then-restored. The seat read the mutated assertions in the diff.
  • Choice: retire the CLI's slicing. It is derived by the file's own minimality rule. On chore(ci): refresh the Test Core shard-timings dataset #20388's dataset K / R / R-worst read 1.124x / 1.124x / 1.053x, with spec heaviest at 1391s in each. PREVIOUS_FILE_SHARDED_PACKAGES is a closed, hash-exact decode bridge, bounded by the summaries' one-day retention. It is not a looser match.
  • CI on d049d353. The refresh rehearsal Regenerate the shard-timings dataset is green; it was red at c614a094 and that red is fixed by this head. Also green: Test Core, TypeScript Type Check, Dogfood Regression Gate and Governed Surface Queue Guard. Lint & Repo Gates was still running at this stamp; the PR is not readied until it concludes success.
  • Nightly tiers. The empty shard 2/2 is handled: the workflow says "An EMPTY shard short-circuits the test step". It wastes a runner but does not red.

Out-of-scope findings, each disposed

Body. The live body is the dev's v2, written by this seat (the role file forbids a dev PATCH). Read back: 18406 bytes, identical.

Landing plan.

  1. Once Lint & Repo Gates is success: pr_ready + automerge_enable through the relay.
  2. On MERGED: this seat merges main into chore(ci): refresh the Test Core shard-timings dataset #20388 (update-branch), which starts its CI, and the auto-merge the maintainer armed there lands it on green.
  3. The window between the two merges splits on stale weights with the CLI whole: modeled worst CLI bin 1614s, actual walls lower. Keep it short.

Generated by Claude Code

@objectstack-fleet
objectstack-fleet Bot added this pull request to the merge queue Oct 4, 2026
Merged via the queue into main with commit ea7ff39 Oct 4, 2026
31 checks passed
@objectstack-fleet
objectstack-fleet Bot deleted the claude/shard-timings-refresh-36380128221 branch October 4, 2026 14:48
@objectstack-fleet

Copy link
Copy Markdown
Contributor

Landed · domain:devx seat 2 (session_01HRYqpqGcWpJuJkDmbRF75w) · 2026-10-04T14:49Z


Generated by Claude Code

akarma-synetal pushed a commit to akarma-synetal/framework that referenced this pull request Oct 7, 2026
…'s own slice-count derivation (objectstack-ai#21487)

Unblocks objectstack-ai#20388 (the Test Core shard-timings refresh), which objectstack-ai#16465 and
objectstack-ai#16468 wait on.

This PR binds no card: objectstack-ai#20388, objectstack-ai#16465 and objectstack-ai#16468 all remain open. objectstack-ai#20388
lands by itself after this merges, on its own green, through the
auto-merge the maintainer armed.

## What this changes

`scripts/partition-test-shards.mjs --self-test` now passes on BOTH
datasets: the `scripts/test-shard-timings.json` on `main`, and objectstack-ai#20388's
(blob `84342b45`, byte-identical to its head `8d60ae86`, overlaid
unstaged in a second worktree and never committed).

- **`FILE_SHARDED_PACKAGES` is emptied** (the CLI's `2` is retired). The
mechanism stays: the item grammar, `expandSlices`, the vitest file-count
floor, the `OS_TEST_SHARD` wiring judge, the generator's slice
reassembly, and the dormant CLI wiring in `turbo.json` and
`packages/cli/vitest.config.ts`.
- **Pin 3c is rewritten.** It no longer substitutes the hard-coded
`CLI_MEASURED = 1231.52` bridge. It asks the committed dataset, for
every map entry, whether `n - 1` slices would also meet the bound
(`sliceCountProblems`), and refuses an `n` that `n - 1` could replace.
Five fixtures hold each refusal in both directions: needed, retire,
lower, unmeasured entry, and an entry below 2.
- **Pin 3b is rewritten.** It grades the real split as before. It also
grades a cut of the dataset's heaviest package in two, so the spread
check is not vacuous while the map slices nothing.
- **The mechanism's pins read a fixture map** through new optional
`sliced` parameters (default: the live map) on `sliceCountFor`,
`weighItems` and `driftReport`. The re-pointed cases are the vitest
floor, the slice-share prediction, drift on a sliced package,
observed-run-wins, `weighItems` slicing, and the wiring reader pointed
at the CLI's real tree.
- **Pin 6's inversion pair is replaced.** `example-todo` over `core`
flipped in the refresh (35.30s vs 57.09s). The new pair is
`plugin-pinyin-search` over `sdui-parser`: 2 vs 13 test files, 14.40s vs
1.62s on `main`'s dataset, 38.77s vs 4.54s on objectstack-ai#20388's. A new guard
reads the dataset's own order, so a flipped pair asks for a new pair
instead of reporting a weighing defect.
- **`PREVIOUS_FILE_SHARDED_PACKAGES` (new, beside the map) holds the
outgoing map, `{ '@objectstack/cli': 2 }`.** The generator's
slice-digest matcher decodes a digest against both declared maps,
exactly by hash, so a run summary written before this change still
reads. Without it, the refresh lane refused every run on `main`; see the
next section. A decoded slice is still summed within its run (an
incomplete set contributes nothing), and a digest neither map names is
still refused. The map has no reader once a day has passed, because run
summaries are kept for one day (`retention-days: 1`).
- **`scripts/measure-test-shard-timings.mjs` (outside the claimed
surface, and why).** This is the matcher change above. Its live-map case
also read `FILE_SHARDED_PACKAGES['@objectstack/cli']`, which reds under
an empty map (measured: the unedited file exits 1). That case now covers
both live maps, and a new case reads a pre-change run's two halves into
their 733.33s whole while still refusing a count neither map names. The
env-carried battery floor goes from 10 to 11. A stale "(2 for
@objectstack/cli today)" parenthetical is dropped.

Battery floors are raised to the measured counts: balancing pins 21 to
25, OS_TEST_SHARD wiring 9 to 11. File-level slice items stays at 20.
The counts are the same on both datasets.

## The three bin readings, and the keep-or-retire choice

Predicted bins at 6 shards against the 1.3x bound, using the
partitioner's own `partition` / `balanceOf` / `expandSlices`:

| dataset | case | bins (s) | max/mean | heaviest item | verdict |
|:--|:--|:--|:--|:--|:--|
| objectstack-ai#20388 (72 pkgs, 7430.00s) | **K** CLI sliced at 2 |
1391/1208/1208/1207/1208/1208 | 1.124x | spec 1391s | meets |
| objectstack-ai#20388 | **R** CLI whole (733.33s) | 1391/1208/1206/1208/1208/1208 |
1.124x | spec 1391s | meets |
| objectstack-ai#20388 | **R-worst** CLI whole at 1231.52s |
1391/1308/1307/1307/1308/1307 | 1.053x | spec 1391s | meets |
| `main` (70 pkgs, 3997.47s) | K | 666/666/666/667/666/666 | 1.000x |
spec 404s | meets |
| `main` | R | 666/666/667/667/667/666 | 1.001x | cli 458s | meets |
| `main` | R-worst (the old bridge) | 1232/708/707/709/708/707 | 1.549x
| cli 1232s | breach |

On objectstack-ai#20388's dataset, both R and R-worst meet the bound, and slicing
changes no bin's maximum (spec is the heaviest item in all three cases).
Solving C ≤ (1.3/6)(6696.67 + C), the CLI fits whole until about 1852s,
which is 1.5x its worst reading. The file's own rule makes n the
smallest count that meets the bound. That count is 1, so the entry is
retired.

Four axes:

- **Real need:** measured. Slicing buys nothing in the predicted maximum
on the refreshed dataset. It costs a duplicated closure build and a
sequential slice leg on two shards. In objectstack-ai#20388's run 36380128221, "Build
the sliced package's dependency closure" took 6m15s on `Test Core (5/6)`
and 6m43s on `(6/6)`, and 5/6 was the longest job at 19m23s.
- **Long-term:** keeping `2` would leave a count no pin can justify. The
old counterfactual cannot be rewritten on any measured basis, because
R-worst meets. Retirement keeps the mechanism, and pin 3 (the floor) is
the live trigger to slice again.
- **AI-error resistance:** the new 3c reds on a slice count that is
larger than needed. A future author cannot leave slicing configured
without a measurement behind it.
- **Startup focus:** fewer live moving parts and no new gate. 3c
replaces a case inside the existing self-test, and the retirement is
immediate.

## The refresh lane across the change: red, then green

- **Red at `c614a094`.** This PR's `pull_request` rehearsal of
`shard-timings-refresh.yml` (run 37074888579, job 111062437870) refused
all ten eligible hourly runs on `main`, 37010481060 through 37070188866.
It then ended with "The 0 eligible run(s) ... NOTHING was regenerated".
- **Cause, reproduced locally** (the run's own log and artifacts are
behind the egress policy here). A synthetic run was built from `main`'s
dataset in the exact turbo 2.10.10 shape: six whole-leg summaries, plus
two slice legs whose `OS_TEST_SHARD` digest is the sha256 of `1/2` or
`2/2` (`d939926f…`, the measured format). It was fed to the lane's own
two commands: the generator with `--run` / `--merge-into`, then
`select-shard-timings-run.mjs --check-coverage`.
  - `aa463223` (the map `{cli: 2}`): exit 0, coverage OK.
- `c614a094` (the empty map): exit 1, "matches no slice the partitioner
can emit for it (none: FILE_SHARDED_PACKAGES does not slice it)".
- `d049d353`: exit 0, coverage OK, and a `packages` map identical to
`aa463223`'s.
- **So the hypothesis holds, and its rival is falsified.** The
2026-09-30 green rehearsals predate the env carrier, so they cannot
separate "the empty map refuses these slices" from "the env carrier
never decoded on real summaries". The rehearsal at `d049d353` does: run
37075730446 (job 111065090886) is **green**. It accepted its first
candidate, with no "dropping that run" warning, so `main`'s real
env-carried summaries decode once the matcher knows the outgoing map.
- **Why decode the outgoing map, not keep the 2 slices.** Read along the
four axes:
- Need: every run summary that exists today carries the CLI's two
slices. That is the lane's only input until a day after the merge.
- Long-term: the matcher stays a whitelist. It reads two declared maps
by hash equality, never a guessed count, and any future map change in
either direction gets the same one-day bridge by setting one constant in
the same PR.
- AI error: the refusal is unchanged for any digest neither map names
(N4 below), and completeness is still judged within a run.
- Startup: no new gate, and no grace window beyond the artifacts' own
one-day life.
- Keeping 2 would bring back a slice count that pin 3c refuses on both
datasets, with no measured counterfactual to replace it.
- **The next scheduled weekly refresh (Mon 2026-10-05 05:30Z), if this
has merged by then: expected to succeed.** With one-day retention, its
candidates are runs made under the new map: whole CLI, no slice digest.
Measured on synthetic summaries at `d049d353`: a post-change run alone
gives exit 0 (cli whole, 740s). A post-change run accumulated with a
pre-change sliced run gives exit 0 (cli 599.08s, the median of 740 and
458.15). So a refresh that straddles the merge also reads. It is still a
prediction: it depends on an eligible full-battery run existing, as
every refresh does.

## Self-test on both datasets (head `d049d353`)

```
BEFORE  main dataset    (aa46322)  exit 0  partition-test-shards: self-test OK (70 measured packages -> 71 shard items, 6 shards, max/mean 1.00x <= 1.3x, floor 404s, bins 666/666/666/667/666/666s)
BEFORE  objectstack-ai#20388 dataset  (aa46322)  exit 1  Error: slice derivation: UNSLICED, @objectstack/cli at 1231.52s is 1391s against a 1321s mean and now fits under 1.3x on its own ... Re-derive the slice count (or retire it) ...
AFTER   main dataset    (d049d35)  exit 0  partition-test-shards: self-test OK (70 measured packages -> 70 shard items, 6 shards, max/mean 1.00x <= 1.3x, floor 458s, bins 666/666/667/667/667/666s, file-level slices: none)
AFTER   objectstack-ai#20388 dataset  (d049d35)  exit 0  partition-test-shards: self-test OK (72 measured packages -> 72 shard items, 6 shards, max/mean 1.12x <= 1.3x, floor 1391s, bins 1391/1208/1206/1208/1208/1208s, file-level slices: none)
```

The BEFORE red reproduces objectstack-ai#20388's AFTER block on today's `main` (line
1075 now, 967 in that body). It also mislabels spec's 1391s as the
CLI's, because the old counterfactual read the overall heaviest item. A
second red was masked behind it. With the 3c throw muted on `aa463223`,
pin 6 reds on objectstack-ai#20388's dataset with "The run is weighing test-file count
again". That is a misdiagnosis: the pair had flipped.

## Mutation proof, one per rewritten or added pin

Every leg was taken from committed `c614a094` through
`scripts/ablation-replace.mjs`. The whole table plus N1 to N4 was then
re-run from committed `d049d353` on both datasets: 48 legs, every one
landed and restored. In each leg the anchor hit 1 and the replacement
went 0 to 1. Each leg was restored to the HEAD blob with `git diff HEAD`
empty, under a shell `trap` that re-proved the hashes in both worktrees
at the end. The red line below is the self-test's first `Error:`, the
same on both datasets unless shown.

| # | mutation | first red |
|:--|:--|:--|
| M1 | re-add `'@objectstack/cli': 2` to the live map | `slice
derivation, committed dataset (1 of 1 ...)`, "sliced 2 ways at 458.15s
(main) / 733.33s (objectstack-ai#20388), but at 1 the split already meets 1.3x ...
Retire the entry" |
| M2 | `meetsBound` always meets | `a count of 2 that 1 cannot replace
was refused` |
| M3 | n-1 = 1 never judged | `a package that fits whole kept its
slicing with no refusal` |
| M4 | only n-1 = 1 judged | `a count of 3 where 2 meets the bound was
accepted` |
| M5 | unmeasured entry not refused | `an entry the dataset never
measured was accepted` |
| M6 | the "at least 2" floor dropped | `an entry of fewer than 2 slices
was accepted` |
| M7 | `expandSlices` stops slicing | `slice spread: cutting
@objectstack/cli (main) / @objectstack/spec (objectstack-ai#20388) in two produced no
... pair to grade` |
| M8 | pin 6 back to the old pair | **green on `main`** (the pair still
holds there); on objectstack-ai#20388: `the dataset no longer measures
@objectstack/example-todo slower than @objectstack/core (35.3s vs
57.09s) ... Pick a new inversion pair` |
| M9 | `weighItems` weighs test-file count | `weight:
@objectstack/plugin-pinyin-search weighed 2 and @objectstack/sdui-parser
weighed 13 ...` |
| M10 | every package takes the map's first count | `slice count: a
package outside the slice map was sliced` |
| M11 | `sliceCountFor` ignores `sliced` | `slice count: the configured
package did not read its configured count` |
| M12 | vitest floor refusal dropped | `slice floor: slicing below the
test-file count was not refused (no throw)` |
| M13 | floor refuses below 1000 files | the floor's own refusal for 500
files, thrown from the "plenty of test files" case |
| M14 | prediction stops dividing | `prediction: a sliced package was
charged its WHOLE dataset entry` |
| M15 | `driftReport` ignores `sliced` | `drift: a sliced overshoot read
0.83x and was not reported as drift` |
| M16 | observed slices ignored | `drift: an observed WHOLE run was
charged a slice-sized prediction (1.67x)` |
| M17 | `weighItems` ignores `sliced` | `weighItems: 1 package(s)
produced 1 item(s), expected 2` |
| M18 | wiring reader's default is not the live map | `slice wiring:
judged 1 of 0 sliced package(s) ...` |
| M19 | `packages/cli/vitest.config.ts` reads `OS_TEST_SHARD_UNREAD` |
`slice wiring, the tree read through a fixture map ... never reads
OS_TEST_SHARD into vitest's shard` |
| M20 | measure: `samplesFromSummary`'s default `sliced` is not the live
map | `env slice: a @objectstack/cli digest of 1/3, a count neither live
map names, was not refused listing (1/2, 2/2) (got "no throw")` |
| N1 | the matcher stops reading the previous map | the live-maps case:
`@objectstack/cli ran with OS_TEST_SHARD set ... matches no slice the
partitioner can emit for it, or emitted under the map it replaced (none:
...)` |
| N2 | `samplesFromSummary`'s default `previous` is not the live one |
the same refusal, from the live-maps case |
| N3 | `samplesFromSummary` drops its `previous` argument | the
across-change case: `a: cli ran with OS_TEST_SHARD set (digest
d939926f…) ... matches no slice ...` |
| N4 | the matcher decodes a count neither map names | `env slice: a
@objectstack/cli digest of 1/3, a count neither live map names, was not
refused listing (1/2, 2/2)` |

## Premise checks (the dispatch's A1 to A4)

- **A1** holds on `aa463223`: the map was `{ '@objectstack/cli': 2 }`,
pin 3b carried the 1231.52s/800.7s prose, and pin 3c carried
`CLI_MEASURED = 1231.52`.
- **A2** reproduced on current `main`; see BEFORE above.
- **A3** recomputed. On `main`: 70 packages, 3997.47s, cli 458.15s, spec
403.65s. On objectstack-ai#20388: 72 packages, 7430.00s, `measuredAt` 2026-09-28, runs
`[36380128221]`, spec 1391.38s (heaviest), cli 733.33s. The two new
packages are `organizations` and `vitest-filter-preflight`. The package
set equals today's workspace minus the CI-excluded `dogfood`.
- **A4: well-formed.** Today's generator writes the identical shape: the
same top-level and `provenance` keys, and byte-identical `note`,
`mergeRule` and `refresh` strings. It accepts the file as a
`--merge-into` target (carried `spec` on a HIT witness).
`skippedAsCached`, `skippedIncompleteSlices` and `carriedOver` are all
empty, and the CLI's 733.33s is a two-slice sum from one run. The 09-28
run carried its slices as a `--shard` passthrough, which today's
generator still reads (`sliceOfCliArguments`). Its run-summary artifacts
are no longer retained (the run lists only `test-core-timing-table` and
`build-output`), so a byte-level re-generation is NOT MEASURED.

## Consequences outside this diff (known, deliberate)

- **The refresh lane.** See its own section above: red at `c614a094`,
green at `d049d353`.
- **Nightly tiers.** `test-nightly-tiers.yml` partitions the one
tier-owning package at 2 shards. Measured locally: shard 1/2 now carries
`@objectstack/cli` whole, and 2/2 carries nothing ("No packages on this
shard", exit 0). The run stays inside its 45-minute timeout by its own
header's estimate. Its header prose and its 2-shard matrix are now
stale; no carrier.
- **The window between this merge and objectstack-ai#20388's.** `main` then splits on
the stale weights with the CLI whole. Modeled with objectstack-ai#20388's weights
standing in for real cost: the heaviest actual bin stays spec's (1775s
sliced, 1773s whole). The CLI's bin is 1116s at 733.33s, or 1614s at
1231.52s. Merging `main` into objectstack-ai#20388 right after this lands keeps the
window short.

## Gates (head `d049d353`)

`node scripts/pm/dispatch-gates.mjs --commands --repo
objectstack-ai/objectstack` (change set from git, 2 paths) derived 32
families. The list is the same on `c614a094` and `d049d353`. On both
heads, all 32 ran with exit 0, recorded and reconciled by `--ran`: "32
derived, 32 run, 0 NOT-MEASURED, 0 UNRUN". `node
scripts/report-test-timings.mjs --self-test` also ran, exit 0. The list
includes the three self-tests (partition / measure /
select-shard-timings-run), `check:cross-package-test-inputs`,
`check:nul-bytes`, `check:pm-dispatch-gates` (1976 cases, 977s),
`check-scripts-symbol-anchors` and `check-self-test-wired`.

Lint, narrowed and proven. `eslint --no-inline-config --format json` on
the 2 changed files reports 2 files, 0 errors and 0 warnings on both
heads, and neither file is ignored. `--print-config` shows 2 per-file
rules (`no-restricted-imports`,
`comment-swallow/no-code-inside-block-comment`) and no
`parserOptions.project` or `projectService`. Type-aware linting is off,
so this diff cannot move any untouched file's verdict. The full `pnpm
lint` is CI's.

`skip-changeset`: root `scripts/` ships in no package's `files[]` (the
root package is private).

## Acceptance notes

- **Observation, not filed:** spec's 1391.38s is larger than every
shard's measured test-step wall in the same run (max 1023s). That is
consistent with the generator's documented fold, which sums the `test`
and `test:repo` windows, and the windows overlapped. Spec is now the
floor, at about 83% of its own breach point (about 1670s). objectstack-ai#16468's
ceilings will read this number.
- **Observed, not filed:** when the generator refuses every candidate,
the refresh lane's final `::error::` blames a coverage shortfall ("a
suite failed, a package was renamed or removed, or its slices could not
be assembled") rather than the refusals, as run 37074888579 showed. No
public door; no carrier.
- **Stale prose outside this diff after the retirement.** The `ci.yml`
slice-leg comments and the 1231.52s note at its drift step are for
objectstack-ai#16465, which edits that file. `packages/cli/vitest.config.ts`'s
"partition-test-shards.mjs slices this package" has no carrier. The
`test-nightly-tiers.yml` header and matrix have no carrier.
`shard-timings-refresh.yml`'s "pin 3c ... the day the CLI comes back
under the bound" is still true in mechanism; no carrier.

---
_Generated by [Claude
Code](https://claude.ai/code/session_01HRYqpqGcWpJuJkDmbRF75w)_

---------

Co-authored-by: Claude <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants