Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
44 commits
Select commit Hold shift + click to select a range
c8780d4
fix: restore guardrail tool error handling on upstream
terisuke Apr 19, 2026
a09bbbc
Merge pull request #170 from Cor-Incorporated/codex/upstream-guardrai…
terisuke Apr 19, 2026
ecb840f
fix: sign macos builds and harden team runtime
terisuke Apr 19, 2026
9a757d6
Merge pull request #171 from Cor-Incorporated/codex/upstream-guardrai…
terisuke Apr 19, 2026
1525c48
fix: harden runtime path and team diagnostics
terisuke Apr 19, 2026
11fb789
Merge pull request #172 from Cor-Incorporated/codex/runtime-live-foll…
terisuke Apr 19, 2026
5461729
fix(team): ignore carried opencode config during merge
terisuke Apr 21, 2026
37150c7
fix(team): rewrite worker absolute paths
terisuke Apr 21, 2026
5c67eec
Merge pull request #174 from Cor-Incorporated/codex/team-session-merg…
terisuke Apr 21, 2026
592010e
Merge remote-tracking branch 'upstream/dev' into codex/upstream-sync-…
terisuke Apr 21, 2026
bb6acdb
fix(cli): run package bin as esm
terisuke Apr 21, 2026
51c5ec5
Merge pull request #175 from Cor-Incorporated/codex/upstream-sync-202…
terisuke Apr 21, 2026
bac4ab7
fix(team): harden isolated worktree setup
terisuke Apr 23, 2026
3c9199f
Merge pull request #177 from Cor-Incorporated/codex/team-worktree-no-…
terisuke Apr 23, 2026
50c812f
fix(team): harden isolated worktree execution (#179)
terisuke Apr 24, 2026
ce65389
merge upstream dev into fork
terisuke Apr 24, 2026
dbe3b3d
Merge pull request #180 from Cor-Incorporated/sync/upstream-dev-20260425
terisuke Apr 24, 2026
86bd761
fix(team): align permission ask test stubs (#181)
terisuke Apr 24, 2026
09fc743
fix(team): avoid operation-only gate deadlocks (#182)
terisuke Apr 24, 2026
273dbd3
fix(team): preserve worktree setup failures (#183)
terisuke Apr 24, 2026
16dbda1
Merge remote-tracking branch 'upstream/dev' into fix/team-limit-defau…
terisuke Apr 25, 2026
2904df6
fix(team): prevent default limit and worker recursion deadlocks
terisuke Apr 25, 2026
439cde3
fix(beta): escape workflow group titles
terisuke Apr 25, 2026
2cbe327
Merge pull request #184 from Cor-Incorporated/fix/team-limit-default-…
terisuke Apr 25, 2026
b6cbbbe
[codex] Fix team worker model routing (#186)
terisuke Apr 25, 2026
ac3d7d7
fix(team): persist run before preflight waits
terisuke Apr 25, 2026
6f4da7a
Merge pull request #187 from Cor-Incorporated/codex/fix-team-run-pref…
terisuke Apr 25, 2026
dfd2790
fix(guardrails): detect external review completion
terisuke Apr 25, 2026
c0167ee
Merge pull request #188 from Cor-Incorporated/codex/fix-external-revi…
terisuke Apr 25, 2026
f02e26d
fix(team): shield workers from parent abort
terisuke Apr 25, 2026
af54e04
Merge pull request #189 from Cor-Incorporated/codex/fix-team-parent-a…
terisuke Apr 25, 2026
c419f7e
fix(guardrails): mask secrets in bash output
terisuke Apr 25, 2026
eda3ef9
Merge pull request #190 from Cor-Incorporated/codex/mask-guardrail-ba…
terisuke Apr 25, 2026
c36d867
fix(guardrails): block merge bypass commands
terisuke Apr 25, 2026
35baa6f
Merge pull request #191 from Cor-Incorporated/codex/fix-merge-guardra…
terisuke Apr 25, 2026
41d3e1b
Merge remote-tracking branch 'upstream/dev' into fix/guardrails-revie…
terisuke Apr 26, 2026
6343a42
fix(guardrails): sync review logs and harden team merge
terisuke Apr 26, 2026
57c868c
Merge pull request #192 from Cor-Incorporated/fix/guardrails-review-t…
terisuke Apr 26, 2026
f0eb2ed
fix: harden guardrails team and review detection
terisuke Apr 27, 2026
9351a77
Merge pull request #193 from Cor-Incorporated/codex/guardrails-hang-r…
terisuke Apr 27, 2026
207305c
Merge upstream dev
terisuke Apr 28, 2026
cd187fb
fix tui spinner render
terisuke Apr 28, 2026
773f9cb
Merge pull request #194 from Cor-Incorporated/codex/fix-tui-spinner-r…
terisuke Apr 28, 2026
4441722
Sync Claude review state in guardrail merge gate
terisuke Apr 28, 2026
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
12 changes: 12 additions & 0 deletions bun.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

86 changes: 86 additions & 0 deletions packages/guardrails/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
# Guardrails Distribution

This package is the thin internal distribution layer for the guardrails plan.

It should be understood as the Cor-Incorporated-specific layer that sits on top of upstream-compatible OpenCode, not as a separate reimplementation of the core runtime.

It keeps upstream OpenCode as the runtime and adds organization policy at the edges:

- `bin/opencode-guardrails` sets `OPENCODE_CONFIG_DIR` to the packaged profile and then delegates to the pinned `opencode` dependency
- `managed/opencode.json` is the admin-managed profile for system deployment
- `profile/` contains the packaged custom config dir defaults, including `AGENTS.md`, `opencode.json`, and the guardrail plugin

## Design intent

This package exists to preserve the operating model imported from `claude-code-skills` without turning OpenCode into a deep fork.

- mechanism-first guardrails
- fast feedback before slower workflow gates
- pointer-based instructions instead of bloated always-loaded prompts
- runtime verifiability over "the code exists, so it must work"

Those principles come from `claude-code-skills` epic `#130` and are tracked in this fork under `docs/ai-guardrails/`.
They now also explicitly inherit Anthropic's `The Complete Guide to Building Skills for Claude` as the BDF-equivalent source for progressive disclosure, use-case-first design, and measurable testing discipline.

## Positioning

When describing this package or this fork externally, use wording close to:

- forked from OpenCode
- compatibility with upstream preserved where practical
- Cor-Incorporated-specific policy and workflow layer added in `packages/guardrails`

Avoid wording that implies this package replaces OpenCode itself. The intended architecture is still upstream engine plus thin internal distribution.

## Upstream strategy

- Keep this package version aligned with `packages/opencode/package.json`
- Upgrade upstream first, then update this package only where the extension surface changed
- Prefer `managed/` and `profile/` assets over core patches

## Current scope

Current contents focus on the first thin-distribution slice:

- packaged wrapper entrypoint
- managed enterprise defaults
- packaged custom config dir profile
- packaged plugin for runtime guardrail hooks
- guarded `implement` and `review` agents plus packaged `/implement`, `/review`, `/ship`, and `/handoff` workflow commands
- declarative provider admission policy for `zai`, `zai-coding-plan`, `openai`, and the isolated OpenRouter evaluation lane
- scenario coverage for managed config precedence, project-local asset compatibility, plugin behavior, and workflow safety defaults

Planned next slices are tracked in the fork:

- epic [#1](https://github.com/Cor-Incorporated/opencode/issues/1)
- MVP readiness epic [#16](https://github.com/Cor-Incorporated/opencode/issues/16)
- safe agents and commands [#5](https://github.com/Cor-Incorporated/opencode/issues/5)
- provider policy [#6](https://github.com/Cor-Incorporated/opencode/issues/6)
- scenario/replay harness [#7](https://github.com/Cor-Incorporated/opencode/issues/7)
- plugin hardening wave 2 [#13](https://github.com/Cor-Incorporated/opencode/issues/13)
- post-MVP CI and release gates [#14](https://github.com/Cor-Incorporated/opencode/issues/14)
- post-MVP broader asset migration [#12](https://github.com/Cor-Incorporated/opencode/issues/12)

## Usage

Run the wrapper directly:

```sh
opencode-guardrails
```

It respects an existing `OPENCODE_CONFIG_DIR` so project- or environment-specific overrides can still replace the packaged profile when needed.

The packaged profile defaults to the `implement` agent. Review and release-readiness work should run through the packaged `/review`, `/ship`, and `/handoff` commands so the workflow stays read-only at the gate layer.

Provider admission is also packaged here. Standard confidential-code work is admitted on the `zai`, `zai-coding-plan`, and `openai` lane. `zai-coding-plan` is kept as a separate provider because Z.AI's official OpenCode guide tells Coding Plan subscribers to select `Z.AI Coding Plan` explicitly. OpenRouter-backed candidates are available only through the dedicated `provider-eval` lane so evaluation traffic does not silently become the default implementation path.

## Managed deployment

Copy [managed/opencode.json](/Users/teradakousuke/Developer/opencode/packages/guardrails/managed/opencode.json) into the system managed config directory:

- macOS: `/Library/Application Support/opencode/opencode.json`
- Linux: `/etc/opencode/opencode.json`
- Windows: `%ProgramData%\\opencode\\opencode.json`

For macOS MDM deployments, use the same keys in the `ai.opencode.managed` payload that OpenCode already reads through managed preferences.
54 changes: 54 additions & 0 deletions packages/guardrails/bin/opencode-guardrails
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
#!/usr/bin/env node

import { spawnSync } from "node:child_process"
import fs from "node:fs"
import path from "node:path"
import { fileURLToPath } from "node:url"
import { parseEnv } from "node:util"

function fail(msg) {
console.error(msg)
process.exit(1)
}

function bin() {
const file = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "..", "..", "opencode", "package.json")
const root = path.dirname(file)
const json = JSON.parse(fs.readFileSync(file, "utf8"))
const rel = typeof json.bin === "string" ? json.bin : json.bin?.opencode
if (!rel) fail("Failed to resolve opencode bin from dependency")
return path.resolve(root, rel)
}

function env(dir) {
let cur = dir
for (;;) {
const file = path.join(cur, ".env")
if (fs.existsSync(file)) return file
const parent = path.dirname(cur)
if (parent === cur) return
cur = parent
}
}

function load(dir) {
const file = env(dir)
if (!file) return
const data = parseEnv(fs.readFileSync(file, "utf8").replace(/^\s*export\s+/gm, ""))
for (const [key, val] of Object.entries(data)) {
process.env[key] ??= val
}
}

const dir = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "..", "profile")
load(process.cwd())
process.env.OPENCODE_CONFIG_DIR ||= dir
process.env.OPENCODE_EXPERIMENTAL_PLAN_MODE ||= "true"

const out = spawnSync(bin(), process.argv.slice(2), {
stdio: "inherit",
env: process.env,
})

if (out.error) fail(out.error.message)
process.exit(typeof out.status === "number" ? out.status : 1)
124 changes: 124 additions & 0 deletions packages/guardrails/managed/opencode.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
{
"$schema": "https://opencode.ai/config.json",
"model": "zai-coding-plan/glm-5.1",
"enabled_providers": [
"zai",
"zai-coding-plan",
"openai",
"openrouter"
],
"share": "disabled",
"server": {
"hostname": "127.0.0.1",
"mdns": false
},
"provider": {
"zai": {
"whitelist": [
"glm-5",
"glm-4.5",
"glm-4.5-air"
]
},
"zai-coding-plan": {
"whitelist": [
"glm-4.5",
"glm-4.5-air",
"glm-4.5-flash",
"glm-4.5v",
"glm-4.6",
"glm-4.6v",
"glm-4.7",
"glm-4.7-flash",
"glm-4.7-flashx",
"glm-5",
"glm-5-turbo",
"glm-5.1"
]
},
"openai": {
"whitelist": [
"gpt-5.5",
"gpt-5.5-mini",
"gpt-5.3-codex",
"gpt-5.2",
"gpt-5.2-codex",
"gpt-5.1-codex",
"gpt-5.1-codex-mini",
"gpt-5.1-codex-max",
"gpt-5",
"gpt-5-mini",
"gpt-5-nano",
"gpt-4.1"
]
},
"openrouter": {
"whitelist": [
"anthropic/claude-haiku-4.5",
"anthropic/claude-opus-4.5",
"anthropic/claude-opus-4.6",
"anthropic/claude-sonnet-4.5",
"anthropic/claude-sonnet-4.6",
"google/gemini-2.5-flash",
"google/gemini-2.5-pro",
"minimax/minimax-m2.1",
"minimax/minimax-m2.5",
"moonshotai/kimi-k2.5",
"openai/gpt-5.2",
"openai/gpt-5.2-codex",
"openai/gpt-5.3-codex",
"openai/gpt-5.5",
"openai/gpt-5.5-mini",
"qwen/qwen3-coder"
]
}
},
"permission": {
"edit": "ask",
"task": "ask",
"webfetch": "ask",
"external_directory": "ask",
"bash": {
"*": "ask",
"node *": "allow",
"npm *": "allow",
"npx *": "allow",
"bun *": "allow",
"git status*": "allow",
"git diff*": "allow",
"git log*": "allow",
"git show*": "allow",
"git branch*": "allow",
"git remote*": "allow",
"git stash*": "allow",
"gh *": "allow",
"ls *": "allow",
"pwd": "allow",
"which *": "allow",
"echo *": "allow",
"cat *": "ask",
"rm -rf *": "deny",
"rm -r *": "deny",
"sudo *": "deny",
"curl * | sh*": "deny",
"wget * | sh*": "deny"
},
"read": {
"*": "allow",
"*.env": "deny",
"*.env.*": "deny",
"*.env.example": "allow",
"*id_rsa*": "deny",
"*id_ed25519*": "deny",
"*.pem": "deny",
"*.key": "deny",
"*.p12": "deny",
"*.pfx": "deny",
"*.cer": "deny",
"*.crt": "deny",
"*.der": "deny",
"*.kdbx": "deny",
"*credentials*": "deny"
}
}
}
20 changes: 20 additions & 0 deletions packages/guardrails/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
{
"$schema": "https://json.schemastore.org/package.json",
"name": "@opencode-ai/guardrails",
"version": "1.3.15",
"private": true,
"type": "module",
"license": "MIT",
"bin": {
"opencode-guardrails": "./bin/opencode-guardrails"
},
"files": [
"bin",
"managed",
"profile",
"README.md"
],
"dependencies": {
"opencode": "workspace:*"
}
}
Loading
Loading