Repository navigation
Expand file tree
/
Copy pathopencode.jsonc
More file actions
88 lines (88 loc) · 5.24 KB
/
Copy pathopencode.jsonc
File metadata and controls
88 lines (88 loc) · 5.24 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
{
// OpenCode V2 project configuration, generated by `arggon init` because no
// OpenCode config existed in this repository. Edit it freely: once modified,
// re-runs treat it as adopter-owned and skip it, and adding your own
// opencode.json(c) stops generating this file entirely.
// The native `arggon` tools and commands ship in the vendored plugin at
// `.opencode/plugins/arggon/` (no `node_modules` needed); there is no MCP
// stanza by default (ADR 0011 §5/§6) — add `mcp.servers.arggon` yourself if
// you want the stdio server for another client.
// Docs: https://opencode.ai/v2/docs/
"$schema": "https://opencode.ai/config.json",
// `formatter: true` runs the built-in prettier as `<prettier> --write $FILE`
// with the session's project directory as cwd. Prettier resolves
// `.prettierignore` from that cwd and matches patterns relative to it, so a
// session rooted in the primary checkout editing a file in a sibling git
// worktree (`../<repo>-<item-id>/...`, the arggon `start` layout) bypasses
// the ignore file: the anchored pattern `opencode/plugins/arggon/` does not
// match `../<repo>-<id>/opencode/plugins/arggon/index.ts`, and a ~4k-line
// semicolon-free file gets reformatted (observed 2026-09-28, reverted by the
// worker; probe evidence on the item). This override keeps the same prettier
// invocation but anchors it at the edited file's own git root (the worktree
// root for worktrees), so the ignore file that actually governs the file
// applies. Non-ignored files format exactly as before; when no prettier
// resolves (e.g. a cold worktree before `start` links the install), the
// command exits 0 and formats nothing — skipping beats wrong-style churn.
"formatter": {
"prettier": {
"command": [
"sh",
"-c",
"f=$1; d=$(CDPATH= cd -- \"$(dirname -- \"$f\")\" && pwd); root=$(git -C \"$d\" rev-parse --show-toplevel 2>/dev/null) || root=$d; p=$root/node_modules/.bin/prettier; [ -x \"$p\" ] || p=$(command -v prettier) || exit 0; cd \"$root\" && exec \"$p\" --write \"$f\"",
"prettier-cwd-guard",
"$FILE",
],
},
},
"compaction": {
"keep": {
"tokens": 15000,
},
},
// Minimal workflow gates (W4, task-native-permissions-worktrees). They
// complement — never replace — the kernel invariants (never steal a claim,
// never reopen done/cancelled) and the methodology's review bar; the kernel
// stays the authority. The base policy stays allow-all: no global `ask`, so
// ordinary and headless sessions are never blocked. The patterns are
// best-effort shell text (documented limits): delete a rule here if your
// workflow needs it, this file is yours once edited.
//
// WHICH LAYER HONORS THIS BLOCK — probed 2026-10-15
// (bug-task-permissions-enforcement-not-observed, harness
// `npm run smoke:permissions-probe`): the OpenCode V2 runtime's own
// permission evaluation reads it, for every agent, and a session picks up an
// edit made after it started (fresh run, continued session and a long-lived
// background service all enforced it). The ZCode and Claude seams do NOT
// read this file: they enforce their own `hooks/gate.mjs` gate, which still
// refuses `--force-with-lease`. The vendored plugin adds no permission
// surface of its own. The kernel stays the enforcement of record.
//
// Force-push discriminator
// (bug-force-push-gate-blocks-the-rebase-path-the-lead-must-use, observed
// live 2026-10-11): one `git push --force*` glob cannot tell the blind
// `--force` from the lease-checked `--force-with-lease` — its `*` matches the
// `-` — so it refused the rebase push the delivery lead must make, and a wave
// stopped at the merge step. The deny stays as it is (that is what keeps
// `;` / `&&` / quoted forms refused) and the lease-checked spellings are
// re-allowed AFTER it: OpenCode selects rules with `findLast` over the
// flattened list, so the last matching rule wins.
// permitted — `--force-with-lease`, `--force-with-lease=<ref>:<expect>`,
// `--force-if-includes` (the lease, not the refname, is what
// makes these safe: git still refuses an unseen remote tip);
// refused — bare `--force`, `-f` and the `+refspec` spelling, wherever
// they sit and whatever else the command carries.
// Known limit of text matching: an allowed lease flag is permitted with any
// tail, so a command that adds a SECOND, bare `--force`/`-f` next to it is
// not caught here — the gate discriminates on the lease spelling, not on
// every flag in the line. The kernel, the pre-commit gate and CI stay the
// enforcement of record.
"permissions": [
{ "action": "shell", "resource": "git commit --no-verify*", "effect": "deny" },
{ "action": "shell", "resource": "git push --force*", "effect": "deny" },
{ "action": "shell", "resource": "git push -f*", "effect": "deny" },
{ "action": "shell", "resource": "git push --force-with-lease *", "effect": "allow" },
{ "action": "shell", "resource": "git push --force-with-lease=*", "effect": "allow" },
{ "action": "shell", "resource": "git push --force-if-includes *", "effect": "allow" },
{ "action": "shell", "resource": "git push *+*", "effect": "deny" },
],
}