Skip to content

fix(ci): regenerate pnpm lockfile and repair the CI failures it uncovered - #2

Merged
bfoxhound merged 19 commits into
mainfrom
claude/pnpm-lockfile-migration-5c6q07
Jul 27, 2026
Merged

fix(ci): regenerate pnpm lockfile and repair the CI failures it uncovered#2
bfoxhound merged 19 commits into
mainfrom
claude/pnpm-lockfile-migration-5c6q07

Conversation

@bfoxhound

@bfoxhound bfoxhound commented Jul 27, 2026

Copy link
Copy Markdown
Owner

What

Regenerates pnpm-lock.yaml against the current manifests, removes the root package-lock.json, and repairs the pre-existing CI failures that the install fix uncovered.

Why

Every workflow running pnpm install --frozen-lockfile (ci.yml, security.yml, canary.yml, release.yml, integration-tests.yml, deploy-vps.yml) failed at the install step:

ERR_PNPM_LOCKFILE_CONFIG_MISMATCH  Cannot proceed with the frozen installation.
The current "overrides" configuration doesn't match the value found in the lockfile

The committed lockfile carried an overrides: block that no package.json in the tree declared any more, so pnpm refused the frozen install. importers: was stale in the same way — it described root devDependencies the root manifest no longer had, and linked packages/ao to @aoagents/ao-cli via workspace:* instead of its current platform-binary optionalDependencies.

Because every job died at install, the failures behind it had never been visible. Fixing the lockfile exposed nine of them. They are unrelated to each other and all pre-date this branch.

The rest of the changes

The root manifest had lost its devDependencies and scripts. The stale lockfile was the only surviving record of them, which is how they were recovered: @changesets/cli, eslint, prettier, typescript-eslint, husky, and the build/test/api/changeset scripts. Roughly half the failures traced to this one cause.

Independent fixes:

Failure Cause
goose migration panic Two migrations claimed version 0020; 0020_review_run_unique_pr_sha.sql landed first, so pr_reviews was renamed to 0021
Typecheck Committed merge-conflict markers under frontend/src/landing
Scan for Secrets Findings on documented placeholders — AWS's published example key, a made-up Slack token in a redaction test, and ghp_xxxx… filler in SECURITY.md. Allowlisted by path and pattern; the Slack rule was tightened at the same time, since its optional-body ? matched a bare xoxb- in prose
api-drift Broken by this PR — see below
format The job's own push was rejected: GITHUB_TOKEN cannot push commits touching .github/workflows/**. Workflows are now in .prettierignore
Test Fresh Onboarding Steps 6–10 drove ao start --no-orchestrator, a flag that no longer exists. Trimmed to steps 1–5
Dependency Review Dependency graph is off by default on forks; the step is now continue-on-error
React Doctor Shallow checkout left no merge base, so it reported findings already on main. Now fetch-depth: 0
Test (windows-latest) Four distinct causes — see below

Correcting the original claim in this PR: the first revision of this description said the root package-lock.json was unreferenced. That was wrong. go.yml's api-drift job ran npm ci at the repo root, so deleting the lockfile broke it. That job now uses pnpm/action-setup and pnpm install --frozen-lockfile. frontend/package-lock.json is untouched — every other cache-dependency-path in CI points there.

Windows

Test (windows-latest) had never passed in this repo. Four causes, in the order they surfaced:

  1. better-sqlite3 bindings — the FTS integration guard now probes the binding by opening :memory: rather than assuming the module loads.
  2. 8.3 short namesos.tmpdir() returns C:\Users\RUNNER~1\… while git and realpath report the long form, so anything comparing the two decided the paths differed. 27 sites across 14 test files now canonicalise through realpathSync.native.
  3. A leaked file descriptorreadline.close() does not close the underlying ReadStream. On Windows this surfaced as ENOTEMPTY during teardown, because NTFS keeps deleted entries alive until every handle closes.
  4. PATH separatorupdate-script.test.ts joined its stub directory with :, which is not a separator on Windows. Correcting that was necessary but not sufficient: Git for Windows supplies bash and the script runs, but it does not treat an extensionless #!/bin/bash stub as executable, so command -v git walks past it and the runner's real git.exe answers. Those tests now carry the skipIf(win32) guard four of their siblings already had.

Separately, the pwsh doctor tests were raised to a 60s timeout. They had been running against vitest's 10s default while pwsh cold start alone took 9.1s for a bare --help, so runner load rather than correctness was deciding the outcome.

A real bug, not a test issue

Cause 3 above is production code. extractKimiSummary in agent-kimicode leaked one file descriptor per call — the daemon path, not a test fixture. It now awaits a deterministic close.

The tmp pin

Dropping the stale overrides block regressed tmp from 0.2.4 to 0.0.33. It arrives via inquirer → @inquirer/prompts → @inquirer/editor → external-editor → tmp, a runtime path in the CLI rather than dev-only, and tmp < 0.2.4 is the version affected by the symlink arbitrary-write advisory.

The pin is restored in the root manifest, which is what the lockfile had been missing all along — the block existed there with nothing backing it, and that mismatch is what broke every frozen install to begin with. Now both agree, and tmp@0.0.33 no longer resolves anywhere in the tree.

The other two entries from the original block are not restored: axios still resolves to 1.15.0 and follow-redirects to 1.16.0 without them, so both were already no-ops.

Left for a maintainer

skills/bug-triage/SKILL.md carried a conflict between a ReverbCode and an aoagents variant. Resolved one way to unblock CI; worth a look from someone who knows which is current.

Diff size

The previous pnpm-lock.yaml was committed with CRLF, and regenerating it on Linux produced LF, so the whole file reads as rewritten. Ignoring line endings the real change is ~2.7k lines. A .gitattributes now pins pnpm-lock.yaml, package-lock.json, and shell/JS sources to eol=lf so a Windows checkout does not reintroduce the churn.

Verification

Lockfile pnpm install --frozen-lockfile
committed (before) ERR_PNPM_LOCKFILE_CONFIG_MISMATCH
regenerated (this PR) Lockfile is up to date, resolution step is skipped

A second frozen install leaves the lockfile byte-identical, so it is stable. All 23 checks pass on 97a7821e, including Test (windows-latest).

The committed pnpm-lock.yaml carried an "overrides" block that no
package.json in the tree declares, so every workflow running
"pnpm install --frozen-lockfile" failed with
ERR_PNPM_LOCKFILE_CONFIG_MISMATCH. Regenerated the lockfile against the
current manifests with pnpm 9.15.0.

Also removes the root package-lock.json. The root is a pnpm workspace
root and no workflow referenced this file; the npm-based jobs all point
at frontend/package-lock.json, which is untouched.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VjPWzWR3yvT35opqeixiWy

Copy link
Copy Markdown
Owner Author

CI status — the lockfile fix worked; the remaining failures are pre-existing

This PR did what it set out to do. On the base commit (28a49c3, main), every CI job died at step 5/7 — pnpm install --frozen-lockfile — with every later step marked skipped. On this branch that step passes and all 33 workspace projects build. CI got further than it has since the lockfile went stale.

What that exposed is that main was already red underneath, on eight separate pre-existing problems that install failure had been masking. None of them are caused by this diff, which touches only pnpm-lock.yaml and package-lock.json:

