opensymphony 2.11.3

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
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
# Operations

This document covers the current local operator workflow for OpenSymphony.

Packaging note: crates.io publishes one package, `opensymphony`. The internal
`crates/opensymphony-*` directories are module trees inside that package, not
separately published dependencies.

## 1. Core commands

Recommended CLI commands:

- `opensymphony init`
- `opensymphony update`
- `opensymphony run`
- `opensymphony app` or `opensymphony desktop`
- `opensymphony debug <issue-id>`
- `opensymphony tui`
- `opensymphony doctor`
- `opensymphony rehydrate <issue-id> --reason "..."`

## 2. First-run flow

```bash
cargo install opensymphony
opensymphony install openhands
opensymphony --help

cd /path/to/target-repo
opensymphony init
opensymphony update
opensymphony run
```

If you already run an external OpenHands agent-server, you can skip
`opensymphony install openhands`.

The desktop launcher is intentionally lazy. `opensymphony app` and its visible
alias `opensymphony desktop` verify and launch a cached desktop bundle from
`~/.opensymphony/desktop/<version>/` without making the normal Cargo install
compile Tauri, npm, or platform desktop dependencies. On a cache miss, it reads
`opensymphony-desktop-release-index.json` from the versioned GitHub release for
the running CLI, downloads the compatible archive, verifies the archive and
installed manifest, then promotes the bundle into the versioned cache. Existing
cached bundles check the latest release index for newer compatible updates
before launch. Set `OPENSYMPHONY_DESKTOP_RELEASE_INDEX_URL` to test a fake
release server or use a private mirror. For early local testing, pass
`--bundle-dir <path>` or set
`OPENSYMPHONY_DESKTOP_BUNDLE_DIR` to a bundle directory containing
`opensymphony-desktop-manifest.json`. The manifest records the OpenSymphony
version, platform, architecture, relative executable path, and executable
SHA-256. Local bundle materialization copies regular files and directories;
symlinked bundle entries should be packaged by the downloaded archive path
instead of this local smoke path.
When no compatible prebuilt asset is available or a release download fails, a
normal run attempts the source-build fallback after checking Rust/Cargo,
Node/npm, source archive extraction, and platform desktop/Tauri prerequisites.
Interactive update prompts use `Update before launch? [Y/n]`; pressing Enter
accepts the update, and non-interactive runs update by default unless
`--no-update` is supplied.

Maintainers can build the current release bundle assets from a checkout:

```bash
npm run build --workspace=@opensymphony/desktop
npm run package:release --workspace=@opensymphony/desktop
```

The package command writes
`dist/desktop-release/opensymphony-desktop-v<VERSION>-<PLATFORM>-<ARCH>.tar.gz`
and `dist/desktop-release/opensymphony-desktop-release-index.json`. Upload the
archive first and the release index last. The index is the CLI-consumable
metadata file; it should never be published before the referenced archive is
available. If an index already exists in the output directory, the package
command preserves entries for other platform/architecture assets and replaces
only the current asset entry while keeping unknown top-level metadata. It also
fails before writing metadata when the desktop package, Tauri crate, or Tauri
config version does not match the release version, or when Cargo lockfile drift
would change the desktop dependency graph.
Use `--install-path <dir>` or `OPENSYMPHONY_DESKTOP_INSTALL_PATH` to choose a
custom install root. That root contains versioned bundles such as
`<dir>/<version>/`; it is not the bundle directory itself. `--dry-run` remains
read-only and never starts source-build prerequisite installation. Download
metadata, auto-update prompting, fallback order, and path-safety rules are defined in
[Desktop App Installer And Auto-Update Spec](specs/desktop-app-installer-auto-update-spec.md).

Important `init` behavior:

- fetches the current template payload
- leaves an existing `AGENTS.md` untouched and writes starter guidance to
  `AGENTS-example.md` during first-time setup
