# Corentic Package Manager (CPM) A **CPM package** is an agent package consisting of an [APM](https://microsoft.github.io/apm/) manifest plus a team configuration (`team-profile.yaml`). The Corentic Package Manager translates this package into the native configuration of a target harness. Translation targets: | Target harness | Status | |---|---| | [oh-my-opencode-slim](https://ohmyopencodeslim.com/) | ✅ implemented | | oh-my-pi | planned | | Codex / Claude / Copilot | vision | Deterministic – the CPM does not guess. It assumes no availability and never picks models automatically. ``` CPM package User Runtime apm.yml + + model-mapping.yaml → cpm render → .opencode/ team-profile.yaml (model class → oh-my-opencode-slim.json (roles, model concrete model ID) (or later: native config classes, MCPs/skills) of another harness) ``` ## Prerequisites - Python 3.10+ with PyYAML (`pip install pyyaml`) - OpenCode with the [oh-my-opencode-slim](https://github.com/alvinunreal/oh-my-opencode-slim) plugin installed - A CPM package with a `team-profile.yaml` ## Quickstart ```bash # 1. Create the model mapping – interactively, choosing from your opencode models python3 cpm.py init --fill # 2. Guided: read team profile, check/fill mapping, render cd python3 /path/to/cpm.py setup --package /path/to/package # 3. Activate opencode # project config gets loaded /preset acme-job-applications # Reload OpenCode -> team is active (by design: no hot-swap) ``` Alternatively manually: ```bash # 1. Create the model mapping once mkdir -p ~/.config/cpm cp examples/model-mapping.yaml ~/.config/cpm/model-mapping.yaml $EDITOR ~/.config/cpm/model-mapping.yaml # adapt to your own models # 2. Validate (dry run) python3 cpm.py check --package examples/package # 3. Render cd python3 /path/to/cpm.py render --package /path/to/package ``` ## The three files | File | Owned by | Purpose | Edit manually? | |---|---|---|---| | `team-profile.yaml` | Package author | Roles, model classes, MCP/skill allowlists per role | Yes (author) | | `~/.config/cpm/model-mapping.yaml` | User | Model class → concrete model ID (+ optional variant/temperature) | Yes (user) | | `.opencode/oh-my-opencode-slim.json` | generated | Preset with concrete model IDs | **No** – always re-render | Plus a provenance file `.opencode/oh-my-opencode-slim.cpm-provenance.json` documenting which role received which model. ## Command reference ```bash python3 cpm.py init [--mapping FILE] [--fill] # create/fill mapping python3 cpm.py setup --package DIR [--mapping F] ... # guided flow python3 cpm.py render --package DIR [--mapping F] [--output F] [--dry-run] python3 cpm.py check --package DIR [--mapping F] # dry-run validation ``` ### `init` – create the mapping Creates `~/.config/cpm/model-mapping.yaml` (if not present). With `--fill`, all `PLACEHOLDER` classes are asked interactively: the CPM lists every model from your `opencode.json(c)`, you pick by number or enter a model ID manually. ### `setup` – guided flow The one-command path: shows the team profile in plain language, creates a missing mapping, interactively asks for missing model classes (same selection as `init --fill`), renders and prints the activation steps. ### `render` / `check` | Option | Default | Meaning | |---|---|---| | `--package` | `.` | CPM package directory containing `team-profile.yaml` | | `--mapping` | `~/.config/cpm/model-mapping.yaml` | Local mapping table | | `--output` | `/.opencode/oh-my-opencode-slim.json` | Target file | | `--team-file` | `team-profile.yaml` (alternatively `team.yaml`) | Alternative profile filename | **Merge behavior:** Existing presets in the target file remain untouched; only the preset for this team ID is replaced. Multiple packages coexist in the same project. Activation is explicit via `/preset `. ## Team profile schema (`corentic.team-profile/v1`) ```yaml schema: corentic.team-profile/v1 id: acme.job-applications # becomes the preset name (namespaced) description: ... roles: - id: researcher # domain role purpose: ... # becomes prompt/description for custom agents runtime_agent: librarian # optional: harness builtin or 'custom' # (default: role id as custom agent) model_class: fast-research # required, must exist in the mapping capabilities: mcps: [websearch, openviking] # MCP allowlist ([] = none) skills: [job-application] # skill allowlist ([] = none) ``` The `runtime_agent` field is deliberately harness-neutral: the adapter decides how the role is represented in the target harness. Builtins recognized by the oh-my-opencode-slim adapter: `orchestrator`, `oracle`, `librarian`, `explorer`, `fixer`, `designer`, `council`, `observer`. Everything else (or `runtime_agent: custom`) creates a custom agent including `prompt` and `orchestratorPrompt` derived from the `purpose` field. ### Mapping formats ```yaml model_classes: fast-research: ollama/qwen3.5:9b # simple high-reasoning: # extended model: ollama/qwen3.6:35b-a3b-q4_K_M variant: thinking temperature: 0.3 ``` All extra fields are passed through 1:1 into the agent entry of the preset. ## What the CPM checks 1. Team profile present, schema known, `id` and `roles` present 2. Every `model_class` has a mapping entry (otherwise error with fix hint) 3. MCPs matched against `~/.config/opencode/opencode.json(c)` (**warning**, not fatal) 4. Roles without MCPs/skills -> note ## Examples | Example | Based on | Team | |---|---|---| | `examples/package/` | Own `job-application` package (OpenViking + ShareLaTeX) | `acme.job-applications` – Researcher, Writer, Checker, Notifier | | `examples/microsoft-design-review/` | Official [microsoft/apm-sample-package](https://github.com/microsoft/apm-sample-package) | `acme.design-review` – Reviewer (Oracle), Style-Checker (Fixer), Accessibility-Auditor | | `examples/microsoft-issue-autopilot/` | Official [`apm-issue-autopilot`](https://github.com/microsoft/apm/tree/main/packages/apm-issue-autopilot) from the microsoft/apm repo | `acme.issue-autopilot` – Triager, Shepherd, PR-Writer, Reviewer (+ GitHub MCP) | The two Microsoft examples are thin CPM wrappers: their own `apm.yml` pulls the official package as a versioned APM dependency (`microsoft/apm-sample-package#v1.0.0` or monorepo subpath `microsoft/apm/packages/apm-issue-autopilot`) and only adds the team recommendation. ```bash cd corentic-package-manager/examples # Dry run: what would be generated? python3 ../cpm.py check --package package --mapping model-mapping.yaml python3 ../cpm.py check --package microsoft-design-review --mapping model-mapping.yaml python3 ../cpm.py check --package microsoft-issue-autopilot --mapping model-mapping.yaml # Render into the example project python3 ../cpm.py render --package package \ --mapping model-mapping.yaml \ --output package/.opencode/oh-my-opencode-slim.json ``` Expected result: preset `acme-job-applications` with five agents – `orchestrator`, `librarian` (alias `researcher`), custom agent `writer`, `oracle` (alias `checker`), custom agent `notifier`. The researcher gets no LaTeX access, the writer sees no job-search tools, the notifier gets no external access at all. Then: ```bash cd package && opencode /preset acme-job-applications ``` ## Troubleshooting | Problem | Cause/Fix | |---|---| | `Model class X is not mapped` | Add to the mapping, re-render | | `Warning: MCP ... not configured` | Set up the MCP in `opencode.jsonc` or remove it from the profile | | `/preset` does not show anything new | Reload OpenCode after rendering; presets do not apply mid-session | | Preset lost after manual editing | The file is generated – changes belong in the mapping or team profile | | YAML errors | Follow the line number in the error message | ## Deliberate limits - The CPM does not start agents and orchestrates nothing at runtime – that is the job of the target harness. - MCP/skill allowlists are capability scoping, not a sandbox. Irreversible actions need server-side authorization + human approval. - Model availability is checked against opencode.json(c) names, not via API health checks.