fix(server): keep macOS service logs in Library#25406

open3
main
maria/takeover-pr-25013
opened16d agobyMmaria
View on GitHubTwo-way sync enabledPR last imported 16h ago

macOS launchd opens stdout and stderr before T3 starts. When T3CODE_HOME is on a restricted external volume, keeping service logs there can prevent startup with 78: EX_CONFIG.

On macOS the service log now lives at ~/Library/Logs/T3Code/boot-service.log, and install creates that directory before loading the service. Install and repair rewrite legacy plists, and triage reports the same path through one resolver. Linux keeps its existing path. Reinstalling replaces custom launchd log paths with the standard one.

Four regression cases in the existing boot-service and triage tests fail on main and pass with the fix, and a resolver check with an injected macOS platform and an external-volume home picks ~/Library/Logs/T3Code. Unverified: native macOS launchd startup, repair, and a restricted external volume. Macroscope asks for human approval of the default-path change.

Replaces https://git.cafe/pingdotgg/t3code/pulls/25013, with thanks to @Zheruel for the original implementation.

Built with GPT-6.1-Sol in the Codex harness on T3 Code, reviewed by Claude Opus 5.5 in Claude Code.

Fixes pingdotgg/t3code#24910

Checks

21 successful · 12 skipped · 1 neutral
All checks passed
b6f5949
Synced from GitHub

Explain Change →

No actionable comments were generated in the recent review.

Walkthrough

The boot service now resolves its log path by platform. On macOS, it uses ~/Library/Logs/T3Code when an account home is available. The installer creates the resolved path’s parent directory, and triage context uses the same resolver.

Changes: Boot-service log path

Layer / File(s)Summary
Resolve and install the service log path
apps/server/src/cloud/bootService.ts, apps/server/src/cloud/bootService.test.ts
The service resolves a macOS log path under ~/Library/Logs/T3Code when an account home is available. Otherwise, it uses the supplied logs directory. Installation creates the resolved path’s parent directory. Tests cover the path, plist output streams, and repair of a legacy plist path.
Use the resolved path in triage
apps/server/src/triage/triageSession.ts, apps/server/src/triage/triageSession.test.ts
Triage context uses the shared log-path resolver. Tests cover available and unavailable account home paths.

Estimated code review effort: 2 (Simple) | ~10 minutes

Change: Bug fix · Severity of issue fixed: Medium

Suggested reviewers: juliusmarminge, t3dotgg

Merge Risk: External image Minimal · up to b6f59

The macOS service is configured to write logs under Library, while Linux retains its existing path. No actionable merge-blocking issue was established; native macOS validation remains prudent.

Pre-merge checks: Passed 4

Check nameStatusExplanation
Title checkPassedThe title clearly and concisely describes the main change: moving macOS service logs to the Library directory.
Description checkPassedThe description explains the problem, implementation, scope, verification results, unverified macOS checks, issue reference, and approval consideration. It omits the template headings and does not inc…
Linked Issues checkPassedIssue #24910 requires a usable macOS launchd log path when T3CODE_HOME is external and a successful service restart after installation or update. resolveBootServiceLogPath selects `~/Library/Logs/T3…
Out of Scope Changes checkPassedThe changes remain within issue #24910. The resolver, launchd plist repair, directory creation, boot-service tests, and triage path reporting all support consistent and usable service-log handling. Li…
Full details: Description check

Explanation

The description explains the problem, implementation, scope, verification results, unverified macOS checks, issue reference, and approval consideration. It omits the template headings and does not include explicit maintainer approval, but it is otherwise mostly complete.

Full details: Linked Issues check

Explanation

Issue #24910 requires a usable macOS launchd log path when T3CODE_HOME is external and a successful service restart after installation or update. resolveBootServiceLogPath selects ~/Library/Logs/T3Code/boot-service.log on macOS and preserves the existing logsDir path on non-macOS systems. make creates the selected parent directory before loading the service. Reinstallation rewrites legacy plist paths. The added boot-service tests cover the external-home path, directory creation, and legacy plist repair. Triage uses the same resolver. The issue's post-bootstrap health check is a suggested fix, not a stated acceptance requirement. Native launchd behavior remains unverified, but the reviewable implementation and regression tests support the required coding behavior.

Full details: Out of Scope Changes check

Explanation

The changes remain within issue #24910. The resolver, launchd plist repair, directory creation, boot-service tests, and triage path reporting all support consistent and usable service-log handling. Linux retains its prior log-path behavior. No unrelated change is demonstrated.

Finishing Touches

Generate docstrings

  • Commit to this branch
  • Create a new PR
Generate unit tests (beta)

  • Commit to this branch
  • Create a new PR
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts
External image Recent review info

External image Run configuration

External image Commits

Reviewing files that changed from the base of the PR and between 30f3dae15280ccbd77c822c11038cd21940d1786 and b6f594945d89425db083b895f8b5a08452a24667.

External image Files selected for processing: 3

  • apps/server/src/cloud/bootService.test.ts
  • apps/server/src/cloud/bootService.ts
  • apps/server/src/triage/triageSession.test.ts

Included review availability: This review used your included allowance. Your plan provides up to 10 included reviews per hour; 5 remain after this review.

Synced from GitHub

Approvability

Verdict: Needs Human Approval

Macroscope's review found this PR requires human approval — macOS service logs move to ~/Library/Logs/T3Code, with triage updated to use the same location. This changes a product default and requires human review of the new location and existing log-collection expectations.

You can add or adjust custom eligibility rules. Learn more.

Synced from GitHub

Thread transfer impact

✅ Thread transfer remains within every enforced ceiling.

ℹ️ The exact PR base did not have a successful artifact. Baseline uses the latest successful main measurement shown below.

ProviderMetricMain baselineThis PRImpactPR ceiling
CodexTotal thread wire5.0 KiB5.0 KiB0 B (0.0%)6.8 KiB✅
CodexThread snapshot wire3.8 KiB3.8 KiB0 B (0.0%)4.9 KiB✅
CodexLive turn WebSocket wire1.2 KiB1.2 KiB0 B (0.0%)2.0 KiB✅
CodexLive turn WebSocket decoded21.5 KiB21.5 KiB0 B (0.0%)24.4 KiB✅
CodexLive turn messages110 (0.0%)8✅
ClaudeTotal thread wire5.0 KiB5.0 KiB0 B (0.0%)6.8 KiB✅
ClaudeThread snapshot wire3.8 KiB3.8 KiB0 B (0.0%)4.9 KiB✅
ClaudeLive turn WebSocket wire1.2 KiB1.2 KiB0 B (0.0%)2.0 KiB✅
ClaudeLive turn WebSocket decoded21.9 KiB21.9 KiB0 B (0.0%)24.4 KiB✅
ClaudeLive turn messages110 (0.0%)8✅

Baseline: 31bf2f7 · PR result: b6f5949 · Source CI: success

Scenario and decoded snapshot size

10 historical turns, 5 command tools per turn, 878.9 KiB retained MCP result per historical turn, and a 1.05 MiB retained result in the measured turn.

  • Codex decoded thread snapshot: 108.5 KiB
  • Claude decoded thread snapshot: 108.8 KiB

Updated in place by a trusted workflow. PR artifacts are strictly validated and never executed.

Note

Written by gpt-6.1-sol on behalf of Maria

Verified in a real dev environment

No changed behavior could be verified on this Linux Boat VM. This is an unverifiable result, not a passing runtime verification.

Read the description, complete four-file diff, discussion, and commit authors for head 35e5b02cb6c91fb0c498c6b8b53e3d7541a08c66. The PR is open and contains no commits by @juliusmarminge or @t3dotgg. The changes affect macOS launchd service log placement, legacy plist repair, and the macOS service-log path reported by triage. Linux retains the existing path.

Ran uname -s (Linux), command -v launchctl (not installed), and checked /bin/launchctl (absent). Inspected command transcript.

Observed 29 successful CI contexts with none pending or failing on this head. Those results do not establish native launchd behavior. No code changes, installs, dev servers, provider turns, or new tests were performed. No screenshots or recording apply because no changed interaction could run here.

Not verified

  • Original startup failure on main with T3CODE_HOME on a restricted macOS external volume, and successful startup on this PR with stdout/stderr at ~/Library/Logs/T3Code/boot-service.log.
  • Directory creation before launchd loads the service, real log writes, legacy plist repair, reinstall replacing custom log paths, and service restart/update/uninstall.
  • Actual macOS triage output, including missing/empty HOME fallback, and neighboring Linux service/triage behavior.
  • Main-versus-PR running-app comparison, project/thread creation, and Codex gpt-6.1-sol turns. A dev-server chat turn on Linux would not exercise launchd, so it would not prove this fix.

Native verification requires a macOS host with launchd and a restricted external volume. No merge, close, rebase, force-push, label changes, or changes to another PR were made.

Added 3 commits

  • fix(server): keep macOS service logs in Library30f3dae
  • Merge remote-tracking branch 'origin/main' into maria/takeover-pr-25013a7133a5
  • test(server): drop duplicate triage service log caseb6f5949

The automated pipeline stopped on this pull request and will not merge it:

the proof has no capture anyone can open:

  • Base launchd exit 78 on a restricted external APFS volume: requires macOS, unavailable on this VM.
  • Head installation, repair, and update producing accessible Library log paths and a reachable server: requires the same macOS environment.
  • Runtime triage service-log location and actual log creation were not exercised.
  • No public capture URLs exist; ghdrop was not invoked because no valid captures were produced.

It stays open for a person to finish or close.