- prompts before overwriting repo-owned files
- optionally scaffolds AI PR review assets
- can configure GitHub Actions variables, the `review-this` label, and the
  optional AI review secret automatically when `gh` is installed and can access
  the target repository
- prompts whether to commit and push the generated OpenSymphony files; when
  accepted, it stages only files it wrote, commits `chore: bootstrap
  OpenSymphony`, and pushes `HEAD` to the detected remote
- supports `--non-interactive` for automation; pass explicit flags for prompt
  decisions and unresolved existing-file conflicts fail before any files are
  written
- copies `.agents/skills/` recursively so helper scripts, query files, and
  reference docs all arrive together
- keeps bootstrap guidance in CLI output and the central OpenSymphony docs
  instead of copying `docs/` files into the target repository

Automation-friendly target repo provisioning can run without stdin prompts:

```bash
cargo install opensymphony
opensymphony install openhands

cd /path/to/target-repo
opensymphony init \
  --non-interactive \
  --linear-project-slug my-linear-project \
  --conflict-policy overwrite \
  --commit-and-push
```

For scripts that scaffold AI PR review too, add the review flags explicitly:

```bash
opensymphony init \
  --non-interactive \
  --ai-pr-review \
  --configure-github \
  --ai-review-provider-kind openai-compatible \
  --ai-review-model-id accounts/fireworks/models/glm-5p1 \
  --ai-review-base-url https://api.fireworks.ai/inference/v1 \
  --ai-review-require-evidence true \
  --ai-review-secret-env LLM_API_KEY \
  --linear-project-slug my-linear-project \
  --conflict-policy overwrite
```

If `--configure-github` is omitted, init still writes the AI PR review files
when `--ai-pr-review` is present, but it prints the manual `gh` commands instead
of mutating repository variables, secrets, or labels. If a non-interactive run
finds an existing generated file and `--conflict-policy` was not supplied, it
fails before applying the template.
When `--ai-review-secret-env` is used, the named environment variable must be
present and non-empty; init fails rather than setting a blank GitHub secret.

For already-initialized repositories, `opensymphony update` is the fast
maintenance path:

- checks the latest published `opensymphony` version and skips
  `cargo install opensymphony --locked` when the running CLI is already current
- refreshes changed or new template-managed files under `.agents/skills/`
- leaves `WORKFLOW.md`, `AGENTS.md`, `.github/*`, and repo-local extra skills
  alone

OpenSymphony 2.11.0 raises the minimum supported Rust version to 1.97.1. An
older CLI may invoke Cargo through a checkout-local toolchain override, so use
this one-time upgrade path when moving from a release before 2.11:

```bash
rustup update stable
cargo +stable install opensymphony --locked
```

Use workflow settings mode when only the managed branch or review-provider
markers need to change:

```bash
opensymphony update --target-branch develop
opensymphony update --target-branch main
opensymphony update --target-branch release/next
opensymphony update --target-branch release/next --code-review openhands
```

Settings mode updates managed `WORKFLOW.md` markers, rewrites known legacy
branch-control phrases when the target branch changes, and skips the CLI
reinstall, template skill refresh, and memory bootstrap. `--code-review
openhands` records the marker and attempts to enable an existing
`.github/workflows/ai-pr-review.yml` through `gh workflow` but does not install
or repair a missing workflow file; `codex` and `none` record the marker and
attempt to disable an existing OpenHands review workflow. If `gh` is
unavailable, unauthorized, or cannot access Actions, verify or adjust the
workflow state manually.

Normal user installs use bundled DuckDB. This keeps `cargo install
opensymphony` and `opensymphony update` turnkey even when the memory database is
enabled.

Power users who want to avoid compiling bundled DuckDB may install a system
DuckDB development package and build without default features. On the
macOS/Homebrew development host, install and pin DuckDB once:

```bash
brew install duckdb
brew pin duckdb
```

