2026-08-23 17:26:28 +02:00
# Corentic Package Manager (CPM)
2026-08-23 17:03:40 +02:00
2026-08-23 17:56:09 +02:00
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.
2026-08-23 17:03:40 +02:00
2026-08-23 17:56:09 +02:00
Translation targets:
2026-08-23 17:26:28 +02:00
2026-08-23 17:56:09 +02:00
| Target harness | Status |
2026-08-23 17:26:28 +02:00
|---|---|
2026-08-23 17:56:09 +02:00
| [oh-my-opencode-slim ](https://ohmyopencodeslim.com/ ) | ✅ implemented |
| oh-my-pi | planned |
| Codex / Claude / Copilot | vision |
2026-08-23 17:26:28 +02:00
2026-08-23 17:56:09 +02:00
Deterministic – the CPM does not guess. It assumes no availability and never picks models automatically.
2026-08-23 17:03:40 +02:00
```
2026-08-23 17:56:09 +02:00
CPM package User Runtime
2026-08-23 17:26:28 +02:00
apm.yml + + model-mapping.yaml → cpm render → .opencode/
2026-08-23 17:56:09 +02:00
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)
2026-08-23 17:03:40 +02:00
```
2026-08-23 17:56:09 +02:00
## Prerequisites
2026-08-23 17:03:40 +02:00
2026-08-23 17:56:09 +02:00
- 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`
2026-08-23 17:03:40 +02:00
2026-08-23 17:56:09 +02:00
## Quickstart
2026-08-23 17:03:40 +02:00
2026-08-23 17:10:35 +02:00
```bash
2026-08-23 17:56:09 +02:00
# 1. Create the model mapping – interactively, choosing from your opencode models
2026-08-23 17:26:28 +02:00
python3 cpm.py init --fill
2026-08-23 17:10:35 +02:00
2026-08-23 17:56:09 +02:00
# 2. Guided: read team profile, check/fill mapping, render
cd < project >
python3 /path/to/cpm.py setup --package /path/to/package
2026-08-23 17:10:35 +02:00
2026-08-23 17:56:09 +02:00
# 3. Activate
opencode # project config gets loaded
2026-08-23 17:10:35 +02:00
/preset acme-job-applications
2026-08-23 17:56:09 +02:00
# Reload OpenCode -> team is active (by design: no hot-swap)
2026-08-23 17:10:35 +02:00
```
2026-08-23 17:56:09 +02:00
Alternatively manually:
2026-08-23 17:10:35 +02:00
2026-08-23 17:03:40 +02:00
```bash
2026-08-23 17:56:09 +02:00
# 1. Create the model mapping once
2026-08-23 17:26:28 +02:00
mkdir -p ~/.config/cpm
cp examples/model-mapping.yaml ~/.config/cpm/model-mapping.yaml
2026-08-23 17:56:09 +02:00
$EDITOR ~/.config/cpm/model-mapping.yaml # adapt to your own models
2026-08-23 17:03:40 +02:00
2026-08-23 17:56:09 +02:00
# 2. Validate (dry run)
2026-08-23 17:26:28 +02:00
python3 cpm.py check --package examples/package
2026-08-23 17:03:40 +02:00
2026-08-23 17:56:09 +02:00
# 3. Render
cd < project >
python3 /path/to/cpm.py render --package /path/to/package
2026-08-23 17:03:40 +02:00
```
2026-08-23 17:56:09 +02:00
## The three files
2026-08-23 17:03:40 +02:00
2026-08-23 17:56:09 +02:00
| File | Owned by | Purpose | Edit manually? |
2026-08-23 17:03:40 +02:00
|---|---|---|---|
2026-08-23 17:56:09 +02:00
| `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 |
2026-08-23 17:03:40 +02:00
2026-08-23 17:56:09 +02:00
Plus a provenance file `.opencode/oh-my-opencode-slim.cpm-provenance.json` documenting which role received which model.
2026-08-23 17:03:40 +02:00
2026-08-23 17:56:09 +02:00
## Command reference
2026-08-23 17:03:40 +02:00
```bash
2026-08-23 17:56:09 +02:00
python3 cpm.py init [--mapping FILE] [--fill] # create/fill mapping
python3 cpm.py setup --package DIR [--mapping F] ... # guided flow
2026-08-23 17:26:28 +02:00
python3 cpm.py render --package DIR [--mapping F] [--output F] [--dry-run]
2026-08-23 17:56:09 +02:00
python3 cpm.py check --package DIR [--mapping F] # dry-run validation
2026-08-23 17:03:40 +02:00
```
2026-08-23 17:56:09 +02:00
### `init` – create the mapping
2026-08-23 17:10:35 +02:00
2026-08-23 17:56:09 +02:00
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.
2026-08-23 17:10:35 +02:00
2026-08-23 17:56:09 +02:00
### `setup` – guided flow
2026-08-23 17:10:35 +02:00
2026-08-23 17:56:09 +02:00
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.
2026-08-23 17:10:35 +02:00
### `render` / `check`
2026-08-23 17:56:09 +02:00
| Option | Default | Meaning |
2026-08-23 17:03:40 +02:00
|---|---|---|
2026-08-23 17:56:09 +02:00
| `--package` | `.` | CPM package directory containing `team-profile.yaml` |
| `--mapping` | `~/.config/cpm/model-mapping.yaml` | Local mapping table |
| `--output` | `<package>/.opencode/oh-my-opencode-slim.json` | Target file |
| `--team-file` | `team-profile.yaml` (alternatively `team.yaml` ) | Alternative profile filename |
2026-08-23 17:03:40 +02:00
2026-08-23 17:56:09 +02:00
**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 <name>` .
2026-08-23 17:03:40 +02:00
2026-08-23 17:56:09 +02:00
## Team profile schema (`corentic.team-profile/v1`)
2026-08-23 17:03:40 +02:00
```yaml
schema: corentic.team-profile/v1
2026-08-23 17:56:09 +02:00
id: acme.job-applications # becomes the preset name (namespaced)
2026-08-23 17:03:40 +02:00
description: ...
roles:
2026-08-23 17:56:09 +02:00
- 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
2026-08-23 17:03:40 +02:00
capabilities:
2026-08-23 17:56:09 +02:00
mcps: [websearch, openviking] # MCP allowlist ([] = none)
skills: [job-application] # skill allowlist ([] = none)
2026-08-23 17:03:40 +02:00
```
2026-08-23 17:56:09 +02:00
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.
2026-08-23 17:03:40 +02:00
2026-08-23 17:56:09 +02:00
### Mapping formats
2026-08-23 17:03:40 +02:00
```yaml
model_classes:
2026-08-23 17:56:09 +02:00
fast-research: ollama/qwen3.5:9b # simple
high-reasoning: # extended
2026-08-23 17:03:40 +02:00
model: ollama/qwen3.6:35b-a3b-q4_K_M
variant: thinking
temperature: 0.3
```
2026-08-23 17:56:09 +02:00
All extra fields are passed through 1:1 into the agent entry of the preset.
2026-08-23 17:03:40 +02:00
2026-08-23 17:56:09 +02:00
## What the CPM checks
2026-08-23 17:03:40 +02:00
2026-08-23 17:56:09 +02:00
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
2026-08-23 17:03:40 +02:00
2026-08-23 17:56:09 +02:00
## Examples
feat(cpm): official Microsoft APM packages as team examples
Two thin CPM wrappers around official upstream packages, each with a
team-profile mapping their primitives to agent roles:
- microsoft-design-review: wraps microsoft/apm-sample-package#v1.0.0
(design-standards, design-review, accessibility-audit, style-checker)
-> roles: reviewer (oracle), style-checker (fixer), accessibility-auditor
- microsoft-issue-autopilot: wraps microsoft/apm/packages/apm-issue-autopilot
(triage-panel, shepherd-driver, pr-description-skill) + github-mcp-server
-> roles: triager, shepherd, pr-writer (custom), reviewer
Both validate with cpm check; README examples table added.
2026-08-23 17:45:55 +02:00
2026-08-23 17:56:09 +02:00
| Example | Based on | Team |
feat(cpm): official Microsoft APM packages as team examples
Two thin CPM wrappers around official upstream packages, each with a
team-profile mapping their primitives to agent roles:
- microsoft-design-review: wraps microsoft/apm-sample-package#v1.0.0
(design-standards, design-review, accessibility-audit, style-checker)
-> roles: reviewer (oracle), style-checker (fixer), accessibility-auditor
- microsoft-issue-autopilot: wraps microsoft/apm/packages/apm-issue-autopilot
(triage-panel, shepherd-driver, pr-description-skill) + github-mcp-server
-> roles: triager, shepherd, pr-writer (custom), reviewer
Both validate with cpm check; README examples table added.
2026-08-23 17:45:55 +02:00
|---|---|---|
2026-08-23 17:56:09 +02:00
| `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) |
feat(cpm): official Microsoft APM packages as team examples
Two thin CPM wrappers around official upstream packages, each with a
team-profile mapping their primitives to agent roles:
- microsoft-design-review: wraps microsoft/apm-sample-package#v1.0.0
(design-standards, design-review, accessibility-audit, style-checker)
-> roles: reviewer (oracle), style-checker (fixer), accessibility-auditor
- microsoft-issue-autopilot: wraps microsoft/apm/packages/apm-issue-autopilot
(triage-panel, shepherd-driver, pr-description-skill) + github-mcp-server
-> roles: triager, shepherd, pr-writer (custom), reviewer
Both validate with cpm check; README examples table added.
2026-08-23 17:45:55 +02:00
2026-08-23 17:56:09 +02:00
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.
2026-08-23 17:03:40 +02:00
```bash
2026-08-23 17:26:28 +02:00
cd corentic-package-manager/examples
2026-08-23 17:03:40 +02:00
2026-08-23 17:56:09 +02:00
# Dry run: what would be generated?
2026-08-23 17:26:28 +02:00
python3 ../cpm.py check --package package --mapping model-mapping.yaml
feat(cpm): official Microsoft APM packages as team examples
Two thin CPM wrappers around official upstream packages, each with a
team-profile mapping their primitives to agent roles:
- microsoft-design-review: wraps microsoft/apm-sample-package#v1.0.0
(design-standards, design-review, accessibility-audit, style-checker)
-> roles: reviewer (oracle), style-checker (fixer), accessibility-auditor
- microsoft-issue-autopilot: wraps microsoft/apm/packages/apm-issue-autopilot
(triage-panel, shepherd-driver, pr-description-skill) + github-mcp-server
-> roles: triager, shepherd, pr-writer (custom), reviewer
Both validate with cpm check; README examples table added.
2026-08-23 17:45:55 +02:00
python3 ../cpm.py check --package microsoft-design-review --mapping model-mapping.yaml
python3 ../cpm.py check --package microsoft-issue-autopilot --mapping model-mapping.yaml
2026-08-23 17:03:40 +02:00
2026-08-23 17:56:09 +02:00
# Render into the example project
2026-08-23 17:26:28 +02:00
python3 ../cpm.py render --package package \
2026-08-23 17:03:40 +02:00
--mapping model-mapping.yaml \
--output package/.opencode/oh-my-opencode-slim.json
```
2026-08-23 17:56:09 +02:00
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.
2026-08-23 17:03:40 +02:00
2026-08-23 17:56:09 +02:00
Then:
2026-08-23 17:03:40 +02:00
```bash
cd package & & opencode
/preset acme-job-applications
```
## Troubleshooting
2026-08-23 17:56:09 +02:00
| Problem | Cause/Fix |
2026-08-23 17:03:40 +02:00
|---|---|
2026-08-23 17:56:09 +02:00
| `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 |
2026-08-23 17:03:40 +02:00
2026-08-23 17:56:09 +02:00
## Deliberate limits
2026-08-23 17:03:40 +02:00
2026-08-23 17:56:09 +02:00
- 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.