Skip to content

feat: add OMO Slim as an optional orchestration plugin#722

Merged
marcusrbrown merged 8 commits into
mainfrom
feat/omo-slim-optional-dependency
Jun 1, 2026
Merged

feat: add OMO Slim as an optional orchestration plugin#722
marcusrbrown merged 8 commits into
mainfrom
feat/omo-slim-optional-dependency

Conversation

@marcusrbrown
Copy link
Copy Markdown
Collaborator

Summary

Adds OMO Slim (oh-my-opencode-slim) as an optional orchestration plugin, alongside the existing Oh My OpenAgent (oMo) integration. OMO Slim is selected with a single preset name rather than oMo's provider list.

What's included

  • enable-omo-slim action input (default false), mutually exclusive with enable-omo — enabling both fails fast.
  • omo-slim-preset input (openai | opencode-go, default openai), validated to the allowlist before reaching the installer.
  • Pinned DEFAULT_OMO_SLIM_VERSION constant with Renovate tracking, mirroring the oMo/Bun/Systematic version-pinning pattern.
  • Setup installs OMO Slim via bunx oh-my-opencode-slim@<version> install --no-tui --reset --preset=<preset> and assembles the OpenCode config in slim mode: registers the slim plugin, pins default_agent to orchestrator, and keeps @fro.bot/systematic.
  • Fail-closed guards: a config containing both orchestration plugins is rejected, and an unverified slim version is rejected before the installer runs. A failed install degrades to a working non-slim config rather than pinning a missing agent.
  • A workflow_dispatch-gated CI job exercises slim mode end to end and asserts the generated config.

The gateway environment variable for selecting slim presets in workspace containers is deferred until the workspace image runs OpenCode.

Mutually exclusive with enable-omo. Validates preset against the
openai/opencode-go allowlist and fails fast when both plugins are enabled.
installOmoSlim runs the pinned slim installer with the validated preset.
buildCIConfig gains a slim mode that registers the slim plugin, pins
default_agent to orchestrator, guards against dual-plugin configs, and
version-gates orchestrator support.
A workflow_dispatch-gated job exercises enable-omo-slim end to end and
asserts the slim config assembly. README documents the new inputs and
the mutual-exclusivity contract with oMo.
Reject unverified slim versions before running the installer, fall back
to a non-slim config when the slim install fails so a missing plugin is
never pinned as default_agent, strip the legacy plugins key in slim mode,
and source the default version from the shared constant.
@marcusrbrown marcusrbrown requested a review from fro-bot as a code owner June 1, 2026 05:05
Copy link
Copy Markdown
Owner

@fro-bot fro-bot left a comment

Choose a reason for hiding this comment

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

Verdict: PASS

Solid, well-tested addition. The slim-mode path is correctly isolated from the existing oMo and disabled paths, mutual-exclusion is enforced early, and the fail-closed degradation (failed install → non-slim build config rather than a pinned-but-missing orchestrator) is handled cleanly via the slimReady reassignment in setup.ts:181. 126 tests in the touched suites pass locally. Nothing here blocks merge.

Blocking issues

None

Non-blocking concerns

  1. verifyOmoSlimInstallation is dead code with a latent bug (src/services/setup/omo-slim.ts:58-72). It is never called from setup.ts (only from its own test). Worse, if it is wired up later it will always return false: execAdapter.exec('ls', ['-la', '~/.config/opencode/oh-my-opencode-slim.json']) passes ~ as a literal argv element — no shell tilde expansion happens with arg arrays, so ls looks for a literal ./~/.config/... path. Either remove the function until it is needed, or expand the home dir explicitly (e.g. join(homedir(), '.config/opencode/oh-my-opencode-slim.json')) and assert on exit code rather than substring-matching 'No such file' (which is locale/ls-implementation dependent). The verification gap is acceptable for now because the slim install already gates on installer exit code.

  2. Redundant double version gate. The R19 verified-version check runs twice: once eagerly in setup.ts:142 (isOmoSlimVersionVerified) and again inside buildCIConfig (ci-config.ts:138). Since omoSlimVersion is currently hardwired to DEFAULT_OMO_SLIM_VERSION in bootstrap.ts:51 (there is no omo-slim-version action input despite the plan referencing one), neither gate can fail at runtime today — both are effectively dead in production. This is fine as forward-looking defense, but the two error strings differ slightly (setup.ts hardcodes known-good: 1.1.1 while ci-config.ts derives it from the list); deriving both from OMO_SLIM_ORCHESTRATOR_VERIFIED_VERSIONS would prevent them drifting when Renovate bumps the version.

  3. oMo silently stripped in slim mode rather than rejected. The dual-plugin guard (ci-config.ts:130-135) only fires when a single user-supplied config contains both plugin families. When enable-omo-slim: true and the user config already lists an oh-my-openagent plugin, slim mode strips it via stripOmoPlugins with no warning. The CLI-input mutual-exclusion (inputs.ts:308) covers the common case, but a config-injected oMo plugin disappears silently. Consider a logger.warning when stripOmoPlugins removes entries in slim mode, mirroring the disabled-mode rewrittenFields warning.

  4. Version-detection regex is best-effort. omo-slim.ts:46 parses the installed version from stdout via /oh-my-opencode-slim@(\d+\.\d+\.\d+)/i and silently falls back to the requested version on no match. That is reasonable, but the reported version in OmoInstallResult is then advisory only — fine since nothing downstream depends on the detected value (the config uses omoSlimVersion, the input).

Missing tests

None that block. Coverage is strong: preset argv assembly (both presets), exit-code failure, exception path, no --skip-auth, slim-mode config assembly, unverified-version rejection in both buildCIConfig and the early setup.ts gate (fix B), mutual-exclusion in inputs.test.ts, and the failed-install degradation. Two gaps worth a follow-up (non-blocking): (a) no test exercises buildCIConfig slim mode when the user config already contains an oh-my-openagent plugin (the silent-strip path in concern #3); (b) no test for the verifyOmoSlimInstallation tilde-path bug — current tests mock getExecOutput and substring-match, so they pass without catching the real-world expansion failure.

Risk assessment (LOW): All new behavior is gated behind enable-omo-slim (default false) and is mutually exclusive with the existing oMo path, so the blast radius for existing users is zero. The shared touch point — buildCIConfig and the setup.ts orchestration — adds new branches without altering the enabled/disabled oMo paths (verified by the unchanged existing assertions). No security exposure: no new secret handling, no --skip-auth, no telemetry env vars, and the installer runs ephemerally via bunx with a pinned, version-gated specifier. Main residual risk is operational (the live bunx install in the workflow_dispatch-only smoke job), not a regression risk to merged code.


Run Summary
Field Value
Event pull_request
Repository fro-bot/agent
Run ID 26736557823
Cache hit
Session ses_17e62e07bffeCDM1nnfBz6x2oQ

Slim config assembly is covered by unit tests; a workflow_dispatch-only
job only adds a perpetually-skipped check to every PR. Dispatch fro-bot.yaml
for an on-demand live install smoke when needed.
Copy link
Copy Markdown
Owner

@fro-bot fro-bot left a comment

Choose a reason for hiding this comment

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

Verdict: PASS

Re-review after the latest push. The only change since my prior review (commit 3f63c17) is the removal of the workflow_dispatch-gated test-action-omo-slim CI job. The implementation code (omo-slim.ts, ci-config.ts, setup.ts, inputs.ts) is unchanged. Dropping the dispatch-only job is a sound call: it was perpetually skipped on every PR (so it added a noisy required-check candidate without ever running), and slim config assembly is fully covered by unit tests. On-demand live install smoke remains available via fro-bot.yaml dispatch. This directly resolves the lone operational note from my prior review. 172 tests across the touched suites pass locally.

Blocking issues

None

Non-blocking concerns

The four items from my prior review remain open and remain non-blocking. Carried forward for visibility:

  1. verifyOmoSlimInstallation is dead code with a latent bug (src/services/setup/omo-slim.ts:58-72). Never called from setup.ts. If wired up later it will always return false: '~' is passed as a literal argv element to ls (no shell tilde expansion with arg arrays). Either remove it until needed, or use join(homedir(), ...) and assert on exit code rather than substring-matching 'No such file'.

  2. Redundant double version gate (setup.ts:142 and ci-config.ts:138). Both currently unreachable since omoSlimVersion is hardwired to DEFAULT_OMO_SLIM_VERSION in bootstrap.ts:51 (no omo-slim-version input). The two error strings differ (setup.ts hardcodes known-good: 1.1.1; ci-config.ts derives from the list) — derive both from OMO_SLIM_ORCHESTRATOR_VERIFIED_VERSIONS to prevent drift on Renovate bumps.

  3. oMo silently stripped in slim mode rather than rejected (ci-config.ts:130-135). The dual-plugin guard only fires when one user config contains both families. A config-injected oh-my-openagent plugin is stripped silently in slim mode. Consider a logger.warning mirroring the disabled-mode rewrittenFields warning.

  4. Version-detection regex is best-effort (omo-slim.ts:46). Falls back to the requested version on no match; advisory only since downstream uses the input version. Acceptable.

Missing tests

None that block. Coverage remains strong (preset argv for both presets, exit-code failure, exception path, no --skip-auth, slim-mode config assembly, unverified-version rejection in both gate locations, mutual-exclusion, failed-install degradation). Two follow-up gaps (non-blocking, unchanged): (a) no test for buildCIConfig slim mode when the user config already contains an oh-my-openagent plugin (the silent-strip path in concern #3); (b) no test catching the verifyOmoSlimInstallation tilde-path bug (current tests mock getExecOutput and substring-match, so they pass without exercising real expansion).

Risk assessment (LOW): Removing a perpetually-skipped, workflow_dispatch-only job has zero regression risk to merged code or to PR gating — it only deletes a check that never executed on PRs. All slim behavior remains gated behind enable-omo-slim (default false) and mutually exclusive with oMo, so blast radius for existing users is zero. No security exposure: no new secret handling, no --skip-auth, no telemetry env vars, ephemeral pinned bunx install. The only loss is the automated end-to-end live-install assertion, which is mitigated by full unit coverage of config assembly plus the retained on-demand fro-bot.yaml dispatch path.


Run Summary
Field Value
Event pull_request
Repository fro-bot/agent
Run ID 26736854151
Cache hit
Session ses_17e62e07bffeCDM1nnfBz6x2oQ

fro-bot
fro-bot previously approved these changes Jun 1, 2026
…l-dependency

# Conflicts:
#	dist/artifact-B_zc1jSr.js
#	dist/artifact-C7LCxgbI.js
#	dist/artifact-CpTI6Kyo.js
#	dist/main.js
#	dist/post.js
@fro-bot fro-bot added the agent: working Agent is currently working on this label Jun 1, 2026
Copy link
Copy Markdown
Owner

@fro-bot fro-bot left a comment

Choose a reason for hiding this comment

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

Verdict: PASS

Approving. This is the third pass on PR #722; my two prior reviews (PASS, comment-only) covered the implementation in full. The only change since then is merge commit 3bbf5ee pulling origin/main into the branch. That merge resolved conflicts only in dist/ build artifacts (dist/main.js, dist/post.js, the renamed artifact-*.js) — no source-level slim files changed. Verified at HEAD: omo-slim.ts, ci-config.ts, setup.ts, inputs.ts, and bootstrap.ts:51 (omoSlimVersion: DEFAULT_OMO_SLIM_VERSION) are identical to the previously reviewed state. Full test run is green: 425 tests pass across the setup, harness-config, and agent suites. No new regression surface introduced by the merge.

Blocking issues

None

Non-blocking concerns

Unchanged from prior reviews — all four remain open and non-blocking. Carried forward for visibility:

  1. verifyOmoSlimInstallation is dead code with a latent bug (src/services/setup/omo-slim.ts:58-72). Never called from setup.ts. If wired up later it always returns false: '~' is passed as a literal argv element to ls (no shell tilde expansion with arg arrays). Remove until needed, or use join(homedir(), ...) and assert on exit code rather than substring-matching 'No such file'.

  2. Redundant double version gate (setup.ts:142 and ci-config.ts:138). Both unreachable today since omoSlimVersion is hardwired to DEFAULT_OMO_SLIM_VERSION (no omo-slim-version input). Error strings differ — setup.ts hardcodes known-good: 1.1.1 while ci-config.ts derives from the list. Derive both from OMO_SLIM_ORCHESTRATOR_VERIFIED_VERSIONS to prevent drift on Renovate bumps.

  3. oMo silently stripped in slim mode (ci-config.ts:130-135). The dual-plugin guard only fires when one user config contains both families; a config-injected oh-my-openagent plugin is stripped silently in slim mode. Consider a logger.warning mirroring the disabled-mode rewrittenFields warning.

  4. Version-detection regex is best-effort (omo-slim.ts:46). Falls back to the requested version on no match; advisory only since downstream uses the input version. Acceptable.

Missing tests

None that block. Coverage remains strong (preset argv for both presets, exit-code failure, exception path, no --skip-auth, slim-mode config assembly, unverified-version rejection in both gate locations, mutual-exclusion, failed-install degradation). Two non-blocking follow-up gaps, unchanged: (a) no test for buildCIConfig slim mode when the user config already contains an oh-my-openagent plugin (the silent-strip path in concern #3); (b) no test catching the verifyOmoSlimInstallation tilde-path bug (current tests mock getExecOutput and substring-match).

Risk assessment (LOW): The merge from origin/main touched only dist/ artifacts at the conflict level and introduced no source-level slim changes, so it adds no new regression surface. All slim behavior remains gated behind enable-omo-slim (default false) and mutually exclusive with oMo — blast radius for existing users is zero. No security exposure: no new secret handling, no --skip-auth, no telemetry env vars, ephemeral pinned bunx install with a version-gated specifier. 425 tests green confirm the merge did not disturb existing behavior. One verification worth the author's glance before merge: confirm dist/ was rebuilt from the post-merge source (the conflict resolution should reflect current src/), since dist/ is the shipped artifact for this action.


Run Summary
Field Value
Event pull_request
Repository fro-bot/agent
Run ID 26750642037
Cache hit
Session ses_17e62e07bffeCDM1nnfBz6x2oQ

@fro-bot fro-bot removed the agent: working Agent is currently working on this label Jun 1, 2026
@marcusrbrown marcusrbrown merged commit 90502db into main Jun 1, 2026
11 checks passed
@marcusrbrown marcusrbrown deleted the feat/omo-slim-optional-dependency branch June 1, 2026 11:03
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