Repository: harbor-framework/harbor
Issue: Node version in installed-agents causes conflict with Node installation within tasks
Root cause: Configuration Error

Agents that use npm (e.g., [claude-code](https://github.com/laude-institute/harbor/blob/68966dc70414c1fe6cc9db908d68a5b24070d872/src/harbor/agents/installed/install-claude-code.sh.j2#L18), [codex](https://github.com/laude-institute/harbor/blob/68966dc70414c1fe6cc9db908d68a5b24070d872/src/harbor/agents/installed/install-codex.sh.j2#L10)) fail to install correctly when Docker containers have node versions other than 22 installed (for example, Node.js 18 base images). Agents work correctly with Node.js 22 base images.

Root cause: When Harbor installs agents via npm in containers that have a pre-existing Node.js 18 installation, the agent binaries are not available in the PATH during execution, resulting in "command not found" errors:

```
bash: claude: command not found
```

Repro Instructions:

1. Create task:

```sh
mkdir -p test-node18/environment test-node18/tests

cat > test-node18/environment/Dockerfile << 'EOF'
FROM node:18-slim
WORKDIR /app
RUN apt-get update && apt-get install -y python3
EOF

cat > test-node18/task.toml << 'EOF'
version = "1.0"
[metadata]
author_name = "Test"
author_email = "test@test.com"
difficulty = "easy"
category = "programming"
[verifier]
timeout_sec = 60.0
[agent]
timeout_sec = 120.0
[environment]
cpus = 1
memory = "2G"
storage = "10G"
EOF

cat > test-node18/instruction.md << 'EOF'
Create a file called hello.txt with "Hello" as the content.
EOF

cat > test-node18/tests/test.sh << 'EOF'
#!/bin/bash
test -f /app/hello.txt && exit 0 || exit 1
EOF

chmod +x test-node18/tests/test.sh

cp -r test-node18 test-node22
sed -i '' 's/node:18-slim/node:22-slim/' test-node22/environment/Dockerfile
```

2. Run installed agents:
```sh
uv run harbor run --path test-node18 --agent claude-code --model anthropic:claude-4-5-haiku

uv run harbor run --path test-node22 --agent claude-code --model anthropic:claude-4-5-haiku
```

3. Inspect outputs:
```sh
# After running both tests, find latest jobs and dump key files
NODE18_JOB=$(ls -td jobs/*/test-node18__* 2>/dev/null | head -1)
NODE22_JOB=$(ls -td jobs/*/test-node22__* 2>/dev/null | head -1)

echo "=== NODE 18 SETUP ===" && tail -5 "$NODE18_JOB/agent/setup/stdout.txt"
echo ""
echo "=== NODE 18 EXECUTION ===" && cat "$NODE18_JOB/agent/claude-code.txt"
echo ""
echo "=== NODE 22 SETUP ===" && tail -5 "$NODE22_JOB/agent/setup/stdout.txt"
echo ""
echo "=== NODE 22 EXECUTION ===" && head -3 "$NODE22_JOB/agent/claude-code.txt"
```

Outputs observed:
```
=== NODE 18 SETUP ===

added 3 packages in 2s

2 packages are looking for funding
  run `npm fund` for details

=== NODE 18 EXECUTION ===
bash: claude: command not found

=== NODE 22 SETUP ===

added 3 packages in 3s

2 packages are looking for funding
  run `npm fund` for details

=== NODE 22 EXECUTION ===
{"type":"system","subtype":"init","cwd":"/app","session_id":"3be38809-f797-48c4-8c0a-7e74c1284285","tools":["Task","TaskOutput","Bash","Glob","Grep","ExitPlanMode","Read","Edit","Write","NotebookEdit","WebFetch","TodoWrite","WebSearch","KillShell","AskUserQuestion","Skill","EnterPlanMode","LSP"],"mcp_servers":[],"model":"anthropic:claude-3-5-sonnet-20241022","permissionMode":"default","slash_commands":["compact","context","cost","init","pr-comments","release-notes","review","security-review"],"apiKeySource":"none","claude_code_version":"2.0.76","output_style":"default","agents":["general-purpose","statusline-setup","Explore","Plan"],"skills":[],"plugins":[],"uuid":"e2218d45-97d4-4145-bcfe-a8074689a020"}
{"type":"assistant","message":{"id":"bc041068-166d-4b2a-b071-53eb2af9ea0e","container":null,"model":"<synthetic>","role":"assistant","stop_reason":"stop_sequence","stop_sequence":"","type":"message","usage":{"input_tokens":0,"output_tokens":0,"cache_creation_input_tokens":0,"cache_read_input_tokens":0,"server_tool_use":{"web_search_requests":0,"web_fetch_requests":0},"service_tier":null,"cache_creation":{"ephemeral_1h_input_tokens":0,"ephemeral_5m_input_tokens":0}},"content":[{"type":"text","text":"Invalid API key · Please run /login"}],"context_management":null},"parent_tool_use_id":null,"session_id":"3be38809-f797-48c4-8c0a-7e74c1284285","uuid":"b61be2df-ff15-45dd-8fd5-6d3f460ef466","error":"authentication_failed"}
{"type":"result","subtype":"success","is_error":true,"duration_ms":445,"duration_api_ms":0,"num_turns":1,"result":"Invalid API key · Please run /login","session_id":"3be38809-f797-48c4-8c0a-7e74c1284285","total_cost_usd":0,"usage":{"input_tokens":0,"cache_creation_input_tokens":0,"cache_read_input_tokens":0,"output_tokens":0,"server_tool_use":{"web_search_requests":0,"web_fetch_requests":0},"service_tier":"standard","cache_creation":{"ephemeral_1h_input_tokens":0,"ephemeral_5m_input_tokens":0}},"modelUsage":{},"permission_denials":[],"uuid":"d4fe631c-4057-40bf-b0ed-62d443f4a58d"}

```