fix(ci): green main's Lint and unblock the 0.9.14 release gates - #6268
Conversation
Four gates that main currently fails. All four are advisory on pull
requests (`continue-on-error: ${{ github.event_name == 'pull_request' }}`)
and **fatal on push**, which is why `Lint` has been red on main since
04:08Z while every PR rollup looked green — CI runs 35054467418,
35054908721 and 35050587333 all failed `Lint` on exactly these.
1. Blocking-call budget: `crates/tui/src/tools/shell.rs` std_fs 2 -> 3.
#6208's Q6 (e522e4f) replaced `if !path.exists()` with
`std::fs::metadata(&path)` in `load_default_policy`. The checker counts
the textual `std::fs::` form, so an equivalent stat that was previously
uncounted became counted. Net blocking work went *down*: the same call
now also carries the cache key that removed a full read plus TOML parse
and regex recompile from every shell execution. `load_default_policy` is
a synchronous fn, so the site cannot move to `spawn_blocking` without
restructuring its callers — this is the "raise the budget if the site
can only run on synchronous code" case the checker names.
2. Runtime contract budget: Act/Operate full catalogs gain `session_get`
and `session_search` (50 -> 52 tools). #5715 (eefdcb4) added them
as bounded read-only workspace-scoped recall. `--update` deliberately
refuses identity changes, so this is the explicit maintainer edit the
`_comment` history calls for, with a note appended in that style. Plan
full is unchanged — the session tools are not offered there.
3. Feature release-note receipts: seven feature commits since v0.9.13
referenced six issues with no changelog entry, which is advisory in PR
CI but **blocking on every release path** (check-versions.sh:33-38).
Added entries for #5715, #6099, #6035 (Added) and #6033, #6085
(Changed), and attached #6151 to the two edit-gating entries whose
commits carry that reference.
4. The `[Unreleased]` compare link still pointed at v0.9.12; check-versions
only validates the link for the current workspace version, so it went
unnoticed across a release.
Verification on this machine (macOS aarch64, source 55a9e1b):
[runtime-contract-budget] PASS: all 55 metrics are exactly at budget.
blocking-call budget: 626 sites across 181 files, within budget
Feature release-note receipts OK: 16 linked issue reference(s) checked
in v0.9.13..HEAD.
Version state OK: workspace=0.9.13, npm=0.9.13, npm-binary=0.9.13,
lockfile in sync.
Ran 19 tests in 0.015s OK (test_check_runtime_contract_budget.py)
Ran 3 tests in 0.000s OK (test_measure_runtime_contract.py)
Not verified here: the runtime-contract byte/token ceilings are measured
from macOS. The `_comment` history records that macOS measurements have
under-counted before and had to be re-locked from a Linux Lint run
(2026-09-13, after b4d48e9). If CI's Lint reports numeric drift on these
values, re-lock them from that run rather than re-measuring locally; the
name-set identities and digests are host-independent and will not move.
Signed-off-by: CodeWhale Bot <bot@codewhale.net>
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
|
You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard. |
Reviewing PR #6268
|
`web/lib/changelog.generated.ts` is derived from CHANGELOG.md by `web/scripts/derive-changelog.mjs`, and `lib/changelog.test.ts` asserts the committed file matches a fresh derivation. The five release-note receipts added in 095f1ef changed the derivation, so the check failed: AssertionError: expected '// AUTO-GENERATED by web/scripts/deri…' to be '// AUTO-GENERATED by web/scripts/deri…' Test Files 1 failed | 50 passed (51) Tests 1 failed | 469 passed (470) Regenerated with the script rather than hand-edited. After: [derive-changelog] wrote 6 releases → lib/changelog.generated.ts Test Files 1 passed (1) Tests 6 passed (6) Signed-off-by: CodeWhale Bot <bot@codewhale.net> Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
|
Claude finished @Hmbown's task in 3m 56s —— View job Reviewing PR #6268
SummaryThis is a CI-hygiene/budget-file PR (no Rust source changes) that raises the four Verified correct:
One thing worth double-checking before merge:
Since Minor nit: both No provider/model-route safety concerns (no routing code touched), no dead code/duplication introduced, and no new tests needed for a pure budget/changelog PR. |
There was a problem hiding this comment.
Codewhale review
Complete review coverage: 1/1 passes, 5 file patches, sha256:861ba649dcef5926a530f605245485feec8fcd97919900305264e73e08ea5411.
Pass 1: Metadata-only CI PR: raises crates/tui/src/tools/shell.rs's std_fs blocking-call budget 2→3, adds session_get/session_search to the Act/Operate full runtime-contract catalogs (50→52) with a new name-set digest, records five new Unreleased changelog receipts plus #6151 on two existing edit-gating entries, and fixes the stale [Unreleased] compare link (v0.9.12→v0.9.13) in CHANGELOG.md and the generated web changelog. The edited JSON is internally consistent (name lists stay sorted, declared tools counts match list lengths, tokens_est is ceil(bytes/4), Act and Operate share the new digest because their name sets are identical) and the generated TypeScript matches the generator's observed behaviour (backtick stripping, per-item clipping, itemCount deltas). The only concrete problem found is an attribution gap in the new budget comment.
Findings
- [INFO] Budget comment claims Plan full is unchanged while its byte/token ceilings (and all active ceilings) were raised (
scripts/runtime-contract-budget.json:89)
The new_commentsays "Plan full is unchanged: the session tools are not offered there" (and the PR description says only Act/Operate full changed), yet the same edit raises numeric ceilings on surfaces where nothing structural moved: theactiveceilings of all three modes go 31438→31453 bytes / 7860→7864 tokens (lines 89, 189, 251) and Plan full goes 50801→50816 / 12701→12704 (line 270), while every active name set, its 11-tool count, its identitycf523fcd…and Plan full's identityac8af1f4…are untouched. A +15-byte move with no name change can only come from a shared eager-tool schema or from measurement drift, and this file's own precedent (Linux run 34766373771, "Lock ceilings to those measured values with no margin") expects the attribution to be stated. Triggering path: any later maintainer runningpython3 scripts/check-runtime-contract-budget.py --update/re-locking after a Lint drift reads the comment, sees 'unchanged', and cannot tell whether the extra 15 bytes were source or host measurement. Nothing here breaks the gate on its own — a numeric ceiling above the measured value still passes (decreases pass) — so the impact is an unauditable receipt, not a functional failure.
Suggestions
scripts/runtime-contract-budget.json:89— Extend the v0.9.14 sentence in_commentto give the +15-byte (and +4-token) movement the same attribution as the rest of the file: say which shared eager-tool schema grew, or state plainly that the active/Plan-full ceilings were captured from this run and must be re-locked from the Linux Lint run before trusting them, and drop the unqualified 'Plan full is unchanged' wording so the comment and the numbers agree.
Assessment
Pass 1: No build, script or test was run for this review, and the numeric truth of the runtime-contract budget could not be independently reproduced: the new full name-set digest 1203d192…, the declared byte/token values, and the shell.rs std_fs count of 3 are all taken from the PR's own verification. What I could check structurally holds up: the added names sit in correct sorted position in both full catalogs, the declared tools counts equal the list lengths (52/52 act and operate, 30/30 plan, 11/11 active), tokens_est equals ceil(bytes/4) for every changed metric, Act and Operate legitimately share one digest, and the two changelogs plus the generated TS keep matching ordering/counts (Added 6→9, Changed 2→4, compareUrl v0.9.13). The generated web/lib/changelog.generated.ts is consistent with derive-changelog.mjs output so far as the diff shows (backticks stripped, *emphasis* retained as in pre-existing context, items clipped at ~470 chars on a word boundary), but it is a generated artifact and was not regenerated here, so if CI runs npm run prebuild plus a diff check, that step is the thing to confirm. Open questions I could not settle from the supplied material: (1) the +15-byte ceiling raise on active/Plan-full has no stated source attribution (see the info issue); (2) the issue-to-commit mapping claimed for #6151 and the five new receipts (and whether the seven feature commits are exactly those issues) cannot be verified without the commit range; (3) crates/tui/CHANGELOG.md is one of the two files not supplied in full, so I cannot tell whether it also carries a stale [Unreleased] compare link like the one fixed in the root file; (4) the blocking-call budget relies on shell.rs now containing exactly three counted std::fs:: sites, which I could not count.
Advisory review by Codewhale (codewhale review --pr 6268 --post, head 13853bd47f5e35cddfcbe8d44fdc89e0b7581166). Line-specific findings are also posted as inline review comments; mechanical fixes arrive as committable suggestions you can apply from the Files tab. CODEOWNERS approval still governs merge.
| "act": { | ||
| "active": { | ||
| "bytes": 31438, | ||
| "bytes": 31453, |
There was a problem hiding this comment.
[INFO] Budget comment claims Plan full is unchanged while its byte/token ceilings (and all active ceilings) were raised
The new _comment says "Plan full is unchanged: the session tools are not offered there" (and the PR description says only Act/Operate full changed), yet the same edit raises numeric ceilings on surfaces where nothing structural moved: the active ceilings of all three modes go 31438→31453 bytes / 7860→7864 tokens (lines 89, 189, 251) and Plan full goes 50801→50816 / 12701→12704 (line 270), while every active name set, its 11-tool count, its identity cf523fcd… and Plan full's identity ac8af1f4… are untouched. A +15-byte move with no name change can only come from a shared eager-tool schema or from measurement drift, and this file's own precedent (Linux run 34766373771, "Lock ceilings to those measured values with no margin") expects the attribution to be stated. Triggering path: any later maintainer running python3 scripts/check-runtime-contract-budget.py --update/re-locking after a Lint drift reads the comment, sees 'unchanged', and cannot tell whether the extra 15 bytes were source or host measurement. Nothing here breaks the gate on its own — a numeric ceiling above the measured value still passes (decreases pass) — so the impact is an unauditable receipt, not a functional failure.
| "act": { | ||
| "active": { | ||
| "bytes": 31438, | ||
| "bytes": 31453, |
There was a problem hiding this comment.
Extend the v0.9.14 sentence in _comment to give the +15-byte (and +4-token) movement the same attribution as the rest of the file: say which shared eager-tool schema grew, or state plainly that the active/Plan-full ceilings were captured from this run and must be re-locked from the Linux Lint run before trusting them, and drop the unqualified 'Plan full is unchanged' wording so the comment and the numbers agree.

main'sLinthas been red since 04:08Z today (CI runs 35054467418, 35054908721, 35050587333) while every PR rollup looked green. The reason is that four gates are declaredso they are advisory on pull requests and fatal on push. A PR can go green, merge, and turn
mainred on the same change.This fixes all four.
1. Blocking-call budget —
shell.rsstd_fs 2 → 3#6208's Q6 (
e522e4f93c) replacedif !path.exists()withstd::fs::metadata(&path)inload_default_policy. The checker counts the textualstd::fs::form, so an equivalent stat that was previously uncounted became counted.Net blocking work went down: that same stat now carries the cache key that removed a full file read, a TOML parse and a regex recompile from every shell execution.
load_default_policyis a synchronousfn, so the site cannot move tospawn_blockingwithout restructuring its callers — this is exactly the "raise the budget with--updateif the site can only run on synchronous code" case the checker names.2. Runtime contract budget — Act/Operate full gain two tools
#5715 (
eefdcb42f507) addedsession_getandsession_searchas bounded, read-only, workspace-scoped recall. Act/Operate full catalogs go 50 → 52 tools; Plan full is unchanged because the session tools are not offered there.--updatedeliberately refuses identity changes (compare()raises before the update branch), so this is the explicit maintainer edit the_commenthistory calls for, written in that same style.3. Feature release-note receipts — the actual release blocker
Seven feature commits since
v0.9.13referenced six issues with no changelog receipt. This is advisory in PR CI but blocking on every release path —release.yml,release-candidate.yml,auto-tag.ymlandprepare-release.shall run it non-advisory (check-versions.sh:33-38). 0.9.14 could not have been tagged without this.Added entries for #5715, #6099, #6035 (Added) and #6033, #6085 (Changed), and attached #6151 to the two edit-gating entries whose commits carry that reference.
4. Stale
[Unreleased]compare linkIt still pointed at
v0.9.12.check-versions.shonly validates the compare link for the current workspace version, so this survived a release.Verification (macOS aarch64, source
55a9e1b778fa)Not verified here
The runtime-contract byte/token ceilings are measured from macOS. The
_commenthistory records that macOS measurements have under-counted before and had to be re-locked from a Linux Lint run (2026-09-13, afterb4d48e9a4). If Lint reports numeric drift on these values, re-lock them from that run rather than re-measuring locally — the name-set identities and digests are host-independent and will not move.No-Issue: CI hygiene — these four gates are red on main today and none of them has a tracking issue.