Skip to content

Commit c4e6315

Browse files
Agent Relayclaude
andcommitted
fix: pass all shadow options through daemon spawn path
Shadow options (shadowMode, shadowAgent, shadowTriggers) were silently dropped when spawning via the daemon socket path. The HTTP API fallback passed all fields via JSON.stringify, but the SDK path used explicit field listing that missed these three fields. Thread shadowMode, shadowAgent, and shadowTriggers through: - Protocol SpawnPayload type - SDK client.spawn() options and envelope payload - Daemon SpawnManager.handleSpawn() pass-through - CLI client.spawn() call Add SDK test verifying shadow options appear in sent envelope. Add sdk-daemon-parity Claude rule to prevent future field omissions. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
1 parent f637ba5 commit c4e6315

File tree

10 files changed

+1410
-1
lines changed

10 files changed

+1410
-1
lines changed

.claude/rules/sdk-daemon-parity.md

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
---
2+
paths:
3+
- "packages/sdk/src/**/*.ts"
4+
- "packages/daemon/src/**/*.ts"
5+
- "packages/protocol/src/types.ts"
6+
- "src/cli/index.ts"
7+
---
8+
9+
# SDK-Daemon Parity
10+
11+
## Principle
12+
13+
The SDK (`RelayClient`) is the canonical interface for daemon communication. All spawn/release fields supported by the spawner and bridge must be threaded through:
14+
15+
1. **Protocol types** (`SpawnPayload` in `packages/protocol/src/types.ts`)
16+
2. **SDK client** (`client.spawn()` options and envelope payload in `packages/sdk/src/client.ts`)
17+
3. **Daemon SpawnManager** (`handleSpawn` pass-through in `packages/daemon/src/spawn-manager.ts`)
18+
4. **CLI** (the `client.spawn()` call in `src/cli/index.ts`)
19+
20+
## Adding New Spawn Fields
21+
22+
When adding a field to `SpawnRequest` in `packages/spawner/src/types.ts` or `packages/bridge/src/types.ts`:
23+
24+
- Add to `SpawnPayload` in `packages/protocol/src/types.ts`
25+
- Add to `client.spawn()` options type in `packages/sdk/src/client.ts`
26+
- Include in the envelope payload construction in `client.spawn()`
27+
- Pass through in `SpawnManager.handleSpawn()` to `this.spawner.spawn()`
28+
- Include in the CLI `client.spawn()` call in `src/cli/index.ts`
29+
- Add a test verifying the field appears in the sent envelope
30+
31+
## Daemon vs HTTP API Parity
32+
33+
The daemon socket path and HTTP API fallback must produce identical behavior. The HTTP fallback passes the entire `spawnRequest` via `JSON.stringify()`, so it gets all fields automatically. The daemon path uses explicit field listing, which requires manual updates when new fields are added.
34+
35+
## SDK Over Direct Protocol
36+
37+
Always use `RelayClient` methods (`spawn`, `release`, `sendMessage`) rather than constructing raw protocol envelopes in CLI commands. The SDK handles:
38+
39+
- Connection lifecycle and reconnection
40+
- Envelope construction with correct protocol version
41+
- Timeout management and cleanup
42+
- Correlation ID tracking for responses
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
{
2+
"id": "traj_itn5hyej5mi6",
3+
"version": 1,
4+
"task": {
5+
"title": "Fix @agent-relay/wrapper module resolution issues - 17 test failures",
6+
"source": {
7+
"system": "plain",
8+
"id": "PR-357"
9+
}
10+
},
11+
"status": "completed",
12+
"startedAt": "2026-02-02T10:32:24.710Z",
13+
"agents": [
14+
{
15+
"name": "default",
16+
"role": "lead",
17+
"joinedAt": "2026-02-02T15:13:33.203Z"
18+
}
19+
],
20+
"chapters": [
21+
{
22+
"id": "chap_g5zlcodg305k",
23+
"title": "Work",
24+
"agentName": "default",
25+
"startedAt": "2026-02-02T15:13:33.203Z",
26+
"events": [
27+
{
28+
"ts": 1770045213205,
29+
"type": "decision",
30+
"content": "Thread shadowMode, shadowAgent, shadowTriggers through protocol, SDK, daemon, and CLI layers: Thread shadowMode, shadowAgent, shadowTriggers through protocol, SDK, daemon, and CLI layers",
31+
"raw": {
32+
"question": "Thread shadowMode, shadowAgent, shadowTriggers through protocol, SDK, daemon, and CLI layers",
33+
"chosen": "Thread shadowMode, shadowAgent, shadowTriggers through protocol, SDK, daemon, and CLI layers",
34+
"alternatives": [],
35+
"reasoning": "Devin review found these fields were silently dropped in daemon spawn path. Both the spawner and bridge packages already support them, but protocol SpawnPayload and SDK client.spawn() were missing them, creating silent data loss when using daemon-based spawning vs HTTP API fallback."
36+
},
37+
"significance": "high"
38+
},
39+
{
40+
"ts": 1770045235751,
41+
"type": "decision",
42+
"content": "Created sdk-daemon-parity.md Claude rule: Created sdk-daemon-parity.md Claude rule",
43+
"raw": {
44+
"question": "Created sdk-daemon-parity.md Claude rule",
45+
"chosen": "Created sdk-daemon-parity.md Claude rule",
46+
"alternatives": [],
47+
"reasoning": "Codifies the requirement that all spawn fields must be threaded through protocol, SDK, daemon, and CLI layers to prevent future silent data loss bugs."
48+
},
49+
"significance": "high"
50+
}
51+
],
52+
"endedAt": "2026-02-02T15:14:01.719Z"
53+
}
54+
],
55+
"commits": [],
56+
"filesChanged": [],
57+
"projectId": "/data/repos/relay",
58+
"tags": [],
59+
"_trace": {
60+
"startRef": "2bf129eb8935904951b0aeb866ddba268611e009",
61+
"endRef": "f637ba5a9d194aff545001bbe091c45fc0c3413d",
62+
"traceId": "trace_17kspa6zdv77"
63+
},
64+
"completedAt": "2026-02-02T15:14:01.719Z",
65+
"retrospective": {
66+
"summary": "Fixed Devin review issue: threaded shadowMode, shadowAgent, shadowTriggers through protocol SpawnPayload, SDK client.spawn(), daemon SpawnManager, and CLI. Added SDK test for shadow options. Created sdk-daemon-parity Claude rule.",
67+
"approach": "Standard approach",
68+
"confidence": 0.9
69+
}
70+
}
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
# Trajectory: Fix @agent-relay/wrapper module resolution issues - 17 test failures
2+
3+
> **Status:** ✅ Completed
4+
> **Task:** PR-357
5+
> **Confidence:** 90%
6+
> **Started:** February 2, 2026 at 10:32 AM
7+
> **Completed:** February 2, 2026 at 03:14 PM
8+
9+
---
10+
11+
## Summary
12+
13+
Fixed Devin review issue: threaded shadowMode, shadowAgent, shadowTriggers through protocol SpawnPayload, SDK client.spawn(), daemon SpawnManager, and CLI. Added SDK test for shadow options. Created sdk-daemon-parity Claude rule.
14+
15+
**Approach:** Standard approach
16+
17+
---
18+
19+
## Key Decisions
20+
21+
### Thread shadowMode, shadowAgent, shadowTriggers through protocol, SDK, daemon, and CLI layers
22+
- **Chose:** Thread shadowMode, shadowAgent, shadowTriggers through protocol, SDK, daemon, and CLI layers
23+
- **Reasoning:** Devin review found these fields were silently dropped in daemon spawn path. Both the spawner and bridge packages already support them, but protocol SpawnPayload and SDK client.spawn() were missing them, creating silent data loss when using daemon-based spawning vs HTTP API fallback.
24+
25+
### Created sdk-daemon-parity.md Claude rule
26+
- **Chose:** Created sdk-daemon-parity.md Claude rule
27+
- **Reasoning:** Codifies the requirement that all spawn fields must be threaded through protocol, SDK, daemon, and CLI layers to prevent future silent data loss bugs.
28+
29+
---
30+
31+
## Chapters
32+
33+
### 1. Work
34+
*Agent: default*
35+
36+
- Thread shadowMode, shadowAgent, shadowTriggers through protocol, SDK, daemon, and CLI layers: Thread shadowMode, shadowAgent, shadowTriggers through protocol, SDK, daemon, and CLI layers
37+
- Created sdk-daemon-parity.md Claude rule: Created sdk-daemon-parity.md Claude rule

0 commit comments

Comments
 (0)