Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,15 +20,15 @@ OMMS (npm `om-memory-system`) is a memory plugin for AI coding agents. One share
| `src/services/` | Storage (Turso/libSQL), embeddings, privacy, deduplication, project tags, profiles, web backend |
| `src/services/ai/live-model-choice.ts` | The live-model rule for both hosts. Pure functions; callers pass `CONFIG`. |
| `src/importer/` | History import: shared option parser (`import-args.ts`), runner (`run-import.ts`), ledger, readers |
| `src/adapters/opencode/`, `src/index.ts` | OpenCode V1 plugin hooks and the OpenCode import command |
| `src/adapters/opencode/`, `src/index.ts` | OpenCode V1 plugin hooks, OpenCode model code, profile learning, and the OpenCode import command |
| `src/v2/` | OpenCode V2 plugin adapter over the V1 plugin |
| `src/adapters/pi/` | Pi extension, Pi model bridge, Pi import command |
| `src/cli/` | `om-memory-system` terminal command for both hosts |
| `web/` | Web UI (Vite). It has its own `package.json`. |

Keep these boundaries:

- `src/core/` and `src/services/` must not import `@opencode-ai/*`, `@earendil-works/*`, or `src/adapters/*`.
- `src/core/` and `src/services/` must not import `@opencode-ai/*`, `@earendil-works/*`, or `src/adapters/*`. Hosts register their models through `registerHostProfileModel` and `registerOpencodeHostModels`.
- `src/importer/` must not import `src/adapters/*`. Each host's history reader lives in `src/importer/`, and adapters import from it.
- `tests/host-neutral-capture-boundary.test.ts` and `tests/pi-adapter-boundary.test.ts` enforce that rule.
- An adapter must not import the other host's adapter modules.
Expand Down
2 changes: 1 addition & 1 deletion docs/adr/006-one-live-model-rule-for-both-hosts.md
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ OpenCode call sites use `resolveOpencodeHostModel(CONFIG)`: capture, profile lea

- `src/services/ai/live-model-choice.ts`, `src/config.ts`
- `src/adapters/pi/live-model.ts`, `src/adapters/pi/extension.ts`, `src/adapters/pi/profile.ts`
- `src/adapters/opencode/auto-capture-summary.ts`, `src/services/user-memory-learning.ts`
- `src/adapters/opencode/auto-capture-summary.ts`, `src/adapters/opencode/profile-learning.ts`
- `src/services/user-profile/user-profile-manager.ts`, `src/services/user-profile/ai-cleanup.ts`
- `tests/live-model-choice.test.ts`
- README "Auto-Capture AI Provider", `docs/pi-adapter.md`
Expand Down
4 changes: 3 additions & 1 deletion docs/adr/011-shared-code-never-imports-adapters.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,9 @@ Adding a host means adding `src/adapters/<host>/` and, when it has importable hi

### Neutral

- `src/services/` still holds OpenCode's own model code (`opencode-provider.ts`, `opencode-sdk-client.ts`, `profile-llm-client.ts`, `user-memory-learning.ts`), which uses OpenCode SDK types. Moving it into the OpenCode adapter is planned as the OpenSpec change `move-opencode-model-code-to-adapter`.
- The OpenSpec change `move-opencode-model-code-to-adapter` moved OpenCode's own model code from `src/services/` into `src/adapters/opencode/`. Shared code now reaches OpenCode models through registrations: `registerHostProfileModel` for profile calls and `registerOpencodeHostModels` for web imports, Health, and Settings. The standalone web app registers neither, so it reports OpenCode models as unavailable, as before.
- Follow-up: OpenCode and Pi still run separate profile learning loops (`src/adapters/opencode/profile-learning.ts` and the Pi adapter). One shared loop is future work.
- Follow-up: the OpenCode V2 plugin (`src/v2/`) still wraps the V1 plugin (`src/index.ts`) through a fake V1 client (`legacy-client.ts`). Rebuild it on the native V2 API and drop V1 support in a separate breaking change (4.0.0).

## Alternatives considered

Expand Down
22 changes: 11 additions & 11 deletions docs/opencode-adapter.md
Original file line number Diff line number Diff line change
Expand Up @@ -89,17 +89,17 @@ History backfill (automatic history import) uses `opencodeBackfillModel`. See

## Lifecycle mapping

