Skip to content

feat(omp): add OMP (Oh My Pi) harness support - #297

Closed
randomvariable wants to merge 1 commit into
cortexkit:masterfrom
randomvariable:feat/omp-support
Closed

feat(omp): add OMP (Oh My Pi) harness support#297
randomvariable wants to merge 1 commit into
cortexkit:masterfrom
randomvariable:feat/omp-support

Conversation

@randomvariable

@randomvariable randomvariable commented Aug 10, 2026

Copy link
Copy Markdown
Contributor

Adds OMP (Oh My Pi) as a supported harness alongside OpenCode and Pi.

Originally authored by @Lynricsy across 19 commits; squashed here onto current master, with the subagent argv contract and test-isolation work described below added on top. Credit preserved via Co-authored-by.

51 files, +3585/−255.

What's included

CLI (packages/cli/) — OMP adapter, host-scoped config discovery and precedence, setup / doctor / migrate support, new doctor-omp command with its own tests.

pi-plugin (packages/pi-plugin/) — OMP runs the Pi-compatible runtime, but its CLI contract is stricter, so subagent argv had to be host-branched (detail below).

Dashboard (packages/dashboard/) — OMP session dedup and evidence gating.

Docs — getting-started, help, reference, and concepts pages widened to cover three harnesses; generated config docs regenerated from build-config-docs.ts with no drift.

CI — new e2e-omp job that installs published @oh-my-pi/pi-coding-agent@latest through OMP's own plugin manager inside Docker and drives a real one-turn session against a mock provider (tests/docker/Dockerfile.omp, tests/docker/test-omp-e2e.sh).

The subagent argv contract

Worth calling out, because it's the one place OMP is not drop-in Pi-compatible. Every Magic Context subagent argv is Pi-shaped, and OMP rejects it at parse time with exit code 2 — before the extension loads, so the failure is invisible to the plugin. Four independent rejections were stacked:

Emitted OMP verdict
--tools ...,find,ls neither is an OMP tool name
--tools ...,aft_search extension tools aren't addressable via --tools
--no-prompt-templates unknown flag
--no-context-files unknown flag

The historian died on the first one; fixing only that would have surfaced the next immediately, so the whole contract is translated in resolveHostToolAllowlist():

  • find / lsglob (deduped); aft_* / ctx_* entries dropped, since OMP's --tools validates against built-ins only.
  • An allow-list containing only extension tools collapses to --no-tools. That is the correct outcome, not a degradation: OMP's --no-tools clears built-ins while extension tools are still appended from the registry, so dreamer keeps ctx_memory and dreamer-retrospective keeps ctx_search.
  • Startup flags branch on host: --no-rules on OMP (it folds AGENTS.md-style context into rules) versus --no-prompt-templates / --no-context-files on Pi.

One honest limitation, documented in the code rather than papered over: OMP's CLI cannot restrict extension-registered tools at all. It maps --tools/--no-tools onto toolNames and never sets restrictToolNames, so getAllRegisteredTools() always appends aft_* / ctx_* / mcp__*. --no-extensions removes AFT but not MCP, and would also strip the aft_search the historian allow-list deliberately requests. Per-agent tool isolation on OMP is therefore a documented budget, not an enforced sandbox; real enforcement needs the SDK spawn path (restrictToolNames + customTools), which is a different architecture than a flag change.

Verification

Against omp 17.2.12: every agent (historian, sidekick, dreamer, dreamer-retrospective, dreamer-docs) passes flag and tool validation, and a historian-shaped child ran live end-to-end and returned an answer — a sentinel string confirmed --system-prompt actually governs the child.

  • typecheck clean across plugin / pi-plugin / cli; biome clean
  • pi-plugin 746 pass; CLI 326 pass / 2 skip
  • compaction-accessor and project-security guards 34 pass
  • build-config-docs.ts regenerates with no diff; git diff --check clean
  • host e2e: OpenCode 44 pass + cache-analysis oracle 10 pass; Pi 47 pass / 12 skip (pre-existing it.skip placeholders) / 0 fail
  • Docker e2e: OpenCode 10/10, Pi 12/12, OMP 12/12 — the OMP image showed the extension initializing, a mock turn completing (agent_end, isTerminal: true), the turn persisting to the shared DB, and doctor at 8 PASS / 0 FAIL

The Rust e2e lane was not run: it needs a sibling subconscious checkout to build ck-subc, which CI also does not provision.

Notes for review

  • packages/plugin/src/config/compaction-accessor-guard.test.ts gains the OMP CLI sources in ALLOWED_READERS. They contain compaction.enabled only as an omp config get lookup key, never as a Magic Context config read — same precedent as project-security.ts.
  • Two doctor-omp tests were reaching the real user database via delete process.env.XDG_DATA_HOME (bun caches os.homedir(), so setting HOME cannot redirect them). Fixed here by redirecting XDG_DATA_HOME to the temp root, matching doctor-pi.test.ts. The underlying shared-core hole — getMagicContextStorageDir() not honouring MAGIC_CONTEXT_TEST_DATA_DIR — is fixed separately in fix(storage): honour MAGIC_CONTEXT_TEST_DATA_DIR in the shared storage resolver #296; this branch does not depend on it.

View with [code]smith Autofix with [code]smith
Need help on this PR? Tag @codesmith-bot with what you need. Autofix is disabled.


Summary by cubic

Add Oh My Pi (OMP) as a first-class harness. Setup, doctor, and the Pi-compatible plugin now work on OMP, sharing one config and database across OpenCode, Pi, and OMP.

  • New Features

    • CLI (@cortexkit/magic-context): add --harness omp support with setup, doctor, and migrate; host-scoped config discovery; checks and auto-fixes for OMP’s native compaction and memory backends; plugin manager integration and version/model detection; new doctor-omp flow and tests.
    • Pi/OMP plugin (@cortexkit/pi-magic-context): OMP runtime support with subagent argv translation (maps Pi-shaped flags/tool allowlists to OMP, adjusts startup flags); adds ompModelRefToCanonical/resolveModelRefForOmp; documents OMP’s limitation that extension tools cannot be restricted via flags; expanded tests.
    • Dashboard: OMP session dedup and evidence gating; OMP model parsing; session path resolution updates.
    • Docs: broadened to include OMP across install, migration, compatibility, and troubleshooting; config reference regenerated.
    • CI: new e2e-omp Docker lane that installs real OMP and runs a smoke session against a mock provider; keeps existing OpenCode/Pi E2E lanes.
  • Migration

    • doctor migrate --from opencode --to omp exports OpenCode sessions to a Pi-compatible JSONL for OMP.
    • Resolves OMP sessions root and project identity, preserving compartments and facts.
    • Reverse migration is not supported yet.

Written for commit c692780. Summary will update on new commits.

Review in cubic

Greptile Summary

Adds Oh My Pi as a third supported harness across installation, diagnostics, subagent spawning, dashboard session discovery, documentation, and CI.

  • Adds OMP-aware setup, doctor, migration, configuration-path resolution, and plugin management.
  • Translates Pi subagent arguments and provider references to OMP-compatible forms.
  • Discovers and deduplicates OMP session data in the dashboard.
  • Adds unit coverage and a real Docker-based OMP integration lane.

Confidence Score: 4/5

The PR appears safe to merge after the non-blocking CI hardening issue is addressed by pinning the new job's external actions to immutable commits.

The OMP integration paths are internally consistent and extensively covered, while the only accepted concern is that the new CI lane executes external actions through mutable tags.

Files Needing Attention: .github/workflows/ci.yml

Security Review

The new OMP workflow uses mutable major-version action tags, adding avoidable CI supply-chain exposure. Pin both actions to full commit SHAs.

Important Files Changed

