Skip to content

Latest commit

 

History

History
1026 lines (928 loc) · 44.6 KB

memory.md

File metadata and controls

1026 lines (928 loc) · 44.6 KB

Project Memory

OpenSymphony project memory turns completed Linear work into durable development context. During opensymphony run, terminal issue transitions are captured automatically when memory auto-capture is enabled. The capture uses Linear issue narrative, active Workpad content, issue hierarchy, milestones, GitHub PR descriptions, reviews, checks, and source refs. It writes private issue capsules under .opensymphony/memory/, updates a DuckDB index, evolves .opensymphony/memory/memory.yaml, and syncs stable topics into public docs.

The operator projection reports memory scope, source freshness, degradation, and overlay provenance without exposing memory grants or tokens. Memory availability does not grant filesystem access.

Related specifications:

Rationale and Model

Linear remains OpenSymphony's short-term planning and coordination surface, but completed issues still carry implementation knowledge that should survive queue cleanup and archival. GitHub PRs preserve code review history, and Workpad comments preserve useful audit details, but neither is a convenient component-oriented project memory on its own.

OpenSymphony memory is the completed-work distillation of what mattered: the intent, shipped outcome, decisions, validation evidence, relevant review feedback, follow-ups, risks, and documentation impact. Implementation agents should keep their focus on code, validation, PRs, and Workpad accuracy; long-term memory is produced by capture and docs sync rather than by ad hoc edits during ordinary feature work.

The memory system has two different outputs:

  • Issue capsules record what happened for one completed Linear issue. They are compact source-referenced closeout documents, not run transcripts.
  • Topic docs describe what is now true about a subsystem. They capture the current model, invariants, gotchas, and recent changes without requiring readers to know which issue introduced the knowledge.

OKF Bundle Compatibility

OpenSymphony treats OKF as the portable Markdown contract for memory, not as a replacement for the current local store. The logical bundle layout follows docs/specs/okf-memory-spec.md:

bundle-root/
  index.md
  log.md
  projects/
  milestones/
  issues/
  areas/
  repositories/
  code/
  runs/
  references/

The current .opensymphony/memory/ paths stay in place for this compatibility slice. Issue capsules map to issues/<issue>.md, milestone nodes map to milestones/<slug>.md, generated topic docs map to areas/<slug>.md, and repository memory remains a facet under repositories/ rather than the root taxonomy.

Every parsed OKF concept requires YAML frontmatter with a non-empty type and a contained bundle-relative Markdown path. Existing legacy top-level fields such as issue, milestone, linear_url, areas, repository, prs, source_refs, and docs_sync are preserved as data during parse/render. The parser also projects those fields into opensymphony extension metadata: visibility, concept kind, scope refs, source refs, and docs-sync state. Unknown frontmatter is kept in the raw frontmatter map so future writers can round-trip documents they do not fully understand. Writers emit canonical YAML and do not preserve the original frontmatter field order or whitespace.

opensymphony memory lint --okf [bundle-root] validates an OKF bundle from the CLI, and the memory MCP admin path accepts the equivalent memory.lint request with okf plus bundleRoot arguments. A user-supplied bundle root is canonicalized and must stay inside the repository root, matching the containment policy used by other memory admin file arguments. When no bundle root is provided, linting uses the configured memory root.

opensymphony memory export-okf --visibility public|private [--output DIR] exports the configured memory root as a directory bundle. The output directory defaults to okf-export-{visibility} under the repository root when omitted and must be new or empty so stale private files cannot survive a public export. Export writes into a repository-contained staging directory first, runs OKF lint on the staged bundle, and only then promotes the completed bundle to the requested output path. If final promotion fails, OpenSymphony preserves the lint-clean staged bundle for recovery and restores the previous empty output directory when possible. Public export skips private concepts and fails if any remaining public concept still references private comments, private memory paths, or private source snapshots. Private export can include private concepts but still keeps normal OKF lint errors fatal except for visible links back into the private memory store, which are expected in private round-trip bundles.

The public export redaction scan is deliberately narrow and explicit: it treats linear:comment:, .opensymphony/memory/issues, .opensymphony/memory/source*, .opensymphony/memory/snapshot*, and their Windows-path variants as private material when they appear in exported public concepts. The scan uses the same markdown-visible text extraction as private memory link linting, so fenced code blocks, inline code spans, escaped text, and HTML comments do not create public export false positives.

The memory MCP admin surface exposes the same export operation as memory.export_okf with visibility (public or private) and optional output arguments. It uses the same repository containment, staging, lint, and public redaction checks as the CLI command.

opensymphony memory import-okf <bundle-root> [--force] validates an OKF directory bundle, copies its Markdown concepts into the configured memory root without rewriting frontmatter, and rebuilds the derived DuckDB catalog from the imported bundle. The import source and target memory root are canonicalized, checked against the repository containment policy, and rejected when they overlap. Import preflights the full copy set before writing so predictable target conflicts do not leave partially imported Markdown files. Existing Markdown files are not overwritten unless --force is supplied. Because import-okf restores both public and private bundles, visible private memory links are allowed during import and preserved in the copied Markdown. Unknown concept types, unknown frontmatter fields, missing optional fields, broken links, and missing generated indexes are warning-level import inputs; malformed concepts remain errors with file paths in the diagnostic.

Import is not transactional after the preflight succeeds. A filesystem write or DuckDB reindex failure can leave already-copied Markdown files in the memory root. Fix the underlying failure, inspect the partially copied files, and rerun with --force only when replacing those files is intentional.

The memory MCP admin surface exposes the same import operation as memory.import_okf with bundleRoot and optional force arguments. Prefer the CLI or MCP admin tools for normal maintenance; direct file or DuckDB inspection is an offline fallback for recovery and diagnostics only.

OKF lint diagnostics are intentionally actionable. Errors cover missing or invalid concept frontmatter, missing type, malformed reserved files, containment failures, and public-export leaks of private memory. Warnings cover missing recommended fields, unknown types, broken Markdown links, wiki-only links without Markdown equivalents, missing generated indexes, missing citations for source-backed claims, and unknown OKF versions. Info diagnostics call out synthesized title/description data, retained legacy fields, and OpenSymphony extension metadata. Warning-level findings remain nonfatal; private-data leakage and containment breakage are reported as errors.

Migration is intentionally incremental:

  • Phase 1 enriches and parses existing documents as OKF concepts while keeping legacy paths and fields.
  • Phase 2 can mirror or move documents into the final bundle layout and rebuild the catalog from OKF concepts.
  • Phase 3 can expose graph, hosted import/export, and visibility-filtered APIs from the OKF-derived catalog.

The memory graph projection is derived from the OKF catalog, not from client edits. Graph snapshots include bundle, directory, concept, tag, resource, citation, source-ref, and community nodes plus derived containment, Markdown, external, citation, tag, resource, scope, source-support, and same-resource edges. Broken Markdown links are kept as unresolved edges. Snapshot metrics report orphan, broken-link, stale-concept, and warning counts, while node metrics report degree, global normalized centrality across all graph node kinds, bridge score, and community ID. Community labels prefer concept areas, then tags, directories, and concept type. Each concept is assigned to exactly one deterministic community; when multiple areas are present the sorted first area wins, and tag fallback uses frontmatter order. Tags, citations, and source refs are excluded from community membership by default and can be included with the memory graph endpoint query flags. Those flags also parameterize node community IDs and bridge scores because the community membership input set changes with the query. Community IDs are stable grouping keys, not graph node IDs; community graph nodes are separately namespaced with community:<id>.

No graph-library dependency is currently selected for memory graph extraction: the shipped backend work only derives deterministic catalog relationships and metadata communities. Add a graph library when the server owns true clustering or graph algorithms beyond these deterministic DTO metrics.

The default visibility posture is private memory with optional public docs. Private capsules may include Linear comments, review context, and source snapshots, while public docs should contain public source refs such as issue identifiers, PR URLs, and commit SHAs. Public docs must not link directly to private capsule paths. Public memory is supported only by explicit configuration, and generated indexes such as DuckDB should remain local unless a project deliberately publishes them.

Generated memory indexes/log.md output groups entries under ## YYYY-MM-DD headings with newest dates first. The date comes from indexed completion time when available, then capture time, and finally a stable ISO sentinel for malformed legacy rows so regeneration is deterministic.

Areas bridge issue memory and topic docs. Area inference uses Linear narrative, labels, milestones, active Workpad content, PR narrative, review summaries, and existing learned aliases in .opensymphony/memory/memory.yaml. GitHub changed files are indexed for path-based lookup, but they do not create areas or appear in capsule or docs prose. Merge SHAs are immutable audit refs, not inference signals.

The CLI remains useful for setup, historical backfill, inspection, and manual operator actions:

opensymphony memory init
opensymphony memory capture COE-123
opensymphony memory context --issue COE-456
opensymphony memory brief COE-123
opensymphony memory related --area openhands-runtime
opensymphony memory sync-docs --since-last-sync
opensymphony memory serve --addr 127.0.0.1:8765
opensymphony memory export-okf --visibility public --output public-okf
opensymphony memory import-okf public-okf
opensymphony linear archive --issues COE-123

Use --dry-run on write commands when you want a non-writing preview.

Configuration

config.yaml controls run-loop automation:

memory:
  auto_capture: true
  auto_archive: false
  serve: true
  bind: 127.0.0.1:0

auto_capture defaults to true. auto_archive defaults to false; when it is enabled, OpenSymphony archives only after fresh capture succeeds with no blocking warnings. serve starts the local memory server during opensymphony run when memory is initialized. The default bind address selects an available loopback port once, records it in <workspace-root>/.opensymphony-memory-bind.json, and reuses that exact port on later starts. This keeps the endpoint stable for an authenticated parent conversation recovered after daemon restart; startup fails if the recorded port cannot be rebound rather than rotating the conversation's endpoint. Workers receive the resulting MCP endpoint through OPENSYMPHONY_MEMORY_ENDPOINT. Workers receive only the normal read token; admin tools require a separate OPENSYMPHONY_MEMORY_ADMIN_TOKEN.

Persistent Code Graph indexing

POST /api/v1/code/repos/{repo_id}/index and the native code_index_repo command build a bounded repository snapshot for the target branch recorded in WORKFLOW.md (default develop). The server resolves the repository root and commit; clients cannot provide arbitrary roots. Files are read from Git tree and blob objects, so indexing does not execute target-repository code.

Snapshot membership is immutable and keyed by repository, commit, and path. Documents, symbols, edges, diagnostics, and skipped coverage are persisted in batches. A later commit reuses unchanged membership, parses changed or added paths, and marks deleted current rows stale without rewriting older revisions. One process-wide index writer lock serializes concurrent indexing requests while DuckDB read paths remain usable. The gateway journals accepted/progress, completed, unavailable, and failed outcomes; code_graph_updated is emitted only after a completed snapshot is available.

This index is a shared target-branch baseline. It must not be treated as the live code state of an issue workspace; workspace overlays provide that view.

An empty DuckDB is a supported starting state. The gateway advertises the configured repository with zero coverage, allowing the web or desktop Code Graph surface to start indexing directly. The surface renders accepted and progress coverage, skipped-file diagnostics, retryable failures, and refreshes from code_graph_updated; during accepted/progress work with no event delivery, the shell polls repository summaries and recognizes a newly indexed baseline. Production web requests use HTTP and packaged desktop requests use the Tauri-native code_index_repo command against the same report contract.

Initialize the shared memory policy and learned ontology file once:

opensymphony memory init

This creates .opensymphony/memory/memory.yaml and updates .gitignore so only that config is tracked. Capsules, indexes, DuckDB, source snapshots, and automation logs remain local runtime artifacts.

The config is not a hand-maintained docs map. It is a policy plus learned structure file that capture can evolve as more work lands:

memory_root: .opensymphony/memory
visibility: private
index_path: .opensymphony/memory/memory.duckdb
confidence_threshold: 75
source_snapshots: hashes
markdown_indexes: true
docs:
  public_root: docs
  default_visibility: public
  deny_private_links: true
areas:
  openhands-runtime:
    title: OpenHands Runtime
    docs_target: docs/openhands-agent-server.md
    visibility: public
    status: stable
    confidence: 85
    aliases:
      - OpenHands Runtime
    source_refs:
      docs:
        - docs/openhands-agent-server.md
      linear_labels:
        - runtime
      linear_issues:
        - COE-123

memory init seeds stable areas from existing top-level docs/*.md files when they exist. It does not scan docs/tasks, README.md, Cargo files, source files, or GitHub changed-file lists to create docs topics. When no docs exist, the config is still valid and starts with an empty areas map.

Capture Evidence

Live capture requires Linear access from WORKFLOW.md and uses GitHub PR discovery by default through gh. For each issue, OpenSymphony reads:

  • Linear title, description, labels, state, URL, milestone, parent, children, and active Workpad comment
  • GitHub PR title, body, branch, checks, review discussion summaries, commits, merge SHA, and changed files

Area inference treats Linear labels named area:<slug> as canonical. Existing label aliases and narrative evidence from Linear and GitHub still work as fallbacks. Merge SHA is not used for inference or search; it is stored only under source_refs as the immutable audit pointer to the exact merged code state. GitHub changed files are indexed for later lookup such as "which issues touched this file?", but they are not rendered into capsules or docs and do not infer areas.

Selecting a parent issue also captures its child issue closure. Capsules link parents, children, and milestones so the Obsidian graph shows the work structure.

Linear and GitHub are part of the normal live flow. A missing WORKFLOW.md, invalid Linear config, missing issue, Linear API failure, or failing gh command fails capture. Use --no-github only for unusual non-PR work.

Import and Backfill

memory import is for deterministic backfills, migrations, tests, or external exports. It is not the normal path.

opensymphony memory import --source-file completed.yaml
opensymphony memory import COE-123 --source-file completed.yaml
opensymphony memory import --issue-range COE-120..COE-130 --source-file completed.yaml

Top-level source YAML fields:

issues: []
prs: []
overrides: {}

Important issue fields:

issues:
  - id: issue-id
    identifier: COE-123
    title: Issue title
    url: https://linear.app/example/issue/COE-123
    description: Optional issue description
    state: Done
    milestone: M3
    milestone_id: milestone-id
    parent:
      identifier: COE-100
      title: Parent title
    children:
      - identifier: COE-124
        title: Child title
    labels:
      - runtime
    comments:
      - id: comment-id
        author: username
        body: "Decision or summary text"
        updated_at: 2026-03-25T22:05:00Z
        source: linear:workpad
    linked_prs:
      - 456

Important PR fields:

prs:
  - number: 456
    title: COE-123 implement reconnect recovery
    url: https://github.com/example/repo/pull/456
    branch: coe-123-reconnect
    body: Pull request summary
    merge_sha: abcdef1234567890
    changed_files:
      - path: crates/opensymphony-openhands/src/client.rs
        change_kind: modified
    checks:
      - name: cargo test
        conclusion: success
    reviews:
      - reviewer: reviewer
        state: APPROVED
        disposition: Looks correct.

All fields except issues[].identifier and prs[].number are optional.

Query and Docs Sync

Useful read commands:

opensymphony memory status
opensymphony memory context --issue COE-456
opensymphony memory brief COE-123
opensymphony memory related --area openhands-runtime
opensymphony memory related --paths crates/opensymphony-openhands
opensymphony memory search "reconnect recovery"
opensymphony memory docs --area openhands-runtime

memory context is a pre-implementation context compiler, not a capture command. It fetches live Linear facts when available, excludes the current issue capsule, and selects captured memory from deterministic buckets: explicit includes, blocking predecessors, completed children, completed siblings, path matches, and canonical area matches. It strips each selected brief's Documentation impact section and appends one deduplicated section at the end. When opensymphony run starts a worker, it asks the supervised memory server for the same style of kickoff bundle and writes it to .opensymphony/generated/memory-context.md inside the issue workspace. If the server is disabled, the runner falls back to direct local memory reads.

Read commands open the DuckDB index in read-only mode and do not run migrations. Startup and write paths own schema creation or migration.

When central configuration is active, one supervised memory server owns one instance-wide catalog. Repository inventory entries are registered in that catalog by canonical repository ID and exact checkout commit. Policy files, public documentation, portable OKF bundles, and legacy stores remain repository-owned sources; private issue, project, milestone, and cross- repository records remain in the instance catalog. Source registration is a startup/write operation and records its status and generation in DuckDB, while ordinary MCP reads only inspect the existing schema. Code-intelligence lookups use the registered canonical repository ID rather than a caller-supplied local path.

Managed local OpenHands workers receive the memory endpoint and their per-conversation scoped read grant through the worker environment. The process-wide server read token is never placed in the shared managed-server environment, so one worker cannot bypass its grant by reading that token from a shared agent-server process.

memory serve exposes the memory command set through a local MCP-style Streamable HTTP JSON-RPC endpoint at /mcp. CLI commands call that endpoint when OPENSYMPHONY_MEMORY_ENDPOINT is set; otherwise they use offline direct mode. Read tools are memory.context, memory.search, memory.related, memory.brief, memory.docs, memory.status, and, when code_intel.ast.enabled is true, code.ast.status, code.ast.outline, code.ast.symbols, code.ast.references, code.ast.context, and code.ast.diagnostics. code.ast.query is also local read-only by default, but requires the admin token when an admin token is configured so hosted or token-gated deployments can restrict ad hoc query execution. Admin tools are memory.capture, memory.sync_docs, memory.lint, memory.reindex, memory.export_okf, memory.import_okf, and memory.ingest_code_intel; these require OPENSYMPHONY_MEMORY_ADMIN_TOKEN or --admin-token on opensymphony memory serve. If an admin token is configured without a separate read token, the admin token also protects read tools. Worker-grant capability checks follow that server access decision: a local read-only code.ast.query does not require an administrative grant capability, while a configured admin token still gates the request at the server boundary. On a supervised server with a configured workspace root, unauthenticated unscoped reads are still rejected as worker requests; an operator using the configured read or admin bearer may perform ordinary read calls without a worker grant. Worker calls remain bound to a server-issued project-set, project, work-item, canonical-repository, visibility, and capability grant. Explicit filters can only narrow those claims. all_accessible is therefore bounded by the grant, and an authorized sibling repository must be named explicitly. Ordinary worker grants have no administrative capability. Persisted sibling memory and target-branch code use the registered canonical source; AST requests may name that source using the repository alias as well as the legacy repo field; live overlays resolve only the execution repository's verified checkout. A parent integration grant instead contains the exact repository set from its durable runtime envelope. Persisted memory may span that set and the parent plus recorded descendants; all_accessible cannot add another repository or work item. Live overlays resolve only the envelope's active integration checkouts, using their opaque handles, contained relative paths, run and attempt, and target commits. An unrelated managed checkout stays inaccessible even when its repository belongs to the same project. The overlay must match the worker's issue, run, attempt, checkout generation, and target commit. A worker may advance that checkout during its run; strict discovery verifies that the current HEAD descends from the target commit instead of freezing the overlay to the startup HEAD. Each result reports the canonical repository, the revision that actually produced its source path or symbol, freshness, and persisted-versus-live provenance. memory.context builds the agent kickoff bundle. Add --include-code-intel to include code-intelligence artifacts alongside selected memory. For requested Rust paths, OpenSymphony renders Tree-sitter AST summaries, symbols, diagnostics, and a trace section before falling back to repository analysis. Unsupported languages, parser diagnostics, oversized files, and calls without requested paths use the existing CodebaseAnalyzer repository-summary fallback; mixed supported and unsupported requests can include both AST artifacts and fallback artifacts. The trace section records parse/query counts and the fallback reason. The rendered artifact/provider contract is owned by opensymphony_code_intel; memory keeps the legacy CodeIntelIndex and CodeIntelArtifact surface as an adapter around that provider contract instead of requiring code-intelligence providers to import memory internals.

Worker-scoped memory access uses a server-local, non-persisted bearer grant bound to the worker's project-set, project, work item, execution repository, authorized repository set, visibility, run/attempt, and checkout generation. An unchanged leaf claim set may reuse the conversation bearer; a changed leaf run, attempt, binding, target commit, or generation rotates the bearer and requires a fresh leaf conversation. The startup checkout HEAD is retained as capture provenance, not as a live-overlay equality requirement. Durable daemon recovery reconstructs leaf claims from the runtime envelope and forces a fresh leaf conversation when the in-memory registry was replaced. A parent controller instead restores the bearer already held by its persisted OpenHands conversation into the reconstructed registry and verifies the same memory endpoint and workspace before reattachment. A missing or different parent conversation manifest is rejected before a replacement session can launch. Terminal, inactive, and binding-superseded lifecycles issue the stop/cancel fence before revoking the issue grant. Raw bearer tokens are never persisted in manifests or diagnostics. With automatic capture enabled, terminal issues seen at daemon startup remain capture candidates instead of being assumed captured. Subtree cleanup revokes a bearer only when its checkout generation matches the cleanup target. If a newer generation for the same issue already holds the live grant, old-generation cleanup leaves that bearer and its lifecycle state unchanged. This grant applies to direct memory.show capsule reads as well as search, context, brief, related, docs, status, and code-intelligence tools. If the central service stops, the control-plane status is explicitly degraded and scoped worker reads remain blocked; they do not silently fall back to an unrelated repository-local store. Leaf capture reads the immutable runtime envelope for repository ownership and commits, and documentation sync uses that explicit owner. Terminal capture reads those durable envelopes from leaf roots and from the generation-bound parents/<parent-key>/<generation> layout. Completed parent roots remain retained across reconciliation and restart so a transient capture failure cannot erase the repository/run provenance needed for the next attempt. Their descendant leases remain active with the root so leaf cleanup cannot invalidate registered integration worktrees before OSYM-893 records capture acknowledgement and performs ordered cleanup. The run loop records that acknowledgement only after the capture workflow completes for the selected parent. Cleanup first receipts hook execution and detaches the parent integration worktrees, then removes unleased descendants bottom-up and the parent root last. Failure to persist the acknowledgement leaves the capture candidate eligible for retry. For a parent, the capture path also reads validated durable controller state and requires a matching terminal lifecycle. Successful completion additionally requires its final attempt to be passed for the same run and input version, its final evidence to be bound to the same conversation, and its exact repository commit map to equal the runtime envelope. A terminal run manifest or harness success by itself cannot authorize successful parent capture. Failed and canceled controllers receive a repository-neutral parent binding with no verified commit claims so their diagnostics can be captured before the explicit retention policy runs. If restart proves that a parent launch never attached and no run.json exists, the owned parent manifest plus the matching terminal controller supplies only that neutral parent classification; it does not invent run, attempt, command, or commit evidence. The durable binding explicitly marks a parent even when its commit map is empty, so repository-neutral capture cannot inherit a configured default leaf repository. A capture with an actual runtime envelope records one repository-neutral parent-runtime source reference with the durable run and attempt identifiers. Retained legacy run envelopes that lack usable run/attempt provenance are skipped as non-bindable entries during the pre-cleanup scan rather than preventing unrelated terminal captures from completing. The direct code.ast.* tools return JSON with path, line range, content hash, parser version, query-pack version, trace, and truncation metadata for targeted agent inspection. memory.context remains the recommended kickoff path. memory.ingest_code_intel generates code-intelligence artifacts without persistence by default. Admin callers can pass persist=true to write derived DuckDB rows for code documents, symbols, query-pack edges, and parser diagnostics. Persisted rows store metadata, hashes, spans, parser/query-pack versions, freshness, and snippet hashes only; full parse trees and source snippets are rendered from files on demand. Re-ingesting a changed file or a different parser/query-pack version marks older derived rows stale before writing current rows. Commit SHA and dirty-worktree state are stored as provenance on the current rows; a clean re-ingest with identical content, parser version, and query-pack version updates that provenance without reporting phantom stale rows.

Generated, vendor, build, and cache directories are skipped during directory traversal with trace warnings, as are files over code_intel.ast.max_file_bytes. Explicit file requests inside skipped directory names still parse when they pass path containment and resource limits. The AST tools only use built-in pinned grammar crates and never execute target-repo source, build scripts, package manager scripts, tests, or macros. See docs/code-intelligence.md for the operator and agent workflow.

opensymphony memory reindex --from-okf [bundle-root] rebuilds the derived DuckDB catalog from OKF concept documents, defaulting to the configured memory root. Broken links and unknown concept types are indexed as warnings; malformed OKF frontmatter remains fatal because those files are not parseable concepts. The OKF rebuild clears derived GitHub metadata tables (pull_requests, changed_files, checks, and reviews) because OKF concepts do not currently carry that capture-enrichment data.

Docs sync writes stable topic docs by default and prints stat-style output with file paths, line counts, and changed-line totals:

opensymphony memory sync-docs --since-last-sync
opensymphony memory sync-docs --issues COE-123

Candidate or low-confidence areas remain private until later captures raise their confidence. Automation records warnings in .opensymphony/memory/indexes so operators can inspect unresolved capture or docs-sync blockers. When the Linear project overview content is available, OpenSymphony also maintains a managed memory-status section there for capture warnings that need attention.

Archive Guard

Archival is guarded by memory capture. For explicit issues, opensymphony linear archive first performs live Linear and GitHub capture, then archives only eligible issues:

opensymphony linear archive --issues COE-123
opensymphony linear archive --issue-range COE-120..COE-130

An issue is eligible when fresh captured memory exists and has no unresolved capture warnings. --force bypasses the guard for a deliberate operator recovery. To archive from already captured memory without recapturing, use --from-memory.

When managed local OpenHands is configured, the archive command also moves matching conversations into the repo-scoped archived/ store. It first tries the issue workspace's .opensymphony/conversation.json manifest, then scans managed conversation meta.json files for a workspace.working_dir ending in the issue key so repo-scoped active conversations and legacy flat conversations are covered by the same archive operation.

Troubleshooting

  • If Linear fails, fix WORKFLOW.md, tracker credentials, or issue selection. Live capture does not fall back to placeholder records.
  • If GitHub discovery fails, install/authenticate gh or intentionally rerun with --no-github.
  • If docs sync writes no topic docs, inspect .opensymphony/memory/memory.yaml for candidate areas below the confidence threshold.
  • Use opensymphony memory capture --help, opensymphony memory import --help, and opensymphony linear archive --help for the current command surface.

Current model

  • COE-252 contributed: PR #10: Implement foundation workflow and scheduler contracts
  • COE-253 contributed: PR #19: COE-253: OpenHands Runtime Adapter (merge 911b0b4)
  • COE-254 contributed: PR #6: COE-254: bootstrap tracker, workspace, and orchestration core
  • COE-255 contributed: PR #4: COE-255: add control plane and FrankenTUI slice
  • COE-256 contributed: PR #1: COE-257: tighten hosted deployment guidance
  • COE-258 contributed: PR #83: Add memory init and mapped docs sync

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-252: Foundation and Contracts
  • COE-253: OpenHands Runtime Adapter
  • COE-254: Tracker, Workspaces, and Orchestration
  • COE-255: Observability and FrankenTUI
  • COE-256: Validation and Local Operations
  • COE-258: Bootstrap workspace and crate boundaries
  • COE-259: Workflow loader and typed config
  • COE-260: Domain model and orchestrator state machine
  • COE-261: Local agent-server supervisor
  • COE-262: REST client and conversation contract
  • COE-263: Workspace manager and lifecycle hooks
  • COE-264: Linear read adapter and issue normalization
  • COE-265: WebSocket event stream, reconciliation, and recovery
  • COE-266: Issue session runner
  • COE-267: Linear MCP write surface
  • COE-268: Orchestrator scheduler, retries, and reconciliation
  • COE-269: Control-plane API and snapshot store
  • COE-270: Repository harness and generated context artifacts
  • COE-271: FrankenTUI operator client
  • COE-272: Fake OpenHands server and protocol contract suite
  • COE-273: Live local end-to-end suite
  • COE-274: CLI packaging, doctor, and local operations docs
  • COE-277: Implement hierarchy-aware task selection
  • COE-280: Support workflow-owned OpenHands auth, provider, and launcher overrides at runtime
  • COE-281: Support path-bearing OpenHands base URLs and MCP config at runtime
  • COE-282: Support workflow-owned OpenHands conversation reuse policy at runtime
  • COE-284: Add orchestrator run command to CLI and make it installable
  • COE-287: Add opensymphony debug command for conversational session debugging
  • COE-294: Detect LLM config changes and rehydrate conversations with updated env vars
  • COE-382: Add supply-chain and security audits to CI
  • COE-383: Decompose oversized session and TUI modules into focused submodules
  • COE-384: Expand error-path tests for Linear client and workspace hooks
  • COE-385: Resolve runtime tracking TODO in OpenHands session runner
  • COE-386: Wire cargo-llvm-cov coverage reporting and regression floor into CI
  • COE-387: Audit tracing spans and diagnostics for secret leakage
  • COE-389: Current Gateway Inventory And Vocabulary
  • COE-390: Gateway Schemas And Stream Feasibility
  • COE-391: Gateway Module, Capabilities, And Dashboard Snapshot
  • COE-392: Task Graph, Run Detail, File, And Diff Read APIs
  • COE-393: Event Journal And Stream Broker
  • COE-394: Frontend Workspace And Shared Schemas
  • COE-395: Planning Artifact Schema And Session Service
  • COE-396: Action Receipts And Initial Run Actions
  • COE-397: Gateway API Client, Transport Adapters, And Reducers
  • COE-398: Tauri Shell And Security Capabilities
  • COE-399: Linear Read Coverage And Task Graph Cache
  • COE-400: OpenHands Event Normalization And Runtime Mirror
  • COE-401: Web App Entry And Deployment Modes
  • COE-402: App Shell, Dashboard, Task Graph, And Run Views
  • COE-403: Terminal And Log Renderer Prototype
  • COE-404: Desktop Connection Profiles And Daemon Management
  • COE-405: Linear Milestone, Issue, And Sub-Issue Mutations
  • COE-406: Repository, Linear, And Research Analysis
  • COE-407: Browser Transport And Remote Stream Protocols
  • COE-408: Harness Adapter And Capability Model
  • COE-409: Desktop Settings, Keychain, And Native Actions
  • COE-410: Desktop Local Stream Optimization
  • COE-411: Task Graph Editor And Runtime Overlay UI
  • COE-412: Runtime Timeline And Terminal/Log Association
  • COE-413: Implementation Plan Generator Stage
  • COE-414: Diff, Validation, Approval, And Run Action Views
  • COE-415: Milestone, Issue, And Sub-Issue Compiler
  • COE-416: Dependency Graph And Plan Checks
  • COE-417: Planning Workspace UI
  • COE-419: Hosted Auth Placeholders And Web Parity
  • COE-423: Model And Credential Settings
  • COE-425: OpenHands Subscription Credential Adapter
  • COE-426: Codex App-Server Prototype And Benchmarks
  • COE-428: Model Configuration UI And Routing Metadata
  • COE-429: Codex Approvals And Cross-Harness Routing
  • COE-434: Long-running harness liveness and scheduler/runtime ownership contract
  • COE-435: Long-running run observability fixtures and client-facing diagnostics
  • COE-448: Multi-repo memory server and deterministic context
  • COE-449: Desktop alpha recovery: replace stubs with functional app
  • COE-452: DuckDB Prebuilt Developer Build Mode
  • COE-453: Non-Interactive Init For Automation
  • COE-454: OKF Bundle Schema And Legacy Capsule Mapping
  • COE-456: OKF Writer, Lint, And Migration Fixtures
  • COE-458: Catalog Reindex And Query Compatibility From OKF
  • COE-460: OKF Export, Import, And Visibility Boundaries
  • COE-461: Memory Graph DTOs And Gateway Endpoints
  • COE-463: Docs Sync And MCP Admin Parity For OKF
  • COE-464: Graph Extraction, Metrics, And Community Pipeline
  • COE-465: Shared Graph Frontend Package And Reducers
  • COE-467: Three.js Graph Renderer And Worker Layouts
  • COE-468: Concept Inspector, Search, Filters, And Accessibility Fallback
  • COE-469: Live Memory Graph Integration And Privacy Gates
  • COE-471: Graph Scale, Visual Regression, And Web/Desktop Hardening
  • COE-473: Desktop task graph dependency and run detail parity
  • COE-475: ChatGPT OAuth For Codex Harness
  • COE-476: Codex Production Harness Enablement
  • COE-478: Harden model profile storage and validation follow-ups
  • COE-479: Codex Debug Session Resume
  • COE-480: Run Detail Metrics And Density
  • COE-481: Model Configuration Codex Subscription Follow-Up
  • COE-482: TUI Codex Token Usage Accounting
  • COE-483: Codex Event Content Summaries
  • COE-484: Desktop Live Snapshot And Run Detail Refresh
  • COE-485: Harden desktop live event resumption and refresh failure visibility
  • COE-486: Harness Interrupt Contract And Run Diagnostics
  • COE-487: Desktop Run Detail TUI Parity
  • COE-488: Lazy Desktop Launcher Command
  • COE-489: OpenHands Agent-Server Interrupt Adapter
  • COE-490: Codex App-Server Turn Interrupt Adapter
  • COE-491: Desktop Run Detail Action Wiring And Cleanup
  • COE-492: Merging Supersedes Human Review Polling
  • COE-493: Desktop Operations Integration Hardening
  • COE-494: Project Metadata For Operator Issue Snapshots
  • COE-495: FrankenTUI Project Headers And Dependency Gutter
  • COE-496: Desktop Project Grouping And Collapse
  • COE-497: Project Grouping Integration Hardening
  • COE-498: Tree-sitter Provider Skeleton And Rust Parsing
  • COE-499: Memory Context AST Provider Integration
  • COE-500: Query Packs For Supported Agent Languages
  • COE-501: Code Intelligence Persistence And Ingestion
  • COE-502: Read-Only AST MCP And CLI Tools
  • COE-503: Code Intelligence Performance Docs And Hardening
  • COE-504: Linear Polling And Rate-Limit Recovery
  • COE-505: Add scheduler-side Codex stdio interrupt channel
  • COE-506: Invert CodeIntelIndex trait ownership after AST memory integration
  • COE-507: Deduplicate query-pack assets for grammar variants
  • COE-508: Cache code-intel parsers and compiled query packs
  • COE-520: Route desktop Knowledge Graph through native gateway commands
  • COE-521: Workflow Target Branch Model And Init Customization
  • COE-522: Init Target Branch Prompt And Flag
  • COE-523: Update Workflow Settings Mode
  • COE-524: Template Docs And Settings Hardening
  • COE-525: Desktop Installer Contract And Release Metadata
  • COE-526: Desktop Release Bundle Pipeline
  • COE-527: Source Build Fallback And Prerequisites
  • COE-528: App Download Install And Launch Flow
  • COE-529: Desktop Auto-Update Flow
  • COE-530: Installer Docs And End-To-End Validation
  • COE-531: Workspace Shell Graph Hero And Surface State
  • COE-532: Symbol Identity Container Chain And Code Read Model
  • COE-533: Code Graph DTOs Gateway Routes And Native Commands
  • COE-534: Code Graph Frontend Surface Adapters And Inspector
  • COE-535: Run Diff Symbol Navigation And Code Overlay
  • COE-536: Cross Graph Code Memory And Work Chips
  • COE-537: Code Graph Scale Accessibility And Parity Hardening
  • COE-540: Canonical Codex Thread Reuse And Workspace Retention
  • COE-541: Durable Codex Thread Archive And Debug Recovery
  • COE-542: Target Branch Code Index And Revision Snapshots
  • COE-543: Workspace Code Overlay And Composite Graph
  • COE-544: Indexed Agent Code Context And Retrieval
  • COE-545: Edge Delta And Module Topology Diff
  • COE-546: Code Graph Bootstrap UX And End-To-End Validation
  • COE-547: Central Multi-Repository Config And Safe Migration
  • COE-548: Canonical Repository Binding And Task Propagation
  • COE-549: Verified Checkouts Instructions And Harness Envelopes
  • COE-550: Per-Instance Memory Catalog And Source Migration
  • COE-551: Scoped Cross-Repository Memory And Leaf Overlays
  • COE-553: Parent Execution Roots And Child Workspace Reuse
  • COE-554: Restart-Safe Parent Integration Controller
  • COE-555: Parent Repair Review And Merge Lifecycle
  • COE-556: Bottom-Up Subtree Cleanup And Recovery
  • COE-562: Implement artifact validation and digest primitives
  • COE-563: Implement task-packet admission and freeze tooling
  • COE-564: Implement verifier execution and outcome records
  • COE-565: Implement isolated workspace materialization
  • COE-566: Implement configurable run matrices and scheduling
  • COE-567: Implement run lifecycle and process-protocol primitives
  • COE-608: ACP Profiles And Executable Protocol Client
  • COE-609: ACP Session Ownership And Durable Recovery
  • COE-610: ACP Client Callbacks And Session Configuration
  • COE-611: ACP Execution Routing And Worker Integration
  • COE-612: ACP Operator Requests And Response Routing
  • COE-613: ACP Extensions And Harness Operations
  • COE-615: ACP Runtime Conformance And Live Qualification

Source refs

  • COE-252
  • COE-253
  • COE-254
  • COE-255
  • COE-256
  • COE-258
  • COE-259
  • COE-260
  • COE-261
  • COE-262
  • COE-263
  • COE-264
  • COE-265
  • COE-266
  • COE-267
  • COE-268
  • COE-269
  • COE-270
  • COE-271
  • COE-272
  • COE-273
  • COE-274
  • COE-277
  • COE-280
  • COE-281
  • COE-282
  • COE-284
  • COE-287
  • COE-294
  • COE-382
  • COE-383
  • COE-384
  • COE-385
  • COE-386
  • COE-387
  • COE-389
  • COE-390
  • COE-391
  • COE-392
  • COE-393
  • COE-394
  • COE-395
  • COE-396
  • COE-397
  • COE-398
  • COE-399
  • COE-400
  • COE-401
  • COE-402
  • COE-403
  • COE-404
  • COE-405
  • COE-406
  • COE-407
  • COE-408
  • COE-409
  • COE-410
  • COE-411
  • COE-412
  • COE-413
  • COE-414
  • COE-415
  • COE-416
  • COE-417
  • COE-419
  • COE-423
  • COE-425
  • COE-426
  • COE-428
  • COE-429
  • COE-434
  • COE-435
  • COE-448
  • COE-449
  • COE-452
  • COE-453
  • COE-454
  • COE-456
  • COE-458
  • COE-460
  • COE-461
  • COE-463
  • COE-464
  • COE-465
  • COE-467
  • COE-468
  • COE-469
  • COE-471
  • COE-473
  • COE-475
  • COE-476
  • COE-478
  • COE-479
  • COE-480
  • COE-481
  • COE-482
  • COE-483
  • COE-484
  • COE-485
  • COE-486
  • COE-487
  • COE-488
  • COE-489
  • COE-490
  • COE-491
  • COE-492
  • COE-493
  • COE-494
  • COE-495
  • COE-496
  • COE-497
  • COE-498
  • COE-499
  • COE-500
  • COE-501
  • COE-502
  • COE-503
  • COE-504
  • COE-505
  • COE-506
  • COE-507
  • COE-508
  • COE-520
  • COE-521
  • COE-522
  • COE-523
  • COE-524
  • COE-525
  • COE-526
  • COE-527
  • COE-528
  • COE-529
  • COE-530
  • COE-531
  • COE-532
  • COE-533
  • COE-534
  • COE-535
  • COE-536
  • COE-537
  • COE-540
  • COE-541
  • COE-542
  • COE-543
  • COE-544
  • COE-545
  • COE-546
  • COE-547
  • COE-548
  • COE-549
  • COE-550
  • COE-551
  • COE-553
  • COE-554
  • COE-555
  • COE-556
  • COE-562
  • COE-563
  • COE-564
  • COE-565
  • COE-566
  • COE-567
  • COE-608
  • COE-609
  • COE-610
  • COE-611
  • COE-612
  • COE-613
  • COE-615