Skip to content

feat: report omp (oh-my-pi) sessions to lich - #18

Merged
omartelo merged 2 commits into
mainfrom
feat/omp-provider
Aug 13, 2026
Merged

omartelo merged 2 commits into
mainfrom
feat/omp-provider

Conversation

@omartelo

Copy link
Copy Markdown
Collaborator

Adds a fifth harness. omp is the second one that loads a module instead of running commands: --hook and --extension are the same list, and it import()s every entry — even the files it calls hooks are modules, never scripts fed a payload on stdin. So omp/lich.js is the whole client, mirroring opencode/lich.js down to the transport and the fire-and-forget rule.

Mapping

Measured against omp v17.3.0 (@oh-my-pi/pi-coding-agent), driving a real omp --hook … -p … run at a stub listener — not read off its documentation. The version is pinned in a comment in both the client and its suite, because 17.x moves fast.

Report omp event
session id session_start, id off ctx.sessionManager.getSessionId()
busy input, and turn_start for the turns no input precedes
busy + tool tool_call
touched tool_result for write / edit / bash / notebook
done + title session_stop (title also re-read on turn_start)

omp exports nothing about the running session to its own process env, so the context is the only source for the id and the title.

Deliberately absent

  • waiting. omp raises tool_approval_requested, but that was never observed on a real run here, and a name taken off a type declaration is a report that silently never fires. An omp card shows a spinner, not a bell, while the agent waits on you.
  • idle. The process that would send it is the one exiting — same as opencode.

The gate is in the module

omp discovers ~/.omp, ~/.claude, ~/.codex and ~/.gemini configuration wholesale, and there is no per-harness registration to key on: a global install is loaded by every omp run on the machine. With no lich environment the factory subscribes to nothing at all, which the suite asserts.

Needs from lich

omp is not a registered provider id upstream yet — tests/fixtures/session-start.jsonl carries claude, codex, opencode and crush. The client sends "provider": "omp" because it is the only correct value; until lich registers it, that one report is rejected and the other three land. The fixture is upstream truth and is not edited here: the session-start assertion runs every contract rule except the one that case trips, and returns to the shared assertion on its own the day refresh-fixtures.sh brings the case down.

Install (for internal/agentplugin)

Either drop the file in ~/.omp/agent/extensions/lich.js (omp scans that directory unprompted), or name any path in extensions: in ~/.omp/agent/config.yml. Both measured. There is no manifest or marketplace entry of omp's own.

Tests

tests/omp.test.mjs — 30 cases against the same tests/contract.mjs fixtures every other client answers to. Gate: node --test tests/*.test.mjs → 157 pass, 0 fail. tests/refresh-fixtures.sh + git diff --exit-code -- tests/fixtures → no drift.

omp is the fifth harness and the second that loads a module instead of
running commands: `--hook` and `--extension` are one list it `import()`s,
so even the files it calls hooks are modules, never scripts fed a payload
on stdin. `omp/lich.js` is the whole client, mirroring opencode/lich.js.

The mapping, measured against omp v17.3.0 driving a real run at a stub
listener:

- session id from `ctx.sessionManager.getSessionId()` at `session_start`
  (omp exports nothing about the session to its process env)
- `busy` on `input`, and on `turn_start` for the turns no input precedes
- the tool line on `tool_call`
- the git-status refresh on a `tool_result` from write/edit/bash/notebook
- `done` plus the generated title when a turn settles

`waiting` and `idle` are deliberately unreported: omp's approval event was
never observed on a real run, and a name taken off a type declaration is a
report that silently never fires; the process that would send `idle` is
the one exiting.

The outside-lich gate is in the module, not in a registration: omp
discovers `~/.claude` and `~/.omp` wholesale, so a global install loads on
every omp run on the machine.

Needs `omp` registered as a provider id in lich; until then the
session-start report is rejected and the other three land. The suite
asserts that payload against every contract rule except the one the
missing fixture case trips, and goes back to the shared assertion on its
own the day the case lands upstream.
@omartelo
omartelo merged commit cf7e78a into main Aug 13, 2026
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant