Skip to content

feat(omp): integrate Oh My Pi provider on current main - #11973

Closed
nullStack65 wants to merge 27 commits into
pingdotgg:mainfrom
nullStack65:feat/omp-main-integration-20260915
Closed

nullStack65 wants to merge 27 commits into
pingdotgg:mainfrom
nullStack65:feat/omp-main-integration-20260915

Conversation

@nullStack65

@nullStack65 nullStack65 commented Sep 15, 2026

Copy link
Copy Markdown

feat(omp): integrate Oh My Pi provider on current main

Status note (2026-09-16): upstream closed the source feature #11791 as outside current scope, pointing to shared ACP support arriving through Orchestrator V2. This branch is therefore kept as a reconciled, fork-held candidate — it now contains current main, stays draft, and is not proposed for merge while first-class provider support is out of scope. Everything below describes the current reconciled state.

Candidate head: 4f9419b72bb92bebc6669dd95f345e1ccdf4bced (draft; mergeable=MERGEABLE)

What this is

Oh My Pi (omp) as a first-class provider, driven through its ACP server (omp acp). The implementation is the 18-commit #11791 chain (14ed34f4e2… tip into 5766179db root), integrated and refreshed on top of current main.

  • Skills and commands. $ lists omp's skills and / lists its commands (machine catalog plus live available_commands_update), including plugin and project commands.
  • Models. The picker is omp's own catalog, grouped by upstream provider, with per-model thinking ladders and context metadata.
  • Context and compaction. usage_update feeds the context meter with omp's own window size; Compact runs /compact.
  • Usage and auth. Provider card reads omp usage --json and shows the authenticated accounts.
  • Session import / resume. Onboarding scan reads omp transcripts; threads resume in place through session/load.
  • /rename. omp's session title becomes the thread title, explicitly overriding client-generated titles; manual T3 titles stay authoritative (expected-title/version guard in the decider).
  • /fresh. omp swaps its provider session id on the same connection; the runtime adopts the new id instead of going silent.
  • Argument autocomplete. Commands advertise hints like [soft|remote|snapcompact]; the composer offers those choices.

Current-main reconciliation

main advanced from 87a12b53f (the candidate's original base) through 57 upstream commits to 71d12d8c4, including heavy changes to shared OMP integration surfaces. Two merges bring current main in:

  • 76a24510e — merge of 901db8966 (54 commits): ProviderRuntimeIngestion rewrite, decider changes, web composer/command palette work, mobile architecture.
  • 4f9419b72 — merge of 71d12d8c4 (3 commits): rich-text composer default (Lexical → Tiptap), keybindings search, PR avatar fallback.

Semantic resolutions (current main owns the architecture; OMP behavior re-expressed on current APIs):

  • AcpSessionRuntime.ts: kept OMP agent-session-id adoption (/fresh) alongside main's new assistantUpdatesOpenRef assistant-chunk gate — both conditions coexist.
  • ProviderRuntimeIngestion.ts: OMP explicit-rename (nameIsExplicit) condition preserved inside main's rewritten pipeline, together with main's expectedTitle/expectedVersion concurrency guard — no stale/replayed rename inversion.
  • ComposerPromptEditor.tsx: main's Tiptap replacement taken wholesale; the OMP skill:// guard (isOpenableSkillPath, no "View instructions" for internal skill URLs) was re-expressed in ComposerPromptEditorTiptap.tsx, with its unit test restored.
  • README.md, docs/user/install.md, settings.ts(.test), acp-mock-agent.ts, composer-logic.ts(.test), CommandPalette.tsx, Sidebar.tsx, ChatComposer.tsx: both sides coexist with no loss; verified by suites and typechecks.

OMP compatibility (verified against current stable)

  • Current stable: 18.2.3, tag commit a2d83061c5d673bf3ee495d7652b63ee5a0ceb14 (updates from 18.0.5/18.2.1 via omp update).
  • Live no-inference acceptance on 18.2.3 (no model turn): ACP initialize (oh-my-pi 18.2.3, auth method agent, loadSession, fork/close/list/resume), session/new, model + thinking set_config_option, available_commands_update (46 entries incl. skill:), /context, /rename (+session_info_update), /fresh (session-id adoption observed), /compact, idle cancel (0 ms), session/load resume (same session id), elicitation decline via elicitation/create (declined, end_turn, no model output), provider snapshot (version/auth/models/grouping/usage), bounded usage probe.
  • 18.2.1 → 18.2.3 delta inspected: no ACP-layer files changed; slash-command diffs are copy-only; session storage gained transactions/atomic renames; auth/header resolver changed only on the inference path.

Hardening (kept, verified in this head)

  • Unattended text generation spawns only omp acp --approval-mode=always-ask --no-tools, plus permission cancellation, elicitation decline, and unknown elicitation/create decline. Live proof on 18.2.3: exact spawn args accepted, /context shows no tools in the session, zero permission/elicitation requests. Interactive provider semantics unchanged.
  • Usage probe: only omp usage --json carries a 10 s bound (version probe stays 4 s; ACP turn timeout, commands/model discovery, and update-check bounds unchanged).

Verification

  • Typechecks: server, web, mobile, contracts, client-runtime — all clean.
  • Suites: OMP provider/adapter/driver suites, OmpAcpSupport/OmpTextGeneration/OmpUsage, ProviderRuntimeIngestion, decider/title/session, provider registry, session scanner/importer, generic ACP runtime, composer/command-palette/autocomplete, contracts/settings, mobile provider suites — all pass.
  • Targeted lint: 0 errors. git diff --check: clean. Commits pass the repo vp fmt hook.

Remaining (Codex-quota-gated)

Successful streamed assistant generation, approval-driven tool execution, subagent execution, and cancelling an in-flight model turn remain unproven until the Codex quota resets (approximately 2026-09-19T17:18:32Z). Everything around inference was exercised live without consuming a model turn.

Kept draft. Not marked ready for review.

omnificate and others added 21 commits September 14, 2026 09:37
Adds omp (https://github.com/can1357/oh-my-pi) as a seventh built-in
provider by driving its native stdio ACP server (`omp acp`) through the
existing generic ACP client stack (effect-acp), mirroring the
Cursor/Grok driver layout:

- OmpDriver: provider bundle; manual-only maintenance (T3 never guesses
  an omp update command); model catalog sourced exclusively from the
  probe ACP session's configOptions during status checks.
- OmpAdapter: session lifecycle on the shared ACP runtime: permission
  bridging via session/request_permission echoing advertised snake_case
  option ids, dual elicitation bridging (typed session/elicitation plus
  the official-SDK ext method elicitation/create with its flat
  response), task-tool subagent projection into the Agents panel,
  steering merge, pre-prompt and in-permit cancel checkpoints, and a
  per-session dispatch lock that serializes the configuration write,
  the turn.started stamp, and the session/prompt dispatch registration
  (omp applies model writes to the shared session). The permit is
  released on dispatch registration or prompt fiber exit (raced), never
  held across the prompt, so steers stay concurrent; the join carries
  onInterrupt interruption so post-dispatch cancels cannot orphan a
  prompt. Rollback is advertised unsupported: the ACP session cannot
  rewind its native conversation history.
- OmpProvider: `omp --version` probe plus ACP model discovery;
  capabilities attach only to the model the probe session currently
  runs (trimmed currentValue), other catalog entries report null. Owns
  both model-option selectors (select-guarded and unguarded existence
  probe) so their category/id normalization cannot drift.
- OmpAcpSupport: spawn args per RuntimeMode (Supervised
  --approval-mode=always-ask, Auto-accept edits --approval-mode=write,
  Auto --auto-approve, Full access --approval-mode=yolo); model writes
  only when the session advertises no model option at all (write
  through) or advertises the requested slug in its select model option;
  unadvertised slugs and non-select model options preserve the session's
  configured model, and the effective model is returned so callers stamp
  truthful turn/session state.
- OmpTextGeneration: unattended commit/PR/branch/title generation with
  --auto-approve and elicitation disabled.
- Contracts: OmpSettings/OmpSettingsPatch, off by default like
  cursor/grok/opencode; display name "Oh My Pi".
- Web/mobile: provider icon, settings metadata, add-provider entry;
  model rows render the provider and upstream label per model.

Tests: adapter/provider/support/text-generation suites on the shared
mock ACP agent covering the four model-write cases (no model option,
advertised slug, unadvertised slug, non-select model option), flat
elicitation responses, prepare-cancel permit release, dispatch
serialization order, thread-filtered event consumers, plus picker row
label coverage. Validated end to end against a real omp 18.1.15
install (11.9k-model catalog, streamed turn in the built desktop UI).

Discussion: pingdotgg#10883.
Merges the OMP provider work from pingdotgg#11791 (head
14ed34f) onto main
3efdcc5.

Conflict resolution in ProviderRuntimeIngestion.ts keeps both sides:
main's manual-title guard from pingdotgg#10720 (`titleState.source !== "manual"`)
and the PR's explicit agent rename override (`nameIsExplicit`), so an
OMP `/rename` replaces a generated title while a manual T3 rename still
wins. Main's `thread.title.generate.complete` dispatch with optimistic
title/version expectations is preserved over the PR's older
`thread.meta.update` call.

pnpm-lock.yaml takes main's version: the PR changed only a peer-suffix
hash for alchemy with no package.json change, which is lockfile drift.

OMP feature work is otherwise carried unmodified per file; see the
integration report for the per-file audit.
`vp lint` on the integrated files surfaced one error and dead imports
carried from the PR:

- AgentSessionScanner.test.ts read `NodeOS.platform()`, which current
  main's `t3code/no-global-process-runtime` rule rejects. Use
  `HostProcessPlatform.defaultValue()`, the pattern main's own tests use
  for module-scope platform checks.
- Drop unused `Dialog*`/`PiAgentIcon` imports in
  AddProviderInstanceDialog after the PR removed the Pi Agent coming-soon
  option, plus unused `EffectAcpSchema` and `acpPermissionOutcome`
  imports in OMP files.

No behavior change.
Current `@effect/tsgo` reports `@effect-diagnostics-next-line
preferSchemaOverJson:off` as TS377000 ("directive has no effect") on
11 OMP lines. effect-tsgo promotes those warnings to a non-zero
`tsc --noEmit` exit, so the server typecheck failed on warnings alone.
The directives suppress nothing on this toolchain; remove exactly the
11 flagged lines and let fmt reflow one JSON.stringify block.

Server typecheck now has 0 errors and 0 warnings (suggestions only).
No behavior change.
@github-actions github-actions Bot added vouch:unvouched PR author is not yet trusted in the VOUCHED list. size:XXL 1,000+ changed lines (additions + deletions). labels Sep 15, 2026
@nullStack65

Copy link
Copy Markdown
Author

Independent exact-head source review — Oh My Pi (omp) integration

Verdict: CLEAN_FOR_LIVE_ACCEPTANCE (source-only). No blockers found. Non-blocking observations are listed separately below and are explicitly not part of the verdict.

Reviewed state (re-fetched immediately before posting):

Ref SHA
Candidate #11973 head d8707173644cfc49c62b1ad2f840a0ffc41a4b5c (draft; mergeable=true, mergeable_state=blocked)
Candidate #11973 base at creation 87a12b53fdff7e2e0318af3edea54005557cea56
Upstream main during review b12c92f695a6b12116fb2cda40d610bdbe2a9566 (moved from 37a8ab2b2… while this review ran)
Source feature #11791 head 14ed34f4e21946819109d2cdf17186d89b4b6d1b (base 549d182aaadbf0e1e195d1a8cdc1805200e6751e; still open, not merged)
Older provenance #10893 b80bfd70c1b02c720787ac3e66822bfc5db1073f (open, not merged; not used by this candidate)

Constraints honored: read-only. No source changes, no commits, no merge, no OMP install, no sign-in, no provider credentials, no inference. Tests were executed in an isolated WSL Ubuntu 24.04 clone (~/review-t3) with Node 24.21.0 + pnpm 11.10.0 and no omp on PATH.


1. Provenance / commit graph

The candidate is a genuine descendant of the #11791 implementation, not a re-implementation:

  • git merge-base --is-ancestor 14ed34f4e2 d870717364true. 14ed34f4e2 is the tip of a linear 18-commit chain, so all 18 feat(omp): Oh My Pi provider with full terminal parity #11791 commits are ancestors of the candidate head (oldest 5766179db → newest 14ed34f4e2). Authorship preserved (17 authored by pedro, the base commit 5766179db authored by omni; OMP titles intact).
  • Integration chain on top:
    • 1434242917 = merge of 3efdcc529 (main) + 14ed34f4e2 (OMP tip) — "integrate on current main"
    • 959429b717 (lint), 2d713044d6 (drop no-op effect-diagnostics directives)
    • ad9837ed5e = merge of f4600d77dd (main) + 2d713044d6 — "refresh onto current main"
    • d870717364 = merge of ad9837ed5e (first parent, feature) + 87a12b53fd (second parent, main) — correct direction, no reverse merge
  • Range 87a12b53f..d87071736 contains exactly 23 commits: the 18 OMP commits + 3 integration commits + 2 refresh merges. Every non-OMP commit in that range is an upstream main commit reachable from current main; no unrelated branch content entered.
  • File-level: candidate net diff 87a12b53f...d87071736 = 71 files; 0 files outside the feat(omp): Oh My Pi provider with full terminal parity #11791 file set, and the source set is fully covered (72 = 71 + retained pnpm-lock.yaml). The net diff is genuinely "current main + OMP integration/conformance only".
  • Drift: current main (b12c92f) advanced 3 commits past the candidate base (GitVcsDriver fix, Hermes lint list, contracts Intl.Segmenter monogram fix). Zero file overlap with the 71 PR files. Harmless new drift, not a review blocker; the branch still reports mergeable=true.

2. Per-file parity audit (independently reproduced)

I recomputed blob-level parity between 549d182...14ed34f (#11791 net) and 87a12b53...d870717 (candidate net):

72 source files = 54 byte-identical + 17 content deltas + 1 source-only (pnpm-lock.yaml). No candidate-only files, no status mismatches. The owner's "54 identical / 18 deltas" is confirmed (the 18th being the retained lockfile).

All 17 deltas classified (A = current-main reconciliation, B = lint/typecheck conformance, C = main already implements differently, D = behavior-changing integration delta, E = suspicious):

Lint/typecheck-only (B) — 6 OMP files, all removals of stale/no-op @effect-diagnostics directives or now-unused imports:
OmpCommands.ts (-1), OmpCommands.test.ts (-11/+6), OmpModelCatalog.ts (-1), OmpModelCatalog.test.ts (-4), OmpAdapter.ts (unused acpPermissionOutcome import), OmpAcpSupport.ts (unused EffectAcpSchema type import), OmpProvider.test.ts (-1). No feature code touched.

Current-main reconciliation (A/C) — shared files keep main's newer code and re-apply only the OMP hunks:

  • AgentSessionScanner.test.ts (+3/-2): adopts main's HostProcessPlatform + listActivitiesByKind mock; OMP tests added on top.
  • ProviderRegistry.test.ts: main's newer Codex-message tests retained; candidate adds "omp" to the registered-driver expectation.
  • ProviderRuntimeIngestion.test.ts: main's list-boundary tests retained; candidate adds the explicit-rename test.
  • CommandPalette.tsx / Sidebar.tsx: main's clone-tracking and custom-snooze features retained; OMP's resolveThreadProviderDisplayName display-name hunks re-applied (region byte-identical to source).
  • ChatComposer.tsx: main's openControl/data-composer-shortcut retained; OMP slash-argument autocomplete re-applied.
  • AddProviderInstanceDialog.tsx: retains main's dialog refactor; removes the piAgent "Pi Agent" coming-soon placeholder and the imports the source PR left unused. The placeholder removal is source intent (it is already absent in 14ed34f); the legacy piAgent slug still maps to "Oh My Pi" (providerModels.ts:20-28), so no functional provider is lost.
  • settings.ts / settings.test.ts: main's followUpBehavior additions retained; OmpSettings (enabled default false), OmpSettingsPatch, provider registration, and exported defaultEnabledForDriver added.
  • ProviderRuntimeIngestion.ts (+8/-1 vs base): see §3.
  • Main's splitBufferedAssistantText list-item splitting (C): candidate keeps main's newer implementation + tests; the older source variant is correctly not restored.

No feature hunk was dropped. Every OMP-specific production file from #11791 exists in the candidate, and the only deltas in OMP-named files are lint removals.

3. Title / session authority

The candidate re-implements #11791's explicit-rename behavior on main's newer title machinery instead of the source's old thread.meta.update dispatch:

  • ProviderRuntimeIngestion.ts:2067-2085 — dispatch now thread.title.generate.complete guarded by thread.titleState?.source !== "manual" && (nameIsExplicit === true || canReplaceThreadTitle(thread.title)), with expectedTitle/expectedVersion optimistic checks.
  • decider.ts:1215-1246 — the command itself re-checks source !== "manual", title === expectedTitle, version === expectedVersion, so concurrency is enforced twice.
  • OmpAdapter.ts:1493-1507 — omp session_info_updatethread.metadata.updated with nameIsExplicit: true.

Walkthrough of the required cases:

  1. generated → OMP explicit rename: applies (explicit bypasses canReplaceThreadTitle; generated is not manual; version matches captured value). Covered by the new test at ProviderRuntimeIngestion.test.ts:3959-3978 (passes).
  2. manual T3 title → OMP rename: blocked at ingestion by source !== "manual" and again at the decider; the manual title is never silently overwritten. Decider-level guard covered by decider.titleRegeneration.test.ts:74-101 ("rejects an initial result after a manual rename to the same text"); manual ownership recording at :103-119.
  3. generated → ordinary provider non-explicit title: unchanged main behavior — only default/seed titles are replaceable (ProviderRuntimeIngestion.test.ts:3914-3957).
  4. no title (New thread) → OMP rename: applies via either branch.
  5. duplicate/replayed title events: command ids embed a random UUID (ProviderRuntimeIngestion.ts:985-988), so replays are not deduped by command id; the decider's expectedTitle/expectedVersion checks make re-application effectively idempotent (same title, needsRefinement:false, generated state). A replayed older rename can in principle re-assert its text if it lands after a newer one — this is the same class as main's existing title-seed path and is not a candidate regression. No corruption or authority inversion found.

/fresh and session/load boundaries: OmpAcpSupport.ts:103-105 passes adoptAgentSessionIdChanges: true; OmpAdapter.ts:1190-1197, 1229-1235 tracks new /fresh ids for event routing while keeping the original id as the resume cursor ("keeps streaming after omp swaps its session id" and "resumes an omp session named by an imported cursor" both pass). Session identity is not corrupted; imported transcripts require a session record before resume (AgentSessionScanner tests: "skips an omp transcript whose session record is missing").

4. Feature parity (traced end-to-end, not file existence)

All 24 capability areas are wired: provider registration (builtInDrivers.ts:27,56; settings.ts:1200), ACP transport (OmpAcpSupport.ts:55-121), OMP-owned model catalog (OmpCommands.ts/OmpModelCatalog.ts via RPC probe with ACP fallback), upstream provider grouping, per-model thinking levels, skill discovery + $ dispatch, command discovery, command argument autocomplete, usage_update context meter, /compact, usage/auth display, self-update advisory, transcript/project discovery, import + session/load resume, /rename, /fresh, permission/approval handling, subagent progress, image input, interrupt/cancel, web UI (settings/form/icon/onboarding), mobile icon, text generation, and documented limitations.

Nothing that #11791 exposed is missing in #11973. Gaps found are present in #11791 too (verified byte-identical files), i.e. scope/robustness observations, not regressions: no live account.rate-limits.updated emitter (OmpUsage.ts:18-23 is aspirational; limits are probe-only), OmpModelCatalog.metadataBySlug has no production consumer, /compact UI depends on the RPC command probe (OmpProvider.ts:696-699), and mobile has no slash-argument autocomplete (web-only in #11791).

5. Shared-runtime regression review

Generic changes are limited and consistent with existing provider patterns:

  • resolveThreadProviderDisplayName (web display only): configured instance label now outranks the persisted session slug, with brand/legacy/humanized fallbacks. Intended by the feature ("honest provider labels"); covered by providerModels.test.ts (passes).
  • defaultEnabledForDriver export widening + OmpSettings default disabled: omp is off by default; serverSettings.ts:275-326 restores previously-used providers exactly like cursor/grok/opencode (same pre-existing pattern, explicit settings always win).
  • Registry/expectation and scanner changes are additive; no provider-independent semantics weakened, no OMP special-casing leaked into generic paths, no lifecycle/optional-handling changes outside the OMP files.
  • Claude/Codex/OpenCode/ACP behavior: no candidate changes found in their generic code paths; shared-file deltas are the display-name resolver and additive schema/registry entries listed above.

6. Security / auth / process boundary

  • Credentials: no capture/persist/log/copy of provider auth material. OmpSettings carries only enabled/binaryPath/customModels; auth is omp-local under ~/.omp (single ACP authMethodId: "agent"); account email/plan appear only in the same status-cache/display path as Claude/Codex.
  • Spawn safety: fixed literal args (["acp","--approval-mode=…"], --mode rpc, usage --json, update --check), binary as a path, no shell interpolation; Windows .cmd/.bat path goes through the repo's escaping resolveSpawnCommand. Model/session/skill values travel over ACP JSON-RPC or prompt text, never argv.
  • Transcript/import boundary: size/record caps, absolute-path + realpath + workspace-identity validation, role/attribution filtering; import creates a stopped, history-only thread and cannot enable omp or grant runtime permissions. Scanner only considers enabled instances; PI_CODING_AGENT_DIR/OMP_PROFILE are resolved per-instance with profile-name validation.
  • Permissions: requests surface to the user; auto-approve exists only in full-access; omp maps decisions onto the agent's advertised option kinds (OmpAdapter.ts:358-376,1325-1399).
  • Auto-enable: off by default; only the shared "restore used providers" path can re-enable after prior use, and an explicit disable wins.

Non-blocking security notes (also present in #11791):

  • Unattended text generation spawns omp with runtimeMode: "auto"--auto-approve and registers no permission/elicitation handler (OmpTextGeneration.ts:62-77, asserted by its tests; OmpAcpSupport.ts:59-60). Other providers constrain this path (read-only/deny tools). Repo-derived prompt content is the input. Recommend approval-required + auto-deny for this path.
  • T3 "Auto" mode maps to unconditional --auto-approve for omp, wider than the mode's documented "automatic review" contract.
  • omp transcript titles/session ids are not length-capped before persistence (robustness only; React escapes text).

7. Lockfile

Keeping main's pnpm-lock.yaml is correct. #11791's lockfile diff is 2 lines / 2 hunks: the alchemy@2.0.0-beta.76 peer-resolution hash string changes in the importer and snapshot entries. No package.json changed anywhere in the source PR, so the churn is resolution noise, not a dependency change. Independently verified:

  • pnpm install --frozen-lockfile with main's lockfile succeeds (4m22s, pnpm 11.10.0);
  • all workspace packages typecheck with the frozen install (no source file relies on a package/version only present in the discarded lockfile);
  • 701 tests pass against the frozen install.

8. Independent test evidence

Run on the exact candidate head in a clean WSL clone (source-only; omp absent from PATH):

Check Result
OMP server suite: adapter/provider/driver/commands/catalog/usage/maintenance/skill-dispatch/ANSI/ACP-support/text-generation (11 files) 161 passed
Shared server: ProviderRuntimeIngestion (79), ProviderRegistry (52), AgentSessionScanner (90), AgentSessionImporter (14) 235 passed
Contracts settings.test.ts 129 passed
Web composer/pickers/readiness (8 files) 176 passed
Total 701 passed, 0 failed (24 files)
Typecheck: packages/contracts, packages/client-runtime, apps/server, apps/web, apps/mobile all EXIT=0
Targeted lint of all 71 changed files (vp lint --report-unused-disable-directives) 0 errors (82 pre-existing-pattern warnings)
git diff --check clean
pnpm install --frozen-lockfile success

Reported Windows scanner flake: not independently reproduced here (Linux-only runner; AgentSessionScanner.test.ts 90/90 passed). Unreproduced, and the candidate's scanner delta vs #11791 is only main-drift imports plus the preserved skipIf(!symlinksSupported) guards; I found no source-level evidence of a candidate-caused flake. Windows-native confirmation remains unproven.

9. Hosted CI state

Workflow runs for d870717364 exist (created 22:52–22:54Z) and are not passing CI: CI, Web Preview, Mobile EAS Preview, Mobile Fingerprint Check all completed with conclusion action_required and 0 jobs — the standard fork-workflow maintainer-approval gate, not a test failure. PR Size and PR Vouch (pull_request_target) passed; CodeRabbit skipped (draft). This should not be cited as green CI.


Verdict: CLEAN_FOR_LIVE_ACCEPTANCE (source-only)

Established: source integration correctness (18/18 source commits preserved as ancestry, correct merge directions, OMP-only net diff), file-level parity (54 identical + 17 justified deltas + lockfile, no dropped feature hunk), current-main compatibility (no-overlap drift; frozen install; all typechecks), feature wiring end-to-end, title/session authority behavior, no security boundary violations, no shared-runtime regressions, and 701 passing source-only tests.

Unproven (requires live acceptance): real omp startup, real authentication, real provider model discovery, live streaming, live context usage, live compaction, live resume/import, live subagents/approvals/images/cancel, and actual inference.

Non-blocking recommendations (not gating): constrain text-generation approval (OmpTextGeneration.ts), align omp "Auto" with a review step or document it, fix the stale live-rate-limit comment or wire the emitter, add length caps for omp titles/session ids, and add mobile slash-argument handling if parity is desired.

@nullStack65

Copy link
Copy Markdown
Author

Operator-authorized live acceptance — Oh My Pi (omp) integration

Verdict: LIVE_ACCEPTANCE_PASS for the integration surface as exercised, with a separate provider/account limitation (details in §5, §13). No candidate defect was found that requires a source change. This is a report only — no changes were made to the branch.

1. Exact refs at test time

Ref SHA
Candidate #11973 head (tested, unchanged since source review) d8707173644cfc49c62b1ad2f840a0ffc41a4b5c
Source feature #11791 head 14ed34f4e21946819109d2cdf17186d89b4b6d1b
T3 main at test start 935c55b3778fdeae0e25b250ce2a9fa7e79c0327
T3 main at test end f8500f11271622ed82df7f6c1d7f73eddb4f43e6 (+4 commits: #12011, #11954, #12002, #12008)
Candidate base at creation 87a12b53fdff7e2e0318af3edea54005557cea56
  • Main advanced twice during acceptance. Both fresh deltas overlap 0 of the 71 candidate files (comm -12 empty both times), so acceptance ran against the reviewed head per the dispatch rule.
  • feat(omp): integrate Oh My Pi provider on current main #11973 is still draft, mergeable=MERGEABLE, mergeStateStatus=BLOCKED, head unchanged, no new comments/reviews since the source review comment.
  • Runtime identity: T3 dev server executed directly from a clean checkout at d8707173…; /.well-known/t3/environment reported serverVersion 0.0.40, environmentId 2982703e-f980-45de-9774-0b2136e449e6. No released build was used.
  • Environment: macOS x64, Node 25.6.0 (repo wants ^24; pre-existing warning), pnpm 11.10.0. Sandboxed T3 home; no writes to the live ~/.t3/userdata.

2. OMP install and state protection

  • Install: ~/.local/bin/omp, omp/18.0.10 (installed 2026-08-28). Latest stable per omp update --check: 18.2.1 — advisory rendered correctly in T3 ("Update available"). No update was performed: 18.0.10 satisfied every exercised path; no compatibility failure appeared.
  • State protection: ~/.omp/agent/config.yml hash identical before/after (8c5d6b0d…); agent.db, history.db, models.db all integrity_check = ok; 401 pre-existing session transcripts intact plus the 1 new acceptance session; auth still readable (openai-codex account present, not logged out). No credential contents were read, printed, or committed.

3. Discovery / auth (no inference)

Enabled Oh My Pi through the real Settings UI (off by default, as designed). Provider snapshot then reported:

  • version 18.0.10, installed: true, status: ready, message "2 upstream providers configured through Oh My Pi".
  • 5 models: openai-codex/gpt-5.5, openai-codex/gpt-5.6-luna, openai-codex/gpt-5.6-sol, openai-codex/gpt-5.6-terra, ollama/qwen2.5:0.5b — grouped by upstream provider with per-model thinking ladders (luna/sol/terra low…max; 5.5 low…xhigh) and context windows (272K codex / 32K ollama).
  • 65 slash commands + 5 skills at machine level; the live session published 66 available_commands_update entries on session/new and again on session/load.
  • Auth: authenticated (agent), account line rendered in the provider card (email redacted here).
  • Onboarding "Agents" step lists Oh My Pi alongside Codex/Claude, and the project-import scan discovered the acceptance workspace's OMP session (1 conversation).
  • Probe observations under machine load (host load avg 7–16, 8 GB RAM): omp --version (4 s budget) and omp usage --json (3 s budget) each timed out once, transiently degrading the snapshot to error (no commands/skills). Opening the client and running a full "Refresh provider status" recovered to ready. This is environment sensitivity, not a data-loss bug; warm probe timings were 1.3–1.5 s.

4. Model selection and attempts

Policy: subscription route, non-Anthropic, low cost. Primary: openai-codex/gpt-5.6-luna (ChatGPT subscription backend, lowest codex cost).

  1. Attempt 1 — luna, text turn (turn started 01:35:50.388Z): OMP ACP turn ran end-to-end, then failed at the upstream provider:
    • UI: "Codex error event: The usage limit has been reached (code=usage_limit_reached)".
    • OMP log: agent turn ended with provider error provider=openai-codex model=gpt-5.6-luna; codex-auto-reset reason no-credits.
    • Account capacity from omp usage --json: chat 7d and base-model-inference ("gpt-reserve") 7d both 100% used; reset 2026-09-19T17:18Z. spark 5h/7d windows were at 0% but map to gpt-5.3-codex-spark, which is not in this account's catalog.
  2. Attempt 2 — single alternate, ollama/qwen2.5:0.5b (model switch round-tripped through session/set_config_option): generation hung for >30 min with no ACP stream frames. Isolation: direct omp -p with the same model also stalls, and a direct curl to ollama for a 24-token completion times out >120 s with the runner spinning at ~200% CPU and flat RSS (model never loads). Restarting ollama did not help. Classified as a local-runtime environment limitation, not T3 or OMP.
  3. Attempt 3 — image turn with luna: same usage_limit_reached (see §9).

No silent fallback occurred; each attempt is recorded above. The quota block is account-wide for the in-catalog codex models until the reset date.

5. Real ACP session lifecycle (verified on the failure-free paths)

Exact frame sequence observed through the candidate adapter (events.<thread>.log), for both session/new and session/load:

initialize → authenticate → session/new|session/load → session/set_config_option → session.started (agentInfo: oh-my-pi 18.0.10) → thread.started (providerThreadId) → turn.started (model) → available_commands_update (66) → session/prompt → usage_update → turn.completed → item.completed.

Token accounting is real: usage_update {size: 272000, used: 16486} mapped to T3 thread.token-usage.updated {usedTokens, maxTokens}. First ACP session/prompt succeeded with stopReason: end_turn while the upstream model call failed — T3 surfaced the provider error text faithfully, with no duplicate/stale terminal event.

6. Model / thinking switching

  • Model switch luna → qwen on the live session emitted session/set_config_option (succeeded) and all subsequent turns used the new model (turn.started payloads).
  • Thinking UI offered OMP's per-model ladder exactly (Off, Auto, Low, Medium, High, Extra High, Max); selecting High updates the control; the config options are sent and accepted by OMP at turn start (two set_config_option successes observed on the luna turn setup, incl. the "High" selection on the image turn).
  • No extra substantive turns were generated for this check.

7. Commands / context / compaction

  • Composer / menu listed the OMP catalog with descriptions and the "Oh My Pi" provider label (/context, /compact, /rename, /fresh, /review, /security, /handoff, /shake, /usage, /model, …).
  • Argument autocomplete verified: typing /compact offered soft / remote / snapcompact from OMP's hint — web-only feature, working.
  • /context executed (local, no model): OMP returned the live breakdown — "Context window: 32768 tokens (50% used); system prompt 6704 (20%); system tools 9174 (28%); auto-compact buffer 16232 (50%)".
  • /compact executed through the real compaction path: OMP replied "Compaction failed: Nothing to compact (session too small)"; session stayed usable. Note: T3 also rendered its generic synthesized "Context compacted" notice (the shared provider-native-command fallback), which contradicts the failure text in that edge case — generic behavior, not OMP-specific, non-gating.

8. Titles and /fresh

  • Generated → explicit OMP rename: OMP /rename OMP Rename Live replaced the generated T3 title in header and sidebar.
  • Manual authority: manual T3 rename to "Manual Title Wins", then OMP /rename OMP Tries Again — OMP renamed its own session ("Session renamed to OMP Tries Again.") while T3 kept the manual title. Authority correct in both directions.
  • /fresh: executed; OMP replied "Fresh provider session started (0 provider states pruned)". No session-id rotation was observable in this state (no live provider stream to prune); T3 kept receiving events and the thread remained coherent. Honest caveat: rotation itself was not reproduced live; source tests cover it.

9. Image input

  • Generated a 64×64 non-sensitive PNG, attached through T3's composer. T3 stored it as an asset, rendered it in the message, and the turn reached the provider (luna) with the prompt; only the upstream quota blocked a model response. Attachment plumbing verified end-to-end; model answer not obtainable (quota).

10. Cancel / interrupt

  • User cancel: Stop generation → turn.completed {state: "cancelled", stopReason: "cancelled"}; no trailing stream; thread stayed usable. Reproduced on two threads.
  • Abrupt process death: killing the ACP process mid-turn produced the same clean terminal state within seconds, with the T3 session reaped correctly.

11. Restart / resume

  • Cleanly stopped and restarted the candidate server (same sandbox home).
  • Reopening the thread showed full prior history; the next turn used session/load (not session/new) with the same providerThreadId 01a0a7db-19a4-7050-a0db-7a0f785185cb and the same native session file.
  • Resume from an imported cursor: the imported thread's first message also drove session/load with the imported session id.

12. Transcript / project import

  • Import scan discovered the acceptance workspace: /Users/businessaccount/Documents/t3-omp-integration-20260915/sandbox — 1 conversation (the live OMP session) — alongside unrelated provider histories.
  • Imported exactly the 1 representative session. Result: thread import:omp:01a0a7db-19a4-7050-a0db-7a0f785185cb, title taken from the OMP session name ("OMP Tries Again"), history-only (18 projected messages, no provider session row, shown settled), original OMP transcript files untouched.
  • Missing/invalid session records fail closed by construction (import path); not fabricated live beyond the representative case.

13. Interactive command / elicitation

  • /review surfaced a real T3 elicitation: "User input requested — Review Mode" with four options. Selecting "2. Review uncommitted changes" round-tripped (user-input.requesteduser-input.resolved {value: "2. Review uncommitted changes"}).
  • OMP then returned no output, and T3 emitted an honest runtime.warning: "Oh My Pi ran /review without returning any output — that command only renders in its own terminal UI." Turn completed cleanly. This matches the documented terminal-only-command behavior.

14. Usage / context evidence (live)

  • Usage page (Limits): Codex weekly 0% left; Oh My Pi rows read from the OMP probe — "5 hours (Spark)" 100% left (reset in ~5 h) and 7-day windows with live reset times ("+33% in 3d 14h", "↻ 5d 0h"). Account email rendered on the auth line (redacted here).
  • Context: model-declared 272K (codex) / 32K (ollama); /context showed active usage 50% of 32K; live usage_update frames fed the T3 meter and token usage.
  • Declared context window, active usage, and provider quota are reported as distinct pieces of data; no unavailable limits were inferred.

15. Known non-blocking source-review notes — live observations

  • Text-generation auto-approve: not triggerable live (title generation failed at the Codex quota; OMP text generation was not exercised).
  • T3 "Auto" ↔ OMP auto-approve: not exercised; Full access correctly launched omp acp --approval-mode=yolo.
  • Titles/session-id length caps: no over-length value observed.
  • Rate-limit live-update comments: no live account.rate-limits.updated emitter observed (probe-only), matching the source review note.
  • Mobile slash-argument parity: not tested (web surface only).

16. Not exercisable in this environment (reported, not fabricated)

  • Approval flow and subagents could not be triggered: both require a model-driven tool call, and the only authenticated subscription route is quota-blocked until 2026-09-19T17:18Z while the local ollama model cannot load on this machine. These are provider/account + local-runtime limitations, unrelated to the candidate.
  • Consequently, a successful streamed assistant generation was not obtained in this window. Everything around inference — discovery, config, streaming lifecycle, usage accounting, commands, cancels, resume, import, elicitation, attachments — was exercised live.

17. Cleanup proof

  • Candidate runtime stopped by captured PIDs (dev-runner + children + a brief server-only descriptor run); ports 13773/5733 free; zero omp acp children remain. No pkill/pattern kills were used.
  • Temporary artifacts removed (test image, browser auth state, probe payloads, pairing scratch); the one minted pairing credential is not active (No active pairing credentials); no credential/token/pairing URL appears in any published artifact.
  • OMP left intact: config hash unchanged, DB integrity ok, sessions preserved (401 + 1), account still authenticated, no logout.
  • Workspace: no repository files changed; git status shows only untracked acceptance scratch under .acceptance/.

18. Remaining risks / limitations

  1. Account quota exhaustion (resets 2026-09-19T17:18Z) blocks real inference with every in-catalog codex model; a follow-up live pass after reset is the only way to cover approval/subagent/successful-streaming.
  2. Local ollama runtime is unusable on this machine (runner never loads the model), independent of T3/OMP.
  3. Probe timeouts under load: a single omp --version timeout transiently degrades the OMP snapshot to error (0 commands/skills, status error) until the next successful check. Low severity; consider whether a version-probe failure should skip catalog discovery (source-design question, not a regression).
  4. The generic synthesized "Context compacted" notice can contradict an OMP "compaction failed" message (shared path; non-gating).

Unattended commit/PR/branch/title generation spawned omp with
--auto-approve and registered no permission handlers, so
repository-derived prompt text could steer the model into write or
destructive tool work that ran without any user in the loop.

Spawn those sessions with --no-tools and always-ask instead, and answer
any remaining permission request with a refusal and any elicitation with
a decline, so nothing can pause on UI that does not exist. The
interactive provider is unchanged.
The omp usage --json probe refreshes provider quota over the network.
Warm runs measure 0.5-1.3s but the first refresh after an omp update
measured 4.8s, so the 3s bound dropped a healthy account's limits and
could transiently degrade the snapshot. 10s matches omp's own
update --check bound and still fails rather than hanging a refresh.
@nullStack65

Copy link
Copy Markdown
Author

Current-runtime refresh + bounded safety hardening — checkpoint

Verdict: CURRENT_RUNTIME_PASS

This slice refreshed the runtime evidence to current OMP, classified current-main drift, repaired one narrow probe-timeout brittleness, and closed the unattended text-generation approval gap found in independent review. No Codex inference was attempted (quota remains exhausted until ~2026-09-19T17:18:32Z).

1. Exact refs

Ref Value
#11973 previous head d8707173644cfc49c62b1ad2f840a0ffc41a4b5c
#11973 new head 8f021c5f389eec3a9a7d7f9266c623686792a2b5 (2 commits, draft kept, MERGEABLE)
T3 main at refresh f8500f11271622ed82df7f6c1d7f73eddb4f43e6
#11791 source head 14ed34f4e21946819109d2cdf17186d89b4b6d1b (unchanged; no newer OMP carrier or superseding provider PR found)
OMP before 18.0.10 (tag 33cc6b9a043a74e00a157e72ca909272796d8461)
OMP after 18.2.1 (tag acf943d3c8dc1ed135b42aa33fef4d9d2ff61c9a)

2. Current-main drift classification

main moved 87a12b53ff8500f112 (9 commits, 44 changed files). The candidate touches 71 files. The intersection is 0 files:

  • f8500f112 mobile licenses toolbar, eed974c12 Claude rewind, 0ec2b08a9 mobile deep links, 8c18b5bb2 Antigravity _MEI cleanup, 935c55b37 environment discovery, 7a368fe7c project monograms, b12c92f69 checkpoint index reuse, 37a8ab2b2 Hermes lint bans, 6f7aaffe2 monogram Intl fix.

No semantic overlap with OMP/shared integration surfaces, so per the dispatch rule the reviewed head was kept and no main merge was performed.

3. OMP user-state proof

  • Pre-update: config.yml sha256 8c5d6b0d…; agent.db 928f5c5c…; history.db 42d92f46…; models.db d84f01c9…; integrity_check = ok ×3; auth = 1 openai-codex OAuth credential; 3624 session files.
  • Update used OMP's supported updater (omp update). Updater verified the installed asset sha256 6a5e678b95fdceec03eb1bdcd5046ff76e25eb092acab5d52a785e7582b4467e; the new binary's on-disk hash matches.
  • Post-update (before first use): all four hashes byte-identical — no eager migration or config rewrite.
  • Post-live: config hash unchanged; auth still 1× openai-codex (never logged out); integrity ok ×3; session files 3624 → 3680 — all new sessions were created in the sandbox project by this slice's live ACP runs, nothing was removed. Credentials were never read, printed, or written to logs/artifacts.

4. 18.0.10 → 18.2.1 delta and current compatibility (no inference)

Release deltas that matter to this integration: ACP always-ask/write granted calls no longer stick pending (#10850); ACP no longer advertises custom/file slash commands that collide with builtin aliases (#12092); file slash commands now carry input.hint (#11647); ACP clients now observe dynamic model changes; ACP JSON-RPC drains inbound requests on EOF (#11567); /drop/delete; /switch added; tool context missing at execute time now fails closed to always-ask (#10362); MCP tool naming preserves digits.

Live run (candidate code driving the real omp 18.2.1 binary, existing auth, no model turn):

  • initializeoh-my-pi 18.2.1, auth method agent, loadSession: true, promptCapabilities {embeddedContext, image}, sessionCapabilities {close, fork, list, resume}, model config option id model.
  • session/new config options: mode (default|plan), model 7 entries (openai-codex/gpt-5.5, …/gpt-5.6-luna, …/gpt-5.6-sol, …/gpt-5.6-terra, …/gpt-6-astra, …/gpt-daybreak-blue-latest, ollama/qwen2.5:0.5b), thinking off|auto|low|medium|high|xhigh|max.
  • Model and thinking set_config_option succeeded without inference; available_commands_update carried 69 entries at session/new (66 on 18.0.10 in the prior live run) including skill: entries.
  • /context returned the live breakdown (272K window, 6% used); /rename <title> returned the rename notice plus a session_info_update title; /fresh reported "Fresh provider session started (0 provider states pruned)." and rotated the session id on the same connection (the runtime adopted it); /compact returned "Nothing to compact (session too small)".
  • /review raised a real elicitation (declined by the handler), produced no model output, and completed end_turn; an idle session/cancel settled in 1 ms and the session stayed usable afterward (/context succeeded).
  • session/load of the same session id returned the same session id with config options; resume parity holds on 18.2.1.
  • Provider snapshot through the candidate driver: version 18.2.1, status ready, "2 upstream providers configured through Oh My Pi." (Openai Codex, Ollama), auth authenticated (account label/email present, redacted here), 6 models with per-provider grouping and thinking ladders (gpt-5.5 low…xhigh; luna/sol/terra/astra low…max; ollama none), 68 slash commands, 5 skills, usage windows openai-codex:5h + 3×7d. The RPC catalog probe (omp --mode rpc --no-session --no-lsp) also works unchanged on 18.2.1 (68 commands, 1 machine-level skill, 6 models with context windows and ladders).

No runtime incompatibility was found. Raw observations: artifacts/omp-delta/live-18.2.1-observations.ndjson and rpc-catalog-probe-18.2.1.json (local evidence, not committed).

5. Probe timings and timeout repair

Probe Measured
omp --version idle 0.08–0.27 s (5 runs), first run after update 0.73 s
omp --version under +8 CPU burners 0.11 s (5 runs)
omp usage --json warm 0.49–0.50 s
omp usage --json after usage invalidate 0.75–1.26 s (3 runs)
omp usage --json first run after update 4.76 s (exceeded the old 3 s bound)
RPC catalog probe 12.4 s at load ~20 (20 s snapshot bound, 45 s inner)
Full live ACP suite 6–16 s total

Conclusion: the 4 s version probe has 15–40× headroom on current OMP and is not brittle — kept. The 3 s usage bound was exceeded by an ordinary cold quota refresh, so it was raised narrowly to 10 s (matching omp's own update --check bound), still bounded so a refresh cannot hang. OmpUsage.ts comment records the measurement. No other timeout was touched and no unbounded waits were introduced.

6. Unattended text-generation security repair

Finding (confirmed in source): OmpTextGeneration spawned omp acp --auto-approve (yolo) and registered no permission/elicitation handlers, so repository-derived prompt text (staged patches, diffs) could steer the model into write/destructive tool work that executed with no user in the loop.

Repair, in the smallest shape that keeps generation unattended:

  • Spawns now use --approval-mode=always-ask and --no-tools (both documented OMP flags, present in the tested 18.0.10 floor and in 18.2.1; no invented flags).
  • Any permission request is answered with {outcome:{outcome:"cancelled"}}; any elicitation is answered with {action:{action:"decline"}}; unknown elicitation/create extension requests are declined, everything else still fails method-not-found, so nothing can wait on absent UI.
  • The interactive OMP provider's semantics are unchanged (ompAcpSpawnArgs("auto") and every other mode are byte-identical).

Regression tests added: spawn args assert ["acp", "--approval-mode=always-ask", "--no-tools"]; a mock agent that requests tool permission now fails the generation as cancelled (no auto-approve, no hang); a mock agent that requests elicitation gets an immediate decline and cannot block (no timeout).

7. Source validation (all on 8f021c5f3)

  • OmpAcpSupport + OmpTextGeneration suites: 18 passed (incl. 3 new tests).
  • OmpUsage/OmpMaintenance/OmpModelCatalog/OmpCommands/OmpSkillDispatch: 43 passed.
  • OmpProvider + OmpDriver: 38 passed.
  • OmpAdapter: 58 passed.
  • vp run --filter t3 typecheck: 0 errors. Lint on changed files: clean (3 pre-existing warnings in OmpUsage untouched). vp fmt --check: clean. git diff --check: clean.
  • Temporary live-acceptance test file removed; worktree has only the two pushed commits plus untracked local scratch.

8. Remaining quota-gated live items

Successful streamed assistant generation, approval-driven tool execution against a real tool call, and subagent execution remain unproven because every in-catalog Codex model is quota-blocked until ~2026-09-19T17:18:32Z; cancelling an in-flight model turn and a real image-answer turn are likewise inference-gated. Everything around inference — discovery, auth, session lifecycle, catalogs, config switching, local commands, elicitation, resume, cancel/cleanup, import-shaped resume — was exercised live on 18.2.1 without consuming a model turn.

Final result: CURRENT_RUNTIME_PASS

…tion-20260915

# Conflicts:
#	apps/server/src/provider/acp/AcpSessionRuntime.ts
…tion-20260915

# Conflicts:
#	apps/web/src/components/ComposerPromptEditor.test.ts
#	apps/web/src/components/ComposerPromptEditor.tsx
@nullStack65

Copy link
Copy Markdown
Author

Current-main reconciliation — checkpoint

Verdict: RECONCILED#11973 now contains current T3 main, all prior OMP integration/hardening history survives as ancestry, conflicts were resolved semantically on current-main architecture, and the integration was re-verified against OMP 18.2.3 live. No Codex inference was performed (Codex 7d quota measures 100% used; resets ~2026-09-19T17:18:32Z).

1. Exact refs

Ref Value
#11973 previous head 8f021c5f389eec3a9a7d7f9266c623686792a2b5
First merge (54 main commits) 76a24510e69bcc99c7a4d0c689ec8dc6e6a16c8b ← parents 8f021c5f3 + 901db896691da5ab7b7428ef8a5da52883f831dd
Second merge (3 more main commits) 4f9419b72bb92bebc6669dd95f345e1ccdf4bced ← parents 76a24510e + 71d12d8c4a05bc50344d6e3fac1b967c6daaff84
#11973 new head 4f9419b72bb92bebc6669dd95f345e1ccdf4bced
T3 main integrated 901db896691da5ab7b7428ef8a5da52883f831dd then 71d12d8c4a05bc50344d6e3fac1b967c6daaff84
Source feature #11791 14ed34f4e21946819109d2cdf17186d89b4b6d1bCLOSED (not merged) 2026-09-16T11:08:12Z
Newer/superseding OMP PRs #10893 (b80bfd70c) still open, not used; no other OMP carrier landed
Competing direction Orchestrator V2 (#2829) still open, not landed

Material authority change: upstream closed #11791 as outside current scope ("first-class Oh My Pi support is outside our current scope… compatibility should be considered through shared ACP support… rather than adding another bespoke provider integration"). This branch is therefore maintained as a reconciled, fork-held candidate: draft kept, no ready-for-review, no upstream merge attempt. Current main contains no native OMP work (oh-my-pi/Oh My Pi have zero matches in the tree), so nothing upstream was duplicated.

2. Provenance / history (unchanged discipline)

  • Merge direction is current mainfeat/omp-main-integration-20260915 (feature is first parent in both merges; upstream main was never merged into).
  • All 18 feat(omp): Oh My Pi provider with full terminal parity #11791 commits remain ancestors (git merge-base --is-ancestor 14ed34f4e2 4f9419b72 → true); prior integration merges 143424291, ad9837ed5, d87071736 and the two hardening commits 0a3e6c72e, 8f021c5f3 are intact.
  • Branch contains 27 commits beyond current main; tree diff vs main is exactly the 71-file OMP surface (+13,535/−186), verified file-for-file.

3. Conflicts and semantic resolutions

Only one textual conflict in the first merge:

  • apps/server/src/provider/acp/AcpSessionRuntime.ts — current main added an assistantUpdatesOpenRef gate that drops late agent_message_chunk/agent_thought_chunk outside a prompt; the branch added OMP session-id adoption for /fresh. Resolved by keeping both in order: adoption/filter first, then main's chunk gate, then processSessionUpdate. Old integration hunk was not restored blindly.

First-merge auto-merge audit confirmed both sides survive in the overlap files: ProviderRuntimeIngestion.ts (OMP nameIsExplicit rename condition kept inside main's rewritten pipeline together with main's expectedTitle/expectedVersion no-stale-inversion guard), its test (OMP explicit-rename test retained), acp-mock-agent.ts (OMP shapes + main's chunk-split changes), CommandPalette.tsx/Sidebar.tsx (OMP display-name resolver on main's new UI), ChatComposer.tsx/composer-logic.ts (slash-argument completion), settings.ts/settings.test.ts (OmpSettings + main's sendShortcut), README/docs.

Second merge (rich-text composer default, #12160) resolved:

  • ComposerPromptEditor.test.tsdeleted by main; Lexical editor is gone, accepted the deletion.
  • ComposerPromptEditor.tsx — took main's Tiptap shim wholesale; the OMP skill:// guard was re-expressed as isOpenableSkillPath in ComposerPromptEditorTiptap.tsx (no "View instructions" for internal skill URLs), with a restored unit test ComposerPromptEditorTiptap.test.ts.

4. OMP runtime refresh + state integrity

  • OMP updated with its supported updater: omp update, 18.0.5 → 18.2.3 (tag a2d83061c5d673bf3ee495d7652b63ee5a0ceb14). Updater-verified asset sha256 aeb3f15c6db527de58b3a2ecab7e466c75568fe445bb8d87951bc6f70352a40c; on-disk binary hash matches.
  • Pre-update: config.yml sha256 5A9C0F0E…; agent.db 757F38D8…; history.db FCE5B008…; models.db 7B7EC298…; integrity_check = ok ×3; 1 openai-codex credential; 269 session files.
  • Post-update and post-live: config.yml byte-identical (5A9C0F0E…, no eager migration, auth intact, never logged out); integrity ok ×3; 269 → 285 session files (all 16 new files are this run's acceptance sessions; nothing removed). Credentials were never read, printed, or written to artifacts.
  • 18.2.1 → 18.2.3 delta inspected beyond release highlights: no ACP-layer files changed (modes/acp/*, session/acp-permission-gate.ts, slash-commands/acp-builtins.ts, tools/acp-bridge.ts untouched); slash-command diffs are copy-only (/handoff description, jobs help text); session storage gained transactions + atomic rename; auth/header-resolution work is inference-path only.

5. Live no-inference acceptance (reconciled code driving real omp 18.2.3)

Candidate modules (OmpAcpSupport, OmpUsage, OmpProvider) driven against the real binary; no model turn sent:

  • initializeoh-my-pi 18.2.3, auth method agent, loadSession: true, sessionCapabilities {close, fork, list, resume}, promptCapabilities {embeddedContext, image}.
  • session/newmode (default|plan), model 6 options, thinking 7 options (off…max); model + thinking set_config_option through the repo helper succeeded (27 ms), final config reflects both writes.
  • available_commands_update → 46 entries at session/new, including skill:omp-cross-model-delivery; argument hints present (compact [soft|remote|snapcompact] [focus], rename [title], switch [model], …).
  • /context (272,000-token window, 6% used), /rename (rename notice + session_info_update), /fresh ("Fresh provider session started"; session-id adoption observed — the last update arrived under the adopted id), /compact (end_turn, local), idle session/cancel (0 ms, session stayed usable).
  • Elicitation: /review raised a real elicitation/create request; the decline handler answered it; prompt completed end_turn with zero text/thoughts/tool calls — no hang, no model output.
  • session/load of the same id → same session id with config options (resume parity holds on 18.2.3).
  • Provider snapshot through the candidate driver: version 18.2.3, status ready, auth authenticated (openai-codex), 5 models grouped by sub-provider with thinking ladders (gpt-5.5 off|auto|low|medium|high|xhigh), 45 machine-level slash commands + 5 skills, usage windows openai-codex:5h + 7d.
  • Usage probe bounded: 896 ms / 264 ms warm runs (well under the 10 s bound).

6. Hardening verification in this head

  • Unattended generation: spawn args are exactly ["acp", "--approval-mode=always-ask", "--no-tools"]; permission → {outcome:{outcome:"cancelled"}}; elicitation → {action:{action:"decline"}}; unknown elicitation/create declined. Live: the real binary accepts the flags, /context in that session shows no System tools row (vs 11,567 tokens of tools in the interactive session), and zero permission/elicitation requests occurred. Interactive provider semantics unchanged.
  • Usage timeout: only OMP_USAGE_PROBE_TIMEOUT_MS is 10 s (OmpUsage.ts); version probe remains 4 s, ACP turn timeout 180 s, commands probe 45 s, model discovery 15 s, RPC catalog 20 s — unchanged.

7. Validation on 4f9419b72

  • Typechecks: server (t3), @t3tools/web, @t3tools/mobile, @t3tools/contracts, @t3tools/client-runtime — all exit 0.
  • Test suites (all passing): OMP provider/adapter/driver (11 files), ProviderRuntimeIngestion + decider title/diff + session scanner/importer + provider registry (6), generic ACP runtime (5), text-generation (4), web composer/autocomplete/palette/context suites (15 across two batches), contracts settings (1), mobile provider suites (3), plus the ported isOpenableSkillPath test.
  • Targeted lint: 0 errors (pre-existing style warnings only). git diff --check: clean. Commits pass the repo's vp fmt pre-commit hook. Validation ran in an isolated WSL clone (~/review-t3) at the exact head; scratch acceptance harness removed afterwards (worktree clean). Local evidence archived under t3-omp-integration-20260915/artifacts/reconcile-20260916/ (not committed).

8. PR state

#11973 is OPEN, DRAFT, head 4f9419b72…, mergeable = MERGEABLE (conflicts resolved). mergeStateStatus = BLOCKED is the draft/review gate, not a conflict. Still intentionally not ready for review, per the upstream out-of-scope disposition above.

9. Remaining quota-gated acceptance items

Successful streamed assistant generation, approval-driven real tool execution, subagent execution, and cancelling an in-flight model turn remain unproven until the Codex quota resets (~2026-09-19T17:18:32Z). Everything around inference — discovery, auth, session lifecycle, catalogs, config switching, local commands, /rename, /fresh, /compact, elicitation decline, resume, cancel/cleanup, usage — was exercised live on 18.2.3 without a model turn.

Final result: RECONCILED (draft held; no upstream merge attempted).

@nullStack65

Copy link
Copy Markdown
Author

Oh My Pi on generic ACP (Orchestrator V2): read-only compatibility verification

Read-only architecture review plus a live zero-inference compatibility proof against a real local OMP install. Nothing in #2829, #11973, or main was modified, no upstream PR was opened, no provider model turn was executed, and no credentials were logged. A temporary isolated probe harness (raw ACP stdio client) was used to speak to omp acp with the exact payloads T3 V2's ACP client emits.

1. Refreshed state (2026-09-17 ~05:45Z)

Item Value
pingdotgg/t3code main c4ca1b0f94e56bd93899704f03015d51948a6b4dfeat(settings): add automatic storage cleanup per machine and project (#11598)
#2829 Orchestrator V2 OPEN, mergeable: CONFLICTING, base main; head 1ee1d0464271295d7b389cff343c5862caf31afa; 1,361 files, +297,447/−159,844 (515 commits at dispatch; still moving)
ACP Registry on main? No. AcpRegistry* files exist only on #2829's branch; main still ships per-provider ACP adapters (Cursor/Grok/Antigravity). No newer/smaller registry slice supersedes #2829: #1601/#2439/#2684/#6071/#9060 closed, #6461 merged was pre-registry standardization, #10893/#9038 are V1-architecture OMP ACP providers already superseded by the V2 registry design
#11973 fallback unchanged head 4f9419b72bb92bebc6669dd95f345e1ccdf4bced, OPEN/MERGEABLE, 71 files, +13,535/−186
#11791 closed 2026-09-16T11:08:12Z; close rationale confirmed verbatim (first-class OMP out of scope; assess through shared ACP in V2; avoid provider-specific maintenance commitments)
OMP stable 18.2.3 (tag a2d83061c5d673bf3ee495d7652b63ee5a0ceb14); npm @oh-my-pi/pi-coding-agent@18.2.3 (bin: omp); GitHub release v18.2.3 with raw per-platform binaries + SHA256SUMS.txt; local probe binary was 18.2.1 (not upgraded)

2. Generic ACP Registry contract in V2 (source trace)

  • Discovery: one catalog fetches the official index https://cdn.agentclientprotocol.com/registry/v1/latest/registry.json (bounded 1 MB, HTTPS-only, cached). Search ranks id/name/authors/description. There is no user-facing custom/third-party registry URL; registryUrl is a test-only injection.
  • Provisioning: binary (archive or raw, SHA-256 when declared, managed cache under the server cache dir), npx (exact-version global install through npm), uvx (exact-version through uv tool). An executable override (commandPath) uses an existing local binary while keeping the registry-declared args/env. Registry membership (agentId) is always required: inspect/resolve return not_found/agent_not_found for unknown ids, so commandPath cannot bypass registration.
  • Auth: agent / env_var / terminal methods surfaced on the provider card; URL auth elicitations wait for explicit user confirmation; logout only when advertised. No credentials are collected by T3.
  • Provider instance: normal ProviderInstanceId with driver acpRegistry; agentId, commandPath, authMethodId, distribution, customModels; official CDN icon derived from the agent id; supportsTextGeneration: false.
  • Probe: disposable initialize + session/new; models come from the session config option with category: "model" (currentValue = default); other config options and session modes are pre-mapped through acpProviderOptionDescriptors (categories thought_level, mode, booleans); auth methods and session-management flags (canList/canLoad/canResume/canLogout/canDelete/canConfigureProviders) are derived from initialize + capabilities.
  • Sessions: session/new; session/load/session/resume for activation; session/list with cursor, per-project cwd; native-session import creates a deterministic T3 thread keyed by instance+session id and launches it with the native ref (idempotent across clients); delete only when advertised.
  • Live surfaces: available_commands_update ($-prefixed names → $ skills menu, others → / provider commands, input.hint preserved), config_option_update → live model/option refresh, usage_update/idle state_update usage → context meter + cost, session_info_update → provider-thread native metadata, elicitation (form → user-input card, url → auth action, anything else declines), permission requests mediated by the thread runtime mode, session/cancel interrupts.
  • Negotiation: T3 sends a v2-first initialize with the v1 clientCapabilities/clientInfo fields merged in; the response shape decides generation (v1 agentInfo vs v2 info). Command input.hint is normalized from the v1 {hint} shape to {type:"text",hint}.
  • Exclusions: registry instances are never used for app-owned text generation (commit/PR/branch/title): the driver rejects every operation and the snapshot advertises supportsTextGeneration: false. Maintenance is manual-only (no self-update advisory, no quota card). Runtime policy is client-boundary: T3 mediates permission requests and its own fs/terminal handlers, but the agent executes its own tools inside its process.

3. Live zero-inference result against real OMP (omp acp, 18.2.1)

Driven with T3's exact negotiating initialize payload:

Probe Result
initialize responds protocolVersion: 1 with v1 agentInfo shape (oh-my-pi, Oh My Pi, 18.2.1) → T3 selects generation 1
Agent capabilities loadSession: true; promptCapabilities: { image: true, embeddedContext: true }; sessionCapabilities: { list, fork, resume, close } (no delete); mcpCapabilities: { http, sse }
authMethods exactly one agent method: “Use existing local credentials”
session/new returns configOptions: mode:mode, model:model, thinking:thought_level; no legacy models state
Model catalog 7 models with exact slugs, e.g. openai-codex/gpt-5.6-luna; currentValue = openai-codex/gpt-5.6-luna
Thinking ladder off, auto, low, medium, high, xhigh, max
session/set_config_option (model) succeeds; OMP pushes config_option_update with the new currentValue
session/set_config_option (thinking) succeeds and restores
session/set_mode succeeds (also expressible as the mode config option)
available_commands_update arrives immediately after session/new: ~80 commands including fresh, rename, compact, model, switch, context, usage, session, skill:agent-network, remote-pi …; input.hint present
session/list works; sessions carry cwd, title, updatedAt, _meta.messageCount; no pagination cursor on this install
session/load works, replay captured
session/close works
invalid session id JSON-RPC -32603 + ACP session not found (fail-closed)
unknown method JSON-RPC -32603 + Unknown ACP ext method (fail-closed)
stdio MCP servers honored: a bogus injected server made session/new fail with the server’s launch error, so T3's t3 acp-mcp-bridge injection path is real and OMP-spawned

Unproven live (requires a model turn, therefore classified rather than fabricated): permission-request shapes during tool use, elicitation during approvals/skill questions, structured usage_update values (context/cost), subagent task event shapes, and real mid-turn session/cancel. These are protocol-covered by the V2 source trace above; OMP advertises the capabilities they rely on.

4. Capability matrix vs #11973

Capability Classification Evidence
Launch/install GENERIC_V2_ALREADY_COVERS binary/npx/uvx + SHA-256 + managed cache + executable override; requires an official registry entry (OMP is not registered today)
Auth GENERIC_V2_ALREADY_COVERS live single agent method; probe readiness; URL-auth confirmation flow
Model catalog GENERIC_V2_ALREADY_COVERS live exact slugs + currentValue from the model config option
Provider grouping OMP_SPECIFIC_EXTRA_NOT_NEEDED_FOR_CORE_USE one flat picker; exact upstream-prefixed slugs still selectable
Thinking ladders GENERIC_V2_ALREADY_COVERS live 7-level ladder; V2 re-reads options after a model switch and skips per-model-invalid values
Context meter GENERIC_V2_ALREADY_COVERS usage_update/state_update → used/max/cost; live emission needs a turn
Commands GENERIC_V2_ALREADY_COVERS live ~80 commands; live refresh via coordinator
Command argument hints GENERIC_V2_ALREADY_COVERS hint normalized and shown in the / menu (description fallback); inline argument completion is cosmetic
Skills OMP_SPECIFIC_EXTRA_NOT_NEEDED_FOR_CORE_USE OMP advertises skill:* as normal commands → / menu; the $ menu requires $-prefixed names OMP does not send
Usage/quota card OMP_SPECIFIC_EXTRA_NOT_NEEDED_FOR_CORE_USE omp usage --json probe not ported; registry maintenance is manual-only
Self-update advisory OMP_SPECIFIC_EXTRA_NOT_NEEDED_FOR_CORE_USE omp update probe not ported; registry agents are version-pinned by the index
Onboarding OMP_SPECIFIC_EXTRA_NOT_NEEDED_FOR_CORE_USE generic add-agent + auth guidance covers install/sign-in; OMP-specific wizard panels are a convenience
Transcript/project discovery GENERIC_V2_ALREADY_COVERS live session/list: 29 real sessions with title/updatedAt/messageCount
Session import GENERIC_V2_ALREADY_COVERS live session/load; deterministic thread mapping. Caveat: OMP replays user turns only, so assistant history is not displayed after import (provider context is intact)
Session resume GENERIC_V2_ALREADY_COVERS loadSession: true; activation prefers session/load
/rename GENERIC_V2_SMALL_GENERIC_GAP live session_info_update {title} is consumed into provider-thread metadata but does not update the T3 thread title yet
/fresh GENERIC_V2_SMALL_GENERIC_GAP live-proven id replacement; V2 drops foreign-session updates (see §5)
Approval handling GENERIC_V2_ALREADY_COVERS client-boundary mediation; full-access auto-approves only when an allow option exists; otherwise fail-closed cancel/reject. Registry args are fixed (omp acp), so T3 runtime modes no longer map to OMP --approval-mode flags; OMP’s own default approval policy applies and T3 mediates the prompts
Subagents OMP_SPECIFIC_EXTRA_WORTH_PRESERVING generic ACP capabilities set supportsSubagents: false; OMP task tool calls would render as plain tool calls (no Agents panel). A generic ACP Task-tool projection would cover this
Images GENERIC_V2_ALREADY_COVERS live promptCapabilities.image: true; V2 sends image blocks when negotiated
Cancel GENERIC_V2_ALREADY_COVERS session/cancel implemented; live no-op path verified, mid-turn cancel unproven
Web GENERIC_V2_ALREADY_COVERS standard registry provider UI
Mobile GENERIC_V2_ALREADY_COVERS mobile ProviderIcon handles driver acpRegistry + registry iconUrl
Unattended text generation GENERIC_V2_ALREADY_COVERS excluded by design; hardening becomes irrelevant (see §7)
Terminal ANSI cleanup GENERIC_V2_SMALL_GENERIC_GAP live: /context output arrives as agent_message_chunk with raw ANSI escapes; no stripping in V2
session/load failure behavior GENERIC_V2_ALREADY_COVERS bounded load with idle-gap + timeout and typed errors; invalid ids surface as failed import/turn rather than hanging

No row required ACP_PROTOCOL_CANNOT_EXPRESS; OMP’s limits that also existed in #11973 (no conversation rewind; skill files not openable) stay provider-side.

5. /fresh (required small generic fix)

Live event shape, captured on the wire:

  1. Client sends session/prompt targeting session A.
  2. Before the prompt response returns, OMP emits session/update under a new session id B (agent_message_chunk: “Fresh provider session started (1 provider state pruned).”).
  3. The /fresh prompt response is a normal end_turn; all subsequent updates for the thread arrive under B.
  4. B is not an addressable ACP session: session/prompt on B fails with Unsupported ACP session, session/load on B fails with ACP session not found. A remains the persistent, loadable session (with the title from /rename).

V2’s AcpSessionRuntime currently returns early for any update whose sessionId differs from the started session (notification.sessionId !== startState.result.sessionId), with no adoption mechanism, so after /fresh a V2 thread goes silent. #11973 solved this with an opt-in adoptAgentSessionIdChanges (and deliberately kept the replaced id in memory only, never persisted as the resumable native id, because B is not loadable).

Minimal generic delta (no if provider === "omp"):

  • apps/server/src/provider/acp/AcpSessionRuntime.ts: an opt-in flag + an adopted-id set; forward updates for adopted ids (schema-compatible with the feat(omp): integrate Oh My Pi provider on current main #11973 patch, ~40 lines).
  • apps/server/src/orchestration-v2/Adapters/AcpRegistryAdapterV2.ts: enable adoption for registry instances and expose the live id in provider-thread metadata for diagnostics; do not change the resumable native ref.
  • If upstream wants strictness, key the opt-in off instance settings (an advanced registry toggle) rather than a hard-coded agent id, since child sessions on other agents (Devin/Grok) must keep being dropped.

6. Session import / discovery

session/list against a real OMP project returned 29 sessions with titles and timestamps, and session/load replayed a six-message session as user_message_chunk updates plus available_commands_update and session_info_update. OMP does not replay assistant messages over ACP in this build, so an imported T3 thread shows the user side of the history while the provider session itself keeps full context for continuation. That is the only user-visible delta versus the bespoke transcript scanner, and it is OMP-side behavior, not a V2 defect. The bespoke scanner is consequently technical debt we can drop.

7. Security

  • Unattended text generation never touches registry agents. The registry driver implements an unsupported TextGeneration service and advertises supportsTextGeneration: false, so commit/PR/branch/title generation can never auto-approve tools through this path. The feat(omp): integrate Oh My Pi provider on current main #11973 always-ask --no-tools hardening is obsolete on the V2 strategy (it only mattered for the bespoke OMP text-generation path).
  • Fail-closed mediation. Full-access auto-approves only when the agent offers an allow-once/allow-always option (otherwise cancel); deny selects a reject option (otherwise cancel); unknown elicitation modes decline; client-mediated fs/terminal go through canonical-containment policy checks; approval-required threads keep asking at the T3 boundary.
  • Boundary honesty. As the V2 docs state, ACP cannot confine tools the agent runs inside its own process; the enforcement point is session/request_permission plus T3’s own handlers. OMP’s default approval mode (as launched by the registry entry, omp acp) is what generates those prompts; T3 no longer injects --approval-mode flags, which is a behavior change but not a safety regression against the documented contract.

8. Maintenance comparison

Option T3 files OMP-specific files Est. lines Upstreamable Drift / conflict OMP-version burden Coverage
A. Keep #11973 71 43 (6,460 test lines; ~5.4k prod) +13,535/−186 Explicitly declined Large shared-surface conflicts (composer, contracts, ingestion, desktop) Per-main rebase + OMP CLI/RPC probes per release Full, incl. nice-to-haves
B. V2 as-is 0 0 0 n/a none ACP only All core except /fresh breaks the thread; ANSI noise
C. V2 + small generic fixes 1–3 0 ~40–120 Yes, generic Low ACP only Full core; subagents remain plain tool calls
D. Wait for V2, then registry metadata only 0 0 0 (entry external) n/a none ACP only Same as B

The registry entry itself is external metadata (agentclientprotocol/registry), not T3 code, and is required in every V2 option today: OMP has no entry in the official index (41 agents; closest is the unrelated pi-acp shim), and commandPath cannot bypass membership.

9. Verdict

Primary strategy: USE_GENERIC_ACP_V2_WITH_SMALL_GENERIC_FIXES.

Why: the generic registry already expresses everything that matters for core OMP use with zero provider-specific T3 code. Live, zero-inference probing showed exact model slugs, thinking ladders, modes, ~80 commands, session list/load/close, and the full ACP handshake working through the same code path T3 V2 will drive. The only blocking behavioral defect is session ID replacement after /fresh; ANSI noise and the /rename title projection are small generically-useful extras.

Exact missing capabilities:

  1. /fresh session replacement is dropped by V2’s runtime (must fix).
  2. ANSI escapes appear in ACP display text (optional small fix).
  3. session_info_update.title is stored but not projected to the thread title (optional small fix).
  4. Subagent/task presentation has no generic ACP projection (deferred; nice-to-have).
  5. OMP is absent from the official ACP Registry (external metadata, mandatory for any V2 path).

Minimum source delta: the adopted-session-id support in AcpSessionRuntime plus its wiring in AcpRegistryAdapterV2 (roughly 40–120 lines total, generic, no provider-name branches). Optionally a shared ANSI strip for ACP display text and a provider-sourced thread-title projection.

What becomes obsolete in #11973: OmpAdapter/OmpProvider/OmpDriver, OmpAcpSupport, OmpModelCatalog, OmpCommands, OmpSkillDispatch, OmpUsage, OmpMaintenance, OmpTextGeneration, OmpAnsi, the OMP composer argument-completion and onboarding/update cards, plus the OMP-specific shared-surface edits (contracts, settings, web, mobile icon, ingestion title change, docs). These are ~5.4k production lines plus ~6.5k test lines and 28 shared files of conflict surface.

Worth salvaging separately (as small generic changes, not OMP code): the adopted-session-id runtime behavior, ANSI stripping for ACP display text, explicit agent-rename precedence for thread titles, a generic ACP Task-tool subagent projection, and the session/load-failure hardening (already effectively subsumed by V2’s load timeout).

10. Exact next implementation task (after this decision)

  1. Freeze feat(omp): integrate Oh My Pi provider on current main #11973. No further polishing; do not mutate the branch.
  2. Draft an official ACP Registry entry for OMP (agentclientprotocol/registry PR): id oh-my-pi, name “Oh My Pi”, authors/license/repository from can1357/oh-my-pi, a 16×16 currentColor icon, and a binary distribution using the raw v18.2.3 release assets (omp-darwin-arm64, omp-darwin-x64, omp-linux-arm64, omp-linux-x64, omp-windows-x64.exe) with cmd: "./omp", args: ["acp"], and SHA-256 values from SHA256SUMS.txt. The npm package @oh-my-pi/pi-coding-agent@18.2.3 is a valid fallback but its CLI shebang is #!/usr/bin/env bun, so the binary distribution is the safer registry form.
  3. Prepare the small generic patch to bring once feat(orchestrator): introduce new orchestrator #2829 lands (or as a reviewable follow-up): adopted-session-id forwarding in AcpSessionRuntime + registry adapter wiring, with an opt-in that does not flatten child sessions; optional ANSI strip and session_info_update title projection.
  4. Re-run this zero-inference probe matrix against OMP 18.2.3 with the local binary updated on the operator’s schedule, and add a live registry-path probe using an isolated test registry (registryUrl test injection + commandPath pointing at the real binary) before enabling the provider.

@nullStack65

Copy link
Copy Markdown
Author

Oh My Pi ACP Registry entry — implemented upstream (registry PR open)

Follow-up to the compatibility verdict above: the registry-metadata implementation now exists as a real upstream contribution. Registry use only — no changes to #2829, #11973, OMP, or any client; no provider inference was run; no credentials involved.

Refreshed basis (2026-09-17 ~18:24Z)

Item Value
agentclientprotocol/registry main d003cf8a36b6d9daad87b3b7013bcb1bb5409293 (the b8978f1b… dispatch baseline had moved; everything was re-fetched before authoring)
OMP stable 18.2.4 (v18.2.4, published 2026-09-17T09:10:49Z) — supersedes the 18.2.3 basis in the previous comment
Existing OMP entry? None. No oh-my-pi / Oh My Pi / omp id among the 43 agents. pi-acp is a different project (svkozak/pi-acp) and was left untouched
Fork / branch nullStack65/registryfeat/oh-my-pi-agent @ eed36bcaa677749b0bdf24010dfc3883834612c9
Upstream PR agentclientprotocol/registry#613

Entry

  • Files: oh-my-pi/agent.json + oh-my-pi/icon.svg — id oh-my-pi, name Oh My Pi, MIT, can1357/oh-my-pi, website omp.sh. Icon is the canonical Pi-glyph mark (as used at omp.sh) reduced to the required 16x16 monochrome currentColor SVG.
  • Distribution: raw per-platform release binaries from the official v18.2.4 release, so no npm/Bun runtime is imposed on clients:
Registry target Asset sha256 source
darwin-aarch64 omp-darwin-arm64 release SHA256SUMS.txt
darwin-x86_64 omp-darwin-x64 release SHA256SUMS.txt
linux-aarch64 omp-linux-arm64 release SHA256SUMS.txt
linux-x86_64 omp-linux-x64 release SHA256SUMS.txt
windows-aarch64 omp-windows-arm64.exe release SHA256SUMS.txt
windows-x86_64 omp-windows-x64.exe release SHA256SUMS.txt
  • cmd/args: ./omp + ["acp"] (./omp.exe on Windows) → omp acp. For raw binaries both the registry verifier and T3 V2's provisioner rename the single downloaded file to the declared cmd path (AcpRegistrySupport.ts, kind === "raw" branch), so the same command resolves identically in both.
  • Every declared sha256 was copied from the release SHA256SUMS.txt and additionally cross-checked against the GitHub release asset digests — all six match.
  • Auth metadata is only what initialize advertises: one agent method ("Use existing local credentials"). No credentials or auth state in the entry.

Validation performed

  • build_registry.py --dry-run: schema, id/version/distribution checks, distribution URL accessibility, icon validation — passes (43 agents).
  • Registry workflow tests: 194 passed; ruff check + ruff format --check pass.
  • verify_agents.py --auth-check --agent oh-my-pi (macOS, darwin-x86_64): download → declared SHA-256 accepted → raw binary resolved as ./ompomp acp launched → authMethods received. Pass.
  • Zero-inference smoke on the verified 18.2.4 binary: omp --versionomp/18.2.4; initializeprotocolVersion: 1, agentInfo: oh-my-pi/18.2.4, single agent auth method, loadSession + sessionCapabilities: list/fork/resume/close; clean exit (code 0) on stdin close, no leftover process, no stdout noise. No model prompt, no provider call.

Dependency (unchanged)

Once PR #613 merges, OMP becomes discoverable/provisionable by any ACP-registry client with no client-specific code. The T3 side still depends on #2829 (Orchestrator V2) landing on main plus the small generic /fresh session-id-adoption fix; no OMP-specific integration is needed on top of that. Registry CI on the fork PR is currently held at action_required awaiting first-time-contributor approval.

deathemperor added a commit to deathemperor/infinitus that referenced this pull request Sep 17, 2026
…heirs (#1438)

Upstream has its own Oh My Pi and Pi work — two open PRs for omp
(pingdotgg/t3code#11973, #10893) and a closed set for pi (#10474, #5688,
#9648, #4355, #2800; #7211 merged into an upstream feature branch as an
orchestration-v2 adapter) — and upstream main carries neither today. All of
them claim the same paths and the same `omp` / `pi` driver kinds our drivers
use, down to the `placeholder: "omp"` in OmpSettings, so the sync that brings
one in collides in our files rather than adding a second provider.

Each driver page gains the section that says so and what to do: keep ours,
drop upstream's arm at every shared registration point (two `omp` keys in one
object is a type error at best; two `case "omp"` branches compile and run the
first), and treat anything upstream does better as its own PR. The deliberate
divergences are named — our `omp-default` sentinel in DEFAULT_MODEL_BY_PROVIDER
has no counterpart in #11973, and our quota fold lives in ompUsage.logic.ts
rather than their Drivers/OmpUsage.ts. Both ledgers get the clause that points
a merge resolver at it.

Docs only; no behavior change.

Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
@nullStack65

Copy link
Copy Markdown
Author

Root-session replacement slice — completion checkpoint (generic V2)

Architecture: USE_GENERIC_ACP_V2_WITH_SMALL_GENERIC_FIXES. This is the provider-neutral V2 slice; #11973 is unchanged and remains the frozen bespoke behavioral reference @ 4f9419b72bb92bebc6669dd95f345e1ccdf4bced.

Refs

Changed files (6, +609/-5)

  • apps/server/src/provider/acp/AcpSessionRuntime.ts
  • apps/server/src/orchestration-v2/Adapters/AcpRegistryAdapterV2.ts
  • packages/contracts/src/settings.ts
  • apps/server/scripts/acp-mock-agent.ts
  • apps/server/src/provider/acp/AcpJsonRpcConnection.test.ts
  • apps/server/src/orchestration-v2/Adapters/AcpRegistryAdapterV2.test.ts

Adoption design (generic, default strict)
AcpSessionRuntimeOptions.adoptRootSessionReplacement (default false) + onRootSessionReplaced diagnostics. A replacement id is adopted only when first seen while a root prompt is in flight, at most once per prompt; foreign ids seen while idle stay rejected. Adopted notifications are projected back onto the durable id before either the runtime or the adapter sees them. Wired per instance via the generic AcpRegistrySettings.rootSessionReplacement (default false). No provider branches, no global relaxation.

Durable vs live id
Durable A is never rewritten: prompts, cancel, session/load/close, model/config, and item identity keep using A; live B is only a notification source. Durable stragglers stay accepted; a stale previously-adopted live id is dropped once replaced.

Child-session safety
Adoption requires an in-flight root prompt and is capped at one new id per prompt, so idle/background/child traffic can never become root accidentally. Opt-in contract: only for agents whose connection publishes a single live root session and never child session ids; child traffic must be normalized before it reaches the runtime.

Live zero-inference proof (real omp 18.2.4, zero model prompts)

  • omp updated to 18.2.4; local darwin-x86_64 sha256 780a47a5... matches exactly the sha256 in agentclientprotocol/registry#613 (eed36bcaa677749b0bdf24010dfc3883834612c9); registry served from injected HttpClient using the exact oh-my-pi/agent.json metadata, commandPath → local omp, authMethodId: "agent".
  • Through the patched V2 registry adapter with the opt-in: /contextContext window: 272000 tokens (6% used); /freshFresh provider session started (1 provider state pruned).; post-/fresh /context → updates continue; durable native id after /fresh unchanged (01a0b151-096c-...); command catalog published.
  • Direct patched runtime: session/list contains durable id; /fresh fired onRootSessionReplaced {previous A → live B}; idle session/cancel on the durable id; /context after /fresh; session/load(A) returned A; session/list after load still contains A.

Tests / validation

  • AcpJsonRpcConnection.test.ts 47/47, incl. 6 new tests covering strict default, A→B adoption, A→B→C, durable prompt/cancel identity, stale-id behavior, idle foreign rejection, opt-in-off parity.
  • AcpRegistryAdapterV2.test.ts 3/3 (new end-to-end opt-in test).
  • AcpAdapterV2.test.ts 105/105; OrchestratorReplayFixtures.integration.test.ts 73/73.
  • apps/server and packages/contracts tsc --noEmit clean; targeted vp lint clean; git diff --check clean.

#2829 base failure (classified, pre-existing)
On the exact base snapshot 3d45b3056, AcpRegistryAdapterV2.test.ts > opens a real ACP child process resolved from registry configuration fails on this darwin-x64 host: ACP Registry agent fixture-agent has no compatible distribution for darwin-x64. Reproduced on base; it is a fixture/host platform gap in #2829, not a regression. This branch adds the missing darwin-x86_64 fixture distribution (test-only).

Remaining dependencies

  • Registry metadata still depends on agentclientprotocol/registry#613 (oh-my-pi 18.2.4); nothing vendored here.
  • Inference-gated items (model prompt round-trips, thinking/model config application, usage) were intentionally not exercised; this proof is zero-inference only.
  • Deferred to separate slices: ANSI cleanup, thread-title projection, subagent presentation, usage UI, onboarding.

@juliusmarminge

Copy link
Copy Markdown
Member

Thanks for the PR. We're not taking changes to the orchestration and provider layers right now: that part of the server is being rewritten for V2, and merging into the current code would either conflict with or be thrown away by that work.

Closing for now. If this is still an issue once V2 lands, please reopen (or open a fresh PR against the new code) and we'll take a proper look.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:XXL 1,000+ changed lines (additions + deletions). vouch:unvouched PR author is not yet trusted in the VOUCHED list.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants