greptile: my earlier existence-check anchor was necessary but insufficient.
`rootDir` (= process.cwd() when FUSION_PROJECT_DIR is unset) drives ALL workspace
discovery (readWorkspacePatterns / listWorkspacePackageInfos /
packageHasVitestConfig). Launched from a package subdir, cwd-based discovery
found no packages, so decideExecutionPlan saw "no affected package", ran only the
gate, and exited successfully WITHOUT running the live changed package tests.
Fix the root cause: resolveRepoRoot() resolves the git toplevel as the fallback
(FUSION_PROJECT_DIR still the explicit override; cwd only when git can't report a
toplevel). This is correct from any cwd inside the repo, including a git worktree
(how the engine runs per-task verification). repoRootForExistence is now
redundant and removed; the existence check defaults back to rootDir.
Demonstrated: resolveRepoRoot() from packages/core (no FUSION_PROJECT_DIR) now
resolves the repo root and finds the workspace. +1 regression test. 121/121.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- P2 (greptile): anchor the changed-test existence check at the git repo root
(repoRootForExistence via `git rev-parse --show-toplevel`) instead of rootDir,
so a script run from a package subdir without FUSION_PROJECT_DIR no longer
forms a doubled path and silently drops live tests into the delegate path.
+1 regression test (default root resolves to repo root).
- coderabbit: fix stale "1-worker lane" wording in the delegation log (now
"heavy memory-envelope lane") and the "single-worker envelope" test title,
both stale after the 1->4 worker change.
test-changed 118/118, eslint clean.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Three changes to make `pnpm test` reliably minimal and fail gracefully:
- @fusion/core is now a memory-envelope/wide-fan-out package (was unguarded).
It's the hub nearly everything imports (~354 test files), so a core source
edit made `vitest --changed` expand to ~the whole core suite and blow past the
engine's 15-min verification kill -> SIGKILL + task restart. Adding it to
SCOPED_AFFECTED_MEMORY_ENVELOPES applies the wide-fan-out guard (run only
directly-changed core tests, else delegate) and the bounded env. core is NOT
gate-covered, so delegation warns loudly rather than false-greens.
- Lower CLASS_BUDGET_BANDS.changed ceiling 20min -> 13min so the script watchdog
fails a runaway local lane itself (exit 124, no restart) BEFORE the engine's
15-min kill restarts the whole task. A tightening, not a timeout-widening.
Guard test pins ceiling < 900_000ms.
- Raise scoped-affected worker fan-out 1 -> 4 (operator decision). Was 1 only
for OOM safety (FN-6854/FN-6874); the fan-out guard now bounds the set so the
hundreds-of-files OOM driver no longer reaches these workers. Heap stays
6144MB/worker (~4x6GB on the lane) — revisit if a RAM-constrained CI runner
OOMs. Trades FN-5048 worker-knob guidance for throughput, scoped to the
bounded affected lanes only.
Tests: test-changed 117/117, watchdog 15/15, eslint clean.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- P2: filter directly-changed test files to paths that still exist on disk
(existingChangedTestFilesInPackage) so deleted/renamed .test paths from
`git diff` never reach `vitest run` positionally; all-deletions diff falls
into the delegate-to-gate path.
- P1: make heavy-package delegation gate-coverage-aware
(GATE_COVERED_MEMORY_ENVELOPE_PACKAGES). Engine delegation keeps the accurate
"curated engine-core subset ran above" note; dashboard delegation now warns
that the gate runs no dashboard tests and names the CI full-suite backstop,
so the coverage gap is loud instead of a silent false-green.
- +4 regression tests (115/115).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Split the clean-room AI merger into smaller focused modules while preserving its public behavior.
- Extract prompt builders and review verdict parsing into merger-ai-prompts.
- Extract AI merge worktree lifecycle and cleanup helpers into merger-ai-worktree.
- Re-export the extracted APIs from merger-ai and cover prompt/verdict behavior with tests.
- Remove the merger-ai line-count baseline now that the file is under the guardrail.
Files changed:
.../engine/src/__tests__/merger-ai-prompts.test.ts | 86 ++++
packages/engine/src/merger-ai-prompts.ts | 312 ++++++++++++
packages/engine/src/merger-ai-worktree.ts | 287 +++++++++++
packages/engine/src/merger-ai.ts | 555 ++-------------------
scripts/line-count-baseline.json | 1 -
5 files changed, 723 insertions(+), 518 deletions(-)
Fusion-Task-Id: FN-7029
Fusion-Task-Lineage: 59adc31f-7386-4008-b74f-8fb9bbae078a
`pnpm test`'s changed-affected lane ran `vitest run --changed <base>` for the
heavy packages (@fusion/engine, @fusion/dashboard). `vitest --changed` does
unbounded transitive module-graph expansion: one changed hub source file
selects ~8,393 test entries (79s just to list), which at the OOM-pinned
workers=1 exceeds the engine's 15-min VERIFICATION_TIMEOUT_WORKSPACE_MS. The
engine SIGKILLs and restarts the task, producing the observed loop of nine
15-min verification timeouts (~2.8h) on a single task.
Guard the lane with a git-only predictor: when a heavy package has changed
non-test source in its graph, run only the directly-changed test files;
when no test files changed, delegate cross-cutting coverage to the merge gate
(already run in changed mode). Test-only diffs keep normal --changed.
Mirrors the existing reverse-dependent blast cap one level down. No widened
timeouts, retries, or worker bumps. test:full remains the explicit full sweep.
Bounded engine run: 2.79s vs 79s. Regression suite 111/111.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
## What this adds
A **test-free verification command** — `pnpm verify:fast`
(`scripts/verify-fast.mjs`) — that gives deterministic, flake-free
signal without running the test suite. It is fully **additive**: `pnpm
test`, the merge gate (`test:gate`), and CI are untouched.
`docs/testing.md` observes the broad test gate "caught no recalled real
bugs while consuming ~70% of shipping time in flake triage."
`verify:fast` is the opt-in path for non-test verification, suitable as
a project `testCommand`/verification command.
## What verify:fast runs
1. **typecheck — scoped to the changed packages** (each package's
`typecheck` script, or `pnpm --filter <pkg> exec tsc --noEmit -p .` when
none exists).
2. **build — scoped to the changed packages** (`pnpm --filter <pkg>
build`, only for packages that declare a build script).
3. **boot smoke once** (`scripts/boot-smoke.mjs`: CLI `--help` + a real
`fn serve` answering `GET /api/health`), after builds so it runs against
fresh artifacts.
Change-detection **reuses `scripts/test-changed.mjs`** (`getBaseBranch`
/ `detectComparisonBase` / `changedFilesSince` /
`resolveAffectedPackages` / workspace resolution — newly `export`ed)
instead of reinventing git-diff, so it scopes to exactly the packages a
changed-only test run would. With no affected package (root/docs-only
diff) it runs the boot smoke only. Each step is bounded by the existing
`runWithWatchdog` (class `changed`) so a hung tsc/build/serve fails
fast; it streams progress and exits nonzero on the first failing step.
`@fusion/desktop` and `@fusion/mobile` are skipped, mirroring the root
`build`/`typecheck` exclusions.
## Measured wall-time
On this branch's diff (which resolves to the heaviest package,
`@fusion/dashboard`), end-to-end:
```
[verify:fast] plan: typecheck:@fusion/dashboard -> build:@fusion/dashboard -> boot-smoke
[verify:fast] OK typecheck @fusion/dashboard (~44s)
[verify:fast] OK build @fusion/dashboard (26.2s)
[verify:fast] OK boot smoke (CLI --help + real serve /api/health) (19.6s)
[verify:fast] PASS — 3 step(s) green in 90.3s (no tests run).
```
**~90s total**, deterministic and flake-free. By contrast a typical
**scoped test run for the same package** is far heavier and flake-prone:
`docs/testing.md` notes a dashboard task "otherwise re-ran all 822
dashboard test files (~5-8 min)", and `pnpm test` additionally runs the
merge-gate suite first. verify:fast trades that test-suite cost (and its
flake-triage tax) for a typecheck+build+boot signal in ~1.5 min.
## Doc additions
- `AGENTS.md` + `docs/testing.md` testing-commands lists now include
`pnpm verify:fast`, described as the recommended **test-free
verification** (typecheck + build + boot-smoke), suitable as a project
`testCommand`/verification command; the full suite stays available and
runs non-blocking.
## Tests / verification
- New `scripts/__tests__/verify-fast.test.mjs` (11 tests) pins the pure
planning / arg-construction logic — scoped typecheck/build selection,
build-script gating, desktop/mobile exclusion, boot-smoke-only fallback,
and reuse of `resolveAffectedPackages`. It never spawns real
tsc/build/vitest.
- `pnpm verify:fast` runs end-to-end and exits 0 (output above).
- Lint clean on all new/changed files; `agents-md-invariants`,
`check-test-inventory`, `verify-fast`, and `test-changed` script tests
all green (132 tests).
No changeset (scripts + docs + CI-tooling, behavior-additive;
`@runfusion/fusion` runtime unaffected).
🤖 Generated with [Claude Code](https://claude.com/claude-code)
<!-- stage-review-badge-begin -->
---
<a href="https://stagereview.app/Runfusion/Fusion/pull/1777">
<picture>
<source media="(prefers-color-scheme: dark)"
srcset="https://stagereview.app/assets/gh-open-in-stage-dark.svg">
<img src="https://stagereview.app/assets/gh-open-in-stage-light.svg"
alt="Open in Stage">
</picture>
</a>
<!-- stage-review-badge-end -->
## What
A **test value audit**: a heuristic that scores every test file under
`packages/*/src/**/__tests__/**` and
`packages/dashboard/app/**/__tests__/**` by how much real regression
signal it has encoded over its git history, then ranks **slow AND
low-value** files first as deletion candidates. This is the **evidence
base** for a human/follow-up deletion decision — **the script deletes
nothing**.
Motivated by AGENTS.md "Do Not Add Slow Tests" (FN-5048) + the
quarantine deletion ratchet: we want data on which slow tests are also
low-signal so they can be cut without losing coverage.
## How it scores (HEURISTIC, not ground truth)
Single whole-history `git log --name-status` pass; per-commit
classification (renames followed backward):
- **Positive** — `fix(...)`/`fix:` with sibling source change (+3), fix
alone (+2), `## Symptom Verification` regression marker (+3, FN-5893),
test added-with-source (+2)/alone (+1), plain test+source co-change
(+1.5).
- **Negative** — subject/body churn keywords
`flake/flaky/deflake/quarantine/stabiliz/appease/timeout/retry` (−3),
test-only modify with no source (−1), quarantine-ledger membership
current+historical (−5).
`valueScore` = sum of weights. `deletionPriority = durationMs / (1 +
max(0, valueScore))` (+ small net-negative boost), joined with
`scripts/test-timings.json` so slow + low-value surfaces first.
Recommendation: `delete` (≤0) / `review` (≤3) / `keep` (>3). A
`safeDelete` flag marks files meeting the ratchet's churn/quarantine
bar.
## Deliverables
- `scripts/test-value-audit.mjs` — runner (git IO + report generation)
- `scripts/lib/test-value-audit-lib.mjs` — pure, unit-tested scoring
logic
- `scripts/__tests__/test-value-audit.test.mjs` — 15 synthetic-record
unit tests
- `docs/test-value-audit.json` + `docs/test-value-audit.md` — generated
artifacts (top 40 + methodology + honest caveats: heuristic limits,
git-follow/squash-merge blind spots, lying subjects, timing snapshot)
## Verification
- `node scripts/test-value-audit.mjs` runs end-to-end (~1s), 2051 files
analyzed, writes both artifacts.
- `node --test scripts/__tests__/test-value-audit.test.mjs` → 15/15
pass.
- `eslint` clean on all three new source files.
No changeset (scripts + docs only; `@runfusion/fusion` runtime
unaffected).
🤖 Generated with [Claude Code](https://claude.com/claude-code)
<!-- stage-review-badge-begin -->
---
<a href="https://stagereview.app/Runfusion/Fusion/pull/1776">
<picture>
<source media="(prefers-color-scheme: dark)"
srcset="https://stagereview.app/assets/gh-open-in-stage-dark.svg">
<img src="https://stagereview.app/assets/gh-open-in-stage-light.svg"
alt="Open in Stage">
</picture>
</a>
<!-- stage-review-badge-end -->
Adds scripts/verify-fast.mjs + root `pnpm verify:fast`, an opt-in, flake-free
verification path that runs typecheck + build scoped to the changed packages
(reusing test-changed.mjs git-diff / changed-package resolution) plus the
existing boot smoke once, with no test suite. Each step is bounded by the
shared runWithWatchdog (class "changed"); exits nonzero on the first failure.
No default changed: pnpm test, the merge gate, and CI are untouched.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Add scripts/test-value-audit.mjs + scripts/lib/test-value-audit-lib.mjs:
a heuristic that scores every test file under packages/*/src/**/__tests__/**
and packages/dashboard/app/**/__tests__/** from git history, classifying
commits as positive (fix+source co-change, Symptom Verification regressions,
added-with-source) vs negative (flake/quarantine/timeout churn, test-only
modifies, quarantine-ledger membership). Joins per-file durations from
scripts/test-timings.json so SLOW + LOW-VALUE files rank first as deletion
candidates. Emits docs/test-value-audit.json + docs/test-value-audit.md
(top 40 + methodology + caveats). Pure scoring logic is unit-tested with
synthetic commit records. The script never deletes tests — evidence only.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Quarantine three test files consistently failing on the non-blocking
full-suite CI on main, per the AGENTS.md deletion-ratchet policy:
- engine self-healing-fn-5488-fast-path-regressions.test.ts (shard 1)
- engine in-review-merge-stall-deadlock-recovery.test.ts (shard 2)
- dashboard DevServerView.mobile.test.tsx (shard 4)
Each has a matching entry in scripts/lib/test-quarantine.json with
the failing CI run link and quarantinedAt date. Tests will be deleted
after 14 days unless rescued with a root-cause fix.
Refresh the opt-in line-count guard so current files match the recorded baseline.
- Document why the guard remains outside the default test gate.
- Re-ratchet current line-count violations after organic growth.
- Tighten or prune stale baseline entries and grandfather two long-existing over-cap files.
Files changed:
scripts/check-file-line-count.mjs | 3 +
scripts/line-count-baseline.json | 133 +++++++++++++++++++-------------------
2 files changed, 69 insertions(+), 67 deletions(-)
Fusion-Task-Id: FN-7013
Fusion-Task-Lineage: bd770058-5b42-4d63-a18d-bf46b7b957e0
Refresh the weekly test velocity baseline with current timing evidence.
- Update the rendered baseline report with the latest capture timestamps and velocity deltas.
- Replace stale slowest-file timing rows with the refreshed snapshot entries.
- Append the latest velocity history sample used by the weekly report.
Files changed:
docs/test-velocity-baseline.md | 61 +-
scripts/test-timings.json | 1772 +++++++++++++++++++++++++++++-------
scripts/test-velocity-history.json | 112 +++
3 files changed, 1580 insertions(+), 365 deletions(-)
Fusion-Task-Id: FN-6968
Fusion-Task-Lineage: 940f3581-3650-4feb-8730-d6dbb760e30c
Add stale timing context to the weekly test velocity baseline so W26 regressions are not misattributed.
- Report timing snapshot age and missing slowest-file paths before the slow-file table.
- Persist timing metadata notes in velocity history and regenerate the W26 baseline report.
- Cover stale and missing timing metadata warnings with node:test assertions.
Files changed:
docs/test-velocity-baseline.md | 23 ++-
scripts/__tests__/test-velocity-baseline.test.mjs | 26 +++
scripts/test-velocity-baseline.mjs | 65 +++++-
scripts/test-velocity-history.json | 231 ++++++++++++++++++++++
4 files changed, 330 insertions(+), 15 deletions(-)
Fusion-Task-Id: FN-6966
Fusion-Task-Lineage: bccac6c2-11c1-4295-b3af-b77dab1748dc
Update AGENTS.md, RELEASING.md, contributing.md with the structured
changeset format guide. Add .changeset/README.md template. Add changeset
for this change. Update distill-release-notes.mjs with final version.
Chain distillation into release:version so both local and CI versioning
flows get distilled notes. Update release.yml to use curated CHANGELOG
notes instead of GitHub's auto-generated release notes.
Capture changeset entries before 'changeset version' deletes them,
distill deterministic notes post-version, and replace the version's
section in the root CHANGELOG with curated end-user notes.
Add scripts/lib/distill-release-notes.mjs with:
- distillDeterministic(): groups parsed changesets by category,
renders clean markdown release notes (Keep a Changelog headings)
- buildDistillationPrompt(): builds the context input for AI mode
- DISTILLATION_SYSTEM_PROMPT: system prompt for AI distillation
- Category display order: New → Fixed → Breaking → Security →
Performance → Internal; empty categories omitted
The AI mode (createFnAgent integration) is deferred to U4 where the
engine runtime is available. The deterministic mode is the fallback
contract: it always produces valid output regardless of model access.
14 tests covering category grouping, ordering, empty/edge cases,
prompt building, and legacy entry handling.
App.tsx dropped from 2,729 to 1,636 lines through the module-breakup refactor
(U1-U7), now well under the 2,000-line cap. Remove its grandfathered entry
from scripts/line-count-baseline.json so the file is subject to the cap going
forward and can never regress above 2,000. Scoped change: only the App.tsx
entry is removed; every other ceiling is untouched (a full `--update` would
have re-derived the whole baseline and re-raised ceilings for unrelated
grown files, which AGENTS.md forbids).
U8 (App.tsx module-breakup plan).
Refresh the weekly test velocity report with the latest captured baseline.
- Update the latest baseline timestamp, metric deltas, quarantine counts, and #leads posting text.
- Append the 2026-06-23 test velocity history row with wall times and slowest test files.
Files changed:
docs/test-velocity-baseline.md | 20 +++----
scripts/test-velocity-history.json | 111 +++++++++++++++++++++++++++++++++++++
2 files changed, 121 insertions(+), 10 deletions(-)
Fusion-Task-Id: FN-6948
Fusion-Task-Lineage: 7b2d265a-b6c9-494c-aa87-31ae2c71c5f0
Remove the orphaned session-cross-tab quarantine ledger entry after confirming the test remains active and rescued.
- Document FN-6937's rescue proof and ledger/config lockstep expectation in testing guidance.
- Keep the dashboard Vitest quarantine list empty with a note explaining the stale ledger-only cleanup.
- Remove the session-cross-tab row from the flaky-test quarantine ledger.
Files changed:
docs/testing.md | 8 ++++++--
packages/dashboard/vitest.config.ts | 3 +++
scripts/lib/test-quarantine.json | 8 +-------
3 files changed, 10 insertions(+), 9 deletions(-)
Fusion-Task-Id: FN-6937
Fusion-Task-Lineage: 34a67bf3-2a7f-49ea-93ab-68fadc81f893
Re-ratchet the opt-in line-count audit baseline so current oversized files no longer fail the ceiling check.
- Document that the pnpm test blocker premise is stale because the guard is opt-in.
- Refresh grandfathered line-count ceilings to the current merged tree.
- Add TerminalModal.tsx to the grandfathered oversized-file baseline and drop entries that no longer need it.
Files changed:
scripts/check-file-line-count.mjs | 3 ++
scripts/line-count-baseline.json | 80 +++++++++++++++++++--------------------
2 files changed, 42 insertions(+), 41 deletions(-)
Fusion-Task-Id: FN-6917
Fusion-Task-Lineage: aaa018d8-f1a3-47a5-b63b-f18bac87b910
Add a non-measured build setup step so velocity baselines do not misclassify missing dist artifacts as lane time.
- Run a default `pnpm build` preflight before measured test velocity lanes, with an explicit skip flag for pre-built CI.
- Add injectable command-runner coverage for preflight ordering, failure reporting, and skip behavior.
- Document the preflight behavior in the generated baseline report and testing docs.
Files changed:
docs/test-velocity-baseline.md | 2 +
docs/testing.md | 4 +-
scripts/__tests__/test-velocity-baseline.test.mjs | 159 ++++++++++++++++++++++
scripts/test-velocity-baseline.mjs | 38 +++++-
4 files changed, 195 insertions(+), 8 deletions(-)
Fusion-Task-Id: FN-6905
Fusion-Task-Lineage: 3016a542-4395-4d06-9f2e-1a91f4939e07
Refresh the weekly test velocity report with the latest captured baseline data.
- Advance the documented baseline from 2026-W25 to 2026-W26.
- Record the latest gate, changed-only test, quarantine, and boot-smoke measurement status.
- Append the new measurement row to the persisted test velocity history.
Files changed:
docs/test-velocity-baseline.md | 22 +++----
scripts/test-velocity-history.json | 116 +++++++++++++++++++++++++++++++++++++
2 files changed, 127 insertions(+), 11 deletions(-)
Fusion-Task-Id: FN-6901
Fusion-Task-Lineage: 06f42104-b3c5-4a26-86ee-fb2791f7006d
Refresh the line-count audit baseline to match current repository drift.
- Update the grandfathered large-file baseline counts for current source and test files.
- Document that the line-count guard is now an opt-in audit rather than a pretest blocker.
Files changed:
scripts/check-file-line-count.mjs | 3 +++
scripts/line-count-baseline.json | 22 +++++++++++-----------
2 files changed, 14 insertions(+), 11 deletions(-)
Fusion-Task-Id: FN-6871
Fusion-Task-Lineage: d2fcf11e-2959-45a0-9bd1-1dc33b591ccf
Stabilize changed-test runs by giving the engine affected Vitest lane its own memory envelope.
- Split @fusion/engine out from other scoped affected-package Vitest runs.
- Apply a capped heap and single-worker settings to the isolated engine lane while preserving watchdog timing.
- Cover the partitioning and environment behavior with script tests and document the envelope.
Files changed:
docs/testing.md | 3 +++
scripts/__tests__/test-changed.test.mjs | 45 +++++++++++++++++++++++++++++++++
scripts/test-changed.mjs | 40 ++++++++++++++++++++++++++---
3 files changed, 84 insertions(+), 4 deletions(-)
Fusion-Task-Id: FN-6854
Fusion-Task-Lineage: 144acf15-4ccb-4974-b06c-99cdcc2814dd
Refresh the line-count guardrail baseline so pretest accepts the current grandfathered source sizes.
- Document the FN-6849 maintenance re-ratchet in the line-count guard script.
- Regenerate the grandfathered line-count baseline for current oversized source and test files.
- Keep the guardrail active while unblocking unrelated pretest runs.
Files changed:
scripts/check-file-line-count.mjs | 7 ++++
scripts/line-count-baseline.json | 74 +++++++++++++++++++--------------------
2 files changed, 44 insertions(+), 37 deletions(-)
Fusion-Task-Id: FN-6849
Fusion-Task-Lineage: 07c04c2a-535c-43b0-9dd5-700ead4e06f0
Resolve conflicts from main's analytics schema additions (plugin
activations, per-model token buckets) against the PR's contract-assertion
type column:
- db.ts: renumber behavioral-verification migration 124 -> 126, bump
SCHEMA_VERSION to 126 so it follows main's migrations 124/125
- core/roadmap tests: adopt main's SCHEMA_VERSION-constant assertions
instead of stale literal 124
- test-quarantine.json: keep all four quarantine entries from both sides
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- Import URL from node:url to clear ESLint no-undef (coderabbit)
- Throw on unreadable tracked files instead of silently skipping, so a
file can't evade the cap and false-pass (coderabbit)
- Emit the "baseline can be tightened" note for deleted-only stale entries
too, with a correct count (greptile)
- Add FNXC:CI comments to the guard and its test per AGENTS.md (greptile)
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Add a pretest guard that caps new source files at 2,000 lines to stop
god-files from being born, following the existing check-no-* guard pattern.
Existing oversized files (106 of them) are grandfathered via a ratchet
baseline (scripts/line-count-baseline.json): each is pinned to its current
line count and may shrink but never grow. Files refactored under the cap
drop out of the baseline and cannot regress. Generated, lock, locale, and
.d.ts files are out of scope via the source-extension filter.
Wired into pretest and pretest:full; covered by 11 unit tests.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>