Homebrew currently provides `duckdb`, not a versioned `duckdb@...` formula.
Pinning keeps the verified local version from moving during routine Homebrew
upgrades. The expected version for this release line is DuckDB `1.5.3`. To
build manually against that system library:

```bash
export DUCKDB_LIB_DIR="$(brew --prefix duckdb)/lib"
export DUCKDB_INCLUDE_DIR="$(brew --prefix duckdb)/include"
export DYLD_LIBRARY_PATH="$DUCKDB_LIB_DIR${DYLD_LIBRARY_PATH:+:$DYLD_LIBRARY_PATH}"
cargo install opensymphony --no-default-features --features duckdb-prebuilt
```

On Linux, set `DUCKDB_LIB_DIR`, `DUCKDB_INCLUDE_DIR`, and `LD_LIBRARY_PATH` to
the matching DuckDB installation. On Windows, set `DUCKDB_LIB_DIR`,
`DUCKDB_INCLUDE_DIR`, and add the DuckDB DLL directory to `PATH` before running
the same Cargo install command. This is a manual optimization path: verify a
memory command after installation, and expect to keep the runtime library
available anywhere the installed binary runs.

To update a power-user system-linked install, run the same Cargo install command
with the same environment first. Then run `opensymphony update` from a target
repository only to refresh template-managed agent assets. Starting with
`opensymphony update` may reinstall the default bundled build when a newer
release exists.

## 3. Recommended validation commands

For fast iterative development inside this repository on the macOS/Homebrew
host, use the system-linked developer aliases:

```bash
cargo fmt --check
cargo check-system-duckdb
cargo test-system-duckdb
cargo test-system-duckdb --test memory
cargo clippy-system-duckdb
```

If system DuckDB is unavailable, use the portable downloaded fallback aliases:

```bash
cargo check-dev
cargo test-dev
cargo clippy-dev
```

The system aliases set `DUCKDB_LIB_DIR`, `DUCKDB_INCLUDE_DIR`, and
`DYLD_LIBRARY_PATH` for the aliased command. The fallback aliases set
`DUCKDB_DOWNLOAD_LIB=1` only for the aliased command. Both alias families use
`--no-default-features --features duckdb-prebuilt`. If a downloaded fallback
command must override `CARGO_TARGET_DIR`, use an absolute path. Release-
sensitive, packaging, and dependency work should still include the default
bundled-mode checks so `cargo install opensymphony` remains turnkey for users:

```bash
cargo fmt --check
cargo clippy --all-targets -- -D warnings
cargo test
cargo test --test init
cargo test --test help
cargo test --test update
./scripts/smoke_local.sh
```

Dependency audit notes:

- COE-429 adds `jsonschema = 0.46.5` as the runtime validator for installed
  Codex app-server JSON Schema payload checks. Release provenance was checked
  against the `Cargo.lock` crates.io source/checksum entries for `jsonschema`
  and its called-out transitive crates (`fancy-regex`, `fluent-uri`, and
  `fraction`), the dependency tree was reviewed with `cargo tree -p jsonschema
  --depth 2`, and `cargo audit` exited successfully against the current lockfile
  on 2026-06-21. Re-run those checks when upgrading `jsonschema`.

Useful runtime checks:

```bash
curl http://127.0.0.1:2468/healthz
curl http://127.0.0.1:2468/api/v1/snapshot
curl http://127.0.0.1:2468/api/v1/capabilities
curl http://127.0.0.1:2468/api/v1/dashboard/snapshot
opensymphony tui --url http://127.0.0.1:2468/ --exit-after-ms 1200
```

## 4. Doctor expectations

`opensymphony doctor` is a real preflight tool.

It is optional troubleshooting/preflight help, not the primary install path for
managed local OpenHands. The normal setup flow is `cargo install opensymphony`
followed by `opensymphony install openhands`.

Current scope:

