Skip to content

ci: move Fork CI test and nightly Windows to free runners - #112

Merged
incognitojam merged 1 commit into
mainfrom
t3code/audit-blacksmith-ci-usage
Aug 13, 2026
Merged

ci: move Fork CI test and nightly Windows to free runners#112
incognitojam merged 1 commit into
mainfrom
t3code/audit-blacksmith-ci-usage

Conversation

@incognitojam

@incognitojam incognitojam commented Aug 13, 2026

Copy link
Copy Markdown
Collaborator

Note

The repo is public, so standard GitHub-hosted runners are free. Moves the two
jobs that gain least from paid hardware onto free runners and right-sizes a
third. Runner changes only — follow-ups tracked at the bottom.

Problem

An audit of the last 8 days of run history (all GitHub retains) put Blacksmith
at roughly $176/mo, with Fork CI the largest bucket at ~$80/mo. Two jobs were
paying for cores they could not use:

  • Fork Test spends 209s of its 248s in the Test step. Only the first ~30s
    is parallel transform/import fan-out at 100% CPU; the remaining ~2.5min at
    15-20% is apps/server alone (transform 4.85s, import 75s, tests 211s
    await-bound tests pinning one or two workers while every other package has
    finished). It is long-poled, not short of cores, so slower cores cost far
    less than proportionally.
  • Nightly Windows x64 was the least CPU-bound of the three desktop targets
    per the Review Fork Nightly runner sizing with Blacksmith metrics #51 metrics review.
  • Fork Check peaks at 4-5 cores during Typecheck; only ~54s of its 97s is
    CPU work at all.

Fix

  • Fork Test → ubuntu-24.04, nightly Windows → windows-2025 (free).
  • Fork Check → blacksmith-4vcpu-ubuntu-2404.

macOS deliberately stays on Blacksmith — it is genuinely CPU-bound (P95 ≥ 91%)
and paces the whole nightly.

Expected cost after this lands: ~$176/mo → $90/mo, leaving macOS ($29/mo) as
the largest Blacksmith item.

Verification

actionlint reports no new findings, both workflows parse, and the desktop
build matrix script still emits the expected runner for each target
(macos-arm64blacksmith-6vcpu-macos-15, linux-x64
blacksmith-8vcpu-ubuntu-2404, windows-x64windows-2025).

Note this PR's own checks run under the old config; the new runner choices
are not exercised until it lands on main.

Risks

Two things only a real run can confirm: disk headroom for the NSIS build on the
GitHub-hosted Windows runner, and Fork Test's actual wall time on 4 cores
(predicted ~250s → ~300s, since only the 30s phase scales with cores).

Follow-ups

Split out of this PR to keep it to one concern:

  1. MessagesTimeline.test.tsx silently skips itself under load. It defers
    await import("./MessagesTimeline") into beforeAll(..., 30_000). In
    isolation the file runs in 3s, but under full-suite contention that hook hits
    its timeout and the file reports 18 tests | 18 skipped at 30100ms without
    failing
    . Moving the DOM stubs to vi.hoisted fixes it structurally. This is
    pre-existing, but the slower runner in this PR makes it more likely — worth
    landing soon after.
  2. Drop the merge_group trigger, now that the merge queue is retired.

Written by an agent (Claude Code, claude-opus-5).

@github-actions github-actions Bot added vouch:trusted PR author is trusted by repo permissions or the VOUCHED list. size:S labels Aug 13, 2026
@incognitojam
incognitojam force-pushed the t3code/audit-blacksmith-ci-usage branch from 253c24d to 52a8a51 Compare August 13, 2026 12:09
@incognitojam incognitojam changed the title ci: cut Blacksmith spend on Fork CI and nightly Windows ci: move Fork CI test and nightly Windows to free runners Aug 13, 2026
The repository is public, so standard GitHub-hosted runners are free.
Fork Test is the largest paid line item yet is long-poled by apps/server's
await-bound suite rather than by cores, and nightly Windows was the least
CPU-bound desktop target, so both move to free runners. Fork Check drops
8 -> 4 vCPU to match its 4-5 core typecheck peak.

macOS stays on Blacksmith; it is genuinely CPU-bound and paces the nightly.
@incognitojam
incognitojam force-pushed the t3code/audit-blacksmith-ci-usage branch from 52a8a51 to 8ce70c1 Compare August 13, 2026 12:31
@incognitojam
incognitojam merged commit 8eba5d3 into main Aug 13, 2026
11 checks passed
@incognitojam
incognitojam deleted the t3code/audit-blacksmith-ci-usage branch August 13, 2026 12:55
incognitojam added a commit that referenced this pull request Aug 13, 2026
## Problem

The merge queue was retired because it duplicated CI work, but Fork CI
still
carries its plumbing: a `merge_group` trigger and
`github.event.merge_group.*`
fallbacks in the `changes` job's SHA resolution. Nothing fires it, so it
is dead
config that implies a workflow the repo no longer uses.

## Fix

Remove the trigger and the two fallbacks. `pull_request` and `push`
events
already resolve the same SHAs on their own:

- `BASE_SHA` → `pull_request.base.sha` or `github.event.before`
- `HEAD_SHA` → `pull_request.head.sha` or `github.sha`

## Verification

Confirmed no merge queue is configured, so nothing is stranded by this:

- The `PR + CI` ruleset on `main` contains only `pull_request` and
  `required_status_checks` rules — no `merge_queue` rule.
- All four required checks (`Fork Changes`, `Fork Check`, `Fork Release
Smoke`,
  `Fork Test`) run on `pull_request`, so they still report on every PR.

Workflow parses and `actionlint` reports no new findings.

Follow-up to #112.

---
Written by an agent (Claude Code, claude-opus-5).
incognitojam added a commit that referenced this pull request Aug 13, 2026
…118)

## Problem

`MessagesTimeline.test.tsx` needs DOM globals stubbed before its module
graph is
evaluated, because the web `unit` project runs on the **node**
environment. It
did that by deferring the import into a hook:

```ts
let MessagesTimeline: typeof import("./MessagesTimeline").MessagesTimeline;

beforeAll(async () => {
  vi.stubGlobal("window", { /* ... */ });
  ({ MessagesTimeline } = await import("./MessagesTimeline"));
}, 30_000);
```

That puts the module graph's transform cost *inside a hook timeout*. Run
alone
the file takes 3s, but under full-suite contention the hook hit its 30s
timeout
and the file reported `18 tests | 18 skipped` at 30100ms — **without
failing**.
CI stayed green having run 18 fewer tests than it appeared to.

This is pre-existing, but #112 moved Fork Test to a 4-core free runner,
which
makes the contention that triggers it more likely.

## Fix

Move the stubs into `vi.hoisted`, which runs ahead of imports, so
`MessagesTimeline` is imported statically and no hook timeout wraps the
module
graph. This removes the failure mode structurally rather than by raising
the
timeout. `vi.hoisted` is already the idiom in ~10 other web test files.

## Verification

- File alone: 18/18 pass.
- Timing confirms the cost moved out of the hook phase: `tests 2.62s /
import 619ms` before, `tests 98ms / import 2.16s` after. No hook timeout
  applies to the import phase.
- Full `@t3tools/web` suite: 250 files / 2451 tests, **0 skipped**, exit
0.
Previously this run showed MessagesTimeline at `18 tests | 18 skipped`.
- `@t3tools/web` typecheck clean.

Worth noting the original stall was intermittent (1 of 2 full runs), so
a green
run is not by itself proof. The argument for the fix is structural:
there is no
longer a timed hook around the import.

---
Written by an agent (Claude Code, claude-opus-5).
yngatech-nightly Bot pushed a commit that referenced this pull request Aug 13, 2026
> [!NOTE]
> The repo is public, so standard GitHub-hosted runners are free. Moves
the two
> jobs that gain least from paid hardware onto free runners and
right-sizes a
> third. Runner changes only — follow-ups tracked at the bottom.

## Problem

An audit of the last 8 days of run history (all GitHub retains) put
Blacksmith
at roughly $176/mo, with Fork CI the largest bucket at ~$80/mo. Two jobs
were
paying for cores they could not use:

- **Fork Test** spends 209s of its 248s in the `Test` step. Only the
first ~30s
is parallel transform/import fan-out at 100% CPU; the remaining ~2.5min
at
15-20% is `apps/server` alone (`transform 4.85s, import 75s, tests 211s`
—
await-bound tests pinning one or two workers while every other package
has
finished). It is long-poled, not short of cores, so slower cores cost
far
  less than proportionally.
- **Nightly Windows x64** was the least CPU-bound of the three desktop
targets
  per the #51 metrics review.
- **Fork Check** peaks at 4-5 cores during Typecheck; only ~54s of its
97s is
  CPU work at all.

## Fix

- Fork Test → `ubuntu-24.04`, nightly Windows → `windows-2025` (free).
- Fork Check → `blacksmith-4vcpu-ubuntu-2404`.

macOS deliberately stays on Blacksmith — it is genuinely CPU-bound (P95
≥ 91%)
and paces the whole nightly.

Expected cost after this lands: ~$176/mo → ~$90/mo, leaving macOS
(~$29/mo) as
the largest Blacksmith item.

## Verification

`actionlint` reports no new findings, both workflows parse, and the
desktop
build matrix script still emits the expected runner for each target
(`macos-arm64` → `blacksmith-6vcpu-macos-15`, `linux-x64` →
`blacksmith-8vcpu-ubuntu-2404`, `windows-x64` → `windows-2025`).

Note this PR's own checks run under the **old** config; the new runner
choices
are not exercised until it lands on main.

## Risks

Two things only a real run can confirm: disk headroom for the NSIS build
on the
GitHub-hosted Windows runner, and Fork Test's actual wall time on 4
cores
(predicted ~250s → ~300s, since only the 30s phase scales with cores).

## Follow-ups

Split out of this PR to keep it to one concern:

1. **`MessagesTimeline.test.tsx` silently skips itself under load.** It
defers
`await import("./MessagesTimeline")` into `beforeAll(..., 30_000)`. In
isolation the file runs in 3s, but under full-suite contention that hook
hits
its timeout and the file reports `18 tests | 18 skipped` at 30100ms
*without
failing*. Moving the DOM stubs to `vi.hoisted` fixes it structurally.
This is
pre-existing, but the slower runner in this PR makes it more likely —
worth
   landing soon after.
2. **Drop the `merge_group` trigger**, now that the merge queue is
retired.

---
Written by an agent (Claude Code, claude-opus-5).
yngatech-nightly Bot pushed a commit that referenced this pull request Aug 13, 2026
## Problem

The merge queue was retired because it duplicated CI work, but Fork CI
still
carries its plumbing: a `merge_group` trigger and
`github.event.merge_group.*`
fallbacks in the `changes` job's SHA resolution. Nothing fires it, so it
is dead
config that implies a workflow the repo no longer uses.

## Fix

Remove the trigger and the two fallbacks. `pull_request` and `push`
events
already resolve the same SHAs on their own:

- `BASE_SHA` → `pull_request.base.sha` or `github.event.before`
- `HEAD_SHA` → `pull_request.head.sha` or `github.sha`

## Verification

Confirmed no merge queue is configured, so nothing is stranded by this:

- The `PR + CI` ruleset on `main` contains only `pull_request` and
  `required_status_checks` rules — no `merge_queue` rule.
- All four required checks (`Fork Changes`, `Fork Check`, `Fork Release
Smoke`,
  `Fork Test`) run on `pull_request`, so they still report on every PR.

Workflow parses and `actionlint` reports no new findings.

Follow-up to #112.

---
Written by an agent (Claude Code, claude-opus-5).
yngatech-nightly Bot pushed a commit that referenced this pull request Aug 13, 2026
…118)

## Problem

`MessagesTimeline.test.tsx` needs DOM globals stubbed before its module
graph is
evaluated, because the web `unit` project runs on the **node**
environment. It
did that by deferring the import into a hook:

```ts
let MessagesTimeline: typeof import("./MessagesTimeline").MessagesTimeline;

beforeAll(async () => {
  vi.stubGlobal("window", { /* ... */ });
  ({ MessagesTimeline } = await import("./MessagesTimeline"));
}, 30_000);
```

That puts the module graph's transform cost *inside a hook timeout*. Run
alone
the file takes 3s, but under full-suite contention the hook hit its 30s
timeout
and the file reported `18 tests | 18 skipped` at 30100ms — **without
failing**.
CI stayed green having run 18 fewer tests than it appeared to.

This is pre-existing, but #112 moved Fork Test to a 4-core free runner,
which
makes the contention that triggers it more likely.

## Fix

Move the stubs into `vi.hoisted`, which runs ahead of imports, so
`MessagesTimeline` is imported statically and no hook timeout wraps the
module
graph. This removes the failure mode structurally rather than by raising
the
timeout. `vi.hoisted` is already the idiom in ~10 other web test files.

## Verification

- File alone: 18/18 pass.
- Timing confirms the cost moved out of the hook phase: `tests 2.62s /
import 619ms` before, `tests 98ms / import 2.16s` after. No hook timeout
  applies to the import phase.
- Full `@t3tools/web` suite: 250 files / 2451 tests, **0 skipped**, exit
0.
Previously this run showed MessagesTimeline at `18 tests | 18 skipped`.
- `@t3tools/web` typecheck clean.

Worth noting the original stall was intermittent (1 of 2 full runs), so
a green
run is not by itself proof. The argument for the fix is structural:
there is no
longer a timed hook around the import.

---
Written by an agent (Claude Code, claude-opus-5).
yngatech-nightly Bot pushed a commit that referenced this pull request Aug 13, 2026
> [!NOTE]
> The repo is public, so standard GitHub-hosted runners are free. Moves
the two
> jobs that gain least from paid hardware onto free runners and
right-sizes a
> third. Runner changes only — follow-ups tracked at the bottom.

## Problem

An audit of the last 8 days of run history (all GitHub retains) put
Blacksmith
at roughly $176/mo, with Fork CI the largest bucket at ~$80/mo. Two jobs
were
paying for cores they could not use:

- **Fork Test** spends 209s of its 248s in the `Test` step. Only the
first ~30s
is parallel transform/import fan-out at 100% CPU; the remaining ~2.5min
at
15-20% is `apps/server` alone (`transform 4.85s, import 75s, tests 211s`
—
await-bound tests pinning one or two workers while every other package
has
finished). It is long-poled, not short of cores, so slower cores cost
far
  less than proportionally.
- **Nightly Windows x64** was the least CPU-bound of the three desktop
targets
  per the #51 metrics review.
- **Fork Check** peaks at 4-5 cores during Typecheck; only ~54s of its
97s is
  CPU work at all.

## Fix

- Fork Test → `ubuntu-24.04`, nightly Windows → `windows-2025` (free).
- Fork Check → `blacksmith-4vcpu-ubuntu-2404`.

macOS deliberately stays on Blacksmith — it is genuinely CPU-bound (P95
≥ 91%)
and paces the whole nightly.

Expected cost after this lands: ~$176/mo → ~$90/mo, leaving macOS
(~$29/mo) as
the largest Blacksmith item.

## Verification

`actionlint` reports no new findings, both workflows parse, and the
desktop
build matrix script still emits the expected runner for each target
(`macos-arm64` → `blacksmith-6vcpu-macos-15`, `linux-x64` →
`blacksmith-8vcpu-ubuntu-2404`, `windows-x64` → `windows-2025`).

Note this PR's own checks run under the **old** config; the new runner
choices
are not exercised until it lands on main.

## Risks

Two things only a real run can confirm: disk headroom for the NSIS build
on the
GitHub-hosted Windows runner, and Fork Test's actual wall time on 4
cores
(predicted ~250s → ~300s, since only the 30s phase scales with cores).

## Follow-ups

Split out of this PR to keep it to one concern:

1. **`MessagesTimeline.test.tsx` silently skips itself under load.** It
defers
`await import("./MessagesTimeline")` into `beforeAll(..., 30_000)`. In
isolation the file runs in 3s, but under full-suite contention that hook
hits
its timeout and the file reports `18 tests | 18 skipped` at 30100ms
*without
failing*. Moving the DOM stubs to `vi.hoisted` fixes it structurally.
This is
pre-existing, but the slower runner in this PR makes it more likely —
worth
   landing soon after.
2. **Drop the `merge_group` trigger**, now that the merge queue is
retired.

---
Written by an agent (Claude Code, claude-opus-5).
yngatech-nightly Bot pushed a commit that referenced this pull request Aug 13, 2026
## Problem

The merge queue was retired because it duplicated CI work, but Fork CI
still
carries its plumbing: a `merge_group` trigger and
`github.event.merge_group.*`
fallbacks in the `changes` job's SHA resolution. Nothing fires it, so it
is dead
config that implies a workflow the repo no longer uses.

## Fix

Remove the trigger and the two fallbacks. `pull_request` and `push`
events
already resolve the same SHAs on their own:

- `BASE_SHA` → `pull_request.base.sha` or `github.event.before`
- `HEAD_SHA` → `pull_request.head.sha` or `github.sha`

## Verification

Confirmed no merge queue is configured, so nothing is stranded by this:

- The `PR + CI` ruleset on `main` contains only `pull_request` and
  `required_status_checks` rules — no `merge_queue` rule.
- All four required checks (`Fork Changes`, `Fork Check`, `Fork Release
Smoke`,
  `Fork Test`) run on `pull_request`, so they still report on every PR.

Workflow parses and `actionlint` reports no new findings.

Follow-up to #112.

---
Written by an agent (Claude Code, claude-opus-5).
yngatech-nightly Bot pushed a commit that referenced this pull request Aug 13, 2026
…118)

## Problem

`MessagesTimeline.test.tsx` needs DOM globals stubbed before its module
graph is
evaluated, because the web `unit` project runs on the **node**
environment. It
did that by deferring the import into a hook:

```ts
let MessagesTimeline: typeof import("./MessagesTimeline").MessagesTimeline;

beforeAll(async () => {
  vi.stubGlobal("window", { /* ... */ });
  ({ MessagesTimeline } = await import("./MessagesTimeline"));
}, 30_000);
```

That puts the module graph's transform cost *inside a hook timeout*. Run
alone
the file takes 3s, but under full-suite contention the hook hit its 30s
timeout
and the file reported `18 tests | 18 skipped` at 30100ms — **without
failing**.
CI stayed green having run 18 fewer tests than it appeared to.

This is pre-existing, but #112 moved Fork Test to a 4-core free runner,
which
makes the contention that triggers it more likely.

## Fix

Move the stubs into `vi.hoisted`, which runs ahead of imports, so
`MessagesTimeline` is imported statically and no hook timeout wraps the
module
graph. This removes the failure mode structurally rather than by raising
the
timeout. `vi.hoisted` is already the idiom in ~10 other web test files.

## Verification

- File alone: 18/18 pass.
- Timing confirms the cost moved out of the hook phase: `tests 2.62s /
import 619ms` before, `tests 98ms / import 2.16s` after. No hook timeout
  applies to the import phase.
- Full `@t3tools/web` suite: 250 files / 2451 tests, **0 skipped**, exit
0.
Previously this run showed MessagesTimeline at `18 tests | 18 skipped`.
- `@t3tools/web` typecheck clean.

Worth noting the original stall was intermittent (1 of 2 full runs), so
a green
run is not by itself proof. The argument for the fix is structural:
there is no
longer a timed hook around the import.

---
Written by an agent (Claude Code, claude-opus-5).
yngatech-nightly Bot pushed a commit that referenced this pull request Aug 14, 2026
> [!NOTE]
> The repo is public, so standard GitHub-hosted runners are free. Moves
the two
> jobs that gain least from paid hardware onto free runners and
right-sizes a
> third. Runner changes only — follow-ups tracked at the bottom.

## Problem

An audit of the last 8 days of run history (all GitHub retains) put
Blacksmith
at roughly $176/mo, with Fork CI the largest bucket at ~$80/mo. Two jobs
were
paying for cores they could not use:

- **Fork Test** spends 209s of its 248s in the `Test` step. Only the
first ~30s
is parallel transform/import fan-out at 100% CPU; the remaining ~2.5min
at
15-20% is `apps/server` alone (`transform 4.85s, import 75s, tests 211s`
—
await-bound tests pinning one or two workers while every other package
has
finished). It is long-poled, not short of cores, so slower cores cost
far
  less than proportionally.
- **Nightly Windows x64** was the least CPU-bound of the three desktop
targets
  per the #51 metrics review.
- **Fork Check** peaks at 4-5 cores during Typecheck; only ~54s of its
97s is
  CPU work at all.

## Fix

- Fork Test → `ubuntu-24.04`, nightly Windows → `windows-2025` (free).
- Fork Check → `blacksmith-4vcpu-ubuntu-2404`.

macOS deliberately stays on Blacksmith — it is genuinely CPU-bound (P95
≥ 91%)
and paces the whole nightly.

Expected cost after this lands: ~$176/mo → ~$90/mo, leaving macOS
(~$29/mo) as
the largest Blacksmith item.

## Verification

`actionlint` reports no new findings, both workflows parse, and the
desktop
build matrix script still emits the expected runner for each target
(`macos-arm64` → `blacksmith-6vcpu-macos-15`, `linux-x64` →
`blacksmith-8vcpu-ubuntu-2404`, `windows-x64` → `windows-2025`).

Note this PR's own checks run under the **old** config; the new runner
choices
are not exercised until it lands on main.

## Risks

Two things only a real run can confirm: disk headroom for the NSIS build
on the
GitHub-hosted Windows runner, and Fork Test's actual wall time on 4
cores
(predicted ~250s → ~300s, since only the 30s phase scales with cores).

## Follow-ups

Split out of this PR to keep it to one concern:

1. **`MessagesTimeline.test.tsx` silently skips itself under load.** It
defers
`await import("./MessagesTimeline")` into `beforeAll(..., 30_000)`. In
isolation the file runs in 3s, but under full-suite contention that hook
hits
its timeout and the file reports `18 tests | 18 skipped` at 30100ms
*without
failing*. Moving the DOM stubs to `vi.hoisted` fixes it structurally.
This is
pre-existing, but the slower runner in this PR makes it more likely —
worth
   landing soon after.
2. **Drop the `merge_group` trigger**, now that the merge queue is
retired.

---
Written by an agent (Claude Code, claude-opus-5).
yngatech-nightly Bot pushed a commit that referenced this pull request Aug 14, 2026
## Problem

The merge queue was retired because it duplicated CI work, but Fork CI
still
carries its plumbing: a `merge_group` trigger and
`github.event.merge_group.*`
fallbacks in the `changes` job's SHA resolution. Nothing fires it, so it
is dead
config that implies a workflow the repo no longer uses.

## Fix

Remove the trigger and the two fallbacks. `pull_request` and `push`
events
already resolve the same SHAs on their own:

- `BASE_SHA` → `pull_request.base.sha` or `github.event.before`
- `HEAD_SHA` → `pull_request.head.sha` or `github.sha`

## Verification

Confirmed no merge queue is configured, so nothing is stranded by this:

- The `PR + CI` ruleset on `main` contains only `pull_request` and
  `required_status_checks` rules — no `merge_queue` rule.
- All four required checks (`Fork Changes`, `Fork Check`, `Fork Release
Smoke`,
  `Fork Test`) run on `pull_request`, so they still report on every PR.

Workflow parses and `actionlint` reports no new findings.

Follow-up to #112.

---
Written by an agent (Claude Code, claude-opus-5).
yngatech-nightly Bot pushed a commit that referenced this pull request Aug 14, 2026
…118)

## Problem

`MessagesTimeline.test.tsx` needs DOM globals stubbed before its module
graph is
evaluated, because the web `unit` project runs on the **node**
environment. It
did that by deferring the import into a hook:

```ts
let MessagesTimeline: typeof import("./MessagesTimeline").MessagesTimeline;

beforeAll(async () => {
  vi.stubGlobal("window", { /* ... */ });
  ({ MessagesTimeline } = await import("./MessagesTimeline"));
}, 30_000);
```

That puts the module graph's transform cost *inside a hook timeout*. Run
alone
the file takes 3s, but under full-suite contention the hook hit its 30s
timeout
and the file reported `18 tests | 18 skipped` at 30100ms — **without
failing**.
CI stayed green having run 18 fewer tests than it appeared to.

This is pre-existing, but #112 moved Fork Test to a 4-core free runner,
which
makes the contention that triggers it more likely.

## Fix

Move the stubs into `vi.hoisted`, which runs ahead of imports, so
`MessagesTimeline` is imported statically and no hook timeout wraps the
module
graph. This removes the failure mode structurally rather than by raising
the
timeout. `vi.hoisted` is already the idiom in ~10 other web test files.

## Verification

- File alone: 18/18 pass.
- Timing confirms the cost moved out of the hook phase: `tests 2.62s /
import 619ms` before, `tests 98ms / import 2.16s` after. No hook timeout
  applies to the import phase.
- Full `@t3tools/web` suite: 250 files / 2451 tests, **0 skipped**, exit
0.
Previously this run showed MessagesTimeline at `18 tests | 18 skipped`.
- `@t3tools/web` typecheck clean.

Worth noting the original stall was intermittent (1 of 2 full runs), so
a green
run is not by itself proof. The argument for the fix is structural:
there is no
longer a timed hook around the import.

---
Written by an agent (Claude Code, claude-opus-5).
yngatech-nightly Bot pushed a commit that referenced this pull request Aug 14, 2026
> [!NOTE]
> The repo is public, so standard GitHub-hosted runners are free. Moves
the two
> jobs that gain least from paid hardware onto free runners and
right-sizes a
> third. Runner changes only — follow-ups tracked at the bottom.

## Problem

An audit of the last 8 days of run history (all GitHub retains) put
Blacksmith
at roughly $176/mo, with Fork CI the largest bucket at ~$80/mo. Two jobs
were
paying for cores they could not use:

- **Fork Test** spends 209s of its 248s in the `Test` step. Only the
first ~30s
is parallel transform/import fan-out at 100% CPU; the remaining ~2.5min
at
15-20% is `apps/server` alone (`transform 4.85s, import 75s, tests 211s`
—
await-bound tests pinning one or two workers while every other package
has
finished). It is long-poled, not short of cores, so slower cores cost
far
  less than proportionally.
- **Nightly Windows x64** was the least CPU-bound of the three desktop
targets
  per the #51 metrics review.
- **Fork Check** peaks at 4-5 cores during Typecheck; only ~54s of its
97s is
  CPU work at all.

## Fix

- Fork Test → `ubuntu-24.04`, nightly Windows → `windows-2025` (free).
- Fork Check → `blacksmith-4vcpu-ubuntu-2404`.

macOS deliberately stays on Blacksmith — it is genuinely CPU-bound (P95
≥ 91%)
and paces the whole nightly.

Expected cost after this lands: ~$176/mo → ~$90/mo, leaving macOS
(~$29/mo) as
the largest Blacksmith item.

## Verification

`actionlint` reports no new findings, both workflows parse, and the
desktop
build matrix script still emits the expected runner for each target
(`macos-arm64` → `blacksmith-6vcpu-macos-15`, `linux-x64` →
`blacksmith-8vcpu-ubuntu-2404`, `windows-x64` → `windows-2025`).

Note this PR's own checks run under the **old** config; the new runner
choices
are not exercised until it lands on main.

## Risks

Two things only a real run can confirm: disk headroom for the NSIS build
on the
GitHub-hosted Windows runner, and Fork Test's actual wall time on 4
cores
(predicted ~250s → ~300s, since only the 30s phase scales with cores).

## Follow-ups

Split out of this PR to keep it to one concern:

1. **`MessagesTimeline.test.tsx` silently skips itself under load.** It
defers
`await import("./MessagesTimeline")` into `beforeAll(..., 30_000)`. In
isolation the file runs in 3s, but under full-suite contention that hook
hits
its timeout and the file reports `18 tests | 18 skipped` at 30100ms
*without
failing*. Moving the DOM stubs to `vi.hoisted` fixes it structurally.
This is
pre-existing, but the slower runner in this PR makes it more likely —
worth
   landing soon after.
2. **Drop the `merge_group` trigger**, now that the merge queue is
retired.

---
Written by an agent (Claude Code, claude-opus-5).
yngatech-nightly Bot pushed a commit that referenced this pull request Aug 14, 2026
## Problem

The merge queue was retired because it duplicated CI work, but Fork CI
still
carries its plumbing: a `merge_group` trigger and
`github.event.merge_group.*`
fallbacks in the `changes` job's SHA resolution. Nothing fires it, so it
is dead
config that implies a workflow the repo no longer uses.

## Fix

Remove the trigger and the two fallbacks. `pull_request` and `push`
events
already resolve the same SHAs on their own:

- `BASE_SHA` → `pull_request.base.sha` or `github.event.before`
- `HEAD_SHA` → `pull_request.head.sha` or `github.sha`

## Verification

Confirmed no merge queue is configured, so nothing is stranded by this:

- The `PR + CI` ruleset on `main` contains only `pull_request` and
  `required_status_checks` rules — no `merge_queue` rule.
- All four required checks (`Fork Changes`, `Fork Check`, `Fork Release
Smoke`,
  `Fork Test`) run on `pull_request`, so they still report on every PR.

Workflow parses and `actionlint` reports no new findings.

Follow-up to #112.

---
Written by an agent (Claude Code, claude-opus-5).
yngatech-nightly Bot pushed a commit that referenced this pull request Aug 14, 2026
…118)

## Problem

`MessagesTimeline.test.tsx` needs DOM globals stubbed before its module
graph is
evaluated, because the web `unit` project runs on the **node**
environment. It
did that by deferring the import into a hook:

```ts
let MessagesTimeline: typeof import("./MessagesTimeline").MessagesTimeline;

beforeAll(async () => {
  vi.stubGlobal("window", { /* ... */ });
  ({ MessagesTimeline } = await import("./MessagesTimeline"));
}, 30_000);
```

That puts the module graph's transform cost *inside a hook timeout*. Run
alone
the file takes 3s, but under full-suite contention the hook hit its 30s
timeout
and the file reported `18 tests | 18 skipped` at 30100ms — **without
failing**.
CI stayed green having run 18 fewer tests than it appeared to.

This is pre-existing, but #112 moved Fork Test to a 4-core free runner,
which
makes the contention that triggers it more likely.

## Fix

Move the stubs into `vi.hoisted`, which runs ahead of imports, so
`MessagesTimeline` is imported statically and no hook timeout wraps the
module
graph. This removes the failure mode structurally rather than by raising
the
timeout. `vi.hoisted` is already the idiom in ~10 other web test files.

## Verification

- File alone: 18/18 pass.
- Timing confirms the cost moved out of the hook phase: `tests 2.62s /
import 619ms` before, `tests 98ms / import 2.16s` after. No hook timeout
  applies to the import phase.
- Full `@t3tools/web` suite: 250 files / 2451 tests, **0 skipped**, exit
0.
Previously this run showed MessagesTimeline at `18 tests | 18 skipped`.
- `@t3tools/web` typecheck clean.

Worth noting the original stall was intermittent (1 of 2 full runs), so
a green
run is not by itself proof. The argument for the fix is structural:
there is no
longer a timed hook around the import.

---
Written by an agent (Claude Code, claude-opus-5).
incognitojam added a commit that referenced this pull request Aug 15, 2026
> [!NOTE]
> The repo is public, so standard GitHub-hosted runners are free. Moves
the two
> jobs that gain least from paid hardware onto free runners and
right-sizes a
> third. Runner changes only — follow-ups tracked at the bottom.

## Problem

An audit of the last 8 days of run history (all GitHub retains) put
Blacksmith
at roughly $176/mo, with Fork CI the largest bucket at ~$80/mo. Two jobs
were
paying for cores they could not use:

- **Fork Test** spends 209s of its 248s in the `Test` step. Only the
first ~30s
is parallel transform/import fan-out at 100% CPU; the remaining ~2.5min
at
15-20% is `apps/server` alone (`transform 4.85s, import 75s, tests 211s`
—
await-bound tests pinning one or two workers while every other package
has
finished). It is long-poled, not short of cores, so slower cores cost
far
  less than proportionally.
- **Nightly Windows x64** was the least CPU-bound of the three desktop
targets
  per the #51 metrics review.
- **Fork Check** peaks at 4-5 cores during Typecheck; only ~54s of its
97s is
  CPU work at all.

## Fix

- Fork Test → `ubuntu-24.04`, nightly Windows → `windows-2025` (free).
- Fork Check → `blacksmith-4vcpu-ubuntu-2404`.

macOS deliberately stays on Blacksmith — it is genuinely CPU-bound (P95
≥ 91%)
and paces the whole nightly.

Expected cost after this lands: ~$176/mo → ~$90/mo, leaving macOS
(~$29/mo) as
the largest Blacksmith item.

## Verification

`actionlint` reports no new findings, both workflows parse, and the
desktop
build matrix script still emits the expected runner for each target
(`macos-arm64` → `blacksmith-6vcpu-macos-15`, `linux-x64` →
`blacksmith-8vcpu-ubuntu-2404`, `windows-x64` → `windows-2025`).

Note this PR's own checks run under the **old** config; the new runner
choices
are not exercised until it lands on main.

## Risks

Two things only a real run can confirm: disk headroom for the NSIS build
on the
GitHub-hosted Windows runner, and Fork Test's actual wall time on 4
cores
(predicted ~250s → ~300s, since only the 30s phase scales with cores).

## Follow-ups

Split out of this PR to keep it to one concern:

1. **`MessagesTimeline.test.tsx` silently skips itself under load.** It
defers
`await import("./MessagesTimeline")` into `beforeAll(..., 30_000)`. In
isolation the file runs in 3s, but under full-suite contention that hook
hits
its timeout and the file reports `18 tests | 18 skipped` at 30100ms
*without
failing*. Moving the DOM stubs to `vi.hoisted` fixes it structurally.
This is
pre-existing, but the slower runner in this PR makes it more likely —
worth
   landing soon after.
2. **Drop the `merge_group` trigger**, now that the merge queue is
retired.

---
Written by an agent (Claude Code, claude-opus-5).
incognitojam added a commit that referenced this pull request Aug 15, 2026
## Problem

The merge queue was retired because it duplicated CI work, but Fork CI
still
carries its plumbing: a `merge_group` trigger and
`github.event.merge_group.*`
fallbacks in the `changes` job's SHA resolution. Nothing fires it, so it
is dead
config that implies a workflow the repo no longer uses.

## Fix

Remove the trigger and the two fallbacks. `pull_request` and `push`
events
already resolve the same SHAs on their own:

- `BASE_SHA` → `pull_request.base.sha` or `github.event.before`
- `HEAD_SHA` → `pull_request.head.sha` or `github.sha`

## Verification

Confirmed no merge queue is configured, so nothing is stranded by this:

- The `PR + CI` ruleset on `main` contains only `pull_request` and
  `required_status_checks` rules — no `merge_queue` rule.
- All four required checks (`Fork Changes`, `Fork Check`, `Fork Release
Smoke`,
  `Fork Test`) run on `pull_request`, so they still report on every PR.

Workflow parses and `actionlint` reports no new findings.

Follow-up to #112.

---
Written by an agent (Claude Code, claude-opus-5).
incognitojam added a commit that referenced this pull request Aug 15, 2026
…118)

## Problem

`MessagesTimeline.test.tsx` needs DOM globals stubbed before its module
graph is
evaluated, because the web `unit` project runs on the **node**
environment. It
did that by deferring the import into a hook:

```ts
let MessagesTimeline: typeof import("./MessagesTimeline").MessagesTimeline;

beforeAll(async () => {
  vi.stubGlobal("window", { /* ... */ });
  ({ MessagesTimeline } = await import("./MessagesTimeline"));
}, 30_000);
```

That puts the module graph's transform cost *inside a hook timeout*. Run
alone
the file takes 3s, but under full-suite contention the hook hit its 30s
timeout
and the file reported `18 tests | 18 skipped` at 30100ms — **without
failing**.
CI stayed green having run 18 fewer tests than it appeared to.

This is pre-existing, but #112 moved Fork Test to a 4-core free runner,
which
makes the contention that triggers it more likely.

## Fix

Move the stubs into `vi.hoisted`, which runs ahead of imports, so
`MessagesTimeline` is imported statically and no hook timeout wraps the
module
graph. This removes the failure mode structurally rather than by raising
the
timeout. `vi.hoisted` is already the idiom in ~10 other web test files.

## Verification

- File alone: 18/18 pass.
- Timing confirms the cost moved out of the hook phase: `tests 2.62s /
import 619ms` before, `tests 98ms / import 2.16s` after. No hook timeout
  applies to the import phase.
- Full `@t3tools/web` suite: 250 files / 2451 tests, **0 skipped**, exit
0.
Previously this run showed MessagesTimeline at `18 tests | 18 skipped`.
- `@t3tools/web` typecheck clean.

Worth noting the original stall was intermittent (1 of 2 full runs), so
a green
run is not by itself proof. The argument for the fix is structural:
there is no
longer a timed hook around the import.

---
Written by an agent (Claude Code, claude-opus-5).
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:S vouch:trusted PR author is trusted by repo permissions or the VOUCHED list.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant