You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
fix(admission): a busy process outside any repository is host load, not uncovered work of unknown ownership #294
dot admit deferred agent-hub's local checks five times on 2026-10-20 (exit 75). Each time the blocker was a background process that runs no build or test, in no repository:
Maru's dotfiles commands (parent Maru.app), reported as dotfiles(pid=...,parent=8703,repo=);
claude-mem's observer, a one-turn headless claude --max-turns=1 summarizer whose cwd is ~/.claude-mem/observer-sessions.
Cause, in internal/admission/uncovered.go:
unownedHeavyJobs counts any row at 100% CPU or more as heavy, whatever its name (heavyweight(...) || r.cpu >= 100).
resolveJobDirectories resolves the cwd, and repositoryIdentity fails when the walk reaches / without a .git. That leaves Repository empty.
filterUncovered treats an empty Repository as unknown ownership and blocks every caller.
So a busy process whose cwd is known and lies outside every repository (an app launched with cwd /, or a tool's state directory) blocks all admission in every repository. Its CPU use is host load, which the pressure thresholds already cover.
Decisions
D1: repositoryIdentity returns a sentinel (errNotRepository) when the walk ends without finding .git. Every other failure (permission, invalid Git pointer, symlink error) stays a plain error, meaning unknown.
D2: HeavyJob records two facts:
CPUOnly: the row matched only the CPU rule, not heavyweight(name, args);
OutsideRepository: its cwd was observed and repositoryIdentity returned errNotRepository.
D3: filterUncovered no longer counts a job that is both CPUOnly and OutsideRepository as unknown ownership. The maintenance rule is unchanged: a maintenance-shaped job still blocks the maintenance class.
D4: unchanged:
build- or test-shaped work outside a repository still blocks;
a job whose cwd could not be observed (lsof failure, partial batch) still blocks;
the 20-job inventory cap and the pressure thresholds are unchanged.
Acceptance criteria
AC1: filterUncovered drops a CPUOnly && OutsideRepository job, and still blocks:
a CPU-only job of unknown ownership (cwd unobserved, or a non-sentinel resolution error);
a heavyweight-shaped job outside a repository;
a maintenance-shaped CPU-only job outside a repository for the maintenance class (table test).
AC2: repositoryIdentity returns errNotRepository for a temporary directory with no .git above it, and a plain error for an invalid Git pointer (test).
AC3: unownedHeavyJobs sets CPUOnly only when the CPU rule alone matched (test with claude at 150% CPU and cargo build at 150% CPU).
AC4: make test (GOMAXPROCS=2 -p 2 -parallel 2) and make lint pass; CI green.
D5: the same-repository clause matches only a known repository: j.Repository != "" && j.Repository == project. Before this, when the caller ran outside every repository (project == ""), every job with an empty Repository, including an exempted CPU-only job outside a repository, matched "same repository" and blocked. Unknown jobs still block through the unknown-ownership rule.
D6: the exemption trusts a process's cwd as the repository it works on. Unshaped work whose cwd lies outside every repository but which builds or tests a repository (for example a Gradle daemon under ~/.gradle, a VM process running a container build, or a script runner launched from ~) is no longer deferred, and a single such process can stay under the pressure thresholds on a many-core host. Native compiler children (rustc, clang, swift-frontend, ld) are still name-shaped and still block. This is recorded as an accepted ceiling in docs/CEILINGS.md, with a code marker.
AC5: tests pin:
resolveJobDirectories sets OutsideRepository=true for a live child process whose cwd is a temporary directory outside every repository, and false for one whose cwd was removed after start;
repositoryIdentity on a nonexistent path is not errNotRepository;
filterUncovered drops the exempted job when project == "".
Activity
entelecheia commentedon Oct 19, 2026
Amendment (PR #295 review, 2026-10-20)
j.Repository != "" && j.Repository == project. Before this, when the caller ran outside every repository (project == ""), every job with an emptyRepository, including an exempted CPU-only job outside a repository, matched "same repository" and blocked. Unknown jobs still block through the unknown-ownership rule.~/.gradle, a VM process running a container build, or a script runner launched from~) is no longer deferred, and a single such process can stay under the pressure thresholds on a many-core host. Native compiler children (rustc, clang, swift-frontend, ld) are still name-shaped and still block. This is recorded as an accepted ceiling indocs/CEILINGS.md, with a code marker.resolveJobDirectoriessetsOutsideRepository=truefor a live child process whose cwd is a temporary directory outside every repository, andfalsefor one whose cwd was removed after start;repositoryIdentityon a nonexistent path is noterrNotRepository;filterUncovereddrops the exempted job whenproject == "".test(admission): pin outside-repository resolution and the empty-proj…
fix(admission): match only a known repository as the caller's, record…
fix(admission): a busy process outside any repository is host load, n…