- loads and resolves the target repo `WORKFLOW.md`
- renders the workflow prompt with a synthetic issue
- validates required local tools
- validates bundled OpenHands tooling
- probes the configured OpenHands transport
- can create a temp conversation and verify runtime readiness

Expected checks include:

- config parses
- target repo exists
- `WORKFLOW.md` resolves cleanly
- required env-backed config values exist
- `cargo`, `curl`, `git`, and `uv` are on `PATH`
- the pinned OpenHands toolchain is present
- loopback/local safety warnings are surfaced

When the configured transport uses managed local OpenHands, `doctor` can
bootstrap the pinned tooling into the configured `openhands.tool_dir` before
continuing the rest of its checks.

## 4.0 Code Graph repository indexing

Trigger a target-branch repository snapshot through the gateway or desktop
native mirror:

```bash
curl -X POST http://127.0.0.1:2468/api/v1/code/repos/opensymphony/index
```

The server reads the branch marker in `WORKFLOW.md` (default `develop`) and
resolves the commit from `origin/<branch>` or the local branch. It reads Git
objects without running repository code, applies the configured Tree-sitter
limits, and writes immutable revision membership in bounded batches. Repeated
indexing of a later commit reuses unchanged paths and records deletions without
removing older revisions. Requests return an accepted report; inspect the event
journal for progress and the terminal completion/failure event. Concurrent
requests are serialized by the index writer.

The operator-facing equivalent is the Code Graph empty state: select the
configured repository and choose `Index repository`. It is safe to start from
an empty `.opensymphony/memory/memory.duckdb`; the repository row is exposed
with zero counts until the job begins. `accepted` and `progress` reports show
coverage, `failed` and `unavailable` reports show diagnostics with a retry
action, and `code_graph_updated` causes the shell to refresh the baseline. If
the event stream is silent during an accepted/progress job, the shell polls the
repository summary and refreshes as soon as an indexed baseline is visible.
The provenance strip should show the configured target revision and whether a
view is baseline, workspace-composed, stale, truncated, or partially analyzed.

For a production transport smoke, use the gateway endpoint rather than the
fixture workbench:

```bash
curl http://127.0.0.1:2468/api/v1/code/repos
curl -X POST http://127.0.0.1:2468/api/v1/code/repos/<repo-id>/index
curl 'http://127.0.0.1:2468/api/v1/code/repos/<repo-id>/graph?mode=atlas'
```

## 4.1 Subscription Credential Operations

OpenAI ChatGPT/Codex subscription mode is explicit and feature-gated. Build or
install OpenSymphony with `--features openhands-subscription-credentials`, then
configure the target repo workflow with
`openhands.conversation.agent.llm.credential_mode: openai_subscription`.

Credential establishment belongs to the documented OpenHands SDK flow or to a
future hosted credential broker. For local or self-hosted use, run the
OpenHands SDK browser or device-code login in the environment that owns the
credential store, keep refresh material in the selected auth directory, and
export only the short-lived access-token reference expected by the workflow
before starting `opensymphony run`. Do not place OAuth JSON files, access
tokens, or refresh tokens inside issue workspaces or repository files.
`auth_directory_env`, `auth_method`, `open_browser`, and `force_login` are
operator/bootstrap metadata for that credential setup step; they are preserved
for status and diagnostics, while the runtime conversation request resolves only
the short-lived access token and optional account identity header.

Validation for subscription mode should include:

- mocked subscription request construction tests
- redaction checks for manifests, diagnostics, and debug output
- live integration only when a valid subscription credential and pinned SDK
  support are available

Codex app-server subscription readiness is separate from the OpenHands SDK auth
directory. The gateway reports local Codex readiness through model settings by
running supported Codex CLI checks only:

```bash
codex --version
codex app-server --help
codex login status
```

When `codex login status` is logged out or expired, run
`codex login --device-auth`. Some ChatGPT accounts require enabling
**Security and login -> Enable device code authorization for Codex** before the
device-code flow succeeds. To revoke local Codex access, run `codex logout` and
use ChatGPT account settings for account-side revocation. OpenSymphony must not
read private Codex credential files or copy access/refresh material into
workspaces, logs, workflow files, Linear comments, or browser payloads. Gateway
readiness checks are cached briefly and have bounded per-command timeouts so
operator UI polling cannot hang on a stalled local Codex command.

The local Codex app-server harness path launches
`codex --dangerously-bypass-hook-trust app-server --stdio` and is advertised as
available when clients read `/api/v1/capabilities`. Before starting a run,
OpenSymphony generates the JSON Schema from the installed Codex CLI and
validates its full-automation `thread/start`, `thread/resume`, rollback
`thread/list`, `thread/archive`, `thread/unarchive`, and `turn/start` payloads. A new issue starts a thread; a
workspace with its canonical manifest resumes it. If the first manifest write
fails after a start, OpenSymphony archives that newly created thread and does
not start a turn. If the installed schema rejects any lifecycle payload, update
Codex before running the Codex harness. Unsupported or logged-out Codex
installations must fail with the readiness guidance above instead of partially
starting an issue. Loopback WebSocket and hosted Codex worker pools remain
non-production paths.

For cross-harness route testing, run `opensymphony run --dry-run`.
OpenSymphony will still poll Linear and prepare workspaces, but the worker
returns a route preview instead of launching a model-backed harness. The preview
is recorded as a `routing.decision` runtime event and includes the selected
harness, model, and model profile. To force a local process override without
editing workflow config, start the daemon with `OPENSYMPHONY_HARNESS`, and pass
`OPENSYMPHONY_MODEL` / `OPENSYMPHONY_MODEL_PROFILE` when a launcher wants to use
the active model profile selected in the desktop or web UI.

The Codex local stdio route executes the configured Codex binary with
`cwd == issue_workspace_path`. `OPENSYMPHONY_CODEX_BIN` is a trusted local
operator override and must not be treated as a hosted or multi-tenant input.
Approval requests are surfaced through normalized runtime events and shared
approval-center data models, but approval decisions are not yet forwarded from
the operator action plane into a live Codex stdio session in this alpha route.

The alpha model configuration panel exposed by the web and desktop shells uses
the shared model profile state store, but those entrypoints currently construct
it without durable storage. Treat profile edits as session-local until a
desktop secure-settings backend or hosted settings service is wired in. The UI
may keep model strings, routing hints, subscription bootstrap metadata, and
stored credential references in memory, but raw provider keys and OAuth refresh
material must stay in the selected keychain, OpenHands auth directory, or
hosted secret store.

## 5. Linear operational model

OpenSymphony 1.0.0 is GraphQL-only for agent-side Linear operations.

Operational implications:

- there is no separate local Linear bridge process to start
- initialized target repos rely on `LINEAR_API_KEY`
- operators may set `LINEAR_CLIENT_ID` and `LINEAR_CLIENT_SECRET` instead of
  relying on a long-lived `LINEAR_API_KEY`; `opensymphony run` mints a Linear
  OAuth client-credentials token at startup and uses it for scheduler and
  worker Linear calls
- `opensymphony run` keeps its local worker/snapshot tick every 5s, while
  Linear reads use cheaper internal cadences: running state every 30s,
  dispatch discovery every 60s, terminal cleanup every 5 minutes, and full
  issue details hourly after startup/dispatch
- if Linear returns a long rate-limit reset, the scheduler pauses all Linear
  reads behind one shared cooldown but continues processing worker updates; the
  Linear client only sleeps inline for short rate-limit retry windows up to the
  lower of `tracker.retry_policy.max_backoff` and 30 seconds
- the checked-in helper lives at
  `.agents/skills/linear/scripts/linear_graphql.py`
- checked-in query files under `.agents/skills/linear/queries/` are the
  supported mutation/query surface
- issue creation, issue rewrite passes, blocker relations, comments, PR
  attachments, and project updates should all use those checked-in assets

Smoke test:

```bash
cd /path/to/target-repo
python3 .agents/skills/linear/scripts/linear_graphql.py \
  --query-file .agents/skills/linear/queries/viewer.graphql
```

## 6. Project memory

Project memory stores policy and learned structure in
`.opensymphony/memory/memory.yaml` and private runtime artifacts under
`.opensymphony/memory/`. `opensymphony run` captures terminal issue transitions
automatically when `memory.auto_capture` is enabled in `config.yaml`:

```yaml
memory:
  auto_capture: true
  auto_archive: false
```

Manual commands remain available for setup, backfill, inspection, and guarded
archive operations:

```bash
opensymphony memory init
opensymphony memory capture COE-123
opensymphony memory status
opensymphony memory brief COE-123
opensymphony memory related --paths crates/opensymphony-openhands
opensymphony memory sync-docs --since-last-sync
opensymphony memory lint --public-docs
opensymphony memory lint --okf
opensymphony memory reindex --from-okf
opensymphony memory export-okf --visibility public --output public-okf
opensymphony memory import-okf public-okf
```

Add `--dry-run` to write commands when an operator wants a non-writing preview.

Use `opensymphony memory import --source-file completed.yaml` only for
deterministic imports, migrations, tests, or external exports. Failed Linear or
GitHub access should be fixed before live capture is retried.

`memory capture` creates or refreshes issue capsules, updates
`.opensymphony/memory/memory.duckdb`, and refreshes markdown indexes when
enabled. Normal builds use DuckDB's bundled native library so operators do not
need to install DuckDB separately, at the cost of heavier Rust compile time and
a larger binary. Repository development can opt into the `duckdb-prebuilt`
feature through the system-linked `cargo check-system-duckdb`,
`cargo test-system-duckdb`, and `cargo clippy-system-duckdb` aliases, or the
downloaded fallback `cargo check-dev`, `cargo test-dev`, and `cargo clippy-dev`
aliases. Treat that native dependency as part of the hosted deployment threat
model before enabling memory in a multi-tenant service.
Memory capture does not archive Linear issues.

Read commands such as `memory status`, `memory brief`, `memory related`, and
`memory context` open the DuckDB index in read-only mode and do not run schema
migrations. Run capture, import, OKF import/export, docs sync, or reindex-style
admin operations serially if a local DuckDB writer is active. Prefer the CLI or
MCP admin surface for maintenance; direct file or DuckDB access is an offline
recovery and diagnostics fallback only.

For worker or tool access, `opensymphony run` starts the read-only memory server
when memory is initialized and `memory.serve` is not disabled. The supervised
server binds to loopback on an ephemeral port by default, reports the endpoint
through the control-plane recent events, and passes
`OPENSYMPHONY_MEMORY_ENDPOINT` into managed local OpenHands workers. Manual
operation is also available with `opensymphony memory serve --addr
127.0.0.1:8765`, which exposes MCP-style `initialize`, `tools/list`, and
`tools/call` JSON-RPC methods at `/mcp`. Set `OPENSYMPHONY_MEMORY_TOKEN` or
pass `--token` to require bearer-token access for read tools. Admin tools
(`memory.capture`, `memory.sync_docs`, `memory.lint`, `memory.reindex`,
`memory.export_okf`, `memory.import_okf`, and `memory.ingest_code_intel`)
require `OPENSYMPHONY_MEMORY_ADMIN_TOKEN` or `--admin-token`. When only the
admin token is configured, it also gates read tools; do not inject that token
into ordinary worker environments. When `code_intel.enabled` is true,
`tools/list` exposes the read-only `code.graph.context` indexed discovery tool;
when `code_intel.ast.enabled` is true, it also exposes `code.ast.*` inspection
tools. The graph tool is bounded and can use the
server-resolved run workspace overlay; it never accepts a client filesystem
root or source-snippet override. The ad hoc
`code.ast.query` tool is available for local trusted use without tokens, and is
admin-gated when an admin token is configured. AST work runs off the async
server thread, enforces configured file/match/capture limits, rejects paths and
symlinks outside the repo root, skips generated/vendor/build/cache directories
during traversal and oversized files with trace warnings, and never executes
target-repo code. Direct file requests inside skipped directory names still pass
through containment and resource checks. See
[`docs/code-intelligence.md`](code-intelligence.md) for agent and operator
usage.

Linear archival is a separate command and is guarded by captured memory:

```bash
opensymphony linear archive --issues COE-123
```

For explicit issue selectors, the archive command captures live Linear and
GitHub evidence before evaluating the guard. It blocks issues that have no
capsule or unresolved capture warnings unless `--force` is supplied. Normal mode
resolves Linear credentials from `WORKFLOW.md` and calls the Linear GraphQL
archive mutation.

If the repo uses managed local OpenHands, archive also moves the issue's
persisted OpenHands conversation into the repo-scoped `archived/` store. Archive
uses the workspace `.opensymphony/conversation.json` manifest when present and
falls back to scanning managed conversation `meta.json` files for a matching
`workspace.working_dir` issue key, so legacy flat conversations and repo-scoped
`active/` conversations can still be moved even when workspace metadata is
stale. Normal orchestrator runs use the sibling `active/` store, while
`opensymphony debug COE-123` searches active and archived stores and starts the
managed server against the store containing the requested conversation. If
another OpenHands server is already bound to the configured port with a
different store, stop it and retry the debug command.

For issues last run through the local Codex app-server harness,
`opensymphony debug COE-123` reads the recorded Codex thread id, unarchives it
when terminal reconciliation archived it, and then runs `codex resume
<thread-id>` from that exact issue workspace. Set `OPENSYMPHONY_CODEX_BIN` to
override the Codex binary. Use `opensymphony debug COE-123 --app` to unarchive
and print `codex://threads/<thread-id>` without launching interactive Codex.

See [Project Memory](memory.md) for the full command surface, import YAML
schema, and troubleshooting notes.

## 7. Rehydration

Rehydration is the explicit recreation of an OpenHands conversation while
preserving enough history for continuation.

Use it for:

- API key rotation
- broken persisted conversation state
- intentional provider/model changes

Examples:

```bash
opensymphony rehydrate COE-123 --reason "API key rotation"
opensymphony doctor --config ./config.yaml --rehydrate
```

## 8. Local safety

- prefer loopback-only OpenHands targets for local development
- treat target repos and prompts as trusted local input
- do not keep unrelated OpenHands servers running on the same configured port
- stop `opensymphony run` with Ctrl-C so the orchestrator can terminate its
  managed OpenHands process tree; Ctrl-Z only suspends the orchestrator and can
  leave the server bound to the configured port
- do not store provider secrets in checked-in files

## 9. Migration note

If an older target repo still contains `openhands.mcp`, remove that block.
OpenSymphony 1.0.0 expects Linear access through `LINEAR_API_KEY` and the
repo-local GraphQL helper assets copied by `opensymphony init`.

<!-- BEGIN OPENSYMPHONY MANAGED MEMORY SYNC -->

## Current model

- COE-546 contributed: PR #217: Code Graph bootstrap indexing UX and E2E validation (merge `5cc1e83`)

## Important invariants

- Preserve the behavior described in the recent captured changes unless current code and tests show it has changed.
- Use capsule source refs to inspect the original PR or Linear issue when context is ambiguous.

## Operational flow

- No generated diagram requested for this sync.

## Known gotchas

- No area-specific gotchas were inferred from the selected memory.

## Recent changes

- COE-546: Code Graph Bootstrap UX And End-To-End Validation

## Source refs

- COE-546

<!-- END OPENSYMPHONY MANAGED MEMORY SYNC -->