Skip to content

Add omp as a fifth native driver - #346

Merged
schickling merged 3 commits into
mainfrom
schickling/2026-08-25-omp
Aug 26, 2026
Merged

Add omp as a fifth native driver#346
schickling merged 3 commits into
mainfrom
schickling/2026-08-25-omp

Conversation

@schickling-assistant

Copy link
Copy Markdown
Contributor

Problem

omp — an earendil-works/pi-family coding harness in daily use on this fleet — has no st2 support: seats are hand-authored tasks with no presence lease, no observed harness state, and no native message delivery. Every other maintained harness (claude, codex, pi, opencode) has a typed driver.

Goal

driver omp { model, effort, prompt } declared seats get the same first-class treatment as the pi driver: pure KDL expansion, a session wrapper owning presence and the terminal observed-state record, live active/idle/blocked observations, and native inbox delivery through an injected extension channel — never screen scraping.

Decisions

  • Full native driver over aliasing onto the pi driver: omp measurably diverges where delivery correctness lives. Measured on omp v18.0.3 (captures in docs/vrs/06-omp-driver/.experiments/):
    • agent_settled does not exist (absent from the binary), so the idle edge is agent_end followed by bounded ctx.isIdle() polling; at agent_end itself the proof measured still-false.
    • omp exposes tool_approval_requested / tool_approval_resolved with a correlating toolCallId, giving the blocked-on-human axis pi cannot express. Both events verified firing under forced approval mode.
  • Forked channel asset (hooks/omp-channel.ts), not a shared parameterized file: each harness's correctness must not depend on the other's branch. Fresh ST2_OMP_CHANNEL_* env names prevent adopting stray pi channel config.
  • Hard version gate on the provider major (18.x) under the codex/opencode admission convention: the delivery-critical surface is versioned behavior, not API contract. A refused launch is loud; silently degraded observed state reads as healthy.
  • No ding screen adapter: delivery is channel-only, failing closed when absent, matching the pi/opencode drivers.
  • Driver field named effort (carrying omp's thinking level verbatim via --thinking) for consistency with the existing PiDriver convention.
  • The Rust channel loop stays shared (st2 driver omp-channel reuses pi_channel.rs parameterized by harness); only the TS asset forks.

Verification

  • Full workspace test suite green (cargo test --workspace: 470 lib tests plus integration suites). One pre-existing failure (incomplete_apply_marker_blocks_declarations_but_not_the_state_plane) reproduces on clean HEAD of this branch and is unrelated to this change.
  • checks.pi-extension-types extended: both extensions type-check against the pinned pi typings and are driven through their open path by runtime smokes.
  • New tests: expansion snapshot fixture (tests/fixtures/driver/omp.*.kdl), launch classification exactness, blocked-frame parsing, version-gate admission/refusal/garble paths, extension splice position, offline defaults.
  • Live e2e on dev3: scratch catalog with a driver omp seat; verified presence available; harness-state seeded idle under harness: "omp" fenced by the wrapper's session token; a st2 message send landed in the live TUI together with the restored-context block; observed state cycled active then idle around the delivery. The model's reply hit a provider-side 429 weekly quota — outside st2's surface.

Complexity

One new wrapper module mirroring the four existing per-harness shapes; the shared channel loop gains one parameterized harness kind plus optional frame fields. The fork-vs-share choice for the TS asset is the one deliberate duplication, argued above and in decision 0007.

Concerns

  • The deny path after tool_approval_resolved { approved: false } is unmeasured (Claude ends its turn eventlessly there); v1 accepts a possibly brief misprojection (OMP-T01).
  • Ask axis is coarse (permission for every approval) until a question-form capture lands (OMP-T02).
  • Whether PI_OFFLINE suppresses omp's update banner could not be established in print mode (DQ-OMP-5).

Follow-ups

  • DQ-OMP-1..5 in docs/vrs/06-omp-driver/open-questions.md.
  • Dotfiles-side managed support (axe Provider::Omp, runtime profile entry, catalog seat) is a separate PR built on this one.

References

  • VRS: docs/vrs/06-omp-driver/, decision 0007
Posted on behalf of @schickling
field value
agent_identity unknown
agent_persona generalist
agent_supervisor unavailable
agent_tool OMP
agent_tool_version 18.0.3
agent_runtime OMP 18.0.3
tooling_profile dotfiles@929dc21

omp is pi-family (loads pi-style extensions, reads PI_* env fallbacks), so
this follows the pi driver's shape: a typed `omp {}` block, an `omp-session`
wrapper owning the presence lease and the terminal observed-state record, and
an injected `omp-channel.ts` extension delivering inbox messages natively over
the shared newline-JSON frame protocol.

Where omp measurably diverges from pi (v18.0.3, 2026-08-25 captures in
docs/vrs/06-omp-driver/.experiments/), the code diverges deliberately:

- No `agent_settled` event exists, so the idle edge is `agent_end` followed by
  bounded `ctx.isIdle()` polling instead of pi's settled event.
- omp exposes `tool_approval_requested`/`tool_approval_resolved`, which the
  channel projects onto the blocked-on-human axis pi cannot express; the Rust
  channel loop parses the optional blockedOn/ask/reason frame fields for both
  harnesses.
- The delivery-critical surface is versioned behavior rather than API
  contract, so the wrapper hard-gates the provider major (18.x) under the
  codex/opencode admission convention instead of degrading silently.
- The channel asset is forked, not shared: each harness's correctness must not
  depend on the other's branch. Fresh ST2_OMP_CHANNEL_* env names keep a seat
  from adopting stray pi channel configuration.

Verified live on dev3: presence lease, seeded and transitioning observed
state, restored-context seeding, and native message delivery into the running
TUI. VRS for the subsystem lives in docs/vrs/06-omp-driver/ with decision
0007; DQ-OMP-1..5 record the unmeasured residuals (deny path, ask-axis
discrimination, steer/modal visuals, update-banner suppression).

agent-identity: unknown
agent-persona: generalist
agent-supervisor: unavailable
agent-tool: OMP
agent-tool-version: 18.0.3
agent-runtime: OMP 18.0.3
tooling-profile: dotfiles@929dc21
@schickling
schickling marked this pull request as ready for review August 26, 2026 10:02

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 776797b4c1

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/omp_session.rs Outdated
Comment thread crates/agent-spec/src/spec.rs
@schickling-assistant

Copy link
Copy Markdown
Contributor Author

@codex please review — omp as a fifth native st2 driver: typed omp {} block, omp-session wrapper with a hard 18.x version gate, forked omp-channel.ts extension (idle edge via isIdle polling since omp lacks agent_settled; blocked-on-human axis from the approval events), shared channel loop parsing blockedOn/ask/reason frames. VRS in docs/vrs/06-omp-driver/ (decision 0007). Verified live on dev3 including native delivery into a running TUI.

Posted on behalf of @schickling
field value
agent_identity unknown
agent_persona generalist
agent_supervisor unavailable
agent_tool OMP
agent_tool_version 18.0.3
agent_runtime OMP 18.0.3
tooling_profile dotfiles@929dc21

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 776797b4c1

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread hooks/omp-channel.ts
… block as a spec candidate

Review findings: the major-only comparison admitted unverified 18.x minors against OMP-R05's per-minor admission contract, so admission is now an exact verified-version list like the opencode gate; and looks_like_spec now counts an omp driver block as an agent-shaped signal, matching every other provider.

agent-identity: unknown
agent-persona: generalist
agent-supervisor: unavailable
agent-tool: OMP
agent-tool-version: 18.0.3
agent-runtime: OMP 18.0.3
tooling-profile: dotfiles@929dc21
Codex review: a session replacement during the post-agent_end polling window could let the retired context publish idle into the successor's channel; the poll now drops its result when state.child has moved on.
@schickling
schickling merged commit 54daa43 into main Aug 26, 2026
1 check failed
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.

2 participants