| OpenCode hook | omms behaviour |
| -------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Plugin start | Load shared config for the project directory, remove old capture traces, update the web login item when `webServerAutoStart` is set, warm storage and embeddings, read connected providers, register the OpenCode backfill model resolver, start automatic backfill when `autoBackfill` is on, start the web UI |
| `config` | Register the `omms-structured` agent and the `/memory-import-opencode-history` command |
| `chat.message` (V1) | Record the user prompt for capture and profile learning; inject recent project memories (`chatMessage.injectOn`: first or every prompt) |
| `prompt` + `context` (V2) | Record the prompt once OpenCode admits it; semantic retrieval injected as a delimited `<omms-retrieval>` system section |
| `chat.params` | Record the prompt's model when capture follows the session model |
| `session.idle` | After 10 seconds of quiet, capture every uncaptured prompt in the session; the web-UI owner also runs profile learning and cleanup |
| `session.compacted` (V1) / `compaction` (V2) | Restore the session's own memories after compaction |
| `command.execute.before` (V1) / command (V2) | Run `/memory-import-opencode-history`; see [opencode-history-import.md](opencode-history-import.md) |
| `memory` tool | Shared add/search/profile/list/forget/help plus migrate/list-shards/export/import |
| OpenCode hook | omms behaviour |
| -------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Plugin start | Load shared config for the project directory, remove old capture traces, update the web login item when `webServerAutoStart` is set, warm storage and embeddings, read connected providers, register the OpenCode backfill model resolver, the profile model, and the import models, start automatic backfill when `autoBackfill` is on, start the web UI |
| `config` | Register the `omms-structured` agent and the `/memory-import-opencode-history` command |
| `chat.message` (V1) | Record the user prompt for capture and profile learning; inject recent project memories (`chatMessage.injectOn`: first or every prompt) |
| `prompt` + `context` (V2) | Record the prompt once OpenCode admits it; semantic retrieval injected as a delimited `<omms-retrieval>` system section |
| `chat.params` | Record the prompt's model when capture follows the session model |
| `session.idle` | After 10 seconds of quiet, capture every uncaptured prompt in the session; the web-UI owner also runs profile learning and cleanup |
| `session.compacted` (V1) / `compaction` (V2) | Restore the session's own memories after compaction |
| `command.execute.before` (V1) / command (V2) | Run `/memory-import-opencode-history`; see [opencode-history-import.md](opencode-history-import.md) |
| `memory` tool | Shared add/search/profile/list/forget/help plus migrate/list-shards/export/import |

### Toasts

Expand Down
25 changes: 20 additions & 5 deletions docs/shared-core.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,9 @@ Rules:
- `src/core/*`, `src/services/*`, and `src/types/*` must not import
`src/importer/*`. The one exception is `src/services/web-server.ts`. It
reaches the importer only through dynamic imports of
`src/importer/web-import-api.ts`, `src/importer/settings-health.ts`, and
`src/importer/web-import-jobs.ts`. `tests/pi-adapter-boundary.test.ts`
enforces this.
`src/importer/web-import-api.ts`, `src/importer/settings-health.ts`,
`src/importer/web-import-jobs.ts`, and `src/importer/settings-models.ts`.
`tests/pi-adapter-boundary.test.ts` enforces this.
- The OpenCode entry points (`src/index.ts`, `src/v2/adapter.ts`,
`src/v2/plugin.ts`) must not import `importer/` or `@earendil-works`
directly. They load importer code through `src/adapters/opencode/*`.
Expand All @@ -50,6 +50,13 @@ Rules:
depend on shared code; shared code never depends on an adapter.
- `session-loader.ts` loads the Pi SDK. The importer loads it with dynamic
`import()`, only when it reads Pi history.
- Only three importer files name a host SDK: `session-loader.ts`,
`import-readiness.ts`, and `settings-models.ts`. Only `session-loader.ts`
imports it statically. The boundary test checks every file.
- OpenCode's model access for web imports, Health, and Settings reaches the
importer through `registerOpencodeHostModels` in `backfill-controls.ts`.
The OpenCode adapter registers it at plugin start. With nothing registered,
as in the standalone web app, OpenCode models report as unavailable.
- `src/core/internal-prompt.ts` recognises omms's own summary and profile
prompts, which are the same text on both hosts.

Expand All @@ -58,14 +65,22 @@ Rules:
The shared capture pipeline depends on two interfaces only:

- `CaptureSummaryProvider.summarize(request)` does structured extraction.
- The OpenCode provider path (`src/services/ai/*`) and the Pi model bridge (`src/adapters/pi/provider.ts`) both implement it.
- The OpenCode provider path (`src/adapters/opencode/opencode-provider.ts`) and the Pi model bridge (`src/adapters/pi/provider.ts`) both implement it.
- Throw to defer or skip the work unit. Do not return partial data. Manual memory operations stay available.
- `AutoCaptureHost` extends `CaptureSummaryProvider`. It adds session
conversation access (`getConversation`), readiness (`isCaptureReady`), and
optional notifications (`notify`).
- The OpenCode adapter implements it.
- The Pi adapter calls `captureConversation` directly from `agent_settled`.

`ModelPort` in `src/core/profile-analysis.ts` is the profile model port.
It has `complete` for plain text and an optional `completeStructured` for
host-enforced JSON. Profile dedup, conflict, description, and cleanup calls in
`src/services/user-profile/` use the model a host registers with
`registerHostProfileModel` (`profile-model.ts`). With none, they use the
external API. OpenCode registers `adaptOpencodeProfileModel`. Pi registers
nothing, so its behaviour does not change.

`CaptureWorkUnit` in `src/core/capture.ts` is the only shape the shared
pipeline accepts. It holds visible conversation content and provenance.
Hidden reasoning and host SDK objects never go into it.
Expand All @@ -77,7 +92,7 @@ Hidden reasoning and host SDK objects never go into it.
| `src/core` | Ports, capture pipeline, context budgeting, shared extraction schema and parsing, retrieval, `memory` tool operations |
| `src/services` | Storage (Turso/libSQL), embeddings, vector search, privacy, deduplication, project identity, profiles, portability, cleanup, web backend, live-model rule (`ai/live-model-choice.ts`) |
| `src/importer` | History import and automatic backfill, import ledger, import runs and progress, backfill controls, path maps, the web import API |
| `src/adapters/opencode` + `src/index.ts` + `src/v2` | OpenCode lifecycle, session reading, provider bridge, OpenCode backfill model resolver, V2 compatibility |
| `src/adapters/opencode` + `src/index.ts` + `src/v2` | OpenCode lifecycle, session reading, provider bridge, OpenCode model code and profile learning, OpenCode backfill model resolver, V2 compatibility |
| `src/adapters/pi` | Pi lifecycle (`session_start`, `before_agent_start`, `agent_settled`, `session_shutdown`), retrieval injection, model bridge, Pi backfill model resolver, `memory` tool registration |

### Shared modules added for import and settings
Expand Down
6 changes: 3 additions & 3 deletions docs/tdr/004-exclude-omms-internal-sessions-from-import.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ Their prompts are OMMS's own summarisation requests, so importing them would sto

## Decision

`INTERNAL_CAPTURE_SESSION_TITLES` in `src/services/ai/internal-capture-sessions.ts` lists every title OMMS has used. When the `session` table has a `title` column, the reader adds `AND (s.title IS NULL OR s.title NOT IN (...))` to the session query and to both session counts. Any new internal title must be added to that list.
`INTERNAL_CAPTURE_SESSION_TITLES` in `src/importer/opencode-internal-sessions.ts` lists every title OMMS has used. When the `session` table has a `title` column, the reader adds `AND (s.title IS NULL OR s.title NOT IN (...))` to the session query and to both session counts. Any new internal title must be added to that list.

## Consequences

Expand All @@ -49,7 +49,7 @@ Their prompts are OMMS's own summarisation requests, so importing them would sto
## How to Recognise / Handle This Again

1. Symptom: imported memories or profile prompts describe summarising conversations or `save_memory` calls.
2. Check with the query above, or look for a new title in `internal-capture-sessions.ts`.
2. Check with the query above, or look for a new title in `opencode-internal-sessions.ts`.
3. Add the title to `INTERNAL_CAPTURE_SESSION_TITLES` and rerun; the "never imports omms's own internal capture sessions" test covers the filter.

## Revisit Triggers
Expand All @@ -59,6 +59,6 @@ OMMS changes its internal session title, or OpenCode stores a reliable internal
## References

- `src/importer/opencode-reader.ts`
- `src/services/ai/internal-capture-sessions.ts`
- `src/importer/opencode-internal-sessions.ts`
- `tests/history-import-commands.test.ts`
- ADR-005
Loading
Loading