Skip to content

fix: eliminate daemon-env.json — derive env at spawn time#119

Merged
c-h- merged 2 commits intomainfrom
eliminate-daemon-env-json
Mar 7, 2026
Merged

fix: eliminate daemon-env.json — derive env at spawn time#119
c-h- merged 2 commits intomainfrom
eliminate-daemon-env-json

Conversation

@c-h-
Copy link
Copy Markdown
Collaborator

@c-h- c-h- commented Mar 7, 2026

Summary

  • Rewrites buildSpawnEnv() to source ~/.zshenv at spawn time via /bin/zsh -c instead of loading stale daemon-env.json
  • Removes saveEnvironment(), loadSavedEnvironment(), and ENV_FILE const from src/utils/daemon-env.ts
  • Removes saveEnvironment() call from daemon startup in src/daemon/server.ts
  • Simplifies buildSpawnEnv signature (drops unused first param) across all 5 adapter callers
  • Adds 6 tests for getCommonBinDirs() and buildSpawnEnv()

Closes #118

Test plan

  • npm run typecheck — zero errors
  • npm run lint — zero errors
  • npm run build — succeeds
  • npm test — all 474 tests pass (including 6 new)

🤖 Generated with Claude Code

Rewrite buildSpawnEnv() to source ~/.zshenv at spawn time instead of
loading stale JSON. Remove saveEnvironment(), loadSavedEnvironment(),
and ENV_FILE. Simplify buildSpawnEnv signature (drop first param).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Copy link
Copy Markdown
Collaborator Author

@c-h- c-h- left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review: CI green, docs clean, one concern before merge.

buildSpawnEnv() does sourceZshEnv() || process.env — if sourcing ~/.zshenv succeeds, it replaces the daemon's process.env instead of merging with it. Any env vars only in process.env (temporary exports, launchd-injected vars, test/runtime vars) get dropped unless they're also in ~/.zshenv.

Issue #118's intended contract was the opposite: start with process.env, layer ~/.zshenv on top, then apply opts.env.

Suggested fix: merge zsh-derived env onto process.env, not replace:

const zshEnv = sourceZshEnv();
const base = { ...process.env, ...(zshEnv ?? {}) };

Add a test proving a process.env-only var survives when sourceZshEnv() succeeds.

@c-h-
Copy link
Copy Markdown
Collaborator Author

c-h- commented Mar 7, 2026

Addressed this review:

  • buildSpawnEnv() now starts with process.env, overlays sourced ~/.zshenv, then applies extraEnv
  • added a regression test proving a process.env-only var survives when sourceZshEnv() succeeds

Local verification passed:

  • npm test
  • npm run typecheck

@c-h- c-h- merged commit ef340fa into main Mar 7, 2026
1 check passed
c-h- pushed a commit that referenced this pull request Mar 10, 2026
Features:
- Phase 1 ACP adoption — Codex adapter via ACP transport (#127)
- Callback metadata + lifecycle webhooks (#123)
- ADR-001: adopt ACP as primary agent interface (#126)
- Stateless daemon core (#117)

Fixes:
- Eliminate pending- session IDs — resolve real ID at launch (#131)
- Webhook numeric exit_status + compatible HMAC headers (#128)
- Daemon env derivation at spawn time (#119)
- Binary resolve util update (#121)

Docs:
- Full documentation audit and alignment (#132)
c-h- added a commit that referenced this pull request Mar 10, 2026
Features:
- Phase 1 ACP adoption — Codex adapter via ACP transport (#127)
- Callback metadata + lifecycle webhooks (#123)
- ADR-001: adopt ACP as primary agent interface (#126)
- Stateless daemon core (#117)

Fixes:
- Eliminate pending- session IDs — resolve real ID at launch (#131)
- Webhook numeric exit_status + compatible HMAC headers (#128)
- Daemon env derivation at spawn time (#119)
- Binary resolve util update (#121)

Docs:
- Full documentation audit and alignment (#132)

Co-authored-by: Doink (OpenClaw) <charlie+doink@kindo.ai>
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.

Eliminate daemon-env.json — derive env at spawn time (stateless inversion)

1 participant