opensymphony 1.4.0

A Rust implementation of the OpenAI Symphony orchestration design
Documentation
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
# AGENTS.md

This file provides persistent context for AI agents working on this repository.

## Project Overview

<!-- Describe your project here. What does it do? What problem does it solve? -->

## Technology Stack

<!-- List your technologies: languages, frameworks, databases, etc. -->

- Language: <!-- e.g., Python 3.11, TypeScript 5.0 -->
- Framework: <!-- e.g., FastAPI, React, Next.js -->
- Database: <!-- e.g., PostgreSQL, SQLite -->
- Testing: <!-- e.g., pytest, vitest -->

## Coding Standards

### General

- Keep functions small and focused
- Write self-documenting code with clear names
- Add comments only for "why", not "what"
- Follow existing patterns in the codebase

### Formatting

<!-- Add your formatting commands -->

- Format command: `<!-- e.g., make format, npm run format -->`
- Lint command: `<!-- e.g., make lint, npm run lint -->`
- Type check: `<!-- e.g., make typecheck, npm run typecheck -->`

### Testing

<!-- Add your testing requirements -->

- Test command: `<!-- e.g., make test, npm test -->`
- Coverage requirement: <!-- e.g., 80%, 100% for critical paths -->
- Test location: `<!-- e.g., tests/, __tests__/ -->`

## Project Structure

```
<!-- Customize this structure for your project -->
.
├── src/                    # Source code
├── tests/                  # Test files
├── docs/                   # Documentation
├── configs/                # Configuration files
├── scripts/                # Utility scripts
├── AGENTS.md               # This file
├── WORKFLOW.md             # OpenSymphony configuration
└── README.md               # Project readme
```

## Key Directories

<!-- Document important directories -->

- `src/` - <!-- Main source code -->
- `tests/` - <!-- Test files -->
- `docs/` - <!-- Documentation -->

## Dependencies

### Runtime

<!-- List key runtime dependencies -->

### Development

<!-- List key dev dependencies -->

## Environment Variables

| Variable | Description | Required |
|----------|-------------|----------|
| `EXAMPLE_VAR` | <!-- Description --> | Yes/No |

## Local Development Setup

<!-- Steps to set up local development -->

```bash
# Example setup steps
# 1. Install dependencies
# 2. Configure environment
# 3. Run tests
```

## PR Requirements

Before submitting a PR:

1. All tests pass
2. Code is formatted
3. Lint checks pass
4. New code has tests
5. Documentation updated if needed

## Architecture Decisions

<!-- Document key architecture decisions -->

### Decision 1

- **Context**: <!-- Why this decision was needed -->
- **Decision**: <!-- What was decided -->
- **Consequences**: <!-- Impact and trade-offs -->

## Known Issues / Gotchas

<!-- Document any quirks or known issues -->

## References

<!-- Links to relevant external documentation -->

- [Framework Docs]https://example.com
- [API Reference]https://example.com/api

## Preserved Existing AGENTS.md

The following content was preserved from the repository's previous `AGENTS.md` during `opensymphony init`.

# AGENTS.md

## Mission

Build OpenSymphony as a Rust implementation of the Symphony service specification using OpenHands agent-server for execution and FrankenTUI for the optional terminal UI.

This repository is an orchestrator. It is not a chat app, not a general workflow engine, and not a thin wrapper around OpenHands.

## Authority order

When sources disagree, use this order:

1. upstream `openai/symphony` `SPEC.md`
2. pinned OpenHands SDK agent-server docs and the wire-contract notes in `docs/websocket-runtime.md`
3. this repository's `docs/`
4. the task file currently being implemented
5. local code comments and tests

Do not silently invent behavior when the upstream spec or chosen integration contract is explicit.

## Hard invariants

### Orchestration

- The Rust orchestrator is the sole authority over scheduling state.
- Workers report events and outcomes to the orchestrator.
- No background task may mutate scheduling state except through orchestrator-owned commands or messages.
- Tracker polling remains required even though agent runtime updates use WebSockets.

### Workspace safety

- Every issue maps to exactly one sanitized workspace key.
- Workspace paths must remain inside the configured workspace root.
- The agent runtime must execute with `cwd == issue_workspace_path`.
- Never run agent code in the orchestrator repository root, temp root, or an unsanitized path.

### OpenHands integration

- Target the SDK agent-server HTTP and WebSocket contract.
- Do not implement against `openhands serve`.
- Do not implement against the web-app Socket.IO protocol.
- Operations are REST. Runtime streaming is WebSocket.
- The WebSocket readiness barrier is the first `ConversationStateUpdateEvent`.
- Always reconcile events after WebSocket readiness and after reconnect.
- One OpenHands conversation is reused per issue by default.
- A fresh conversation gets the full workflow prompt. A resumed conversation gets continuation guidance only.
- Local MVP uses one local agent-server subprocess shared across issues, not one server per issue.
- Local MVP does not require Docker per workspace.

### Tracker contract

- The orchestrator reads Linear directly.
- Tracker writes are done by agent-side GraphQL helpers and checked-in query assets unless a future operator API explicitly documents otherwise.
- Scheduler correctness must not depend on agent-side tracker writes succeeding.

### UI separation

- FrankenTUI is optional.
- The daemon must remain correct without any UI attached.
- The UI consumes the control-plane snapshot and event stream only.
- UI code must not reach into orchestrator internals directly.

### CLI surface

- `opensymphony run` is the real local orchestrator entrypoint.
- `opensymphony daemon` is demo-only and exists for smoke tests or UI-focused development.
- When documenting, validating, or operating the system, prefer `opensymphony run` unless the task is specifically about the demo control-plane publisher.

## Design rules

### Keep boundaries explicit

Preferred crate and trait boundaries:

- `opensymphony-domain`
- `opensymphony-workflow`
- `opensymphony-workspace`
- `opensymphony-linear`
- `opensymphony-openhands`
- `opensymphony-orchestrator`
- `opensymphony-control`
- `opensymphony-cli`
- `opensymphony-tui`
- `opensymphony-testkit`

Add new crates only when there is a clear ownership boundary.

### Prefer actor ownership over shared locks

The orchestrator should own mutable runtime state in one async task.

Use channels and message passing for worker reports, retries, and control-plane publication.

Avoid spreading `Arc<Mutex<...>>` through the daemon.

### Keep the WebSocket client resilient

The runtime client must:

- connect after conversation creation
- wait for readiness
- reconcile the REST event backlog
- deduplicate by event ID
- preserve timestamp order
- reconnect with bounded exponential backoff
- refresh cached state after reconnect

### Preserve forward compatibility

OpenHands event schemas can evolve. Implement:

- typed decoding for known high-value events
- raw JSON retention for unknown events
- compatibility tests against the pinned version
- version notes in `docs/sources.md`

### Separate Symphony hooks from OpenHands hooks

Symphony workspace hooks:

- `after_create`
- `before_run`
- `after_run`
- `before_remove`

These are owned by OpenSymphony.

OpenHands hook configuration such as `pre_tool_use` is a separate, optional agent runtime feature. Do not conflate them.

## Local safety posture

The local MVP is a trusted-environment mode.

- Expect host filesystem access.
- Expect host process execution.
- Do not overstate isolation.
- Harden later for hosted mode with remote or container-backed workspaces.
- Document risky defaults clearly in `README.md` and `docs/operations.md`.

## Coding standards

- Rust stable toolchain
- `cargo fmt` clean
- `clippy` clean under repo lints
- explicit error enums with context
- structured logs, not ad hoc print-only debugging
- `tokio` cancellation handled deliberately
- serde models for all external payloads
- integration code isolated inside `opensymphony-openhands`
- no direct OpenHands protocol types leaking into orchestrator core types

## Required tests by subsystem

### Workflow and config

- front matter parsing
- strict template rendering failure modes
- env indirection
- extension namespace validation
- path normalization

### Workspace

- identifier sanitization
- containment checks
- hook timeout handling
- create and reuse semantics
- terminal cleanup behavior

### OpenHands runtime

- conversation create payload
- event send and run trigger
- WebSocket readiness
- event reconciliation
- out-of-order event ordering
- reconnect and replay
- terminal `execution_status` detection
- conversation reuse and reset paths

### Orchestrator

- candidate sorting
- active vs terminal reconciliation
- bounded concurrency
- normal continuation retry
- failure backoff
- stall detection
- restart recovery

### Control plane and TUI

- snapshot derivation
- control-plane API serialization
- no daemon mutation from UI
- pane layout state
- log and event rendering

## Change-management rules

When changing behavior in any of these files, update the corresponding docs in the same change:

- `docs/architecture.md`
- `docs/configuration.md`
- `docs/openhands-agent-server.md`
- `docs/websocket-runtime.md`
- `docs/workspace-and-lifecycle.md`
- `docs/linear-and-tools.md`
- `docs/operations.md`
- `docs/testing-and-operations.md`

When changing milestones or task sequencing, update `docs/implementation-plan.md`.

When changing the pinned OpenHands assumptions, update `docs/sources.md`.

## File map

- `README.md`: project summary and implementation path
- `docs/architecture.md`: runtime architecture
- `docs/symphony-spec-alignment.md`: upstream spec mapping
- `docs/openhands-agent-server.md`: agent-server integration choices
- `docs/websocket-runtime.md`: wire contract and recovery behavior
- `docs/workspace-and-lifecycle.md`: workspace ownership and hooks
- `docs/linear-and-tools.md`: Linear integration and GraphQL helper assets
- `docs/memory-capture-and-doc-sync.md`: issue memory capture, DuckDB indexing,
  documentation sync, and archive guard design
- `docs/ui-frankentui.md`: operator UI design
- `docs/repository-layout.md`: crate ownership
- `docs/deployment-modes.md`: local MVP and hosted follow-on
- `docs/configuration.md`: target repo bootstrap and runtime config
- `docs/operations.md`: doctor, rehydration, diagnostics, packaging, and local ops
- `docs/testing-and-operations.md`: test strategy and validation layers
- `docs/tasks/`: issue-ready implementation work items

---

## AI PR Review Overlay

This repository uses an automated AI PR review system via OpenHands.

### How it works

- The `.github/workflows/ai-pr-review.yml` workflow runs on PR events
- It uses the OpenHands PR review plugin with repository-specific guidance
- Reviews focus on correctness, security, and maintainability
- The AI reviewer is **advisory only** and does not count as a human approval

### Repository-specific review guidance

The `.agents/skills/custom-codereview-guide.md` file contains project-specific rules:

- Async/concurrency safety (locks, cancellation, blocking operations)
- Error handling patterns (explicit enums, context-rich errors)
- Workspace safety (path containment, sanitization)
- WebSocket resilience (reconnect, reconciliation)
- State machine correctness
- Forward compatibility (serde patterns)
- Testing requirements

### Evidence requirements

Substantive PRs should include an `Evidence` section showing:
- Test output for behavior changes
- Benchmarks for performance changes
- Usage examples for new features
- Reproduction case and verification for bug fixes

### Triggering review

The AI review runs automatically on:
- PR opened (non-draft, same-repo)
- PR synchronized (new commits)
- PR marked ready for review
- `review-this` label added

To manually retrigger, add the `review-this` label.