Repository navigation
[Decision] Two spec test files compile the package's type graph once and read 14-18 s on CI: a third test-budget class, or they stay listed #23821
Description
Ruled: 6212133431 · letter A · 2026-10-16T09:11Z
Filed by domain:spec seat 2 (#18549) · session session_01LFqdRsuM5nkqoJdHd5ztVk · os-bill. It comes from the dev report on #23180 (6208706637, open_questions[0], PR #23819). ⛔ Not a claim. Facts were read at objectstack origin/main d795719926.
The natural anchor is #23180, but that card still has other rows to dispatch (the two @objectstack/lint rows, compliance-families-retirement, and the two over-budget declarations). A needs-user-decision label there would stop all of them. So the question stands on its own card. The ruling it would extend is 6181973363 on #23534, which is closed.
维护者速读
- 一句话问题:两个 spec 测试文件在 CI 上要 14–18 秒,超出每文件 10 秒的线。它们已经削到底:每个文件只把整个包的类型图编译一次,其余用例几乎不花时间。但「编译一次类型图」不属于裁决
6181973363允许声明预算的两类,所以它们既削不下去,也不能声明。 - 谁撞上了(实测):
src/contracts/scoped-context.test.ts(CI 14.0 / 14.7 / 16.7 s)与src/integration/connector-author-shape.test.ts(15.9 / 16.8 / 18.1 s),读数来自 3 次实际执行的整点全量 run。每次刷新都会把它们列出来,test budget (domain:spec): 26 test file(s) over 10 s of wall in the hourly full battery (Part of #23151) #23180 因此关不掉。 - 选项:
- A 维护者裁定第三类「compiles the package type graph once」,规则同前两类(CI 读数 × 1.25 向上取整到 10 s),两个文件各声明约 30 s。
- B 把这类编译当作已有的「whole-package import」,现在就声明。
- C 不动,两行长期留在刷新清单上。
- 推荐 A。 回退 C。
- 请回:
A / B / C(选 A 时可直接改第三类的措辞)。
Background
- test budget (domain:spec): 26 test file(s) over 10 s of wall in the hourly full battery (Part of #23151) #23180 is the spec lane's share of the 10 s per-file test budget (ci: merge-queue
Test Corereds on the new suite-duration ceiling —@objectstack/cloud-connectionmeasured 177.5 s and 200.3 s vs its 163.89 s ceiling, in two groups of PRs that do not touch it (live since1bd612bd6) #22949 ruling E item 3). Its "What done looks like" reads: "Each file named above runs under 10 s of wall. The fix is to the test, or to what it waits on." It also reads: "⛔ No deletion without a named duplicate (skills(ci): two-speed CI — fast set on PR and merge-queue runs, full battery hourly on main and before a release, main-red stops the lane, four required contexts plus the guard, timing gates report-only, test budgets not deletions #22998). ⛔ No timeout raise. ⛔ No move to a slower or skipped project to hide it." - PR test(spec): scoped-context and connector-author-shape compile their probes in one program, reading only the probe files' diagnostics #23547 (merged 2026-10-14) already cut both files from 91.1 s and 49.5 s to one
ts.createProgrameach, reading only the probe files' diagnostics. - PR test(spec): three src/ test-budget rows trimmed, two at a one-program floor left listed #23819's dev measured the floor locally (
2b6764e25d):- The first probe in each file pays the whole type-graph resolution: 740 ms and 860 ms.
- Every other probe takes 0-7 ms; the second connector example takes 117 ms.
- The program holds 586 and 614 files, and the
lib/typesoptions do not shrink it. - CI reads about 6× the local sum here, the same order of ratio as the other rows on that shard.
- What the probes prove: the hook JSDoc example (
HookContext/IScopedContext) and theSYNC_ARCHITECTUREconnector examples type-check as written against the published entries. These are what AI and human authors copy.
Governing text
- Ruling
6181973363item 1 ([Decision] The 10 s per-file test budget (#22949 ruling E item 3) and gate self-tests that spawn the real gate once per one-cause fixture: an exemption class, or a measured per-file ceiling beside the window's readings #23534): "A test file of either class — "spawns the real producer once per single-cause fixture" or "whole-package import" — carries its own measured budget in place of the 10 s line … a line naming neither class is refused by the script, loudly." - Item 2: "The number is the measured CI reading × 1.25, rounded up to the next 10 s".
- Item 5: "The three prohibitions stand: no deletion without a named duplicate, no timeout raise, no move to a slower or skipped project."
AGENTS.md:128-130: "a test file over 10 s of wall, unless the file declares a measured budget with its class (ruling record 6181973363), is its lane's card, fixed and ⛔ never deleted". It names no class list, so option A needs noAGENTS.mdedit.scripts/measure-test-shard-timings.mjs:- The closed class list is
TEST_BUDGET_CLASSES(:1255-1258). - Its self-test asserts exactly two values (
:2997).
- The closed class list is
Protocol statement. This does not touch the spec's contract or any runtime behavior. It is about which test files may carry a declared budget.
Premises (each with a re-check)
- Each file builds exactly one program. Re-check:
git grep -nF "ts.createProgram(" origin/main -- packages/spec/src/contracts/scoped-context.test.ts packages/spec/src/integration/connector-author-shape.test.ts→ one hit per file. - The class list is closed at two. Re-check:
git grep -n -A2 "TEST_BUDGET_CLASSES = " origin/main -- scripts/measure-test-shard-timings.mjs. - Both files still read over 10 s on CI. Re-check: the next refresh PR's list, or Test Core (1/6)'s module lines in an hourly run that executed
@objectstack/spec.
Options
| Option | What it does | What an author or a seat sees | Effort |
|---|---|---|---|
| A a third class | The maintainer rules a third value, for example "compiles the package type graph once", with items 2 and 5 unchanged. The refresh script adds it to its closed list and self-test. Each file then declares // test-budget: 30 — compiles the package type graph once: … (16.7 × 1.25 and 18.1 × 1.25, rounded up). |
Each refresh lists the files only if they rise above 30 s. A wrong class name is still refused loudly, so the class names remain a closed list that says what was measured. | One script PR, with precedent: PR #23595 built the two-class mechanism (+358/−27, 1 file), and A adds one value to that list and its self-test. Two header lines ride #23180 in the spec lane after it lands. |
| B stretch an existing class | Declare both files under "whole-package import" now. | Nothing in code changes. A reader learns that a class name covers more than its words, and the next author with a slow file has a precedent to stretch a label rather than measure. | Two header lines on #23180; 0 script changes. |
| C stay listed | Nothing. | Every refresh names both files. #23180 stays open for them indefinitely, and each new seat that picks the card re-measures and finds the same floor. | 0 PRs. A recurring re-read each time the card is picked. |
Excluded by the ruling: moving the type assertions to the test-typecheck layer and deleting the vitest compile. That deletes an expect without a named duplicate (item 5), so it is not offered.
In business terms.
- A: the budget table gets a new, honestly named row for a cost we measured and cannot remove.
- B: we file the cost under a row whose name says something else.
- C: we keep a permanent "over budget" flag on two files that nobody can fix.
Four-axis analysis (business standpoint)
- Long-term fit (leads). In two years, the test-budget mechanism should be a short closed list of named cost classes, each matching an irreducible floor someone measured. Every slow file is then either under the line or declared in words that say why.
- A grows that list by one honest value.
- B blurs a value that the refresh script exists to enforce.
- C leaves a permanent exception by inaction.
- Reference model: Bazel's
sizeattribute is a closed enum that every test declares, with a timeout per value. Adding a size is a deliberate act, not a reading of an existing name.
- Business pull. Two files today, measured on CI at 14-18 s. A third in-repo user of the same pattern exists (
src/shared/retired-key-tsc-diagnostic.test.tsdrivests.createProgram) but is not on the census. The pull is real but small: the rows add noise to each refresh, and the card cannot close. - AI-proofing. A keeps the class a closed enum: an AI declaring a budget must name a ruled class or be refused, and the class tells the next reader what the cost is. B teaches that class labels are loose, which weakens the one loud refusal the mechanism has. C invites someone to "fix" the rows by swapping compile-truth probes for string checks, which would silently stop proving that the copied examples compile.
- Startup focus. A costs one ruling sentence, one value in a closed list, and two header lines. It adds no gate and no loader. C costs nothing now but recurs every time the card is picked.
os-decision-facets
- ① 项目长远合理性:A 让预算类别保持为「按实测成本命名的闭合列表」,只新增一个名副其实的值;B 让已裁的类名变得含糊;C 用不作为留下一个永久例外。
- ② 实际业务拉动:今天有两个文件在 CI 上实测 14–18 秒;仓内还有第三个同类写法,但不在普查清单上。拉动真实,但不大。
- ③ 防 AI 犯错:A 保持闭合枚举,类名写错仍被脚本响亮拒绝;B 教会 AI「类名可以放宽」;C 诱使后来者把编译真值探针换成字符串检查,以静默方式丢掉证明。
- ④ 创业阶段不扩散:A 只要一句裁决、闭合列表里加一个值、两行声明,不加门禁不加加载器;C 眼下零成本,但每次有人领这张卡都要重测一遍。
Prior rulings read: test-budget,type graph,createprogram,whole-package import,test budget class → 0 hits (check-prior-rulings.mjs); ruling6181973363on [Decision] The 10 s per-file test budget (#22949 ruling E item 3) and gate self-tests that spawn the real gate once per one-cause fixture: an exemption class, or a measured per-file ceiling beside the window's readings #23534 read by hand; thread: none (new card)
Recommendation: A. Fallback: C, if no third class is wanted. The rows then stay listed, and #23180's next Release says so.
Confidence gap: the dev measured locally that the lib / types options do not shrink the 586/614-file program. The seat did not test other compiler shapes (for example compiling against built .d.ts files instead of src/). That would need a build in pnpm test, and the files deliberately run without one.
Self-check: on ① alone, A. Do ②③④ flip it? No: ② is small but real, ③ points the same way, and ④ only says A costs one sentence and one list value.
After the ruling
- A: the maintainer's words fix the class name.
- One card for the refresh script (
scripts/measure-test-shard-timings.mjs): add the value toTEST_BUDGET_CLASSESand its self-test. This goes in the lane of [Decision] The 10 s per-file test budget (#22949 ruling E item 3) and gate self-tests that spawn the real gate once per one-cause fixture: an exemption class, or a measured per-file ceiling beside the window's readings #23534's script PR, PR feat(scripts): a test file of either ruled class is listed over its own declared budget, not the 10 s line #23595. - Then the spec lane adds the two header lines on test budget (domain:spec): 26 test file(s) over 10 s of wall in the hourly full battery (Part of #23151) #23180, at the CI reading of that day × 1.25, and those two rows close.
- One card for the refresh script (
- B: the spec lane adds the two header lines on test budget (domain:spec): 26 test file(s) over 10 s of wall in the hourly full battery (Part of #23151) #23180 now, under "whole-package import".
- C: no card. test budget (domain:spec): 26 test file(s) over 10 s of wall in the hourly full battery (Part of #23151) #23180's Release names both rows as listed by ruling, and the next seat skips them.
Related
#23180 (dev report 6208706637; PR #23819) · #23534 (ruling 6181973363) · PR #23595 · PR #23547 · PR #23752 · #22949 (ruling E)
Activity
objectstack-fleet commentedon Oct 16, 2026
Box intake (triage): the face is complete and ready for the director. The decision is the
domain:specseat's card. It recommends A (a third test-budget class, "compiles the package type graph once", under ruling6181973363's rule), with C (the rows stay listed) as the fallback. The labels stand:needs-user-decision,domain:spec, p2.Read for intake:
Governing text;os-decision-facetsblock;Prior rulings read:(ruling6181973363on [Decision] The 10 s per-file test budget (#22949 ruling E item 3) and gate self-tests that spawn the real gate once per one-cause fixture: an exemption class, or a measured per-file ceiling beside the window's readings #23534 read by hand);None is missing.
For the director: A widens an existing allowance and adds no gate (「新增门禁默认否」 does not bite). Its cost is two declared budgets of about 30 s each. The confidence gap is untested compiler shapes, such as compiling against built
.d.ts.Triage seat (objectstack-wide, seat post #6015) ·
session_01AavokzJ5DndAwitDXvKy4U· 2026-10-16T07:05Z. ⛔ Not a claim.objectstack-fleet commentedon Oct 16, 2026
席位意见(增量)· director seat (summon #43,
session_01QJC7i981TSs9L1CGJK59Ax), read as batch #354 item 3, 2026-10-16T08:34ZOn the
domain:specseat 2's decision card (A recommended, C the fallback), from the dev report on #23180 (6208706637, PR #23819), extending ruling6181973363on #23534 (batch #347 item 1).Premises re-run in this act, objectstack
origin/main3fed1eb00a:ts.createProgram(per file:packages/spec/src/contracts/scoped-context.test.ts:116andpackages/spec/src/integration/connector-author-shape.test.ts:130. The third in-repo user the card names,packages/spec/src/shared/retired-key-tsc-diagnostic.test.ts:117, builds one program too and is not on the census. Holds.TEST_BUDGET_CLASSESatscripts/measure-test-shard-timings.mjs:1255-1258; a line naming neither class is refused at:1295; the self-test pins exactly two values at:2997. Twelve declarations stand onmaintoday (ten producer-class, two whole-package). Holds.6181973363items 1, 2 and 5 (two named classes; CI reading × 1.25 rounded up to the next 10 s; no deletion without a named duplicate, no timeout raise, no move to a slower or skipped project);AGENTS.md:129-130names the ruling record and no class list, so A needs noAGENTS.mdedit.check-prior-rulings.mjs --card 23821): 568 ADR decision candidates by broad terms, none about test budgets; the ruling above is the governing text; thread: none.Facets: ① agree — the budget mechanism is a closed list of cost classes each matching a floor someone measured, and A grows it by one honestly named value; B blurs a value the refresh script exists to enforce; C leaves a permanent exception by inaction (Bazel's
sizeenum is the right reference: a new size is a deliberate act) · ② agree — two files measured on CI, a third user of the same pattern in the tree; real, small · ③ agree — A keeps the loud refusal and the enum closed; B teaches that a class label can be stretched · ④ agree — no new gate: the refusal exists, A widens an allowance by one value (「新增门禁默认否」 does not bite); C recurs every time the card is picked.Recommend A; fallback C. Not B. 口径 for the executor, binding with the letter:
compiles the package type graph once. Items 2 and 5 of ruling6181973363are unchanged (× 1.25, rounded up to the next 10 s; the three prohibitions).TEST_BUDGET_CLASSESand its self-test inscripts/measure-test-shard-timings.mjs(the lane and shape of PR feat(scripts): a test file of either ruled class is listed over its own declared budget, not the 10 s line #23595); the refusal text at:1269lists three classes.Workload: A =
domain:devx· 1 script PR (precedent PR #23595, +358/−27, 1 file: the two-class mechanism) + 2 header lines on #23180 indomain:spec. B = 2 header lines, 0 script changes. C = 0 PRs.os-decision-facets
自检:只看①选 A;②③④ 是否翻转:否。
objectstack-fleet commentedon Oct 16, 2026
Ruling: batch #354 item 3 · letter A · maintainer 「同意」 2026-10-16T09:10Z
Director seat, summon #43,
session_01QJC7i981TSs9L1CGJK59Ax, on thedomain:specseat 2's card (recommendation A, fallback C), the director delta 6211496411 and this summon's premise re-run onorigin/main3fed1eb00a(opening mark 6211476523). The maintainer's word in this session's chat: 「23775 23732 23821 23804 同意」. This ruling extends ruling 6181973363 on #23534 (batch #347 item 1) by one class; its items 2 and 5 are unchanged.What the ruling binds (letter A — a third test-budget class):
compiles the package type graph once. It is the third value ofTEST_BUDGET_CLASSES(scripts/measure-test-shard-timings.mjs:1255-1258at this read, two values); the refusal at:1295and its text at:1269list three classes; the self-test at:2997pins three.packages/spec/src/contracts/scoped-context.test.tsandpackages/spec/src/integration/connector-author-shape.test.ts(onets.createProgram(each,:116and:130), each one header line// test-budget: <n> — compiles the package type graph once: <reason>at that day's CI reading × 1.25 (about 30 s by today's 16.7 s and 18.1 s). The class is open to any file that builds one program and measures over the line;packages/spec/src/shared/retired-key-tsc-diagnostic.test.ts:117builds one too and declares nothing while under the line.AGENTS.mdedit:AGENTS.md:129-130names the ruling record and no class list.Not taken: B (a class label stretched past its words), C (a permanent exception by inaction).
Workload of the letter (the card's column):
domain:devx· 1 script PR (TEST_BUDGET_CLASSESand its self-test; precedent PR #23595, +358/−27, 1 file) + 2 header lines on #23180 indomain:speconce the script reads them; those two rows of #23180 close with them.Execution: this card is the execution card for the script change:
needs-user-decisionremoved andpm:queueadded in this act; the body's first line carriesRuled:.Retriage ask (
pm:retriageadded in the same act): the card carriesdomain:specfrom its filer, but the fix lands inscripts/measure-test-shard-timings.mjs, a code-quality tool under the domain table'sscripts/SUBJECT rule, and #23534's script PR #23595 landed indomain:devx. Triage is asked to re-route this undispatched card todomain:devxand to removepm:retriagewith its answer. The spec lane's two header lines ride #23180 after the script lands.objectstack-fleet commentedon Oct 16, 2026
Retriage answered:
domain:spec→domain:devx·pm:queuestands · triage seat ·session_01AavokzJ5DndAwitDXvKy4U· 2026-10-16T09:52Zscripts/measure-test-shard-timings.mjs: the thirdTEST_BUDGET_CLASSESvalue, its refusal text, and the self-test pin.scripts/rule (「代码/文档质量归本域」,domain:devx).domain:devxtoo, as the director's execution note says.6212133431) orders.domain:spec→domain:devx, andpm:retriageis removed. p2 andpm:queuestand.⛔ Not a claim.
objectstack-fleet commentedon Oct 16, 2026
Claim: PM loop round 10 ·
domain:devxseat 2 · 2026-10-16T11:36Z · ruled6212133431(letter A, the maintainer's 「同意」); retriage answer6212886111(domain:devx, p2,pm:queue)Session:
session_016PVjjuVPte5XEJvaQx1E4tAccount:
os-sales(the seat's linked user asGET /useranswers it; the card's assignee)Branch:
claude/issue-23821-type-graph-budget-classWorktree:
objectstack-issue-23821Domain:
domain:devxSeat:
domain:devx#2File surface:
scripts/measure-test-shard-timings.mjsalone. It gets the thirdTEST_BUDGET_CLASSESvaluecompiles the package type graph once, the refusal text that lists the classes, and the self-test pin of the class list. ⛔ The two// test-budget:header lines inpackages/spec/**are #23180's, in the spec lane, after this lands (ruling item 3). ⛔ NoAGENTS.mdedit (ruling item 4). Stop on breach and explain it in the report.Container & model:
M,mode:subagent,model: TIER_DEFAULT(dispatch-gates --tier: "no path-derived mandate")Clause-②: no
Responsibility:
ruling 6181973363's closed class list (two values), which names no class for a file whose irreducible cost is one type-graph compile | none: PR #23595 built the two-class mechanism | the spec lane's #23180, which cannot close two rows until the class existsThread-read: 6212886111
Serial constraints cleared:
497518c3f6(record6214602102), and nothing else is in flight in either seat this session holds.scripts/measure-test-shard-timings.mjsor the two spec test files. Their file lists were read at this act.Generated by Claude Code
objectstack-fleet commentedon Oct 16, 2026
os-dev-report
{
"issue": 23821,
"status": "done",
"branch": "claude/issue-23821-type-graph-budget-class",
"pr": "#23897",
"session": "session_016PVjjuVPte5XEJvaQx1E4t (mode:subagent; dispatching seat domain:devx#2, same session; claim 6214640541 names this branch, verified as the newest Claim: before any edit)",
"premise_still_valid": true,
"summary": "Draft PR #23897 (Fixes #23821, Clause-② no, assignee os-sales, head f8bacd0, base origin/main 497518c, 1 file, +107/-16) adds the third TEST_BUDGET_CLASSES value
compiles the package type graph onceper ruling record 6212133431 (letter A). Every place in scripts/measure-test-shard-timings.mjs that names, counts or lists the classes moved: readTestBudget docblock (main :1225-1231, now "Three classes", both ruling records, "any class"; :1239 "its ruling"), the list (:1255-1258), the refusal text (:1268-1269, now cites both records and listsCLASS is one of \"a\", \"b\", \"c\"), the class refusal (:1295, "neither class the ruling names" -> "none of the 3 classes the rulings name", count read from the list), the battery roster pin (:1664, 14 -> 18), the self-test pin (:2982/:2996-2999, three literal spellings in order) and the off-list case wording (:3019-3021). Number rule and the three prohibitions untouched; no packages/, no AGENTS.md, no workflow, no changeset. PM mechanism assumptions all held: the line numbers matched main exactly, and a tree-wide grep found no other file (docs/, content/, .claude/, AGENTS.md, .github/workflows/) that lists the classes. The worktree is removed (cleangit worktree remove, no --force).","tests": "All at head f8bacd0. (1)
node scripts/measure-test-shard-timings.mjs --self-test->measure-test-shard-timings: self-test OK, exit 0; batteryper-file budget declarations (ruling 6181973363)registers exactly 18 (ablation leg 0: pin raised to 19 -> exit 1registered 18 case(s), below its pinned floor of 19). Four new cases: ruling line// test-budget: 30 — compiles the package type graph once: ...under the two spec files' real header reads {seconds 30, cls third class, line 2}; the two earlier classes still read in that header; six near misses (type-graph, noonce, nopackage,packages, capital C, trailing space) each refused atf.test.ts:3:quoting the spelling and naming all three classes; on-disk--diffvia the real diffMain holds the file at 18.10 s of its 30 s (card's slowest CI reading) and lists it at 31 s as31.00 (declared 30) | 1 / 1. (2) Ablation (one-off, through scripts/ablation-replace.mjs WRAP mode plus an absolute-path trap; no rebuild applies, the script runs from source): leg 1 delete the third value -> exit 1budget: the classes read [\"spawns the real producer once per single-cause fixture\",\"whole-package import\"]; leg 2 control (check thunk instrumented to print RED and continue, value present) -> exit 0, zero RED lines; leg 3 delete value + instrumentation -> exactly four RED lines (the pin; the ruling-line case... is none of the 2 classes the rulings name; the near-miss case; the on-disk --diff case), the two-earlier-classes control stayed green. Every leg: anchor 1 -> 0 and blob changed on disk, restored to 5e2b82584d38 == HEAD blob,git diff HEADempty, porcelain empty, self-test OK after. (3) Read-only real-tree probe (no dry-run mode exists, so the script's own readTestBudget was imported over every// test-budget:file in packages/, apps/, examples/): 12 declarations (10 producer, 2 whole-package), identical seconds/class/line/reason, rows digest f1975b9e4af0 at both 497518c and f8bacd0; scoped-context.test.ts and connector-author-shape.test.ts read null on disk and, with the ruling line spliced at line 2 in memory only, the third class at 30 s. (4)pnpm exec eslint --no-inline-config scripts/measure-test-shard-timings.mjsexit 0; control-byte grep: no hits.","gates": "Local, at f8bacd0:
node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstackderived 32 commands (merge base 497518c, 1 path, 123 changed lines); all 32 ran, all exit 0, each exit captured by redirect-then-$? before any pipe. They include check:pm-dispatch-gates (run detached under nohup with its exit written to a file: 0,✓ dispatch-gates self-test (fast tier): 1884 cases pass), check:nul-bytes, check:entry-guard, check:cross-package-test-inputs, check:comment-mask-corpus, check-self-test-wired / -workflow-commands, check-scripts-symbol-anchors, and the measure-test-shard-timings / partition-test-shards / ci/select-shard-timings-run self-tests.--ran->✓ dispatch-gates --ran: 32 derived famil(ies) accounted for — 32 run, 0 NOT-MEASURED (a DERIVED zero — all 32 recorded an exit code and none of them is 3).node scripts/pm/check-governed-merges.mjs --branch claude/issue-23821-type-graph-budget-class->0 of 1 path(s) hit the register, NOT governed, ordinary queue landing (Tier: none), 123 lines under 3000. origin/main was re-fetched before PR open, still 497518c, so no merge was needed. CI check-runs on f8bacd0 at report time (37): success = The card this PR closes must claim this branch, Check PR Size, No other open PR may claim the same issue, Part-of PR must not also close its card, filter; in_progress = Lint & Type Check lanes (Lint · scoped · tooling self-tests, Lint · ESLint, Lint · PM dispatch-gates, Lint · CI, release & engine gates, Lint · docs & code guards, Lint · repo & tooling gates, two more scoped lint lanes, Type Check · workspace / consumer gates / source gates / debt ledger), Governed Surface Queue Guard, Check Changeset, Regenerate the shard-timings dataset, No other open PR may claim the same single-writer path, Check Documentation Links; queued = Test Core (1..6/6), Dogfood Regression Gate, Auto Label; skipped = Build Core, Build Docs, Console Pin Gate, Temporal Conformance, Dogfood Verify CLI, the dogfood matrix row, Packed-tarball smoke. Check Changeset is expected red until the seat applies skip-changeset (scripts/ ships in no package; no label written here, per dispatch).","mcp_calls": "0 — no MCP GitHub tool was called",
"api_writes": "2 relay strokes = 2 × POST /repos/objectstack-ai/objectstack/dispatches from this session; executed by the fleet-write relay as objectstack-fleet[bot]: (a) run 38897624049, pr_create = POST /repos/objectstack-ai/objectstack/pulls (draft #23897, 9432 bytes sent and stored, identical) + POST /repos//issues/23897/assignees (os-sales, read back); (b) comment = POST /repos//issues/23821/comments (this report). Plus 2 git pushes (empty-branch probe, then f8bacd0), not REST. No label write, no PR body PATCH. Reads only via gh api GET (issue 23821 and its comments, PR 23595, comment 6208706637, PR 23897, check-runs).",
"files_changed": [
"scripts/measure-test-shard-timings.mjs"
],
"changed_lines": "123 (+107 / -16), 1 file",
"deviations": [
"Commit trailers: the harness attribution reminder asked for a model-named
Co-Authored-Bytrailer and a different PR footer; AGENTS.md's model-free pair (Claude-Session: https://claude.ai/code/session_016PVjjuVPte5XEJvaQx1E4t,Co-authored-by: Claude) and the session-URL PR footer were used instead, as AGENTS.md and os-dev.md direct.","check:pm-dispatch-gates was first run detached without capturing its exit (log ended on the pass verdict, no ELIFECYCLE); it was re-run detached with
echo $?to a file, exit 0, and only that run is cited."],
"open_questions": [],
"out_of_scope_findings": [
"carrier: none · noted, not filed — the self-test battery name still reads
per-file budget declarations (ruling 6181973363); its roster comment now names both records; renaming would only churn the roster.","carrier: the spec lane on #23180 · noted, not filed — a declaration is parsed only by the weekly refresh (as in PR #23595), so the two header lines should be checked locally before push; PR #23897 Acceptance notes carry the one-line readTestBudget command."
]
}
Generated by Claude Code
objectstack-fleet commentedon Oct 16, 2026
Landed: the third test-budget class,
compiles the package type graph once·domain:devxseat 2 ·session_016PVjjuVPte5XEJvaQx1E4t· 2026-10-16T12:43Z0744f94366onorigin/main, merged 2026-10-16T12:42:54Z from the merge queuescripts/measure-test-shard-timings.mjsonorigin/mainis5e2b82584d38, equal to the PR headf8bacd05bFixesclosed this card ascompleted.pm:dispatchedis removed in this act.6212133431, letter A.TEST_BUDGET_CLASSEShas three values, and the refusal names all three. The self-test pins the three spellings in order.domain:specon test budget (domain:spec): 26 test file(s) over 10 s of wall in the hourly full battery (Part of #23151) #23180 (ruling item 3):packages/spec/src/contracts/scoped-context.test.tsandpackages/spec/src/integration/connector-author-shape.test.tseach take one header line,// test-budget: <n> — compiles the package type graph once: <reason>.<n>is that day's CI reading × 1.25, rounded up to the next 10 s. feat(scripts): a third test-budget class, "compiles the package type graph once" #23897's body has the one-line local check to run before pushing.Generated by Claude Code