Conversation
resolvingSymlinksInPath() drops the directory marker for paths that do not exist on disk, so a root canonical URL depended on whether the directory was already created. Restore the marker so root identity is stable before and after the directory appears.
AgentSessionsStore lives in an Objective-C ivar of StatusItemController, so its deinit runs inside __ivar_destroyer on whichever thread performs the release. On macOS < 26 the back-deployed runtime cannot hop to the main actor from that context and aborts in swift_task_deinitOnExecutorMainActorBackDeploy (SIGABRT in StatusMenuTokenAccountSwitcherTests on macOS 15).
agy -p /usage starts the user's MCP servers in a private temp directory and then exits. Servers that call setsid are reparented to launchd and keep a core busy after every refresh. Record descendants while the probe is alive, and kill anything still using that directory once it finishes.
The directory sweep now stores each process start token and checks it again before SIGTERM and SIGKILL, so a reused PID is not signaled. SwiftFormat also wants the short usleep delay ungrouped and a normal comment on the runner flag.
Every Codex binary lookup ran `spctl --assess` on the native executable, and nothing cached the verdict. Each assessment re-hashes the whole binary in syspolicyd (~2.5 s of CPU for a 281 MB x86_64 codex), so the cost scaled with refresh cadence: ~1.7% of a core at a 5-minute refresh, ~55% when lookups ran every few seconds. Remember definitive verdicts (accepted/rejected) for regular files, keyed by path plus device, inode, size, mtime and ctime, for up to an hour. ctime is not settable from user space, so a content write, chmod or xattr change (quarantine included) always re-assesses. Timeouts and spctl errors stay retryable, concurrent callers share one in-flight assessment, and app bundles are never memoized, matching the steipete#3838 rule that bundle metadata cannot prove sealed resources unchanged. Fixes steipete#4078 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_014giiyt6RgBarhNPpjn2Xiz
Review found that the memo read the file identity before `spctl` ran and stored the verdict under it, so a symlink swapped during the assessment and swapped back would leave another executable's verdict in the cache. The key now resolves the path itself, recording every symlink it crosses (a link cannot be retargeted in place, so a swap changes its inode or ctime even when reverted), plus the resolved file's identity. A verdict is kept only when the key read after `spctl` returns equals the one read before. Adds regressions for a leaf link and an intermediate directory link swapped during assessment, and a final-effect test through isLaunchCandidateAllowed: a replaced executable is blocked on the next lookup, and a revocation that leaves the file untouched takes effect when the verdict expires. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_014giiyt6RgBarhNPpjn2Xiz
…te lifetime Review round 2 found that a caller joining an in-flight assessment returned the leader's verdict without rechecking its own path, so a link retargeted to a forbidden executable mid-assessment could be allowed on the old target's verdict. The leader already declined to cache that verdict but still published it to waiters. Every caller now gets a verdict only when the path still names the assessed file after `spctl` returns; otherwise it runs a fresh, unshared assessment. Adds a final-decision regression through isLaunchCandidateAllowed where the link is retargeted to an unsigned binary during a shared assessment: both the leader and the waiter are blocked. Also shortens the verdict lifetime from one hour to 15 minutes, per the review's recommendation on the certificate-revocation window. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_014giiyt6RgBarhNPpjn2Xiz
Review round 3 found that a parent directory moved aside, replaced while spctl ran, and restored could leave a different tool's verdict cached for the original, because the path spctl traversed could change under it. Instead of tracking every link and directory on the path, the memo now has Gatekeeper assess `/.vol/<device>/<inode>`, which names the resolved file directly: nothing on the path can change what was assessed. Verdicts are keyed by that file's identity (device, inode, size, mtime, ctime), kept only if it is unchanged when spctl returns, and handed to a caller only while the caller's path still names that file; otherwise the caller gets a fresh, unshared assessment. Verdicts are reported for the caller's path. Where /.vol cannot reach the file, nothing is memoized. Replaces the path-walking key from the previous revision (simpler, and it also removes the noise that directory timestamps would have added). Adds the reviewer's directory-swap scenario and link swaps during assessment as final-decision tests: the unsigned CLI stays blocked in every case. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_014giiyt6RgBarhNPpjn2Xiz
Adopt ClawSweeper's recommended five-minute bound on how long a cached Gatekeeper verdict can outlive an in-place certificate revocation. The elevated-cadence case that motivated steipete#4078 still collapses to one assessment per five minutes. Adds .github/pr-proof/codex-gatekeeper-assessment-memo.log with the Intel Mac before/after spctl counts and the production-path harness output. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_014giiyt6RgBarhNPpjn2Xiz
Review of revision 5 found that the cache-hit branch returned a remembered verdict after the initial stat without re-checking that the caller's path still names that file, unlike the shared and fresh branches. All three branches now return through one `deliver` step that re-checks the caller's path immediately before answering, and otherwise runs a fresh, unshared assessment. Adds a final-decision regression through isLaunchCandidateAllowed with a test hook that retargets the link to an unsigned CLI inside the cache-hit window: the decision is blocked. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_014giiyt6RgBarhNPpjn2Xiz
…steipete#4079) Xcode 26.3 / Swift 6.2 could not type-check two optional-cost #expect expressions in CostUsageQuotaWeekLinuxTests (built on macOS too), so the test build failed on the release toolchain; bind each cost to a Double first. CI gains a macos-15 Xcode 26.3 job running swift build --build-tests on Swift changes, wired into the aggregate gate, so release-toolchain type-check regressions are caught before tagging. Fixes steipete#4070. Thanks @RowboTony!
) Plugin host gains an opaque, nonpersistent browser-cookie jar: imported cookies stay host-owned and each ctx.http request gets the RFC 6265 match for its URL (host-only/domain scope, path boundary, Secure, expiry) on both engines, with cross-origin redirects still blocked. LongCat now runs entirely as a bundled plugin (six native fetch/import/header files deleted), and browser cookie import no longer merges host-only and domain cookies that share a name. Net -43 production lines.
A zero-byte or whitespace-only config file now behaves like a missing one (defaults, usage keeps working, next save writes valid JSON with 0600 permissions) instead of failing closed and blanking usage; malformed non-empty JSON keeps its decode error and protected writes. Fixes steipete#4071. Thanks @kvnloo!
Status-item position preservation now validates the saved position before and after hide/remove/visibility mutations: an invalid value written during the operation is not kept, a valid replacement is retained, and an already-corrupt snapshot is never restored (bound: widest attached display + 512 pt). Split-provider visibility uses the same helper. Refs steipete#3355.
…e#4087) Codex cost catch-up now publishes each validated snapshot after every bounded pass instead of only the first, so a completed discovery replaces an older partial total before the next sleep (completeness, account/settings scope, cancellation, and freshness checks unchanged). Refs steipete#3508. Thanks @kernnel!
…ipete#4089) Keychain signature validation runs on bounded utility workers with a two-second wait per caller, so a stalled native validation no longer blocks background quota refresh after app updates (late successes cannot authorize reads). Claude OAuth rechecks fresh, profile-scoped memory after stale-cache cleanup and persists it with its original owner binding. Fixes steipete#3249; refs steipete#3395 steipete#3798. Thanks @lozcalver and @SilentKnight87!
…teipete#4084) Antigravity: repair grouped model-family quotas on the OAuth path to match the agy CLI grouping, and parse weekly-only Starter (free-tier) quota fixtures with explicit cadence through the shared parser. Refs steipete#2427 steipete#3789.
Kimi CLI refresh tokens rotate and belong to the CLI, so CodexBar keeps CLI authentication read-only; when the CLI access token expires after the CLI quits, the error now says to run kimi or add a Kimi Code API key for unattended use, and configured web/API sources still take over. Fixes steipete#4063. Thanks @kid0114!
Claude/Vertex cost caches keep the decoded value of each successful save under its committed file stamp, skip re-encoding unmodified values, and use compact row keys (a 24k-row history artifact shrinks from 9.3 MB to 6.9 MB). Schema 3 -> 4 rebuilds once from existing transcripts; Unicode text is preserved exactly. Refs steipete#3882 steipete#3247. Thanks @djbclark for the CPU sample that pinned this down!
Kimi: when the monthly membership is known to be exhausted, shorter windows show as blocked by the monthly limit instead of fresh capacity. z.ai: unsupported quota shapes explain that usage is unavailable instead of inventing numbers, while recognized limits stay visible. Refs steipete#3536 steipete#2522; closes steipete#2871 (five-hour cadence already derived from API fields, now covered by the reported payload).
…teipete#4093) Grok local token history now reaches Usage & Spend and share output when x.ai billing is unavailable: wider dashboard requests keep the scan's actual 30-day coverage instead of an unknown horizon that the dashboard rejected, fresh local history publishes before retained-quota early returns, and the scanner clips files to its advertised calendar days so aggregates match daily buckets. Fixes steipete#3716. Thanks @Chipagosfinest!
…ce (steipete#4088) Codex credential reads retry with a bounded reread when auth.json is missing, partial, incomplete, or expiring while the Codex CLI publishes fresh credentials mid-fetch, and a fresh plan change invalidates the old quota/reset evidence so usage from the new plan replaces the previous one. Fixes steipete#3389; refs steipete#3635 steipete#3523. Thanks @theDanielJLewis and @coygeek!
Adaptive agent-aware refresh now recognizes the Codex app-server nested inside the ChatGPT app (both documented executable paths under /Applications/ChatGPT.app), after checking the running PID's kernel-reported path, OpenAI code signature, and symlink redirects on every scan; the outer bundle's Gatekeeper assessment is cached by bundle, Info.plist, executable, and CodeResources identity and retried on failure. Recent rollout activity stays authoritative. Fixes steipete#4069. Thanks @jaychou0642-create!
Widget snapshots now retain each provider's last eligible reading with its original measurement time instead of an all-or-nothing guard, so a disabled, invalidated, or failing provider no longer blanks the others; an invalidated account stays retired until replacement usage is published. Refs steipete#3500 steipete#3627 steipete#3339 steipete#2838. Thanks @jaxleezhang!
Merge the contributor work from PR steipete#4077, replacing directory sweeps and descendant polling with a fresh per-probe environment marker. Recheck same-user ownership and process start identity before signaling detached leftovers. Co-authored-by: Brandon Charleson <b.charleson1@gmail.com>
Keep the contributor's directory-marker fix in one shared helper. Remove pass-through URL wrappers and unused FileManager arguments without changing selector parsing or filesystem checks. Extend the cost-root regression to check identity after directory creation, and document the marker contract. Refs steipete#4067 Co-authored-by: Sogl <artyom@mezin.me>
Cancel stored task handles before reading the observed assertion ID. Its getter escapes self, so doing that read last lets the four task fields retain their existing main-actor isolation while deinit stays nonisolated. Add an off-actor final-release regression using a synthetic assertion, and document the teardown boundary and reported macOS 15 crash fix. Refs steipete#4068 Co-authored-by: Sogl <artyom@mezin.me>
Cover price-table ordering, legacy unqualified prices, and unmatched API zones and service tiers while preserving consumed-token and paid-unit accounting. Share category and daily aggregation without changing library token coverage. Refs steipete#4076. Co-authored-by: Tom Vaucourt <34662901+T0mSIlver@users.noreply.github.com>
Merge current main without rewriting contributor history for steipete#4077. Run marker reaper coverage in the portable test target, verify Linux environment reads, and use a timing margin that still detects natural child exit. Keep the reaper immutable and reuse subprocess logging metadata, reducing the approved production growth from 121 to 102 lines. Focused verification passed 249 tests; make check and independent review are clean.
…rectory-marker # Conflicts: # CHANGELOG.md
…nonisolated-deinit # Conflicts: # CHANGELOG.md
steipete#4097) Security: failing Swift Testing expectations reflected the whole process environment stored in UsageFetcher, ClaudeUsageFetcher.Configuration, and the shared fetch context, so local test logs could contain credentials. A ProcessEnvironment wrapper now renders only an entry count in descriptions, debug descriptions, and mirrors while keeping dictionary access, and the test scripts, Makefile targets, and CI scrub credential-shaped environment variables (documented allowlist) before running tests.
…teipete#4098) Plugin host gains validated cookie-session policies on the steipete#4059 jar: ranked source domains with required-cookie admission, validated single-entry persistence with legacy cache migration, host-owned migration of native session files with conditional invalidation and interactive commit/rollback, and an explicit opt-in to keep over-quota percentages above 100. Notion and ZoomMate now run entirely as bundled plugins; their native fetchers, importers, cookie-header code, and session stores are deleted.
Pi: preserve the directory marker when canonicalizing a missing session root, through one shared canonicalizer, so cost-root identity stays stable before and after the directory is created. Thanks @Sogl!
…-assessment-memo # Conflicts: # CHANGELOG.md
AgentSessionsStore: use a plain nonisolated deinit that cancels stored task handles before reading the observed assertion ID, keeping main-actor isolation for its task fields and fixing an abort on final release off the main actor. Thanks @Sogl!
Antigravity usage probes no longer leave MCP server processes behind: the probe runs with a fresh ownership marker in its environment, and cleanup terminates its process group and then only same-user processes carrying that exact marker (surviving setsid/double-fork), with identity checks before SIGTERM and bounded SIGKILL. Nothing is matched by name, path, or working directory, so unrelated processes are never touched. Thanks @bcharleson!
…-assessment-memo Resolves the CHANGELOG conflict from the 0.69.0 release: the entry moves to 0.69.1's Fixed section. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Official 0.68.0 vs this branch's memo, 30 minutes each, back to back: spctl runs 14 -> 10, syspolicyd CPU 50.2 s -> 33.4 s, on a cold-cache Intel Mac where most assessments hit the existing 5 s timeout. Log only; no code change. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…#4106) Security follow-up to steipete#4097: every remaining stored process-environment dictionary (app, CLI, provider contexts, session scanners, optional environments) now uses the redacting ProcessEnvironment wrapper, so reflection, descriptions, dumps, and Swift Testing expansions can never print environment values; a repository guard test rejects new unredacted stored environment properties. Net -9 production lines.
# Conflicts: # CHANGELOG.md
…-assessment-memo Resolves the CHANGELOG conflict with steipete#4106: the entry follows 0.69.1's Security section. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Mistral billing usage is priced by event type, zone, and tier through a dimension-aware lookup, fixing a price collision between billing dimensions without changing token totals. Thanks @T0mSIlver!
…4108) Process ownership cleanup stays responsive under load: a timed-out or cancelled subprocess returned only after ~13 s on a busy Linux process table because cleanup waited on full ownership sweeps; it now returns in ~3 s under the same load with the existing assertion bound. Adaptive scan deadline tests use the injected clock instead of wall time.
…-assessment-memo Resolves the CHANGELOG conflict with steipete#4076 and steipete#4108: the entry joins 0.69.1's Fixed list. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Runs CodexBar's own CI workflow (Xcode 26.6 macOS tests and lint) on the branch behind steipete#4080, because the upstream run is waiting on first-contributor approval. Not for merging here.