Filename Overview
packages/cli/src/adapters/omp.ts Adds OMP detection and plugin lifecycle operations, including post-install verification and rollback behavior.
packages/cli/src/commands/setup-omp.ts Adapts the shared Pi-compatible setup flow to OMP paths, plugin management, and native-conflict settings.
packages/cli/src/commands/doctor-omp.ts Adds OMP-specific installation, path, plugin, conflict, configuration, and storage diagnostics and repairs.
packages/cli/src/lib/paths.ts Adds host-scoped OMP path resolution across profiles, custom agent directories, and initialized XDG layouts.
packages/pi-plugin/src/subagent-runner.ts Detects OMP hosts and translates model references, extension paths, startup flags, and strict built-in tool lists.
packages/dashboard/src-tauri/src/pi_sessions.rs Expands Pi-compatible session discovery to OMP stores and profiles with installation evidence, XDG handling, and session-ID deduplication.
.github/workflows/ci.yml Adds a real Docker OMP integration job, but its external actions are referenced by mutable tags.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart LR
    CLI[Magic Context CLI] --> Detect{Selected harness}
    Detect --> OpenCode[OpenCode adapter]
    Detect --> Pi[Pi adapter]
    Detect --> OMP[OMP adapter]
    OMP --> Paths[Resolve profile / XDG / agent paths]
    OMP --> Plugins[OMP plugin manager]
    Plugins --> Runtime[Pi-compatible Magic Context runtime]
    Runtime --> Subagents[OMP-translated subagent argv]
    Runtime --> Store[(Shared context database)]
    Sessions[Pi and OMP JSONL stores] --> Dashboard[Dashboard discovery and dedup]
    Store --> Dashboard
Loading

Reviews (1): Last reviewed commit: "feat(omp): add OMP harness support" | Re-trigger Greptile

Greptile also left 1 inline comment on this PR.

Add OMP (Oh My Pi) as a supported harness across the CLI, dashboard, and
pi-plugin: discovery and precedence for host-scoped config, doctor/setup
diagnostics, dashboard session dedup and evidence gating, docs, and
end-to-end smoke tests.

Squashed from 19 commits on feat/omp-support.

Co-authored-by: Lynricsy <im@ling.plus>
Comment thread .github/workflows/ci.yml
Comment on lines +224 to +225
- uses: actions/checkout@v5
- uses: oven-sh/setup-bun@v2

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 security Mutable action tags expand exposure

The new OMP job executes actions/checkout@v5 and oven-sh/setup-bun@v2 through mutable major-version tags. Pinning both actions to full commit SHAs prevents a repointed tag from running unreviewed code with the job's repository and workflow permissions.

Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Declining in this PR, deliberately — this is a repo-wide policy call, not something the OMP job introduced.

Every action reference in .github/workflows/ uses a mutable major tag today:

24  actions/checkout@v5
20  oven-sh/setup-bun@v2
 3  actions/setup-node@v5
 2  SethCohen/github-releases-to-discord@v1
 2  dtolnay/rust-toolchain@stable
 2  actions/setup-node@v4
 1  tauri-apps/tauri-action@v0
 1  softprops/action-gh-release@v2
 1  peaceiris/actions-gh-pages@v4
 1  actions/github-script@v7

Zero SHA pins across 57 references. The new e2e-omp job follows that convention exactly.

Pinning just these two would add a second convention alongside the existing one while 55 references stay mutable — the threat model is unchanged (any repointed @v5 still runs in the other 24 jobs, several with broader permissions than this one), so the benefit is cosmetic and the inconsistency is real.

Worth doing as its own change across all workflows, ideally with Dependabot package-ecosystem: github-actions to keep the pins current. Happy to open that separately if a maintainer wants it — flagging rather than silently expanding this PR.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

That's a fair and well-reasoned pushback. You're right — flagging two references while 55 others stay mutable is inconsistent and doesn't move the threat model. A repo-wide sweep with Dependabot package-ecosystem: github-actions is the correct fix, and this PR shouldn't carry a partial one.

Shall I remember this as a rule: "Do not flag mutable action tags on individual jobs in this repo — it's an established convention; recommend a repo-wide Dependabot fix instead"?

Tip: You can customize Greptile's behavior for this repo with .greptile/rules.md and .greptile/config.json.

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

7 issues found across 51 files

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="packages/dashboard/src-tauri/src/pi_sessions.rs">

<violation number="1" location="packages/dashboard/src-tauri/src/pi_sessions.rs:195">
P2: OMP sessions are skipped when `PI_PACKAGE_DIR` uses supported `~/...` syntax and no fallback binary is discoverable, because this validation reads the literal `~` path. Expand the package override with the same home-directory semantics as `getOmpPackageDir()` before checking `package.json`.</violation>
</file>

<file name="packages/pi-plugin/src/subagent-runner.ts">

<violation number="1" location="packages/pi-plugin/src/subagent-runner.ts:234">
P1: Named OMP profiles can load relative subagent extensions from a stale `PI_CODING_AGENT_DIR` instead of the active profile’s agent directory. Give the normalized profile precedence here, matching OMP path resolution, so profile-specific provider extensions remain discoverable.</violation>
</file>

<file name="packages/plugin/src/config/compaction-accessor-guard.test.ts">

<violation number="1" location="packages/plugin/src/config/compaction-accessor-guard.test.ts:30">
P3: These allow-list entries exist only because the guard's regex DOES match `compaction.enabled` inside string literals (verified: `"compaction.enabled"` matches `\bcompaction\??\s*\.\s*enabled\b(?!_)`), yet the regex's own doc comment above it claims it matches only property access 'not a string literal'. Consider correcting that comment so future reviewers aren't misled about why string-literal-only files are allow-listed.</violation>
</file>

<file name="packages/cli/src/commands/doctor-omp.ts">

<violation number="1" location="packages/cli/src/commands/doctor-omp.ts:456">
P2: `doctor --force` skips the planned default-config repair when missing config is its only finding, because `first.fail === 0` returns before `repair()`. Keep the forced path when `writeUserConfig` is set so the advertised repair creates the config.</violation>
</file>

<file name="tests/docker/test-omp-e2e.sh">

<violation number="1" location="tests/docker/test-omp-e2e.sh:31">
P3: The version floor check passes falsely when `omp --version` cannot be parsed (empty `OMP_VERSION`): `sort -V -C` returns 0 for a single-line input, so the "reports the tested 17.1.7 floor or newer" check masks a missing binary or a version-parse regression. Replace the printf/sort comparison with a numeric semver comparison that fails on an empty/unparseable value.</violation>
</file>

<file name="packages/cli/src/commands/setup-omp.test.ts">

<violation number="1" location="packages/cli/src/commands/setup-omp.test.ts:106">
P3: Tests 1 and 2 pass `cwd: process.cwd()`, so the `getOmpNonGlobalConfigSources(cwd)` guard in `beforeWrite` is resolved against the directory the suite happens to be run from rather than an isolated temp dir. If a developer runs the suite from a working tree that contains `.omp/config.yml` or has `PI_CONFIG_FILES` exported in their shell, the implementation returns `false` ("refusing to mutate the global config") instead of a rollback function and these tests fail spuriously. Use a temp dir (as test 4 does) for the `cwd` argument so the assertions are hermetic.</violation>
</file>

<file name="packages/pi-plugin/README.md">

<violation number="1" location="packages/pi-plugin/README.md:166">
P3: The claim "omits them only from ephemeral --no-session child processes" is inaccurate for ctx_reduce: the code also omits ctx_reduce whenever compaction is disabled. tools/index.ts registers ctx_reduce only when `!opts.sessionScopedToolsDisabled && !opts.compactionOff`, and compactionOff is a real reachable mode (index.ts line 921: `const compactionOff = !isCompactionEnabled(config)`). Suggest tightening the sentence so readers don't assume --no-session children are the only case where ctx_reduce is hidden.</violation>
</file>

Reply with feedback, questions, or to request a fix.

Re-trigger cubic