Check Failure Cause
Test (ubuntu/windows) ERR_PNPM_NO_SCRIPT Missing script: test Root package.json has no test script; ci.yml runs pnpm test
Integration Tests Command "test:integration" not found Same — no test:integration script anywhere
Coverage Report ERR_MODULE_NOT_FOUND: Cannot find package 'istanbul-lib-coverage' .github/scripts/coverage-report.mjs imports it; not in any package.json
Lint Go test panics: goose: duplicate version 20 detected migrations/0020_review_run_unique_pr_sha.sql and migrations/0020_pr_reviews.sql share version 20
Typecheck tsc exit 2 Type errors in the workspace typecheck step
format (Prettier) SyntaxError: Merge conflict marker encountered Unresolved <<<<<<< Updated upstream markers committed under frontend/src/landing/**
Scan for Secrets gitleaks: 4 leaks Pre-existing: UUIDs in pi_test.go / vibe_test.go, PostHog key in frontend/src/shared/posthog-config.ts
Dependency Review Dependency review is not supported on this repository Repository setting — Dependency graph is not enabled

I'm not fixing these here. Each is a real bug outside the scope of a lockfile repair, and several are decisions rather than mechanical fixes — resolving ~30 files' worth of conflict markers, renumbering a shipped migration, deciding whether those gitleaks hits are false positives, and enabling a repo-level security setting. Bundling them into this PR would bury the one-line-of-intent change that actually fixes the install.

The likely root cause of several of these

The stale overrides: block was not the only thing the old lockfile was carrying. Its root importers: entry recorded devDependencies that the current root package.json no longer declares:

@changesets/cli, @eslint/js, @next/eslint-plugin-next, @types/node,
eslint, eslint-config-prettier, husky, istanbul-lib-coverage,
prettier, typescript-eslint

The current root manifest declares exactly one: openapi-typescript. That lines up precisely with the Coverage Report failure — istanbul-lib-coverage is in that list, CI's coverage script imports it, and it is no longer installable. The old lockfile appears to be the last surviving record of a root package.json that has since lost its devDependencies and several scripts.

If that truncation was accidental, restoring those devDependencies plus the missing test / test:integration scripts is probably the real fix, and it would clear four of the eight rows above. That's a call for a maintainer to make, not something to infer from a lockfile — happy to do it in a follow-up PR if you confirm the manifest should be restored.


Generated by Claude Code

claude added 2 commits July 27, 2026 12:43
Regenerating the lockfile got `pnpm install --frozen-lockfile` past the
gate it had been failing at, which let every later CI step run for the
first time in a while and surfaced eight independent breakages. None
were caused by the lockfile change; all of them predate it.

Root manifest had lost its devDependencies and scripts. The stale
lockfile still recorded ten root devDependencies that package.json no
longer declared, which is why `.github/scripts/coverage-report.mjs`
could not resolve istanbul-lib-coverage and why the root eslint.config.js
imports were unresolvable. Restored those, plus the `test`,
`test:integration`, `build` and `changeset` scripts that ci.yml,
integration-tests.yml, deploy-vps.yml and release.yml invoke.

Duplicate goose migration version. 0020_pr_reviews.sql and
0020_review_run_unique_pr_sha.sql both claimed version 20, so goose
panicked on every migrate and took three Go packages down with it.
0020_review_run_unique_pr_sha.sql landed first (Untrivial-ai#2193, ancestor of
Untrivial-ai#2200) and review_store.go documents its index as "migration 0020", so
the later collider becomes 0021.

CRLF line endings broke two toolchains. ao-doctor.sh and ao-update.sh
were unrunnable on the Unix runners, and Vite could not parse
packages/ao/bin/postinstall.js because its hashbang line ended in \r.
Converted the seven shell scripts and that module to LF, and added a
.gitattributes pinning the formats where CRLF is actively harmful.

Committed merge-conflict markers. Forty files under frontend/src/landing
and skills/bug-triage carried unresolved `<<<<<<< Updated upstream`
markers from a stash pop, which made Prettier exit 2. Kept the upstream
side throughout: 38 of the conflicts were pure formatting, ci-recovery
differed only in emphasis markers, and for SKILL.md the upstream side is
the one matching this repo (aoagents org, port 3001, hookPATH in
session_manager/manager.go).

Gitleaks false positives. Allowlisted the two agent session-ID fixtures
in the Go adapter tests and the PostHog *project* key, which is bundled
into the renderer and public by design. Listed by value rather than by
path so any other secret in those files still trips the scan.

Dependency Review is non-blocking. The action hard-fails unless the
Dependency graph is enabled in repository settings, which is off by
default on forks, so it was failing on a repo setting rather than on the
diff. Enabling that setting re-arms it with no further change here.

Also gitignores packages/web/.next, which the documented web build
creates and nothing was excluding.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VjPWzWR3yvT35opqeixiWy
The .gitattributes added in the previous commit pins *.js/*.mjs to LF,
so these twelve files were left permanently dirty in every working tree:
CRLF in the index, LF on checkout. Renormalizing them settles that. Each
is byte-identical once carriage returns are stripped.

Also excludes pnpm-lock.yaml from Prettier, alongside the two npm
lockfiles already listed. The format job commits its own output back, so
leaving a pnpm-generated file in scope means every push rewrites ~2900
lines of it.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VjPWzWR3yvT35opqeixiWy
@github-actions

github-actions Bot commented Jul 27, 2026

Copy link
Copy Markdown

React Doctor found no new issues. 🎉

Reviewed by React Doctor for commit 97a7821.

Copy link
Copy Markdown
Owner Author

All eight failures fixed

Pushed 7ce83b2 + 073c332. Every failure listed above is addressed. Two of them turned out not to be what the check name suggested.

Check Cause Fix
Test (ubuntu + windows) root package.json had no test script restored test, plus test:integration / build / changeset
Integration Tests no test:integration script same
Coverage Report istanbul-lib-coverage undeclared restored the 10 root devDependencies the stale lockfile still recorded
Lint goose panic: duplicate migration version 20 renumbered the later collider to 0021_pr_reviews.sql
Typecheck root @types/node etc. missing same manifest restore
format committed <<<<<<< Updated upstream markers in 40 files resolved, upstream side throughout
Scan for Secrets 4 false positives allowlisted by value in .gitleaks.toml
Dependency Review Dependency graph disabled on this fork made non-blocking

The root manifest was the common cause

Four of the eight traced back to one thing: package.json had lost its devDependencies and half its scripts. The old lockfile was the only surviving record of what it used to declare, which is what made istanbul-lib-coverage and the root eslint.config.js imports unresolvable and left ci.yml calling scripts that no longer existed.

Two findings worth flagging

The duplicate migration was a genuine data-integrity bug, not just a broken test. 0020_pr_reviews.sql and 0020_review_run_unique_pr_sha.sql both claimed version 20, so goose panicked on every migration — no database could get past version 19. I renumbered pr_reviews rather than the other one because 0020_review_run_unique_pr_sha.sql landed first (Untrivial-ai#2193, an ancestor of Untrivial-ai#2200) and review_store.go:44 documents its index as "migration 0020". Renumbering the already-applied one would have broken existing databases.

CRLF line endings were breaking two toolchains. ao-doctor.sh and ao-update.sh were literally unrunnable on the Unix runners, and Vite could not parse packages/ao/bin/postinstall.js because its hashbang line ended in \r — that one presents as a bare SyntaxError: Invalid or unexpected token pointing at the importing file, which is why it reads as unrelated. Converted the seven shell scripts and that module to LF and added a .gitattributes pinning the formats where CRLF is actively harmful.

On the two judgement calls

For skills/bug-triage/SKILL.md the two sides genuinely differed — one describes filing against aoagents/ReverbCode (Go daemon, port 3001), the other ComposioHQ/agent-orchestrator (pm2/tmux, port 3000). I kept the former: this repo's Go module is github.com/aoagents/…, the daemon binds 127.0.0.1:3001, and hookPATH is exactly where that side says it is. The other 39 conflicts were pure formatting. Please sanity-check that one — if bug reports should go somewhere else, it's a one-line change.

Dependency Review is now continue-on-error. It was failing on a repository setting rather than on anything in the diff — the Dependency graph is off by default on forks. Turning it on under Settings → Code security and analysis re-arms the check with real findings and no further change to the workflow. I did not weaken the severity threshold.

Verified locally

Every job reproduced against the pushed commit, on Node 22 / pnpm 9.15.0 / Go 1.24:

pnpm install --frozen-lockfile   ✅ lockfile up to date
go test ./...                    ✅ (backend, all packages)
golangci-lint run                ✅ exit 0
pnpm test                        ✅ 3400+ tests, 0 failures
pnpm test:integration            ✅
pnpm -r typecheck                ✅
pnpm --filter ao-web build       ✅
prettier --check .               ✅ 0 parse errors
gitleaks detect                  ✅ no leaks (tree + commit-range)

Two caveats on that run, both environmental rather than code: packages/core needs gh on PATH (present on Actions runners, absent in my container — I stubbed it), and two Go tests assert on a https://github.com/ remote that my sandbox's git proxy rewrites, so I neutralised the rewrite. Both pass cleanly once the environment matches CI.

One thing I deliberately did not do

prettier --write . touches 861 files (~217k lines), almost all of it CRLF normalisation. That's the format workflow's own job — it auto-commits the result on every push — so I left it to run rather than burying this diff in it. I did add pnpm-lock.yaml to .prettierignore, since otherwise that bot rewrites ~2900 lines of a pnpm-generated file on every push. I confirmed a Prettier-formatted lockfile still passes --frozen-lockfile, so this is churn-prevention, not a correctness fix.

The tmp 0.2.4 → 0.0.33 regression from the original PR is still open and still a deliberate non-decision — see the description above.


Generated by Claude Code

@github-actions

github-actions Bot commented Jul 27, 2026

Copy link
Copy Markdown

Test Coverage Report

Metric Value
Lines covered 24483/31514
Lines not covered 7031/31514
Overall coverage 77.7%
Per-file breakdown
File Coverage
packages/cli/src/commands/completion.ts 23/23 (100.0%)
packages/cli/src/commands/config.ts 19/83 (22.9%)
packages/cli/src/commands/dashboard.ts 18/28 (64.3%)
packages/cli/src/commands/doctor.ts 208/317 (65.6%)
packages/cli/src/commands/events.ts 75/174 (43.1%)
packages/cli/src/commands/migrate-storage.ts 66/74 (89.2%)
packages/cli/src/commands/open.ts 120/120 (100.0%)
packages/cli/src/commands/plugin.ts 304/481 (63.2%)
packages/cli/src/commands/project.ts 103/147 (70.1%)
packages/cli/src/commands/report.ts 103/116 (88.8%)
packages/cli/src/commands/review-check.ts 111/117 (94.9%)
packages/cli/src/commands/send.ts 153/173 (88.4%)
packages/cli/src/commands/session.ts 359/409 (87.8%)
packages/cli/src/commands/setup.ts 255/421 (60.6%)
packages/cli/src/commands/spawn.ts 333/390 (85.4%)
packages/cli/src/commands/start.ts 1024/1419 (72.2%)
packages/cli/src/commands/status.ts 365/455 (80.2%)
packages/cli/src/commands/update.ts 293/302 (97.0%)
packages/cli/src/commands/verify.ts 16/133 (12.0%)
packages/cli/src/index.ts 17/17 (100.0%)
packages/cli/src/lib/bun-tmp-janitor.ts 78/81 (96.3%)
packages/cli/src/lib/caller-context.ts 2/10 (20.0%)
packages/cli/src/lib/cli-errors.ts 9/22 (40.9%)
packages/cli/src/lib/completion.ts 248/341 (72.7%)
packages/cli/src/lib/config-instruction.ts 2/6 (33.3%)
packages/cli/src/lib/constants.ts 1/1 (100.0%)
packages/cli/src/lib/create-session-manager.ts 3/31 (9.7%)
packages/cli/src/lib/credential-resolver.ts 29/73 (39.7%)
packages/cli/src/lib/daemon.ts 37/37 (100.0%)
packages/cli/src/lib/dashboard-rebuild.ts 103/131 (78.6%)
packages/cli/src/lib/detect-agent.ts 10/47 (21.3%)
packages/cli/src/lib/detect-env.ts 34/37 (91.9%)
packages/cli/src/lib/format.ts 97/107 (90.7%)
packages/cli/src/lib/git-utils.ts 7/26 (26.9%)
packages/cli/src/lib/install-helpers.ts 54/76 (71.0%)
packages/cli/src/lib/lifecycle-service.ts 64/64 (100.0%)
packages/cli/src/lib/openclaw-probe.ts 124/127 (97.6%)
packages/cli/src/lib/path-equality.ts 18/18 (100.0%)
packages/cli/src/lib/plugin-marketplace.ts 110/183 (60.1%)
packages/cli/src/lib/plugin-scaffold.ts 126/133 (94.7%)
packages/cli/src/lib/plugin-store.ts 16/118 (13.6%)
packages/cli/src/lib/plugins.ts 41/52 (78.8%)
packages/cli/src/lib/portfolio-display.ts 4/16 (25.0%)
packages/cli/src/lib/preflight.ts 44/44 (100.0%)
packages/cli/src/lib/prevent-sleep.ts 25/25 (100.0%)
packages/cli/src/lib/project-detection.ts 8/177 (4.5%)
packages/cli/src/lib/project-resolution.ts 15/15 (100.0%)
packages/cli/src/lib/project-supervisor.ts 146/154 (94.8%)
packages/cli/src/lib/prompts.ts 2/26 (7.7%)
packages/cli/src/lib/repo-utils.ts 9/9 (100.0%)
packages/cli/src/lib/resolve-project.ts 237/349 (67.9%)
packages/cli/src/lib/routes.ts 3/3 (100.0%)
packages/cli/src/lib/running-state.ts 126/248 (50.8%)
packages/cli/src/lib/script-runner.ts 96/167 (57.5%)
packages/cli/src/lib/session-utils.ts 56/56 (100.0%)
packages/cli/src/lib/shell.ts 71/72 (98.6%)
packages/cli/src/lib/shutdown.ts 126/143 (88.1%)
packages/cli/src/lib/startup-preflight.ts 153/232 (65.9%)
packages/cli/src/lib/update-channel-onboarding.ts 49/57 (86.0%)
packages/cli/src/lib/update-check.ts 298/317 (94.0%)
packages/cli/src/lib/web-dir.ts 15/137 (10.9%)
packages/cli/src/options/version.ts 6/6 (100.0%)
packages/cli/src/program.ts 54/55 (98.2%)
packages/core/src/activity-events.ts 72/76 (94.7%)
packages/core/src/activity-log.ts 69/71 (97.2%)
packages/core/src/activity-signal.ts 28/28 (100.0%)
packages/core/src/agent-report.ts 163/173 (94.2%)
packages/core/src/agent-selection.ts 19/19 (100.0%)
packages/core/src/agent-workspace-hooks.ts 53/53 (100.0%)
packages/core/src/atomic-write.ts 10/20 (50.0%)
packages/core/src/cleanup-stack.ts 12/12 (100.0%)
packages/core/src/config-generator.ts 85/101 (84.2%)
packages/core/src/config.ts 205/252 (81.3%)
packages/core/src/daemon-children.ts 164/218 (75.2%)
packages/core/src/events-db.ts 48/56 (85.7%)
packages/core/src/feature-flags.ts 0/3 (0.0%)
packages/core/src/feedback-tools.ts 52/54 (96.3%)
packages/core/src/file-lock.ts 26/28 (92.8%)
packages/core/src/format-automated-comments.ts 16/16 (100.0%)
packages/core/src/gh-trace.ts 50/139 (36.0%)
packages/core/src/git-activity.ts 5/5 (100.0%)
packages/core/src/global-config.ts 308/371 (83.0%)
packages/core/src/key-value.ts 10/10 (100.0%)
packages/core/src/lifecycle-manager.ts 825/894 (92.3%)
packages/core/src/lifecycle-state.ts 99/103 (96.1%)
packages/core/src/lifecycle-status-decisions.ts 59/62 (95.2%)
packages/core/src/lifecycle-transition.ts 58/60 (96.7%)
packages/core/src/metadata.ts 153/174 (87.9%)
packages/core/src/migration/storage-v2.ts 599/699 (85.7%)
packages/core/src/notifier-resolution.ts 4/4 (100.0%)
packages/core/src/observability.ts 161/186 (86.5%)
packages/core/src/opencode-agents-md.ts 19/20 (95.0%)
packages/core/src/opencode-config.ts 5/5 (100.0%)
packages/core/src/opencode-session-id.ts 5/5 (100.0%)
packages/core/src/opencode-shared.ts 52/58 (89.7%)
packages/core/src/orchestrator-prompt.ts 56/58 (96.5%)
packages/core/src/orchestrator-session-strategy.ts 4/4 (100.0%)
packages/core/src/paths.ts 50/65 (76.9%)
packages/core/src/platform.ts 65/68 (95.6%)
packages/core/src/plugin-registry.ts 150/178 (84.3%)
packages/core/src/portfolio-projects.ts 23/26 (88.5%)
packages/core/src/portfolio-registry.ts 49/107 (45.8%)
packages/core/src/portfolio-routing.ts 10/10 (100.0%)
packages/core/src/portfolio-session-service.ts 79/92 (85.9%)
packages/core/src/process-cache.ts 7/7 (100.0%)
packages/core/src/project-resolver.ts 7/8 (87.5%)
packages/core/src/prompt-builder.ts 48/48 (100.0%)
packages/core/src/query-activity-events.ts 58/72 (80.5%)
packages/core/src/recovery/actions.ts 60/73 (82.2%)
packages/core/src/recovery/logger.ts 6/21 (28.6%)
packages/core/src/recovery/manager.ts 50/71 (70.4%)
packages/core/src/recovery/scanner.ts 12/13 (92.3%)
packages/core/src/recovery/types.ts 1/1 (100.0%)
packages/core/src/recovery/validator.ts 86/102 (84.3%)
packages/core/src/report-watcher.ts 47/47 (100.0%)
packages/core/src/scm-webhook-utils.ts 0/17 (0.0%)
packages/core/src/session-manager.ts 1107/1222 (90.6%)
packages/core/src/spawn-target.ts 11/11 (100.0%)
packages/core/src/storage-key.ts 28/29 (96.5%)
packages/core/src/tmux.ts 47/47 (100.0%)
packages/core/src/types.ts 48/58 (82.8%)
packages/core/src/update-cache.ts 0/16 (0.0%)
packages/core/src/utils.ts 56/68 (82.3%)
packages/core/src/utils/metadata-flatten.ts 7/7 (100.0%)
packages/core/src/utils/pr.ts 23/25 (92.0%)
packages/core/src/utils/session-from-metadata.ts 11/13 (84.6%)
packages/core/src/utils/session-id.ts 2/3 (66.7%)
packages/core/src/utils/validation.ts 6/7 (85.7%)
packages/core/src/version-compare.ts 34/34 (100.0%)
packages/core/src/windows-pty-registry.ts 0/32 (0.0%)
packages/web/server/direct-terminal-ws.ts 61/87 (70.1%)
packages/web/server/mux-websocket.ts 702/806 (87.1%)
packages/web/server/start-all.ts 0/113 (0.0%)
packages/web/server/terminal-observability.ts 0/16 (0.0%)
packages/web/server/tmux-utils.ts 162/170 (95.3%)
packages/web/src/app/api/backlog/route.ts 0/15 (0.0%)
packages/web/src/app/api/browse-directory/route.ts 7/7 (100.0%)
packages/web/src/app/api/filesystem/browse/route.ts 55/68 (80.9%)
packages/web/src/app/api/issues/route.ts 0/89 (0.0%)
packages/web/src/app/api/observability/route.ts 24/43 (55.8%)
packages/web/src/app/api/orchestrators/route.ts 76/76 (100.0%)
packages/web/src/app/api/projects/[id]/route.ts 235/315 (74.6%)
packages/web/src/app/api/projects/reload/route.ts 33/42 (78.6%)
packages/web/src/app/api/projects/route.ts 82/140 (58.6%)
packages/web/src/app/api/prs/[id]/merge/route.ts 113/119 (95.0%)
packages/web/src/app/api/runtime/terminal/route.ts 22/24 (91.7%)
packages/web/src/app/api/sessions/[id]/kill/route.ts 52/68 (76.5%)
packages/web/src/app/api/sessions/[id]/message/route.ts 77/109 (70.6%)
packages/web/src/app/api/sessions/[id]/remap/route.ts 81/108 (75.0%)
packages/web/src/app/api/sessions/[id]/restore/route.ts 101/109 (92.7%)
packages/web/src/app/api/sessions/[id]/route.ts 99/143 (69.2%)
packages/web/src/app/api/sessions/[id]/send/route.ts 83/85 (97.6%)
packages/web/src/app/api/sessions/patches/route.ts 32/32 (100.0%)
packages/web/src/app/api/sessions/route.ts 144/166 (86.7%)
packages/web/src/app/api/setup-labels/route.ts 0/56 (0.0%)
packages/web/src/app/api/spawn/route.ts 107/109 (98.2%)
packages/web/src/app/api/update/route.ts 52/60 (86.7%)
packages/web/src/app/api/verify/route.ts 25/89 (28.1%)
packages/web/src/app/api/version/route.ts 28/30 (93.3%)
packages/web/src/app/api/webhooks/[...slug]/route.ts 164/171 (95.9%)
packages/web/src/app/apple-icon.tsx 0/9 (0.0%)
packages/web/src/app/dev/terminal-test/page.tsx 408/409 (99.8%)
packages/web/src/app/error.tsx 26/26 (100.0%)
packages/web/src/app/global-error.tsx 20/20 (100.0%)
packages/web/src/app/icon-192/route.tsx 0/14 (0.0%)
packages/web/src/app/icon-512/route.tsx 0/14 (0.0%)
packages/web/src/app/icon.tsx 0/9 (0.0%)
packages/web/src/app/layout.tsx 28/37 (75.7%)
packages/web/src/app/loading.tsx 16/16 (100.0%)
packages/web/src/app/manifest.ts 22/22 (100.0%)
packages/web/src/app/not-found.tsx 10/10 (100.0%)
packages/web/src/app/page.tsx 0/24 (0.0%)
packages/web/src/app/projects/[projectId]/layout.tsx 0/5 (0.0%)
packages/web/src/app/projects/[projectId]/loading.tsx 37/37 (100.0%)
packages/web/src/app/projects/[projectId]/page.tsx 18/33 (54.5%)
packages/web/src/app/projects/[projectId]/project-layout-client.tsx 60/65 (92.3%)
packages/web/src/app/projects/[projectId]/sessions/[id]/page.tsx 0/441 (0.0%)
packages/web/src/app/projects/[projectId]/settings/page.tsx 64/68 (94.1%)
packages/web/src/app/projects/layout.tsx 0/13 (0.0%)
packages/web/src/app/providers.tsx 8/8 (100.0%)
packages/web/src/app/prs/page.tsx 0/23 (0.0%)
packages/web/src/app/sessions/[id]/error.tsx 37/48 (77.1%)
packages/web/src/app/sessions/[id]/loading.tsx 16/16 (100.0%)
packages/web/src/app/sessions/[id]/not-found.tsx 12/12 (100.0%)
packages/web/src/app/sessions/[id]/page.tsx 567/740 (76.6%)
packages/web/src/app/test-direct/page.tsx 64/67 (95.5%)
packages/web/src/components/ActivityDot.tsx 34/34 (100.0%)
packages/web/src/components/AddProjectModal.parts.tsx 89/133 (66.9%)
packages/web/src/components/AddProjectModal.tsx 306/378 (81.0%)
packages/web/src/components/AttentionZone.tsx 212/224 (94.6%)
packages/web/src/components/BottomSheet.tsx 176/246 (71.5%)
packages/web/src/components/CIBadge.tsx 79/129 (61.2%)
packages/web/src/components/ConnectionBar.tsx 7/17 (41.2%)
packages/web/src/components/CopyDebugBundleButton.tsx 89/98 (90.8%)
packages/web/src/components/Dashboard.tsx 702/797 (88.1%)
packages/web/src/components/DegradedProjectState.tsx 59/59 (100.0%)
packages/web/src/components/DirectTerminal.tsx 81/91 (89.0%)
packages/web/src/components/DynamicFavicon.tsx 50/50 (100.0%)
packages/web/src/components/ErrorDisplay.tsx 151/153 (98.7%)
packages/web/src/components/MobileBottomNav.tsx 47/54 (87.0%)
packages/web/src/components/PRCommentThread.tsx 77/77 (100.0%)
packages/web/src/components/ProjectSettingsForm.tsx 181/192 (94.3%)
packages/web/src/components/ProjectSettingsModal.tsx 93/106 (87.7%)
packages/web/src/components/ProjectSidebar.tsx 744/857 (86.8%)
packages/web/src/components/PRStatus.tsx 157/188 (83.5%)
packages/web/src/components/PullRequestsPage.tsx 290/331 (87.6%)
packages/web/src/components/RepairDegradedProjectButton.tsx 3/37 (8.1%)
packages/web/src/components/ServiceWorkerRegistrar.tsx 2/11 (18.2%)
packages/web/src/components/session-detail-agent-actions.ts 39/42 (92.8%)
packages/web/src/components/session-detail-utils.ts 34/96 (35.4%)
packages/web/src/components/SessionCard.tsx 723/784 (92.2%)
packages/web/src/components/SessionDetail.tsx 174/185 (94.0%)
packages/web/src/components/SessionDetailHeader.tsx 244/251 (97.2%)
packages/web/src/components/SessionDetailPRCard.tsx 210/255 (82.3%)
packages/web/src/components/SessionDetailTopStrip.tsx 0/90 (0.0%)
packages/web/src/components/SessionEndedSummary.tsx 79/104 (76.0%)
packages/web/src/components/Skeleton.tsx 101/118 (85.6%)
packages/web/src/components/Terminal.tsx 68/71 (95.8%)
packages/web/src/components/terminal/terminal-clipboard.ts 33/33 (100.0%)
packages/web/src/components/terminal/terminal-font.ts 26/28 (92.8%)
packages/web/src/components/terminal/terminal-themes.ts 56/56 (100.0%)
packages/web/src/components/terminal/TerminalControls.tsx 126/173 (72.8%)
packages/web/src/components/terminal/useFullscreenResize.ts 3/74 (4.0%)
packages/web/src/components/terminal/useXtermTerminal.ts 149/300 (49.7%)
packages/web/src/components/ThemeToggle.tsx 23/27 (85.2%)
packages/web/src/components/Toast.tsx 49/57 (86.0%)
packages/web/src/components/UpdateBanner.tsx 100/107 (93.5%)
packages/web/src/components/workspace/SidebarContext.tsx 5/5 (100.0%)
packages/web/src/hooks/useMediaQuery.ts 31/31 (100.0%)
packages/web/src/hooks/useMux.ts 1/1 (100.0%)
packages/web/src/hooks/useMuxSessionActivity.ts 0/7 (0.0%)
packages/web/src/hooks/usePopoverClamp.ts 26/28 (92.8%)
packages/web/src/hooks/useSessionEvents.ts 227/258 (88.0%)
packages/web/src/lib/activity-icons.ts 8/8 (100.0%)
packages/web/src/lib/async-utils.ts 13/13 (100.0%)
packages/web/src/lib/cache.ts 49/49 (100.0%)
packages/web/src/lib/client-fetch.ts 223/276 (80.8%)
packages/web/src/lib/cn.ts 3/3 (100.0%)
packages/web/src/lib/dashboard-page-data.ts 83/87 (95.4%)
packages/web/src/lib/format.ts 36/45 (80.0%)
packages/web/src/lib/github-links.ts 7/7 (100.0%)
packages/web/src/lib/icon-renderer.tsx 0/33 (0.0%)
packages/web/src/lib/observability.ts 48/58 (82.8%)
packages/web/src/lib/path-security.ts 86/98 (87.8%)
packages/web/src/lib/project-name.ts 119/138 (86.2%)
packages/web/src/lib/project-route-data.ts 0/20 (0.0%)
packages/web/src/lib/project-utils.ts 32/32 (100.0%)
packages/web/src/lib/routes.ts 9/9 (100.0%)
packages/web/src/lib/scm-webhooks.ts 51/52 (98.1%)
packages/web/src/lib/serialize.ts 408/440 (92.7%)
packages/web/src/lib/services.ts 151/264 (57.2%)
packages/web/src/lib/session-project.ts 0/9 (0.0%)
packages/web/src/lib/session-utils.ts 3/3 (100.0%)
packages/web/src/lib/terminal-touch-scroll.ts 17/106 (16.0%)
packages/web/src/lib/types.ts 191/219 (87.2%)
packages/web/src/lib/validation.ts 28/32 (87.5%)
packages/web/src/lib/windows-pty-cleanup.ts 63/85 (74.1%)
packages/web/src/providers/MuxProvider.tsx 266/271 (98.2%)

Uncovered lines

  • packages/cli/src/commands/config.ts: L28-L30, L32-L39, L41-L51, L53-L67, L69-L78, L89-L100, L107-L111
  • packages/cli/src/commands/dashboard.ts: L117-L126
  • packages/cli/src/commands/doctor.ts: L139-L141, L170-L174, L176-L179, L181-L195, L197-L202, L204-L205, L208-L210, L212-L222, L224-L225, L228-L239, L241-L245, L247-L252, L254-L259, L261-L262, L270-L272, L276-L277, L306-L307, L311-L313, L321-L323, L340-L342, L397-L399, L414-L416, L423-L425, L428-L429
  • packages/cli/src/commands/events.ts: L28-L33, L35-L38, L40-L47, L49-L52, L54-L62, L95-L103, L136-L139, L141-L147, L157-L159, L161-L170, L172-L175, L177-L183, L190-L194, L196-L200, L202-L208, L210-L216
  • packages/cli/src/commands/migrate-storage.ts: L31-L37, L46
  • packages/cli/src/commands/plugin.ts: L44, L66, L83-L86, L96-L97, L110-L111, L121-L133, L138-L139, L143-L144, L155-L156, L162-L170, L195-L200, L236-L237, L251-L256, L258-L265, L267-L275, L280-L284, L329-L331, L370-L371, L373-L391, L393-L403, L405-L416, L418-L428, L430-L442, L474-L475, L495-L498, L510-L511, L514-L515, L520, L524-L529, L541-L542, L568-L571, L573-L576, L578-L580, L582-L583
  • packages/cli/src/commands/project.ts: L25-L27, L64-L65, L103-L141
  • packages/cli/src/commands/report.ts: L34-L40, L74, L78-L82
  • packages/cli/src/commands/review-check.ts: L25-L26, L54, L107, L140-L141
  • packages/cli/src/commands/send.ts: L67-L69, L78-L80, L98, L168-L170, L176-L180, L207-L210, L213
  • packages/cli/src/commands/session.ts: L47-L49, L56, L109-L110, L215-L216, L305, L308-L309, L340-L342, L375-L378, L381, L449-L450, L453, L455-L456, L459-L461, L469-L470, L472-L492
  • packages/cli/src/commands/setup.ts: L76-L77, L79, L82-L83, L85-L86, L88-L94, L96-L104, L106-L109, L112, L115-L116, L118-L122, L124-L127, L129-L150, L152-L155, L157-L171, L174, L176-L180, L182-L185, L187-L191, L193-L201, L203-L206, L208-L213, L227-L228, L240-L241, L290-L291, L309-L314, L408-L409, L411-L415, L424-L425, L442-L449, L475-L476, L515-L516, L530, L543-L547, L549-L553, L561-L562, L592-L597
  • packages/cli/src/commands/spawn.ts: L30-L31, L39-L40, L49-L52, L63-L64, L87-L89, L91-L93, L214-L215, L263-L266, L268-L269, L334-L336, L399-L401, L409-L411, L413-L417, L468-L471, L486-L489, L491-L492, L494-L499, L513-L515
  • packages/cli/src/commands/start.ts: L129-L130, L141-L143, L146-L148, L150, L152-L156, L159-L160, L162, L164-L168, L170-L177, L179-L181, L219-L220, L225-L243, L245-L252, L254-L255, L261-L267, L269, L300-L301, L315-L317, L326-L327, L330-L354, L399-L411, L413-L416, L418-L432, L459, L470, L494-L495, L498-L499, L507-L508, L515-L520, L558-L559, L583-L586, L600-L603, L611-L612, L617-L627, L630-L631, L652-L653, L656-L658, L666-L671, L678-L679, L714-L717, L732-L737, L754-L756, L758-L765, L767-L769, L771-L774, L776-L777, L881-L884, L929, L962-L981, L1045-L1046, L1056-L1058, L1126-L1127, L1133-L1134, L1136-L1137, L1140-L1147, L1149, L1196-L1201, L1234-L1235, L1241-L1242, L1266-L1270, L1275-L1276, L1279-L1284, L1291-L1295, L1297-L1304, L1306-L1308, L1351, L1369-L1370, L1469-L1470, L1522-L1533, L1597, L1627-L1629, L1652-L1659, L1686-L1692, L1713-L1714, L1748-L1749, L1757-L1768, L1771, L1798, L1804-L1805, L1808-L1816, L1826-L1827, L1883, L1896-L1900, L1902-L1903, L1912-L1913, L1955-L1956, L1986-L1997, L2030-L2031
  • packages/cli/src/commands/status.ts: L59-L60, L62-L65, L110, L124, L170-L174, L176-L178, L180-L181, L203-L207, L212-L227, L279-L280, L330-L332, L499, L517, L536-L538, L545-L546, L557-L564, L566-L582, L584, L586, L588, L592-L594, L596-L597, L599-L604
  • packages/cli/src/commands/update.ts: L174-L175, L183-L185, L196-L197, L207-L208
  • packages/cli/src/commands/verify.ts: L17-L28, L30-L38, L40-L41, L46-L53, L57-L59, L61-L69, L71-L72, L85-L95, L97-L98, L101-L105, L107, L109-L112, L114-L124, L127-L130, L132-L135, L137, L139, L141-L150, L152-L154, L156, L158-L167, L169-L172
  • packages/cli/src/lib/bun-tmp-janitor.ts: L77-L78, L136
  • packages/cli/src/lib/caller-context.ts: L10-L15, L21-L22
  • packages/cli/src/lib/cli-errors.ts: L8-L11, L20-L23, L26-L30
  • packages/cli/src/lib/completion.ts: L91-L93, L105-L107, L109-L110, L112-L121, L123-L126, L128-L129, L131-L132, L134-L151, L153-L156, L158-L159, L161-L165, L171-L173, L175-L180, L187-L191, L323-L335, L338, L342-L343, L380-L381, L384-L387, L400-L401
  • packages/cli/src/lib/config-instruction.ts: L8, L12, L148-L149
  • packages/cli/src/lib/create-session-manager.ts: L23-L25, L32-L34, L36-L38, L41-L48, L50-L51, L57-L60, L66-L70
  • packages/cli/src/lib/credential-resolver.ts: L45-L47, L51, L53-L58, L62, L64-L69, L71-L80, L82, L84-L85, L92-L95, L97-L101, L103-L104, L122-L124
  • packages/cli/src/lib/dashboard-rebuild.ts: L37-L39, L69-L72, L93, L97-L99, L101-L102, L104-L107, L113-L121, L178-L179
  • packages/cli/src/lib/detect-agent.ts: L30-L31, L33-L35, L37-L44, L46-L47, L49-L50, L60-L61, L63-L65, L67-L69, L72, L74-L75, L77-L85
  • packages/cli/src/lib/detect-env.ts: L47-L49
  • packages/cli/src/lib/format.ts: L67, L81, L93, L95, L97, L99, L101, L116-L118
  • packages/cli/src/lib/git-utils.ts: L25-L36, L39-L43, L45-L46
  • packages/cli/src/lib/install-helpers.ts: L30, L32, L34, L46-L47, L85-L97, L99-L102
  • packages/cli/src/lib/openclaw-probe.ts: L44, L86, L175
  • packages/cli/src/lib/plugin-marketplace.ts: L35, L70-L71, L75-L76, L80-L81, L93-L94, L118-L119, L131-L136, L138, L144-L146, L148-L159, L161-L167, L169-L170, L195-L203, L205-L214, L216, L218-L228
  • packages/cli/src/lib/plugin-scaffold.ts: L39-L40, L45-L46, L54-L56
  • packages/cli/src/lib/plugin-store.ts: L21-L23, L25-L27, L29-L33, L35-L41, L43, L45-L57, L60-L61, L64-L65, L67-L70, L72-L73, L76-L77, L79-L85, L87-L89, L91-L96, L98-L99, L101-L104, L106-L108, L111-L117, L119-L125, L127-L128, L130-L144, L146-L147
  • packages/cli/src/lib/plugins.ts: L45-L46, L54-L60, L67-L68
  • packages/cli/src/lib/portfolio-display.ts: L10-L12, L14-L16, L18-L19, L22-L23, L26-L27
  • packages/cli/src/lib/project-detection.ts: L17-L24, L26-L30, L33-L34, L36-L40, L43-L54, L57-L63, L66-L76, L79-L80, L82-L84, L87-L92, L94-L105, L108-L110, L113-L115, L117-L118, L121-L122, L125-L129, L132-L138, L141-L147, L150-L156, L159-L162, L164-L165, L167-L168, L170-L171, L173, L175-L203, L205-L206, L209, L211-L213, L215-L217, L219-L221, L223-L225, L227-L229, L231-L232
  • packages/cli/src/lib/project-supervisor.ts: L130-L136, L203
  • packages/cli/src/lib/prompts.ts: L6-L13, L15-L30
  • packages/cli/src/lib/resolve-project.ts: L146-L158, L176-L186, L194, L198, L220-L223, L225-L227, L229-L240, L246-L248, L250-L256, L258-L271, L329-L331, L389-L390, L405, L409-L419, L457-L458, L460-L461, L478-L486, L507-L517, L525-L526
  • packages/cli/src/lib/running-state.ts: L48-L49, L62-L63, L66-L73, L86-L88, L90-L91, L97, L104, L128-L130, L132-L135, L168-L169, L175-L177, L179, L204-L211, L219-L230, L241-L251, L265-L279, L291-L293, L307-L314, L319-L321, L325-L329, L334-L347, L352-L357, L359-L363
  • packages/cli/src/lib/script-runner.ts: L47-L48, L55, L99-L106, L108-L113, L117-L125, L127-L130, L133-L134, L145-L150, L152-L154, L157-L164, L175-L178, L182-L185, L210-L212, L219-L229
  • packages/cli/src/lib/shell.ts: L85
  • packages/cli/src/lib/shutdown.ts: L46-L47, L80, L110-L119, L130, L136-L137, L188
  • packages/cli/src/lib/startup-preflight.ts: L31-L55, L63-L78, L93-L101, L138-L140, L147-L149, L155-L157, L191-L199, L230, L267, L284-L287, L298-L299, L313-L315
  • packages/cli/src/lib/update-channel-onboarding.ts: L51-L52, L128-L133
  • packages/cli/src/lib/update-check.ts: L91-L92, L101-L102, L119-L120, L140-L142, L144-L145, L210-L211, L230-L231, L331-L332, L395-L396
  • packages/cli/src/lib/web-dir.ts: L31-L48, L57-L62, L68-L88, L95-L110, L117-L126, L128-L129, L139-L145, L148-L150, L152, L156-L158, L160-L161, L163, L165-L167, L169-L171, L173-L175, L177-L178, L180-L183, L185-L186, L195-L198, L202-L209, L212-L214
  • packages/cli/src/program.ts: L56
  • packages/core/src/activity-events.ts: L189-L190, L297, L302
  • packages/core/src/activity-log.ts: L181-L182
  • packages/core/src/agent-report.ts: L314, L330, L340-L342, L345, L365, L369, L541, L554
  • packages/core/src/atomic-write.ts: L18-L23, L28, L41-L42, L46
  • packages/core/src/config-generator.ts: L138-L139, L143, L179-L180, L182-L188, L190, L192-L193, L196
  • packages/core/src/config.ts: L45, L55, L63, L85, L93, L98, L279-L280, L287-L288, L367, L379-L380, L411, L422, L526-L527, L535-L536, L538-L539, L541, L597, L764-L768, L777, L789, L805, L813, L850, L891, L930, L932-L933, L936-L939, L941-L942, L949-L951, L954
  • packages/core/src/daemon-children.ts: L54-L56, L74-L80, L85-L86, L90, L116, L158, L232, L236, L240-L242, L246-L249, L257-L258, L260, L262-L265, L268, L276, L282-L284, L354, L459-L461, L465, L467, L475, L482-L483, L486-L488, L490-L491, L494-L496, L498
  • packages/core/src/events-db.ts: L122, L124, L139, L177, L184, L210-L212
  • packages/core/src/feature-flags.ts: L2-L4
  • packages/core/src/feedback-tools.ts: L120, L179
  • packages/core/src/file-lock.ts: L26, L36
  • packages/core/src/gh-trace.ts: L20-L21, L25-L26, L33-L34, L39-L40, L43-L48, L55, L112, L116-L120, L156, L160-L162, L165, L169-L175, L177-L179, L181-L183, L185-L186, L189, L226-L229, L233-L234, L241-L242, L244-L245, L247-L250, L252, L255-L257, L259, L276, L288, L297-L298, L302, L335, L337, L339-L345, L351, L356, L358-L360, L367-L369, L371-L373, L385-L386, L391
  • packages/core/src/global-config.ts: L27, L39, L98, L374-L375, L397, L440-L442, L445, L462, L469, L477-L478, L480, L483, L511-L513, L526-L528, L530-L532, L534-L535, L537-L539, L587, L598, L606-L612, L615, L642, L652, L695-L696, L708, L717, L848, L856, L974, L985, L987, L991, L993, L995, L997, L1098, L1131, L1143-L1144, L1197-L1199, L1208
  • packages/core/src/lifecycle-manager.ts: L83, L87, L89, L128, L145, L170, L182, L240, L336, L338, L551-L552, L562, L568-L569, L585, L598-L599, L787, L844, L934-L938, L941, L1004, L1022-L1023, L1039-L1040, L1189, L1220, L1366-L1368, L1468, L1499-L1500, L1506-L1507, L1515, L1524, L1630, L1669, L1775-L1777, L1812-L1814, L1910, L1952-L1953, L2013-L2014, L2018, L2020, L2023, L2103-L2105, L2599, L2716, L2721, L2727, L2732, L2763, L2773
  • packages/core/src/lifecycle-state.ts: L188, L196, L200, L466
  • packages/core/src/lifecycle-status-decisions.ts: L231, L256, L366
  • packages/core/src/lifecycle-transition.ts: L194-L195
  • packages/core/src/metadata.ts: L70, L76, L90, L93-L96, L108-L109, L121, L239-L240, L245, L409, L441-L443, L447-L449, L484
  • packages/core/src/migration/storage-v2.ts: L153, L220, L225, L249-L250, L257, L362, L372, L450, L474, L478, L499, L504-L505, L507-L508, L510, L526-L527, L529, L541-L544, L546, L596, L645, L650-L652, L658, L660, L687-L688, L692-L693, L710-L716, L727, L742, L821, L836-L838, L840, L940-L942, L950, L1005, L1023, L1038, L1050-L1053, L1066, L1120, L1127, L1149, L1161, L1186-L1187, L1189, L1312, L1315-L1317, L1388-L1390, L1392, L1574-L1576, L1578-L1580, L1583, L1590-L1591, L1593-L1594, L1596-L1599, L1601, L1604-L1606, L1610, L1632-L1633, L1647
  • packages/core/src/observability.ts: L173, L189, L238, L253, L261-L262, L264, L281-L283, L316, L370, L385, L415, L423-L424, L537, L546-L547, L549, L618, L638, L656, L678, L699
  • packages/core/src/opencode-agents-md.ts: L22
  • packages/core/src/opencode-shared.ts: L126-L127, L176, L203, L224-L225
  • packages/core/src/orchestrator-prompt.ts: L47-L48
  • packages/core/src/paths.ts: L130, L267, L287, L295, L297-L298, L300, L303-L305, L307, L311-L313, L319
  • packages/core/src/platform.ts: L20, L24, L93
  • packages/core/src/plugin-registry.ts: L123, L191, L275-L276, L278-L283, L286-L287, L289-L290, L292, L302, L320-L321, L325-L326, L338-L340, L343, L347-L349, L364
  • packages/core/src/portfolio-projects.ts: L38, L54, L58
  • packages/core/src/portfolio-registry.ts: L25, L33-L34, L37-L40, L42, L47, L50, L57, L62, L70, L78, L83, L88, L91, L94, L97, L125-L127, L129-L131, L133, L139-L141, L154, L171-L173, L205, L228, L245, L250-L253, L268, L284, L294, L310, L320-L323, L326-L327, L332-L333, L335-L339, L342
  • packages/core/src/portfolio-session-service.ts: L27-L28, L30, L74, L98, L135, L137, L185-L186, L213-L214, L218, L224
  • packages/core/src/project-resolver.ts: L11
  • packages/core/src/query-activity-events.ts: L69-L70, L73-L74, L77-L78, L81-L82, L85-L86, L93-L94, L160, L206
  • packages/core/src/recovery/actions.ts: L65, L78, L139-L140, L153, L171, L181, L232, L262, L291, L309, L311, L313
  • packages/core/src/recovery/logger.ts: L9, L34, L41-L42, L45-L46, L49-L50, L53-L54, L57-L60, L64
  • packages/core/src/recovery/manager.ts: L67-L68, L70, L72-L73, L75-L76, L78-L79, L82-L83, L85, L96, L100-L101, L103-L104, L170, L172, L201, L209
  • packages/core/src/recovery/scanner.ts: L43
  • packages/core/src/recovery/validator.ts: L90, L96, L110-L111, L139, L142, L226-L227, L230, L247, L252, L275, L277, L300, L304, L306
  • packages/core/src/scm-webhook-utils.ts: L4-L8, L10, L14-L16, L18, L22-L24, L28-L31
  • packages/core/src/session-manager.ts: L286, L295-L296, L301-L302, L304, L315, L424, L488-L489, L491, L572, L625, L696-L698, L815-L816, L819, L897, L965, L969, L971, L996, L1060-L1062, L1193, L1249, L1328, L1443-L1445, L1565, L1695, L1708-L1709, L1717, L1730-L1731, L1754, L1767-L1768, L1794, L1912-L1914, L1971, L1977, L1988, L2007, L2012, L2024, L2039-L2040, L2047, L2064, L2076, L2096, L2218, L2306-L2308, L2378, L2471, L2497-L2498, L2550-L2551, L2555, L2593-L2594, L2611-L2612, L2616, L2628, L2675, L2680, L2687, L2696, L2717, L2726, L2751, L2761, L2767, L2791, L2824, L2844, L2851, L2857, L2866, L2914, L2916-L2918, L2920, L2923-L2926, L2928-L2929, L2931, L2957, L2963, L2971, L2997, L3046, L3050, L3074, L3148, L3151, L3208, L3238, L3333
  • packages/core/src/storage-key.ts: L35
  • packages/core/src/types.ts: L246, L260, L327, L336-L339, L1640-L1641, L1839
  • packages/core/src/update-cache.ts: L53-L55, L60-L64, L66, L82-L87, L92
  • packages/core/src/utils.ts: L18, L29, L37-L38, L130-L131, L164, L175-L178, L181
  • packages/core/src/utils/pr.ts: L46, L61
  • packages/core/src/utils/session-from-metadata.ts: L23, L30
  • packages/core/src/utils/session-id.ts: L7
  • packages/core/src/utils/validation.ts: L34
  • packages/core/src/windows-pty-registry.ts: L36, L40-L45, L47, L54, L59-L62, L66, L68, L72-L74, L76, L85-L87, L94-L97, L105-L108, L115, L120
  • packages/web/server/direct-terminal-ws.ts: L57, L97, L101-L108, L110, L112-L114, L116-L124, L126-L128
  • packages/web/server/mux-websocket.ts: L87-L89, L91-L92, L125-L126, L132-L137, L207-L209, L258-L259, L313, L319, L336-L337, L380-L381, L390-L392, L490-L491, L567-L568, L762, L817-L819, L839, L915-L916, L924-L928, L950-L958, L992-L998, L1004-L1005, L1012-L1016, L1021-L1023, L1031-L1036, L1039-L1045, L1059-L1077, L1130-L1131, L1139
  • packages/web/server/start-all.ts: L8-L12, L19-L20, L23, L25-L26, L28-L30, L32-L40, L42-L48, L50-L54, L56-L60, L62-L67, L69-L71, L74-L77, L79-L80, L82-L83, L89, L92-L95, L98-L102, L104-L106, L109-L110, L112, L115-L118, L121-L123, L126, L128-L130, L132-L136, L139-L143, L145-L162, L164-L165
  • packages/web/server/terminal-observability.ts: L1, L9, L12-L22, L24-L26
  • packages/web/server/tmux-utils.ts: L73-L74, L296-L297, L315-L316, L324-L325
  • packages/web/src/app/api/backlog/route.ts: L1-L2, L4, L10, L12, L14-L23
  • packages/web/src/app/api/filesystem/browse/route.ts: L19-L20, L28-L29, L55-L56, L64-L68, L83-L84
  • packages/web/src/app/api/issues/route.ts: L1-L4, L6, L12-L16, L18-L20, L27, L29-L31, L33-L34, L36-L41, L43-L44, L46-L50, L56-L60, L62-L65, L67-L70, L72-L78, L80-L82, L84-L87, L89-L97, L99-L105, L107-L120
  • packages/web/src/app/api/observability/route.ts: L32-L50
  • packages/web/src/app/api/projects/[id]/route.ts: L97-L98, L102-L103, L139-L140, L154-L157, L170-L174, L182-L183, L192-L193, L199-L200, L204-L205, L207-L208, L224-L232, L234-L242, L244-L248, L271-L275, L288-L289, L327-L337, L345-L346, L348-L349, L353-L357, L372-L376
  • packages/web/src/app/api/projects/reload/route.ts: L14-L15, L19-L20, L43-L47
  • packages/web/src/app/api/projects/route.ts: L60-L61, L75-L79, L85-L86, L90-L91, L117, L121-L122, L124-L144, L146-L166, L168-L169
  • packages/web/src/app/api/prs/[id]/merge/route.ts: L34-L39
  • packages/web/src/app/api/runtime/terminal/route.ts: L17-L18
  • packages/web/src/app/api/sessions/[id]/kill/route.ts: L19-L20, L49, L52-L64
  • packages/web/src/app/api/sessions/[id]/message/route.ts: L23-L24, L43-L44, L101-L112, L114-L129
  • packages/web/src/app/api/sessions/[id]/remap/route.ts: L18-L19, L91-L115
  • packages/web/src/app/api/sessions/[id]/restore/route.ts: L26-L27, L71-L76
  • packages/web/src/app/api/sessions/[id]/route.ts: L28-L29, L66-L87, L104-L105, L114-L115, L171-L186
  • packages/web/src/app/api/sessions/[id]/send/route.ts: L21-L22
  • packages/web/src/app/api/sessions/route.ts: L23-L24, L93, L176-L194
  • packages/web/src/app/api/setup-labels/route.ts: L1-L5, L7, L9, L11-L16, L22-L25, L27-L28, L30-L53, L55-L62, L64-L68
  • packages/web/src/app/api/spawn/route.ts: L25-L26
  • packages/web/src/app/api/update/route.ts: L92-L99
  • packages/web/src/app/api/verify/route.ts: L16-L20, L41-L42, L50-L51, L54-L55, L57-L62, L64-L65, L67, L69-L70, L72-L93, L95-L101, L103-L115
  • packages/web/src/app/api/version/route.ts: L37-L38
  • packages/web/src/app/api/webhooks/[...slug]/route.ts: L105-L106, L111-L112, L120-L122
  • packages/web/src/app/apple-icon.tsx: L1-L3, L5-L6, L8-L11
  • packages/web/src/app/dev/terminal-test/page.tsx: L53
  • packages/web/src/app/icon-192/route.tsx: L1-L3, L5-L15
  • packages/web/src/app/icon-512/route.tsx: L1-L3, L5-L15
  • packages/web/src/app/icon.tsx: L1-L3, L5-L6, L8-L11
  • packages/web/src/app/layout.tsx: L34-L41, L43
  • packages/web/src/app/page.tsx: L3-L5, L11-L16, L18-L21, L23-L32, L34
  • packages/web/src/app/projects/[projectId]/layout.tsx: L1-L5
  • packages/web/src/app/projects/[projectId]/page.tsx: L14-L15, L27, L29-L39, L41
  • packages/web/src/app/projects/[projectId]/project-layout-client.tsx: L55-L59
  • packages/web/src/app/projects/[projectId]/sessions/[id]/page.tsx: L1-L441
  • packages/web/src/app/projects/[projectId]/settings/page.tsx: L14-L15, L30-L31
  • packages/web/src/app/projects/layout.tsx: L1-L2, L5, L7-L8, L10-L14, L16-L17, L19
  • packages/web/src/app/prs/page.tsx: L2-L3, L9, L11-L16, L18-L21, L23-L31, L33
  • packages/web/src/app/sessions/[id]/error.tsx: L10-L11, L16-L17, L19-L20, L24-L28
  • packages/web/src/app/sessions/[id]/page.tsx: L89-L91, L93-L95, L129-L130, L138-L139, L147-L148, L150-L151, L207-L211, L224-L231, L233-L234, L298-L299, L301-L305, L307-L317, L319-L329, L331-L337, L339-L347, L361, L371-L373, L376, L453, L521-L527, L623-L626, L676-L679, L681, L686-L690, L693-L694, L696-L701, L703-L708, L741-L742, L794-L804, L806-L818, L820, L842-L847, L862-L872, L874-L886, L888
  • packages/web/src/app/test-direct/page.tsx: L9-L11
  • packages/web/src/components/AddProjectModal.parts.tsx: L31-L32, L37-L46, L54-L55, L81-L85, L90-L98, L100, L113-L116, L118, L121-L124, L126, L164-L167, L169
  • packages/web/src/components/AddProjectModal.tsx: L63-L67, L84-L89, L98, L160-L196, L233-L237, L244, L253-L256, L271-L273, L287-L289, L295, L379-L383, L385
  • packages/web/src/components/AttentionZone.tsx: L131-L138, L151, L298, L300, L302
  • packages/web/src/components/BottomSheet.tsx: L21-L27, L73-L74, L97-L106, L114-L115, L118-L124, L204-L207, L212-L237, L247, L275-L283, L285, L303
  • packages/web/src/components/CIBadge.tsx: L84-L92, L94-L100, L102-L103, L105, L107-L108, L110, L113-L121, L123-L128, L130, L132-L138, L140, L142, L144-L145, L147
  • packages/web/src/components/ConnectionBar.tsx: L11-L18, L20, L22
  • packages/web/src/components/CopyDebugBundleButton.tsx: L27-L28, L40-L41, L45-L46, L79-L81
  • packages/web/src/components/Dashboard.tsx: L65-L66, L199-L207, L242, L316-L340, L351-L353, L358-L360, L367-L370, L383-L384, L395-L409, L420-L422, L428-L430, L496, L501-L510, L718-L719, L779-L785, L787, L881-L884
  • packages/web/src/components/DirectTerminal.tsx: L115-L120, L122-L125
  • packages/web/src/components/ErrorDisplay.tsx: L185, L190
  • packages/web/src/components/MobileBottomNav.tsx: L63-L69
  • packages/web/src/components/ProjectSettingsForm.tsx: L58-L60, L82-L83, L90, L160-L162, L164-L165
  • packages/web/src/components/ProjectSettingsModal.tsx: L43-L47, L69-L70, L76-L78, L134-L136
  • packages/web/src/components/ProjectSidebar.tsx: L66-L67, L79-L80, L88-L89, L99-L102, L155-L157, L287, L295, L303, L311, L317-L330, L336-L339, L341-L342, L360, L434-L436, L504, L518-L519, L537-L541, L551, L557, L590-L611, L613-L615, L619, L647-L649, L651-L653, L655-L657, L765-L767, L782-L786, L942-L948, L950-L951, L1035-L1039, L1041-L1045
  • packages/web/src/components/PRStatus.tsx: L89, L95, L98-L100, L103, L105, L108-L110, L130, L132, L143, L145, L162-L164, L168-L170, L187-L189, L196, L198, L201-L203, L211, L213, L216
  • packages/web/src/components/PullRequestsPage.tsx: L38-L43, L257-L267, L270-L280, L285-L294, L296, L298-L299
  • packages/web/src/components/RepairDegradedProjectButton.tsx: L7-L9, L11-L29, L31-L37, L39-L42, L44
  • packages/web/src/components/ServiceWorkerRegistrar.tsx: L6-L14
  • packages/web/src/components/session-detail-agent-actions.ts: L44-L46
  • packages/web/src/components/session-detail-utils.ts: L13-L24, L27-L31, L34-L38, L59, L65-L74, L77-L91, L94-L102, L105-L109
  • packages/web/src/components/SessionCard.tsx: L63-L70, L72-L73, L173-L174, L221-L225, L227-L229, L256-L258, L427, L443, L655-L656, L658, L755-L757, L796, L819-L825, L827, L885-L894, L956-L966
  • packages/web/src/components/SessionDetail.tsx: L53-L55, L63, L80-L81, L90-L92, L119-L120
  • packages/web/src/components/SessionDetailHeader.tsx: L90-L93, L95-L96, L178
  • packages/web/src/components/SessionDetailPRCard.tsx: L141-L158, L170-L171, L173-L185, L187-L188, L281-L287, L289-L290, L296
  • packages/web/src/components/SessionDetailTopStrip.tsx: L4, L6, L23-L49, L51-L65, L67-L68, L70, L72-L90, L92-L93, L95-L101, L103-L108, L110-L112, L114-L116, L118-L119, L121
  • packages/web/src/components/SessionEndedSummary.tsx: L24-L25, L27-L28, L35-L38, L45-L47, L50-L56, L106-L108, L116-L119
  • packages/web/src/components/Skeleton.tsx: L81, L89-L97, L99-L104, L106
  • packages/web/src/components/Terminal.tsx: L35-L36, L61
  • packages/web/src/components/terminal/terminal-font.ts: L30-L31
  • packages/web/src/components/terminal/TerminalControls.tsx: L39-L43, L45-L57, L59-L72, L82, L89-L91, L98, L133-L136, L138, L216-L218, L220-L221
  • packages/web/src/components/terminal/useFullscreenResize.ts: L17-L26, L28-L31, L33-L35, L37-L41, L43-L45, L47-L49, L51-L54, L56-L58, L60-L61, L63, L65-L74, L76-L77, L80-L91, L93-L101
  • packages/web/src/components/terminal/useXtermTerminal.ts: L130-L131, L138-L141, L143-L144, L152-L158, L160-L161, L178-L179, L182-L184, L191-L195, L197-L198, L208-L215, L217-L218, L220-L222, L228-L232, L234-L244, L246-L259, L266, L268, L270-L289, L294-L308, L310-L316, L318-L320, L322, L324-L341, L386, L402, L408-L410, L414-L415, L419-L424
  • packages/web/src/components/ThemeToggle.tsx: L32-L35
  • packages/web/src/components/Toast.tsx: L20-L21, L44-L45, L49-L50, L80-L81
  • packages/web/src/components/UpdateBanner.tsx: L35, L67, L92, L95-L97, L125
  • packages/web/src/hooks/useMuxSessionActivity.ts: L3, L5, L7-L11
  • packages/web/src/hooks/usePopoverClamp.ts: L42-L43
  • packages/web/src/hooks/useSessionEvents.ts: L21-L24, L26-L29, L31-L32, L119, L123, L132-L134, L141, L144-L146, L224-L225, L266-L270, L285, L287, L302-L304
  • packages/web/src/lib/client-fetch.ts: L20-L22, L30-L47, L68-L69, L79-L80, L87-L88, L100, L107-L109, L117, L194-L196, L206-L207, L221-L223, L235-L236, L238-L240, L242, L246-L247, L277, L285-L287, L314
  • packages/web/src/lib/dashboard-page-data.ts: L58-L59, L118-L119
  • packages/web/src/lib/format.ts: L126-L127, L129-L130, L132-L133, L135-L137
  • packages/web/src/lib/icon-renderer.tsx: L4-L10, L12-L14, L17-L21, L23-L37, L39-L40, L42
  • packages/web/src/lib/observability.ts: L50-L51, L73-L74, L83-L88
  • packages/web/src/lib/path-security.ts: L36-L37, L51-L52, L83-L84, L104-L105, L108-L109, L123-L124
  • packages/web/src/lib/project-name.ts: L22-L23, L27-L28, L92-L93, L96, L98-L99, L113-L114, L132-L134, L145-L147, L166-L167
  • packages/web/src/lib/project-route-data.ts: L1, L3, L5-L6, L15-L18, L20-L24, L26-L32
  • packages/web/src/lib/scm-webhooks.ts: L60
  • packages/web/src/lib/serialize.ts: L75-L76, L87, L91-L92, L94-L95, L97-L98, L100-L101, L222-L226, L236-L237, L288, L320, L392-L397, L415-L417, L420-L422
  • packages/web/src/lib/services.ts: L72-L74, L82-L85, L95-L101, L145-L149, L167-L168, L171-L173, L189-L194, L196-L200, L202-L206, L208-L222, L239-L240, L255-L256, L276-L280, L303-L304, L331-L332, L336-L337, L341-L348, L350-L355, L357-L359, L361-L363, L366-L373, L375-L380, L382-L384, L386-L388, L392-L394
  • packages/web/src/lib/session-project.ts: L3-L11
  • packages/web/src/lib/terminal-touch-scroll.ts: L76-L81, L83-L87, L89, L91-L98, L100-L101, L103-L106, L109-L118, L120-L121, L123, L125, L127-L130, L132, L134, L139-L143, L145, L150-L151, L154-L157, L159-L165, L167-L173, L175-L177, L179-L180, L182-L185, L187-L194
  • packages/web/src/lib/types.ts: L283-L284, L292-L293, L300-L301, L304-L305, L308-L309, L313-L314, L317-L323, L351, L353, L355, L410-L414, L416
  • packages/web/src/lib/validation.ts: L7-L8, L23-L24
  • packages/web/src/lib/windows-pty-cleanup.ts: L6-L20, L41-L44, L86-L87, L98
  • packages/web/src/providers/MuxProvider.tsx: L91-L92, L174-L175, L183

Three path-filtered workflows ran for the first time on this branch
because it touches backend/, tests/integration/ and packages/.

api-drift ran `npm ci` at the repo root, which needed the stray
package-lock.json this PR removed. The root is a pnpm workspace and this
job only needs the root openapi-typescript devDependency, so it now uses
pnpm like every other job; keeping a second npm-managed lockfile in sync
by hand is what let it drift in the first place. The root `api` script
switches to `pnpm run` for the same reason. Verified end to end: the job
regenerates schema.ts with no diff.

The format job reformatted .github/workflows/*.yml and then had its
auto-commit push rejected — GitHub refuses a GITHUB_TOKEN-authenticated
push that touches workflow files, so this was fatal to the job the
moment Prettier reached one. There is no permission that grants it, so
workflows are now excluded from Prettier.

Test Fresh Onboarding failed because docker-compose runs
tests/integration/onboarding-test.sh as its `command:` and the file was
mode 644. The node:20 image's entrypoint prepends `node` to anything it
cannot execute, so the shell script was parsed as JavaScript. Set the
executable bit on the five scripts that are invoked by path; the two
bundled CLI assets stay 644 because runRepoScript spawns them via `bash`
explicitly.

Test (windows-latest) failed on six FTS tests because better-sqlite3 has
no compiled binding there. That file already intends to skip when
better-sqlite3 is unavailable, but its guard only caught a require()
failure — the JS wrapper loads fine and only opening a database surfaces
the missing binding. Probe by opening one, so the platform skips as
documented. Linux still runs all six for real.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VjPWzWR3yvT35opqeixiWy

Copy link
Copy Markdown
Owner Author

Round two — four more fixed, one is not mine

Pushed a46ed5a. The last round's changes touched backend/, tests/integration/ and packages/, which tripped three path-filtered workflows that had never run on this branch before. One of the new failures was a genuine regression from this PR.

api-drift — my regression, fixed

The very first commit removed the root package-lock.json as a "stray npm lockfile". It wasn't entirely stray: go.yml's api-drift job ran npm ci at the repo root and needed it.

The root is a pnpm workspace and that job only needs the root openapi-typescript devDependency, so it now uses pnpm install --frozen-lockfile like every other job. Keeping a second, hand-synced npm lockfile is what let it drift to begin with. Verified end to end locally — regenerates schema.ts with no diff, so the job's git diff --exit-code passes.

format — the auto-commit could never have worked

Prettier ran fine this time, but the job still failed, and the reason is structural:

! [remote rejected] ... (refusing to allow a GitHub App to create or update
  workflow `.github/workflows/onboarding-test.yml` without `workflows` permission)

GitHub refuses any GITHUB_TOKEN-authenticated push that touches workflow files. There is no permissions: key that grants this — it's a hard platform restriction. So the moment Prettier reformatted any workflow YAML, the job was doomed, and with the whole repo unformatted it was always going to reach one. Excluded .github/workflows/ from Prettier; nothing else about the job changes.

Test Fresh Onboarding — a 644 file mode

docker-compose.yml runs onboarding-test.sh as its command:, and the file was mode 644. The node:20 image's entrypoint prepends node to anything it can't execute, so the shell script got parsed as JavaScript:

onboarding-test.sh:2
# Integration test: Fresh developer onboarding experience
^
SyntaxError: Invalid or unexpected token

Set the executable bit on the five scripts invoked by path. The two bundled CLI assets stay at 644 deliberately — runRepoScript spawns those via bash <path>, so they don't need it.

Test (windows-latest) — a skip that was never wired up

Six FTS tests failed on Windows with Could not locate the bindings file for better-sqlite3. The file already says, in a comment, "If it's not available, skip" — but the guard only wrapped require("better-sqlite3"). The JS wrapper imports fine without a compiled binding; only opening a database surfaces it. So Database stayed non-null, itIfAvailable resolved to it, and all six ran and threw.

Now it opens a throwaway :memory: database inside the guard. Windows skips as documented; Linux still runs all six for real (verified — 6 passed). I did not change the better-sqlite3 dependency: it resolves to 12.10.0 in both the old and new lockfiles, so this was not caused by the regeneration.

native (windows-latest) — pre-existing, and I'm not fixing it

This is the Go CLI E2E suite in cli-e2e.yml, path-triggered by my backend/ change. It is not a regression:

Run Commit Branch Result
1 0d9fc4e main ❌ failure
2 28a49c3 main ❌ failure
3 073c332 this PR ❌ failure

Every run this workflow has ever had, on main and here alike, has failed. It has never been green in this fork. The same suite passes on Linux with my changes applied (go test -tags e2e ./internal/cli/...ok, 22.8s), so it's Windows-specific — a real bug, but one that predates this PR by two commits on main and needs a Windows box to diagnose. Debugging it from here would be guesswork, and it's a long way from "regenerate the lockfile."

I'd suggest it gets its own issue.


Generated by Claude Code

github-actions Bot and others added 13 commits July 27, 2026 12:57
The action diffs against main so it reports only what a PR introduces.
The shallow default checkout leaves it without a merge base, so it falls
back to listing every finding in the changed files — including
pre-existing ones — and warns about it on each run. Matches the
fetch-depth: 0 already used by the coverage and gitleaks jobs.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VjPWzWR3yvT35opqeixiWy
…rule

The gitleaks `scan` job went red on six findings, every one of them in the
secret-redaction code, its tests, or the audit note describing it:
activity-events.ts names the token prefixes it strips, and the test
asserts the stripping works using AWS's own published example key
(AKIAIOSFODNN7EXAMPLE).

These were already known false positives — the config allowlists them,
but by commit SHA, with a note claiming the files were "already deleted
from the tree". They are not deleted, so that list only held while
nothing touched them again. The prettier auto-format job touched them,
producing a new commit the list does not cover. Allowlisting by path
instead makes it durable; the commit list stays for the history scan.

Also drops the trailing `?` from the Slack rule. The token body was
optional, so a bare `xoxb-` matched anywhere — including prose and
comments that merely name the prefix. Requiring the body still matches
every real token (verified against the fixtures) and stops matching
mentions of the prefix.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VjPWzWR3yvT35opqeixiWy
…indows hashing

Onboarding test: dropped steps 6-10. They ran `ao start --no-orchestrator`
and polled a dashboard on :9000 plus a terminal WebSocket on :14801. That
flag no longer exists — `ao start` resolves the installed desktop app,
opens it, and exits, because the app now owns the daemon and state. There
is no headless dashboard to poll and no desktop app in the container, so
those steps asserted against an architecture the CLI has shed. Steps 1-5
still cover what the test is named for: a clean machine can clone, run
setup.sh, get a working `ao`, and produce a config the CLI accepts.

Gitleaks: the previous allowlist entries went under `files`, which is
matched against the bare filename, so full-path patterns silently never
matched and the job stayed red. Moved them to `paths` and added the two
literal fixture values under `regexes` so the redaction tests stay covered
even if they move file.

Windows: the kimicode test helper hashed the raw workspace path while
resolveWorkspacePath hashes the realpath'd one. Those agree on Linux only
because fakeHome is already resolved; Windows canonicalises further, so
every fixture wrote to a different bucket than discovery scanned and 17
assertions saw undefined. The helper now mirrors production — stat, then
realpath, falling back to the raw string. No production code changed, and
all 103 kimicode tests still pass on Linux.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VjPWzWR3yvT35opqeixiWy
…ormat commits

The Windows log gave the kimicode failures away: the fixture bucket was
under "C:\Users\RUNNER~1\...", an 8.3 short name straight from tmpdir().
The plugin hashes realpath(workspacePath), and realpath expands that to
"C:\Users\runneradmin\...", so discovery looked in a different md5 bucket
than the one the test populated and every lookup returned undefined.

The setup already canonicalised fakeHome for the same reason on macOS
(/var vs /private/var), but plain realpathSync resolves symlinks without
touching short names — it fixes macOS and silently misses Windows.
realpathSync.native does both.

Two more failures were ENOTEMPTY from rmSync in afterEach: Windows holds
a brief handle on files the plugin just read, so whichever test ran last
before the handle dropped failed on cleanup rather than on an assertion.
Retries handle it.

Gitleaks: added the two prettier auto-format commits to the allowlist.
That job reflowed the entire tree, so the redaction fixtures and
security-doc examples reappear as additions under new SHAs — same
offenders and same rationale as the rewrite-graft commits already listed.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VjPWzWR3yvT35opqeixiWy
The previous round took the scan from six findings to one, so the
allowlist is being applied — the log confirms gitleaks v7.4.0 running
with --config-path=.github/.gitleaks.toml.

The survivor is unrelated to the earlier batch: SECURITY.md documents
keeping credentials in env vars and shows
"GITHUB_TOKEN=ghp_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx". `x` is
alphanumeric, so the Github-token rule matches 36 characters of filler.

It has to be matched by pattern rather than added to the commit list:
the finding is attributed to the PR's merge commit, which gets a new SHA
on every run. A 20-character run of literal x cannot occur in a real
credential, so this suppresses placeholders without masking a leak —
verified against a realistic token, and the only files in the tree it
affects are SECURITY.md and this config's own comment.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VjPWzWR3yvT35opqeixiWy
…aking it

realpathSync.native fixed the bucket mismatch — the Windows log now shows
the resolved C:\Users\runneradmin path and the assertions pass. What was
left was 15 failures that were all ENOTEMPTY from afterEach, never an
assertion, with the retry budget stretching the run from 6s to 50s
without ever succeeding. That pointed at a handle nothing was releasing.

extractKimiSummary built a readline interface over a ReadStream and
called rl.close() when done. That ends the interface but leaves the
descriptor open, and every exit from the loop is a `break` — on the byte
cap, or on the first TurnBegin, which is the common path — so the stream
was abandoned mid-read. POSIX lets you unlink a file that still has an
open handle, which is why this never showed up on Linux or macOS; Windows
keeps the session directory alive and rmdir fails.

So this is a real descriptor leak in the daemon, one per summary
extraction, that happened to surface as a Windows-only test failure.
Holding the stream and destroying it in a finally fixes both.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VjPWzWR3yvT35opqeixiWy
…ffort

Two changes for the same Windows teardown failure, which stayed at 15 of
103 after the last round.

destroy() only schedules the close, so extractKimiSummary was returning
while the descriptor was still open. Waiting for the close event makes the
release deterministic, which is what a caller deleting the directory
afterwards actually needs.

The afterEach rmSync is now best-effort. NTFS keeps a deleted entry alive
until every handle to it is released, so rmdir can raise ENOTEMPTY even
after retries. That is a teardown race rather than a fact about the code
under test — the assertions have already run and passed by that point, so
failing them there reports a defect that does not exist. fakeHome lives
under os.tmpdir(), so anything left behind is reclaimed by the OS.

To be explicit about the tradeoff: this makes cleanup non-fatal, it does
not hide a failing assertion. The one real defect behind these symptoms —
the leaked descriptor — is fixed above rather than swallowed.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VjPWzWR3yvT35opqeixiWy
…er leak

kimicode is clean now, and the Windows failure moved to packages/cli with
the same signature: "C:\Users\RUNNER~1\...". os.tmpdir() hands back an 8.3
short name there, while git and realpath report the long form, so
ao-update.sh decided its own temp checkout was outside the repo ("must run
inside the Agent Orchestrator git checkout") and a fixture read missed
commands.log outright.

Routed all 27 mkdtempSync(join(tmpdir(), ...)) sites across the CLI tests
through a helper that applies realpathSync.native, the same fix already
used in agent-kimicode. Only update-script was failing, but the other
thirteen carry the identical latent bug and would have surfaced one CI
round at a time.

Note on the mechanical pass: the first attempt skipped the realpathSync
import in path-equality.test.ts, because that file has a test *named*
"...when realpathSync fails" and the guard matched the bare string rather
than the import. Caught locally — it broke six tests on Linux — and fixed
by matching the import specifically.

Full workspace suite passes.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VjPWzWR3yvT35opqeixiWy
…ests

The ao-update.sh tests prepend a directory of fake git/pnpm/npm/node
scripts to PATH so the script talks to stubs instead of the real tools.
They joined with ":", which on Windows is not a separator at all — binDir
got spliced onto the first genuine entry and the stubs were never on the
search path. The runner's real git answered instead, and since the fake
repo is an ordinary temp dir, `git rev-parse --is-inside-work-tree`
failed and the script exited with "must run inside the Agent Orchestrator
git checkout" before reaching any of the behaviour under test.

Route all seven spawn sites through a helper that joins with
path.delimiter. It also drops the inherited "Path" key before setting
"PATH": Windows environment variables are case-insensitive, so leaving
both in the object handed to spawnSync lets the un-prefixed copy win.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VjPWzWR3yvT35opqeixiWy
Four of the eight ao-update.sh tests already carried this guard; three
that drive the script through the same PATH-injected stubs did not, and
they are the only reason Test (windows-latest) is red.

Correcting the PATH separator was necessary but not sufficient. Git for
Windows does supply bash and the script runs, but the stubs are
extensionless files carrying a "#!/bin/bash" line, and that bash does not
treat them as executable — `command -v git` walks past them and the
runner's real git.exe answers instead. The stub command log is never
written, and the script exits at `git rev-parse --is-inside-work-tree`
because the fake repo is an ordinary temp dir. Winning the PATH lookup
would mean shipping a real .exe, so there is nothing left to assert on
Windows.

Guard the three, and replace the stale rationale on the existing guard,
which blamed bash being unavailable. The one test that needs no stubs
still runs on every platform, and the Windows code path is covered
separately through detectWindowsBash().

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VjPWzWR3yvT35opqeixiWy
@bfoxhound bfoxhound changed the title fix(ci): regenerate pnpm lockfile, drop stray npm lockfile fix(ci): regenerate pnpm lockfile and repair the CI failures it uncovered Jul 27, 2026
claude added 2 commits July 27, 2026 16:27
Regenerating the lockfile dropped the stale `overrides:` block, which
took this pin with it and regressed tmp from 0.2.4 to 0.0.33. It reaches
the tree through inquirer -> @inquirer/prompts -> @inquirer/editor ->
external-editor, a runtime path in the CLI rather than dev-only, and
tmp < 0.2.4 is the version affected by the symlink arbitrary-write
advisory.

Declaring the override in the root manifest is what the lockfile was
missing: the block existed there with nothing to back it, which is the
mismatch that broke every frozen install in the first place. Now both
agree. tmp@0.0.33 no longer resolves anywhere in the tree.

The other two entries from the original block are not restored. axios
still resolves to 1.15.0 and follow-redirects to 1.16.0 on their own, so
both were already no-ops.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VjPWzWR3yvT35opqeixiWy
The full-pipeline test timed out at vitest's 10s default. The timings
show the whole file was running against that ceiling rather than one
test being slow: a bare `--help` took 9130ms, `-h` 428ms, the unknown-
flag case 1795ms, and the pipeline 16171ms before it was killed. Nearly
all of the first figure is pwsh cold start on the runner, so `--help`
was one scheduling blink from failing too.

Raise all four to 60s. None of them assert anything about latency — they
check argparse and that the script survives its own pipeline — so the
default budget was doing nothing but letting runner load decide the
outcome.

Unrelated to the tmp pin in the preceding commit; that commit's own
checks, NPM Audit and Dependency Review, both passed.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VjPWzWR3yvT35opqeixiWy
@bfoxhound
bfoxhound marked this pull request as ready for review July 27, 2026 16:42
@bfoxhound
bfoxhound merged commit 45e9aa8 into main Jul 27, 2026
24 checks passed
bfoxhound added a commit that referenced this pull request Jul 28, 2026
PR #2 converted CI to pnpm (packageManager: pnpm@9.15.0, pnpm install
--frozen-lockfile, pnpm run api in workflows) but AGENTS.md still
documented the root scripts as npm run lint/frontend:typecheck/sqlc/api.

Update the Commands and API-contract sections to pnpm and note the
split: the root is a pnpm workspace while frontend/ deliberately stays
npm-managed (npm ci in its workflows, not in pnpm-workspace.yaml), so
the frontend-specific npm commands are unchanged. Also drop the stale
npx openapi-typescript@7.4.4 wording — api:ts now runs the local
openapi-typescript dependency.

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants