Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
100 changes: 86 additions & 14 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,33 +4,105 @@ on:
push:
branches: [main]
pull_request:
workflow_dispatch:
inputs:
artifact-stage:
description: Candidate, or final exact tarball for controller publication after every gate passes
type: choice
options: [candidate, final]
default: candidate

permissions:
contents: read

jobs:
# Preserve these exact required contexts: verify (22.12.0), verify (24.x).
verify:
runs-on: ubuntu-latest
timeout-minutes: 10
timeout-minutes: 15
strategy:
matrix:
node-version: [22.12.0, 24.x]

steps:
- name: Check out source
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1

- name: Set up Node.js
uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
- uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
with:
node-version: ${{ matrix.node-version }}
cache: npm
- run: npm ci
- name: Install the exact config-smoke host (no acceptance skips)
run: |
npm install --prefix "$RUNNER_TEMP/verify-host" --no-audit --no-fund opencode-ai@1.18.22
echo "$RUNNER_TEMP/verify-host/node_modules/.bin" >> "$GITHUB_PATH"
- run: npm run verify
- run: npm audit --audit-level=high
- run: npm exec playwright install --with-deps chromium
- run: npm run test:browser

- name: Install locked dependencies
run: npm ci

- name: Verify source, tests, and production build
run: npm run verify
pack:
needs: verify
runs-on: ubuntu-latest
timeout-minutes: 10
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
- uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
with:
node-version: 22.12.0
cache: npm
- run: npm ci
- run: npm run build
# Source verification has already passed; never repack in consumers.
- name: Pack one immutable tarball with checksum and source evidence
env:
OMC_ARTIFACT_STAGE: ${{ inputs.artifact-stage || 'candidate' }}
run: node scripts/pack-artifact.mjs artifact
- uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: omc-${{ inputs.artifact-stage || 'candidate' }}-tarball
path: artifact/
if-no-files-found: error
retention-days: 30

- name: Audit dependencies
run: npm audit --audit-level=high
acceptance:
needs: pack
runs-on: ${{ matrix.os }}
timeout-minutes: 25
strategy:
fail-fast: false
matrix:
os: [ubuntu-latest, macos-latest]
node-version: [22.12.0, 24.x]
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
- uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
with:
node-version: ${{ matrix.node-version }}
cache: npm
- run: npm ci
- uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
with:
name: omc-${{ inputs.artifact-stage || 'candidate' }}-tarball
path: artifact
- name: Verify inner tarball digest
run: node scripts/check-artifact.mjs artifact
- name: Install exact OpenCode versions in isolated prefixes
run: |
npm install --prefix "$RUNNER_TEMP/host122" --no-audit --no-fund opencode-ai@1.18.22
npm install --prefix "$RUNNER_TEMP/host128" --no-audit --no-fund opencode-ai@1.18.28
mkdir evidence
- name: Install the pinned browser for exact-artifact acceptance
run: npm exec playwright install --with-deps chromium
- name: Exact tarball plugin on both hosts, production UI, upgrade and MCP
run: OMC_HOST_BINARY_122="$RUNNER_TEMP/host122/node_modules/.bin/opencode" OMC_HOST_BINARY_128="$RUNNER_TEMP/host128/node_modules/.bin/opencode" OMC_EVIDENCE_PATH=evidence/package.json npm run test:package -- artifact/*.tgz
- name: Prove damaged package plugin and UI cannot use checkout fallbacks
if: matrix.os == 'ubuntu-latest' && matrix.node-version == '22.12.0'
run: OMC_HOST_BINARY="$RUNNER_TEMP/host128/node_modules/.bin/opencode" OMC_EVIDENCE_PATH=evidence/artifact-guards.json node scripts/artifact-guards.mjs artifact/*.tgz
- name: Live public metadata smoke, no inference
run: OMC_EVIDENCE_PATH=evidence/live-public-metadata.json npm run test:metadata
- uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
if: always()
with:
name: acceptance-${{ matrix.os }}-${{ matrix.node-version }}
path: evidence/
if-no-files-found: error
retention-days: 30
10 changes: 10 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,16 @@

All notable changes to OpenCode Model Control are recorded here. The project follows [Semantic Versioning](https://semver.org/).

## 0.3.0

- Replace historical free-model authorization with exact provider/model/API pricing evidence from credential-free public Models.dev metadata, including all supported supplied billing dimensions. Refresh every 15 minutes while active; expire evidence after 24 hours and block missing, conflicting, malformed, or expired pricing at dispatch.
- Preserve full effective and supplemental capabilities, including unknown versus false, modalities, tools, reasoning, structured output and limits. Supplemental metadata cannot expand OpenCode's effective restrictions; ranking and benchmark qualification are unchanged.
- Add default-on policy inclusion with explicit enable/disable overrides. Saved Paid policy can authorize future eligible known-paid models; explicit disables, unknown pricing and incompatible models remain blocked.
- Migrate saved intent to schema v3 with private exact backups, cross-process coordination and revision-aware Save. Preserve drafts and blocked pins through refresh/conflicts without overwriting another writer or persisting inferred enrollment.
- Install stable model-free agents and apply current saved roles to all owned turns and ordinary resumed tasks. Recheck host inventory, API identity, capabilities, rates and policy immediately before inference. Already-loaded role changes apply live; newly discovered models absent from the running host require an explicit reload.
- Preserve tool-free media analysis and bounded worker/reviewer repair with message-scoped, revocation-aware runtime guards, verified background completion, and a narrow owned slash-summary allowance. Headless reload guidance requires the OpenCode event stream; instances are never automatically disposed.
- Add exact installed-package Linux/macOS host and production-browser acceptance with tarball and served-asset digests, plus corrupted-package regressions. These synthetic integration checks make no real-provider inference or model-quality claims. Final packaging and public-channel verification use separate release gates.

## 0.2.1 - 2026-09-01

- Made any available, capability-compatible known-paid model selectable in a role dropdown while Paid mode is active, regardless of provider. Selecting a disabled model is now the explicit opt-in that enables only that model for routing; Automatic never enables models by itself.
Expand Down
6 changes: 4 additions & 2 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ npm ci
npm run verify
```

OpenCode 1.18.x is required for full live integration acceptance, but most checks run without it. When OpenCode is installed, the acceptance suite uses isolated temporary configuration directories. Tests and examples must never connect to a real user config, invoke a paid model, or rely on private credentials.
Exact OpenCode 1.18.22 and 1.18.28 binaries are required for release host/package acceptance. The full source gate puts an exact host on PATH so config-smoke tests do not skip. Host and package acceptance fail if their required binaries are absent. All acceptance uses isolated temporary configuration directories. Tests and examples must never connect to a real user config, invoke a paid model, or rely on private credentials.

Documentation-only changes should still run `npm run verify` when practical. State exactly what was not run and why.

Expand All @@ -23,10 +23,12 @@ Documentation-only changes should still run `npm run verify` when practical. Sta
4. Update documentation when behavior, support, security, or benchmark claims change.
5. Run `npm run verify` and report any check you could not run.

Routing changes must keep unknown pricing blocked, preserve the verified-free default, and require an explicit user choice before known paid models become eligible. Connector changes must preserve unrelated OpenCode configuration, fail closed on ownership conflicts, and include isolated install/disconnect tests.
Routing changes must keep unknown/expired pricing blocked and preserve the verified-free default. Saving Paid is the explicit authorization for known-paid routing; with auto-include on, it also authorizes future eligible known-paid models without a per-model click. Preserve explicit disables and never write inferred enrollment as saved intent. Public metadata cannot expand host-effective capabilities. Preserve existing ranking and defer authentication integrations unless separately approved. Connector changes must preserve unrelated OpenCode configuration, fail closed on ownership conflicts, and include isolated install/disconnect tests.

Do not include credentials, private prompts, user transcripts, proprietary source code, benchmark data you cannot redistribute, or code copied from closed-source routers. Contributions must be clean-room work or compatible third-party material with its provenance and license recorded.

Run `npm run test:browser` for panel changes. For runtime or release changes use the exact-binary, installed-tarball commands in [Releasing](docs/releasing.md), including both host versions, production UI assets, digest binding, and corrupted-artifact rejection. Do not substitute checkout tests for installed artifact acceptance. Documentation/version-only changes need no new tests that mirror the edits; run relevant existing checks and report which final-byte/CI gates remain.

## Developer Certificate of Origin

This project uses the [Developer Certificate of Origin 1.1](https://developercertificate.org/). Every commit must include a sign-off certifying that you have the right to submit the contribution under this project's license.
Expand Down
Loading