function getHostAgentSettingsDir(): string {
if (!isOmpHostProcess()) return join(homedir(), ".pi", "agent");
const configured = process.env.PI_CODING_AGENT_DIR?.trim();
if (configured) return resolvePath(configured);

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1: Named OMP profiles can load relative subagent extensions from a stale PI_CODING_AGENT_DIR instead of the active profile’s agent directory. Give the normalized profile precedence here, matching OMP path resolution, so profile-specific provider extensions remain discoverable.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At packages/pi-plugin/src/subagent-runner.ts, line 234:

<comment>Named OMP profiles can load relative subagent extensions from a stale `PI_CODING_AGENT_DIR` instead of the active profile’s agent directory. Give the normalized profile precedence here, matching OMP path resolution, so profile-specific provider extensions remain discoverable.</comment>

<file context>
@@ -176,13 +184,75 @@ const TERMINAL_DRAIN_GRACE_MS = 2_000;
+function getHostAgentSettingsDir(): string {
+	if (!isOmpHostProcess()) return join(homedir(), ".pi", "agent");
+	const configured = process.env.PI_CODING_AGENT_DIR?.trim();
+	if (configured) return resolvePath(configured);
+	const configRoot = join(
+		homedir(),
</file context>
Suggested change
if (configured) return resolvePath(configured);
if (configured && !normalizedOmpProfile()) return resolvePath(configured);

// that never installed OMP, and treating it as evidence would surface OMP
// roots to plain Pi users. Require the same positive package/binary
// evidence the Pi runtime uses.
if trimmed_env_path(std::env::var_os("PI_PACKAGE_DIR"))

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2: OMP sessions are skipped when PI_PACKAGE_DIR uses supported ~/... syntax and no fallback binary is discoverable, because this validation reads the literal ~ path. Expand the package override with the same home-directory semantics as getOmpPackageDir() before checking package.json.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At packages/dashboard/src-tauri/src/pi_sessions.rs, line 195:

<comment>OMP sessions are skipped when `PI_PACKAGE_DIR` uses supported `~/...` syntax and no fallback binary is discoverable, because this validation reads the literal `~` path. Expand the package override with the same home-directory semantics as `getOmpPackageDir()` before checking `package.json`.</comment>

<file context>
@@ -81,27 +81,259 @@ fn test_root() -> &'static RwLock<Option<PathBuf>> {
+    // that never installed OMP, and treating it as evidence would surface OMP
+    // roots to plain Pi users. Require the same positive package/binary
+    // evidence the Pi runtime uses.
+    if trimmed_env_path(std::env::var_os("PI_PACKAGE_DIR"))
+        .is_some_and(|path| omp_package_dir_is_valid(&path))
+    {
</file context>

prompts.intro("Magic Context for Oh My Pi (OMP) Doctor");
const first = await runHealthChecks({ cwd, prompts, deps });
prompts.log.message(`Summary: PASS ${first.pass} / WARN ${first.warn} / FAIL ${first.fail}`);
if (!options.force || first.fail === 0) return first.fail === 0 ? 0 : 1;

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2: doctor --force skips the planned default-config repair when missing config is its only finding, because first.fail === 0 returns before repair(). Keep the forced path when writeUserConfig is set so the advertised repair creates the config.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At packages/cli/src/commands/doctor-omp.ts, line 456:

<comment>`doctor --force` skips the planned default-config repair when missing config is its only finding, because `first.fail === 0` returns before `repair()`. Keep the forced path when `writeUserConfig` is set so the advertised repair creates the config.</comment>

<file context>
@@ -0,0 +1,469 @@
+    prompts.intro("Magic Context for Oh My Pi (OMP) Doctor");
+    const first = await runHealthChecks({ cwd, prompts, deps });
+    prompts.log.message(`Summary: PASS ${first.pass} / WARN ${first.warn} / FAIL ${first.fail}`);
+    if (!options.force || first.fail === 0) return first.fail === 0 ? 0 : 1;
+    if (migrationRefused && first.repairPlan.writeUserConfig) {
+        first.repairPlan.writeUserConfig = false;
</file context>

// The strip operates on a raw Record<string, unknown> by key name, not on
// a parsed MagicContextConfig.
"packages/plugin/src/config/project-security.ts",
// The OMP harness surfaces its OWN `compaction.enabled` setting, read via

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P3: These allow-list entries exist only because the guard's regex DOES match compaction.enabled inside string literals (verified: "compaction.enabled" matches \bcompaction\??\s*\.\s*enabled\b(?!_)), yet the regex's own doc comment above it claims it matches only property access 'not a string literal'. Consider correcting that comment so future reviewers aren't misled about why string-literal-only files are allow-listed.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At packages/plugin/src/config/compaction-accessor-guard.test.ts, line 30:

<comment>These allow-list entries exist only because the guard's regex DOES match `compaction.enabled` inside string literals (verified: `"compaction.enabled"` matches `\bcompaction\??\s*\.\s*enabled\b(?!_)`), yet the regex's own doc comment above it claims it matches only property access 'not a string literal'. Consider correcting that comment so future reviewers aren't misled about why string-literal-only files are allow-listed.</comment>

<file context>
@@ -27,6 +27,13 @@ const ALLOWED_READERS = new Set<string>([
     // The strip operates on a raw Record<string, unknown> by key name, not on
     // a parsed MagicContextConfig.
     "packages/plugin/src/config/project-security.ts",
+    // The OMP harness surfaces its OWN `compaction.enabled` setting, read via
+    // `omp config get compaction.enabled`. These files carry that key only as a
+    // string literal for the external CLI; they never read Magic Context's
</file context>

PLUGIN_LIST=$(omp plugin list --json 2>&1)
echo "OMP version: ${OMP_VERSION:-unknown}"
echo "$PLUGIN_LIST"
check "omp --version reports the tested 17.1.7 floor or newer" \

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P3: The version floor check passes falsely when omp --version cannot be parsed (empty OMP_VERSION): sort -V -C returns 0 for a single-line input, so the "reports the tested 17.1.7 floor or newer" check masks a missing binary or a version-parse regression. Replace the printf/sort comparison with a numeric semver comparison that fails on an empty/unparseable value.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At tests/docker/test-omp-e2e.sh, line 31:

<comment>The version floor check passes falsely when `omp --version` cannot be parsed (empty `OMP_VERSION`): `sort -V -C` returns 0 for a single-line input, so the "reports the tested 17.1.7 floor or newer" check masks a missing binary or a version-parse regression. Replace the printf/sort comparison with a numeric semver comparison that fails on an empty/unparseable value.</comment>

<file context>
@@ -0,0 +1,120 @@
+PLUGIN_LIST=$(omp plugin list --json 2>&1)
+echo "OMP version: ${OMP_VERSION:-unknown}"
+echo "$PLUGIN_LIST"
+check "omp --version reports the tested 17.1.7 floor or newer" \
+    "printf '17.1.7\n%s\n' \"$OMP_VERSION\" | sort -V -C"
+check "OMP lists the linked Magic Context package" \
</file context>

const prompts = new MockPrompts([true, true]);
const rollback = await __test.OMP_HOST.beforeWrite?.({
binaryPath: binary,
cwd: process.cwd(),

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P3: Tests 1 and 2 pass cwd: process.cwd(), so the getOmpNonGlobalConfigSources(cwd) guard in beforeWrite is resolved against the directory the suite happens to be run from rather than an isolated temp dir. If a developer runs the suite from a working tree that contains .omp/config.yml or has PI_CONFIG_FILES exported in their shell, the implementation returns false ("refusing to mutate the global config") instead of a rollback function and these tests fail spuriously. Use a temp dir (as test 4 does) for the cwd argument so the assertions are hermetic.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At packages/cli/src/commands/setup-omp.test.ts, line 106:

<comment>Tests 1 and 2 pass `cwd: process.cwd()`, so the `getOmpNonGlobalConfigSources(cwd)` guard in `beforeWrite` is resolved against the directory the suite happens to be run from rather than an isolated temp dir. If a developer runs the suite from a working tree that contains `.omp/config.yml` or has `PI_CONFIG_FILES` exported in their shell, the implementation returns `false` ("refusing to mutate the global config") instead of a rollback function and these tests fail spuriously. Use a temp dir (as test 4 does) for the `cwd` argument so the assertions are hermetic.</comment>

<file context>
@@ -0,0 +1,208 @@
+        const prompts = new MockPrompts([true, true]);
+        const rollback = await __test.OMP_HOST.beforeWrite?.({
+            binaryPath: binary,
+            cwd: process.cwd(),
+            prompts,
+            dryRun: false,
</file context>

| `ctx_reduce` | `drop` | Queue tagged turns for cache-safe removal from the live context |

`ctx_expand` and `ctx_reduce` from the OpenCode plugin are **intentionally not exposed on Pi** — they depend on raw OpenCode message ordinals, while Pi has its own message identity model. Drops still happen automatically via threshold-driven historian; you don't need an explicit `ctx_reduce` to trigger reduction.
`ctx_note`, `ctx_expand`, and `ctx_reduce` are session-scoped and are exposed in primary Pi/OMP sessions. Magic Context omits them only from ephemeral `--no-session` child processes, where they would otherwise target the hidden child session.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P3: The claim "omits them only from ephemeral --no-session child processes" is inaccurate for ctx_reduce: the code also omits ctx_reduce whenever compaction is disabled. tools/index.ts registers ctx_reduce only when !opts.sessionScopedToolsDisabled && !opts.compactionOff, and compactionOff is a real reachable mode (index.ts line 921: const compactionOff = !isCompactionEnabled(config)). Suggest tightening the sentence so readers don't assume --no-session children are the only case where ctx_reduce is hidden.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At packages/pi-plugin/README.md, line 166:

<comment>The claim "omits them only from ephemeral --no-session child processes" is inaccurate for ctx_reduce: the code also omits ctx_reduce whenever compaction is disabled. tools/index.ts registers ctx_reduce only when `!opts.sessionScopedToolsDisabled && !opts.compactionOff`, and compactionOff is a real reachable mode (index.ts line 921: `const compactionOff = !isCompactionEnabled(config)`). Suggest tightening the sentence so readers don't assume --no-session children are the only case where ctx_reduce is hidden.</comment>

<file context>
@@ -136,26 +160,28 @@ Easiest fix: configure `embedding` once in `~/.pi/agent/magic-context.jsonc` (Pi
+| `ctx_reduce` | `drop` | Queue tagged turns for cache-safe removal from the live context |
 
-`ctx_expand` and `ctx_reduce` from the OpenCode plugin are **intentionally not exposed on Pi** — they depend on raw OpenCode message ordinals, while Pi has its own message identity model. Drops still happen automatically via threshold-driven historian; you don't need an explicit `ctx_reduce` to trigger reduction.
+`ctx_note`, `ctx_expand`, and `ctx_reduce` are session-scoped and are exposed in primary Pi/OMP sessions. Magic Context omits them only from ephemeral `--no-session` child processes, where they would otherwise target the hidden child session.
 
 ---
</file context>
Suggested change
`ctx_note`, `ctx_expand`, and `ctx_reduce` are session-scoped and are exposed in primary Pi/OMP sessions. Magic Context omits them only from ephemeral `--no-session` child processes, where they would otherwise target the hidden child session.
`ctx_note`, `ctx_expand`, and `ctx_reduce` are session-scoped and are exposed in primary Pi/OMP sessions. Magic Context omits them from ephemeral `--no-session` child processes, where they would otherwise target the hidden child session; `ctx_reduce` is additionally omitted when compaction is disabled.

ualtinok pushed a commit that referenced this pull request Aug 10, 2026
Full OMP support, merged after the final re-review verified all asks at source: rebase onto current master, the named OMP scanner split with positive-installation-evidence gating (real-scan regression tests in both directions), plain-Pi child-extension resolution with negative coverage, and the strict child-argv contract ported from #297 with credit. Local gates on the head: 746 Pi / 3632 plugin / 327 CLI / dashboard cargo all green. Thanks for the persistence across three review rounds — this is a large, careful integration.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant