@herjarsa/omo-meta-governor 0.26.0 → 0.26.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +462 -649
- package/dist/config.d.ts +10 -0
- package/dist/index.js +20 -20
- package/dist/index.js.map +6 -6
- package/dist/lib.js +23 -23
- package/dist/lib.js.map +7 -7
- package/dist/types.d.ts +6 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,8 +1,43 @@
|
|
|
1
1
|
# @herjarsa/omo-meta-governor
|
|
2
2
|
|
|
3
|
-
Self-judging agent orchestration layer for OpenCode.
|
|
4
|
-
|
|
5
|
-
|
|
3
|
+
> Self-judging agent orchestration layer for [OpenCode](https://opencode.ai).
|
|
4
|
+
> Observes tool executions, scores progress, dispatches decisions, and exposes
|
|
5
|
+
> **12 custom tools** the agent can invoke across CodeGraph, Graphify,
|
|
6
|
+
> AgentMemory, and SQLite — for cheaper, more accurate code understanding.
|
|
7
|
+
|
|
8
|
+
**Current version:** `0.26.0` · **License:** MIT · **Status:** stable
|
|
9
|
+
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
## Table of Contents
|
|
13
|
+
|
|
14
|
+
- [Install](#install)
|
|
15
|
+
- [What it does](#what-it-does)
|
|
16
|
+
- [12 Custom Tools](#12-custom-tools)
|
|
17
|
+
- [Code search & navigation](#code-search--navigation)
|
|
18
|
+
- [Lesson & memory](#lesson--memory)
|
|
19
|
+
- [File & symbol lookup](#file--symbol-lookup)
|
|
20
|
+
- [Safety & status](#safety--status)
|
|
21
|
+
- [Governance pipeline](#governance-pipeline)
|
|
22
|
+
- [Scoring engine](#scoring-engine)
|
|
23
|
+
- [Intervention modes](#intervention-modes)
|
|
24
|
+
- [Protocol enforcement](#protocol-enforcement)
|
|
25
|
+
- [Skill priming](#skill-priming)
|
|
26
|
+
- [Multi-phase plans](#multi-phase-plans)
|
|
27
|
+
- [Graph sync (codegraph + graphify)](#graph-sync-codegraph--graphify)
|
|
28
|
+
- [Auto-init](#auto-init)
|
|
29
|
+
- [Auto-upgrade (v0.26.0)](#auto-upgrade-v0260)
|
|
30
|
+
- [Git hooks](#git-hooks)
|
|
31
|
+
- [Process safeguards](#process-safeguards)
|
|
32
|
+
- [Persistence & observability](#persistence--observability)
|
|
33
|
+
- [CI monitor (v0.25.0)](#ci-monitor-v0250)
|
|
34
|
+
- [Configuration reference](#configuration-reference)
|
|
35
|
+
- [Architecture overview](#architecture-overview)
|
|
36
|
+
- [Testing](#testing)
|
|
37
|
+
- [Migration from earlier versions](#migration-from-earlier-versions)
|
|
38
|
+
- [License](#license)
|
|
39
|
+
|
|
40
|
+
---
|
|
6
41
|
|
|
7
42
|
## Install
|
|
8
43
|
|
|
@@ -10,9 +45,7 @@ that the agent can invoke across CodeGraph, Graphify, AgentMemory, and SQLite.
|
|
|
10
45
|
npm install @herjarsa/omo-meta-governor
|
|
11
46
|
```
|
|
12
47
|
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
Add as a plugin in your OpenCode config:
|
|
48
|
+
Add as a plugin in your OpenCode config (`~/.config/opencode/opencode.jsonc`):
|
|
16
49
|
|
|
17
50
|
```jsonc
|
|
18
51
|
{
|
|
@@ -20,156 +53,165 @@ Add as a plugin in your OpenCode config:
|
|
|
20
53
|
}
|
|
21
54
|
```
|
|
22
55
|
|
|
23
|
-
The
|
|
24
|
-
|
|
56
|
+
The 12 custom tools register automatically on every load. To also enable
|
|
57
|
+
the governance pipeline (scoring, intervention, protocol enforcement):
|
|
25
58
|
|
|
26
59
|
```jsonc
|
|
27
60
|
{
|
|
28
61
|
"meta_governor": {
|
|
29
62
|
"enabled": true,
|
|
30
|
-
"intervention": {
|
|
31
|
-
"mode": "message",
|
|
32
|
-
"minActionForMessage": "warn"
|
|
33
|
-
}
|
|
63
|
+
"intervention": { "mode": "message", "minActionForMessage": "warn" }
|
|
34
64
|
}
|
|
35
65
|
}
|
|
36
66
|
```
|
|
37
67
|
|
|
38
|
-
|
|
68
|
+
---
|
|
69
|
+
|
|
70
|
+
## What it does
|
|
71
|
+
|
|
72
|
+
`omo-meta-governor` is a single OpenCode plugin that ships **five
|
|
73
|
+
interconnected subsystems**:
|
|
74
|
+
|
|
75
|
+
| Subsystem | Purpose | Surface |
|
|
76
|
+
|---|---|---|
|
|
77
|
+
| **Graph sync** | Auto-install codegraph + graphify, build initial index, wire git hooks, auto-upgrade binaries on every load | `graphSync.*` config |
|
|
78
|
+
| **12 custom tools** | Semantic code search, impact analysis, symbol lookup, lesson recall, file/caller/node queries, health | `omo_*` tools |
|
|
79
|
+
| **Governance pipeline** | Score session progress → dispatch decision (`continue` / `warn` / `escalate` / `stop`) → optionally inject it into the agent's context | `meta_governor.enabled` |
|
|
80
|
+
| **Memory + lessons** | Persist decisions and lessons in SQLite (FTS5) + bridge to AgentMemory for cross-session recall | `omo_recall`, `omo_remember`, `omo_recall_mcp` |
|
|
81
|
+
| **Observability** | Health JSON, rotating JSONL logs, metrics, audit state, CI monitor | `omo_health`, `~/.config/opencode/meta-governor-health.json` |
|
|
82
|
+
|
|
83
|
+
All five run **inside the plugin** — no daemon, no sidecar. They share
|
|
84
|
+
process boundaries, lifecycle, and the opencode event hooks
|
|
85
|
+
(`tool.execute.before` / `tool.execute.after` / `chat.messages.transform`).
|
|
39
86
|
|
|
40
|
-
|
|
87
|
+
---
|
|
88
|
+
|
|
89
|
+
## 12 Custom Tools
|
|
41
90
|
|
|
42
|
-
|
|
91
|
+
The plugin registers 12 tools the LLM can invoke. All are available
|
|
92
|
+
immediately on install (no `enabled: true` required for tools — only the
|
|
93
|
+
governance pipeline needs `meta_governor.enabled: true`).
|
|
94
|
+
|
|
95
|
+
### Code search & navigation
|
|
43
96
|
|
|
44
97
|
| Tool | What it does | Use case |
|
|
45
|
-
|
|
46
|
-
| `omo_search` | Semantic code search via codegraph
|
|
47
|
-
| `omo_find` | Exact symbol lookup (definition + direct callers) via codegraph node | "Find the function `validateToken`" |
|
|
48
|
-
| `omo_impact` | Impact analysis:
|
|
98
|
+
|------|--------------|----------|
|
|
99
|
+
| `omo_search` | Semantic code search via codegraph or graphify | "Where is authentication handled?" — USE THIS FIRST for any architecture question |
|
|
100
|
+
| `omo_find` | Exact symbol lookup (definition + direct callers) via `codegraph node` | "Find the function `validateToken`" |
|
|
101
|
+
| `omo_impact` | Impact analysis: direct + transitive callers, test files, doc files | Run BEFORE modifying a function |
|
|
49
102
|
| `omo_path` | Shortest conceptual path between two concepts via graphify | "How does auth connect to database?" |
|
|
50
103
|
| `omo_explain` | Plain-language explanation of a concept via graphify | "What is the SwinTransformer?" |
|
|
51
104
|
|
|
52
|
-
### Lesson &
|
|
105
|
+
### Lesson & memory
|
|
53
106
|
|
|
54
107
|
| Tool | What it does | Use case |
|
|
55
|
-
|
|
108
|
+
|------|--------------|----------|
|
|
56
109
|
| `omo_recall` | Search past lessons via local SQLite FTS5 (fast, always available) | "How did we set up auth before?" |
|
|
57
110
|
| `omo_recall_mcp` | Search cross-session memory via AgentMemory | "What did we learn about X in previous sessions?" |
|
|
58
|
-
| `omo_remember` | Save a fact/observation to cross-session AgentMemory | "Remember this bug pattern for next time" |
|
|
111
|
+
| `omo_remember` | Save a fact / observation / pattern to cross-session AgentMemory | "Remember this bug pattern for next time" |
|
|
59
112
|
|
|
60
|
-
###
|
|
113
|
+
### File & symbol lookup
|
|
61
114
|
|
|
62
115
|
| Tool | What it does | Use case |
|
|
63
|
-
|
|
116
|
+
|------|--------------|----------|
|
|
117
|
+
| `omo_files` | List files indexed by codegraph or graphify | "What files are in the graph?" |
|
|
118
|
+
| `omo_callers` | List all call sites of a symbol via `codegraph callers` | "Who calls `UserService.create`?" |
|
|
119
|
+
| `omo_node` | Get source + direct callers of a symbol via `codegraph node` | "Show me the source of `validateToken` and its callers" |
|
|
64
120
|
|
|
65
|
-
### Safety &
|
|
121
|
+
### Safety & status
|
|
66
122
|
|
|
67
123
|
| Tool | What it does | Use case |
|
|
68
|
-
|
|
124
|
+
|------|--------------|----------|
|
|
69
125
|
| `omo_health` | Show plugin runtime status: metrics, decisions, errors | "Is the plugin working?" |
|
|
70
126
|
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
cat ~/.config/opencode/meta-governor-health.json
|
|
77
|
-
```
|
|
78
|
-
|
|
79
|
-
Or the agent can call `omo_health` directly to get a formatted report.
|
|
80
|
-
|
|
81
|
-
Structured JSONL logs at `~/.config/opencode/meta-governor.log` with size-based rotation
|
|
82
|
-
(10MB max, 5 rotated files).
|
|
83
|
-
|
|
84
|
-
## Persistence
|
|
85
|
-
|
|
86
|
-
Lessons learned by the plugin persist in **SQLite** at `~/.omo-meta-governor/meta-governor.db`
|
|
87
|
-
with full-text search (FTS5) for fast recall. Zero dependencies needed — uses Bun's built-in
|
|
88
|
-
`bun:sqlite`.
|
|
89
|
-
|
|
90
|
-
Optionally, the Opción A tools (`omo_remember`, `omo_recall_mcp`) can bridge to AgentMemory via `session.prompt()` — the LLM
|
|
91
|
-
receives a structured instruction to call the appropriate MCP tool.
|
|
127
|
+
All tools return a typed `ToolResult` with `title`, `output`, and
|
|
128
|
+
`metadata` (`{tool, kind, durationMs, sessionID}`). They degrade
|
|
129
|
+
gracefully — when codegraph or graphify is missing, they return a
|
|
130
|
+
**friendly hint** (e.g. `npx codegraph init` to recover) instead of
|
|
131
|
+
crashing.
|
|
92
132
|
|
|
93
|
-
|
|
133
|
+
---
|
|
94
134
|
|
|
95
|
-
|
|
96
|
-
**graphify** so each commit automatically reindexes both graphs.
|
|
135
|
+
## Governance pipeline
|
|
97
136
|
|
|
98
|
-
|
|
137
|
+
When `meta_governor.enabled: true`, the plugin attaches to opencode's
|
|
138
|
+
tool-execution stream and runs an **observe → score → decide → (optionally)
|
|
139
|
+
intervene** loop on every turn.
|
|
99
140
|
|
|
100
|
-
|
|
101
|
-
graphify via `pip install graphifyy` (falls back to `uv tool install
|
|
102
|
-
graphifyy`) if they're not already on PATH.
|
|
103
|
-
2. **Run `codegraph init`** + **`graphify . --no-viz`** to build the initial
|
|
104
|
-
indexes for the project.
|
|
105
|
-
3. **Run `graphify hook install`** to wire up the native `post-commit` and
|
|
106
|
-
`post-checkout` git hooks.
|
|
141
|
+
### Scoring engine
|
|
107
142
|
|
|
108
|
-
|
|
143
|
+
`src/scoring-engine.ts` computes a single composite score in `[-1, 1]`
|
|
144
|
+
from weighted signals:
|
|
109
145
|
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
146
|
+
| Signal | Weight | Source |
|
|
147
|
+
|--------|--------|--------|
|
|
148
|
+
| `progress-detector` | 0.30 | did the last 5 tool calls make forward progress? |
|
|
149
|
+
| `deviation-detector` | 0.20 | accumulated protocol violations (capped at 5/session) |
|
|
150
|
+
| `no-progress-detector` | 0.20 | is the agent reading without writing? |
|
|
151
|
+
| `iteration-budget` | 0.15 | are we approaching `maxIterations`? |
|
|
152
|
+
| `oracle-burn` | 0.10 | did recent oracle calls detect issues? |
|
|
153
|
+
| `stop-advice` | 0.05 | did prior lessons recommend stop? |
|
|
113
154
|
|
|
114
|
-
|
|
155
|
+
The score maps to an action via configurable thresholds (see
|
|
156
|
+
[Configuration reference](#configuration-reference)):
|
|
115
157
|
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
the confirmed cause of the Bun/OpenChamber crashes).
|
|
158
|
+
- `score ≥ continueThreshold` → **continue** (silent)
|
|
159
|
+
- `score ≤ -warnThreshold` → **warn** (log + nudge)
|
|
160
|
+
- `score ≤ -escalateThreshold` → **escalate** (block + inject)
|
|
161
|
+
- `score ≤ -stopThreshold` → **stop** (latch intervention)
|
|
121
162
|
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
163
|
+
Default thresholds: `continue: 0.05`, `warn: 0.3`, `escalate: 0.45`,
|
|
164
|
+
`stop: 0.55` (worst-case math gives `stop ≈ -0.55`, so it actually
|
|
165
|
+
fires — verified via Gap C audit).
|
|
125
166
|
|
|
126
|
-
|
|
167
|
+
### Intervention modes
|
|
127
168
|
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
### Modes
|
|
169
|
+
When the decision is `warn` / `escalate` / `stop`, the plugin can inject
|
|
170
|
+
the rationale into the agent's context via `experimental.chat.messages.transform`:
|
|
132
171
|
|
|
133
172
|
| Mode | Mechanism | Effect |
|
|
134
173
|
|------|-----------|--------|
|
|
135
174
|
| `silent` | (none) | Decision is logged only |
|
|
136
|
-
| `message` | `
|
|
137
|
-
| `system` | `
|
|
175
|
+
| `message` | `chat.messages.transform` | Injects a synthetic user message visible to the LLM |
|
|
176
|
+
| `system` | `chat.system.transform` | Appends guidance to the system prompt |
|
|
177
|
+
|
|
178
|
+
`maxInterventionsPerSession: 3` (default) hard-stops injection after 3
|
|
179
|
+
interventions per session to prevent infinite instruction loops
|
|
180
|
+
(v0.10.0). When `respectDoneSignal: true` (default), injection stops
|
|
181
|
+
once the agent emits the terminal signal AND Oracle has verified.
|
|
182
|
+
|
|
183
|
+
### Protocol enforcement
|
|
138
184
|
|
|
139
|
-
|
|
185
|
+
`src/protocol-enforcer.ts` audits tool calls against a configurable
|
|
186
|
+
protocol markdown file. Use it to enforce rules like "do not save
|
|
187
|
+
routine operations to memory" or "always invoke Oracle before declaring
|
|
188
|
+
done".
|
|
140
189
|
|
|
141
190
|
```jsonc
|
|
142
191
|
{
|
|
143
192
|
"meta_governor": {
|
|
144
193
|
"enabled": true,
|
|
145
|
-
"
|
|
146
|
-
"
|
|
147
|
-
"
|
|
148
|
-
"
|
|
149
|
-
"
|
|
150
|
-
"phaseAwareDoneSignal": true // v0.15.0: multi-phase plan support
|
|
194
|
+
"protocolEnforcement": {
|
|
195
|
+
"enabled": true,
|
|
196
|
+
"path": "./PROTOCOL.md",
|
|
197
|
+
"injectIntoSystem": true,
|
|
198
|
+
"auditToolCalls": true
|
|
151
199
|
}
|
|
152
200
|
}
|
|
153
201
|
}
|
|
154
202
|
```
|
|
155
203
|
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
| Field | Default | Description |
|
|
159
|
-
|-------|---------|-------------|
|
|
160
|
-
| `mode` | `"message"` | How to inject: `"silent"`, `"message"`, or `"system"` |
|
|
161
|
-
| `minActionForMessage` | `"warn"` | Minimum action: `"warn"`, `"escalate"`, or `"stop"` |
|
|
162
|
-
| `maxInterventionsPerSession` | `3` | Hard cap on injections per session |
|
|
163
|
-
| `respectDoneSignal` | `true` | Stop injecting after terminal signal + Oracle verified |
|
|
164
|
-
| `phaseAwareDoneSignal` | `false` | **v0.15.0**: when `true`, only `<promise>PLAN-COMPLETE</promise>` latches intervention. DONE/PHASE-N-COMPLETE are per-phase hints. Recommended for multi-phase plans. |
|
|
204
|
+
Violations accumulate in `state.accumulatedDeviations` (capped at 5 per
|
|
205
|
+
session) and feed the `deviation-detector` scoring signal.
|
|
165
206
|
|
|
166
|
-
|
|
207
|
+
### Skill priming
|
|
167
208
|
|
|
168
|
-
|
|
169
|
-
start (or once implementation work begins) prompting the
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
209
|
+
`src/skill-priming.ts` (v0.20.0) injects **one** synthetic user message
|
|
210
|
+
at session start (or once implementation work begins) prompting the
|
|
211
|
+
agent to select precise skills for the task via the AAS skill catalog
|
|
212
|
+
(`aas search_skills` / `get_skill` / `compose_stack`) and/or the
|
|
213
|
+
task-appropriate superpowers skill — before writing code. Minimal context
|
|
214
|
+
cost: the directive forbids enumerating the full catalog.
|
|
173
215
|
|
|
174
216
|
```jsonc
|
|
175
217
|
{
|
|
@@ -177,623 +219,394 @@ directive forbids enumerating the full catalog.
|
|
|
177
219
|
"enabled": true,
|
|
178
220
|
"skillPriming": {
|
|
179
221
|
"enabled": true,
|
|
180
|
-
"trigger": "
|
|
181
|
-
"router": "both"
|
|
222
|
+
"trigger": "firstImplement",
|
|
223
|
+
"router": "both"
|
|
182
224
|
}
|
|
183
225
|
}
|
|
184
226
|
}
|
|
185
227
|
```
|
|
186
228
|
|
|
187
|
-
|
|
188
|
-
|-------|---------|-------------|
|
|
189
|
-
| `enabled` | `false` | Master switch for the skill-priming nudge |
|
|
190
|
-
| `trigger` | `"firstImplement"` | `"sessionStart"`: first transform call of the session. `"firstImplement"`: once a write/edit-like tool is observed |
|
|
191
|
-
| `router` | `"both"` | Which system(s) the directive references: `"aas"`, `"superpowers"`, `"both"` |
|
|
192
|
-
|
|
193
|
-
### Multi-phase plans (v0.15.0)
|
|
229
|
+
### Multi-phase plans
|
|
194
230
|
|
|
195
|
-
For work plans with multiple phases (e.g. Sisyphus/Prometheus work
|
|
196
|
-
|
|
197
|
-
only when the **entire** plan is
|
|
231
|
+
For work plans with multiple phases (e.g. Sisyphus/Prometheus work
|
|
232
|
+
plans), set `phaseAwareDoneSignal: true` and emit
|
|
233
|
+
`<promise>PLAN-COMPLETE</promise>` only when the **entire** plan is
|
|
234
|
+
verified done by Oracle.
|
|
198
235
|
|
|
199
236
|
| Marker | Effect |
|
|
200
237
|
|--------|--------|
|
|
201
238
|
| `<promise>DONE</promise>` | Per-phase hint. Logged but does NOT latch intervention (when `phaseAwareDoneSignal: true`). |
|
|
202
|
-
| `<promise>PHASE-N-COMPLETE</promise>` | Per-phase hint (e.g. `<promise>PHASE-1-COMPLETE</promise>`). Same as DONE
|
|
239
|
+
| `<promise>PHASE-N-COMPLETE</promise>` | Per-phase hint (e.g. `<promise>PHASE-1-COMPLETE</promise>`). Same as `DONE`. |
|
|
203
240
|
| `<promise>PLAN-COMPLETE</promise>` | Terminal. Latches intervention when Oracle has verified. |
|
|
204
241
|
|
|
205
|
-
|
|
206
|
-
`phaseAwareDoneSignal: false` preserves the legacy single-task behavior). Set the
|
|
207
|
-
flag to `true` and switch your terminal marker to `PLAN-COMPLETE` to enable
|
|
208
|
-
multi-phase governance.
|
|
209
|
-
|
|
210
|
-
## v0.16.0 — Audit remediation: memory hygiene, dead code, tool coverage, CI
|
|
211
|
-
|
|
212
|
-
v0.16.0 closes the 50+ findings from the multi-front audit at `.omo/ulw-research/20260727-000530/plan-audit-v0.15.0.md`. The release is **additive in behavior, no breaking API changes** for users — only internal cleanup, dead code removal, and CI hardening.
|
|
213
|
-
|
|
214
|
-
### Highlights
|
|
215
|
-
|
|
216
|
-
#### Memory hygiene (F1)
|
|
217
|
-
|
|
218
|
-
- **`AuditStateCache`** (`src/audit-state-cache.ts`) — TTL+LRU bounded cache (100 entries, 1h TTL) replaces the bare `Map` that accumulated audit state without bounds. Stale sessions are evicted automatically.
|
|
219
|
-
- **`TTLQueue`** (`src/ttl-queue.ts`) — TTL-based expiration for `pendingBotFeedback` and `pendingViolations` queues. Previously unbounded.
|
|
220
|
-
- Removed dynamic `require("node:fs")` inside `shouldInjectPlanReminder` — replaced with static ESM imports (no more runtime module resolution failures).
|
|
221
|
-
|
|
222
|
-
#### Dead code elimination (F2)
|
|
223
|
-
|
|
224
|
-
- `takeAnyDecision()` — deprecated; removed from the active governance pipeline.
|
|
225
|
-
- `systemInjection` — now awaited eagerly instead of fire-and-forget, eliminating a silent failure route.
|
|
226
|
-
- `logToFile` in `graph-sync.ts` — wired to the real JSONL file logger (was a no-op stub).
|
|
227
|
-
- Plugin version — derived from `package.json` at runtime instead of hardcoded "0.13.0" (closes the version-drift bug where `omo_health` reported stale versions).
|
|
228
|
-
|
|
229
|
-
#### Tool bug fixes (F3)
|
|
230
|
-
|
|
231
|
-
- **AFT checkpoint/undo**: args split on whitespace broke names with spaces. Rewrote arg construction with proper quoting.
|
|
232
|
-
- **AFT subcommand**: now uses `options.projectDir` instead of `process.cwd()`.
|
|
233
|
-
- **graphify binary override**: `omo_path` / `omo_explain` honored the `graphifyBin` option (was hardcoded).
|
|
234
|
-
- **`as never` cast** on `setClient` → proper runtime guard that validates client shape.
|
|
235
|
-
- **`session-bridge`**: replaced module-level `_client` with `AsyncLocalStorage` for per-request isolation. Concurrent sessions no longer race on the same client reference.
|
|
236
|
-
|
|
237
|
-
#### Test coverage (F4)
|
|
238
|
-
|
|
239
|
-
- 22 tests covering all 15 custom tools (`src/custom-tools.test.ts`). Previously the entire public tool surface had zero test coverage.
|
|
240
|
-
- 12 tests for `decision-store` (previously untested).
|
|
241
|
-
|
|
242
|
-
#### Type/token pipeline (F5)
|
|
243
|
-
|
|
244
|
-
- `token-predictor` refactor: dead code (`delegate`/`switch-model`) removed; output is now informational-only as designed.
|
|
245
|
-
- Type alignment across `types.ts`, `token-predictor.ts`, `orchestrator.ts`.
|
|
246
|
-
|
|
247
|
-
#### CI matrix (F6)
|
|
248
|
-
|
|
249
|
-
- `bun run typecheck` now runs on **macos-latest** and **windows-latest** (was Ubuntu-only).
|
|
250
|
-
- Removed `package-lock.json` (bun project — canonical is `bun.lock`).
|
|
251
|
-
- Secret redaction layer in `logToFile` (JWT, OpenAI keys, Bearer tokens, GitHub PATs, generic key:value patterns).
|
|
252
|
-
- Implementation plan renamed `IMPLEMENTATION_PLAN.md` → `ARCHITECTURE.md`.
|
|
253
|
-
|
|
254
|
-
#### Final refactors (F7)
|
|
255
|
-
|
|
256
|
-
- Score formula documented (header doc with full formula spec).
|
|
257
|
-
- **NaN guard** in `score()` — defaults to neutral continue when `iterationRatio` or `ambient.iteration/maxIterations` produce NaN.
|
|
258
|
-
- `ACTION_SEVERITY` keyed by `DecisionHandlerOutput["action"]` union literal (was bare `Record<string, number>`).
|
|
259
|
-
- `projectHasCodegraph` / `projectHasGraphify` IIFE booleans replaced with lookup-time calls to `graphRetrieval.hasCodegraphDir(cwd)`.
|
|
260
|
-
- `extractConcepts` includes file basename for FTS lookup by tool/file name.
|
|
261
|
-
- Backup graph-sync uses `triggerReindex` (was `triggerCodegraphSync`) — reindexes both codegraph AND graphify backends.
|
|
262
|
-
|
|
263
|
-
### Test & build status
|
|
264
|
-
|
|
265
|
-
- **495/495 tests pass** (up from 487 in v0.15.0/0.15.1).
|
|
266
|
-
- `bun run typecheck` clean.
|
|
267
|
-
- `bun build.ts` clean (0.34 MB dist).
|
|
268
|
-
- `npm pack --dry-run` validated (no forbidden artifacts).
|
|
269
|
-
|
|
270
|
-
### Migration
|
|
271
|
-
|
|
272
|
-
No user action required. All changes are internal. The default `phaseAwareDoneSignal` is still `false` for backward compatibility; the v0.15.0 multi-phase behavior is preserved when explicitly enabled.
|
|
273
|
-
|
|
274
|
-
### Deferred to v0.17.0
|
|
275
|
-
|
|
276
|
-
- F5.1 — wiring `escalate` action to a real dispatcher (Oracle is recommended but not yet wired).
|
|
277
|
-
- F5.4 — `maxLessonsPerSession` enforcement (config field exists but is not enforced).
|
|
278
|
-
- F3.6 — Bridge tools lying about delivery (5 tools still return "dispatched" without polling). Recommend the user explicitly request this if delivery verification is critical.
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
## v0.17.0 — Wire escalate to Oracle, enforce lesson cap, verify bridge delivery
|
|
284
|
-
|
|
285
|
-
v0.17.0 closes the 3 deferred items from the v0.16.0 audit: **F5.1** (escalate → Oracle), **F5.4** (`maxLessonsPerSession` enforcement), and **F3.6** (bridge tool delivery verification).
|
|
286
|
-
|
|
287
|
-
### Highlights
|
|
288
|
-
|
|
289
|
-
#### F5.1 — Escalate action now fires Oracle (v0.17.0)
|
|
290
|
-
|
|
291
|
-
When the scoring engine produces an `escalate` action with target `oracle`, the plugin's `tool.execute.after` hook now fires a `session.prompt()` instructing the LLM to invoke `task(subagent_type=oracle)`. The prompt includes the decision reasoning, evidence count, and a verification pass directive. New `buildEscalationPrompt()` function in `session-bridge.ts` is the pure prompt builder (testable in isolation). User-targeted escalations get a separate prompt asking the LLM to summarize for human input.
|
|
292
|
-
|
|
293
|
-
```ts
|
|
294
|
-
// Decision flow when score lands in escalate band:
|
|
295
|
-
score ≤ -escalateThreshold (default -0.6)
|
|
296
|
-
→ decision.action = "escalate"
|
|
297
|
-
→ decision.shouldEscalateTo = "oracle" (or "user" for grave deviations)
|
|
298
|
-
→ plugin fires session.prompt with buildEscalationPrompt(...)
|
|
299
|
-
→ LLM invokes Oracle (or summarizes for user)
|
|
300
|
-
→ Oracle verifies → oracleInvoked=true → governance continues
|
|
301
|
-
```
|
|
242
|
+
---
|
|
302
243
|
|
|
303
|
-
|
|
244
|
+
## Graph sync (codegraph + graphify)
|
|
304
245
|
|
|
305
|
-
The
|
|
306
|
-
|
|
307
|
-
- `lessonCount` tracked in per-session `AuditState`
|
|
308
|
-
- `observeAndLearn()` short-circuits when `currentLessonCount >= maxLessonsPerSession`
|
|
309
|
-
- The orchestrator increments `sessionState.lessonCount` after each successful save
|
|
310
|
-
- **Cap semantics: inclusive** — when count equals cap, no more lessons are saved
|
|
246
|
+
The plugin wires the native git hooks of **codegraph** and **graphify**
|
|
247
|
+
so each commit automatically reindexes both graphs.
|
|
311
248
|
|
|
312
|
-
|
|
249
|
+
### Auto-init
|
|
313
250
|
|
|
314
|
-
|
|
251
|
+
On first load in a project (when `graphSync.enabled: true`, default):
|
|
315
252
|
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
253
|
+
1. **Auto-install** codegraph via `npm i -D @colbymchenry/codegraph` and
|
|
254
|
+
graphify via `pip install graphifyy` (falls back to
|
|
255
|
+
`uv tool install graphifyy`) if not already on PATH.
|
|
256
|
+
2. **Run `codegraph init`** + **`graphify . --no-viz`** to build the
|
|
257
|
+
initial indexes for the project.
|
|
258
|
+
3. **Run `graphify hook install`** to wire up the native `post-commit`
|
|
259
|
+
and `post-checkout` git hooks.
|
|
260
|
+
|
|
261
|
+
### Auto-upgrade (v0.26.0)
|
|
262
|
+
|
|
263
|
+
Before v0.26.0, `autoUpgrade: true` (default) silently failed. Six
|
|
264
|
+
bugs in `src/graph-sync.ts:503-628` forced users to manually run
|
|
265
|
+
`npm install -g @colbymchenry/codegraph@latest` and
|
|
266
|
+
`pip install --upgrade graphifyy`.
|
|
267
|
+
|
|
268
|
+
**Root cause bugs fixed in v0.26.0:**
|
|
269
|
+
|
|
270
|
+
1. `getInstalledCodegraphVersion` only probed `npx` — failed when the
|
|
271
|
+
binary was at `node_modules/.bin/codegraph` (Windows users).
|
|
272
|
+
2. `getInstalledGraphifyVersion` had no DI runner — Windows dual-python
|
|
273
|
+
fallback was untestable.
|
|
274
|
+
3. `shouldUpgrade` ignored the cache value (`latest=null`).
|
|
275
|
+
4. Cache cold + undetectable binary → silent noop (no diagnostic code).
|
|
276
|
+
5. **`pip install` without `--upgrade` returned 0** with
|
|
277
|
+
"Requirement already satisfied" but **did NOT upgrade** — most
|
|
278
|
+
visible bug.
|
|
279
|
+
6. `graphify check-update` was ignored — semantic re-extraction flag
|
|
280
|
+
never triggered.
|
|
281
|
+
|
|
282
|
+
**Fixes:**
|
|
283
|
+
|
|
284
|
+
- Tiered probe matching `checkToolAvailability`: `npx` +
|
|
285
|
+
`node node_modules/.bin/codegraph` for codegraph; `graphify` →
|
|
286
|
+
`python -m pip show` → `python3 -m pip show` for graphify.
|
|
287
|
+
- Runner DI seam on `getInstalledCodegraphVersion`,
|
|
288
|
+
`getInstalledGraphifyVersion`, `installCodegraph`, `installGraphify`
|
|
289
|
+
— hermetic tests, no real network in CI.
|
|
290
|
+
- `resolveLatest()` inlines cache into `shouldUpgrade` — avoids
|
|
291
|
+
double-fetch from the registry.
|
|
292
|
+
- Cache written **ONCE** at the end of the upgrade block (was being
|
|
293
|
+
fetched 3× per run).
|
|
294
|
+
- `pip install --upgrade graphifyy` / `uv tool install --upgrade graphifyy`
|
|
295
|
+
flags.
|
|
296
|
+
- `graphify check-update` integration emits
|
|
297
|
+
`graphify-reextract-triggered` when semantic re-extraction is pending.
|
|
298
|
+
- New codes: `codegraph-upgrade-broken`, `graphify-reextract-triggered`,
|
|
299
|
+
`upgrade-cache-written`.
|
|
300
|
+
- New config fields: `autoUpgrade`, `upgradeCachePath`,
|
|
301
|
+
`checkGraphifyNeedsUpdate`.
|
|
302
|
+
|
|
303
|
+
**Verified surface run:** `codegraph 0.6.8 → 1.5.0` and
|
|
304
|
+
`graphify 0.8.30 → 0.9.46` upgraded silently without manual
|
|
305
|
+
intervention.
|
|
306
|
+
|
|
307
|
+
**Configuration:**
|
|
320
308
|
|
|
321
|
-
```
|
|
322
|
-
// Bridge tool result metadata now includes:
|
|
309
|
+
```jsonc
|
|
323
310
|
{
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
311
|
+
"meta_governor": {
|
|
312
|
+
"graphSync": {
|
|
313
|
+
"enabled": true, // default true
|
|
314
|
+
"autoUpgrade": true, // v0.26.0: default true
|
|
315
|
+
"upgradeCachePath": "~/.omo-meta-governor/upgrade-cache.json",
|
|
316
|
+
"checkGraphifyNeedsUpdate": true // emit graphify-reextract-triggered when schema changed
|
|
317
|
+
}
|
|
318
|
+
}
|
|
330
319
|
}
|
|
331
320
|
```
|
|
332
321
|
|
|
333
|
-
###
|
|
334
|
-
|
|
335
|
-
- **514/514 tests pass** (up from 495 in v0.16.0 — 5 + 4 + 10 new tests across F5.4, F5.1, F3.6).
|
|
336
|
-
- `bun run typecheck` clean.
|
|
337
|
-
- `bun build.ts` clean (0.34 MB dist).
|
|
338
|
-
- `npm pack --dry-run` validated.
|
|
339
|
-
|
|
340
|
-
### Migration
|
|
341
|
-
|
|
342
|
-
No user action required. All changes are internal or additive:
|
|
343
|
-
- `deliveryStatus` is an additive metadata field — existing consumers ignore it.
|
|
344
|
-
- `maxLessonsPerSession` is now actually enforced — if you have sessions that previously saved more than 20 lessons (e.g. from before the cap was added), this may surprise you. Bump the cap in your config if needed.
|
|
345
|
-
- `escalate` action now actively fires Oracle — this is the first version where Oracle is auto-invoked, not just manually invoked by the LLM.
|
|
346
|
-
|
|
347
|
-
### Audit roadmap (status as of v0.17.0)
|
|
348
|
-
|
|
349
|
-
| Release | Status | Scope |
|
|
350
|
-
|---------|--------|-------|
|
|
351
|
-
| v0.15.1 (F0) | ✅ Shipped | Hotfix self-dep + npm pack gate |
|
|
352
|
-
| v0.16.0 (F1-F7) | ✅ Shipped | Memory hygiene, dead code, tool coverage, CI |
|
|
353
|
-
| v0.17.0 (deferred) | ✅ Shipped | F5.1 escalate, F5.4 cap, F3.6 delivery verify |
|
|
354
|
-
|
|
355
|
-
All audit findings are now closed. Future work focuses on new features and user-driven feedback.
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
## v0.17.1 — Audit args fix (patch)
|
|
360
|
-
|
|
361
|
-
v0.17.1 is a single-bug patch release. The fix addresses an issue discovered during v0.17.0 verification:
|
|
362
|
-
|
|
363
|
-
### The bug
|
|
364
|
-
|
|
365
|
-
The `tool.execute.before` hook passed an empty `{}` object as the second argument to `auditToolCall()`. This meant the audit function never saw the tool's args (e.g. file content for write tools) and could never detect:
|
|
366
|
-
|
|
367
|
-
- `@ts-ignore` / `@ts-expect-error` directives
|
|
368
|
-
- `as any` type assertions
|
|
369
|
-
- `catch(e) {}` empty catch blocks
|
|
370
|
-
|
|
371
|
-
The hook signature was also incomplete — it didn't receive the `output` parameter that contains the mutable args, even though the SDK provides it.
|
|
372
|
-
|
|
373
|
-
### The fix
|
|
374
|
-
|
|
375
|
-
Two changes in `src/plugin.ts`:
|
|
376
|
-
|
|
377
|
-
1. **Hook signature updated** to receive the `output` parameter:
|
|
378
|
-
```ts
|
|
379
|
-
"tool.execute.before": async (
|
|
380
|
-
toolInput: { tool: string; sessionID: string; callID: string },
|
|
381
|
-
_output: { args: unknown },
|
|
382
|
-
): Promise<void> => {
|
|
383
|
-
```
|
|
384
|
-
|
|
385
|
-
2. **Audit call** now passes `_output.args` instead of `{}`:
|
|
386
|
-
```ts
|
|
387
|
-
const violations = auditToolCall(toolInput.tool, _output.args, { ... })
|
|
388
|
-
```
|
|
389
|
-
|
|
390
|
-
### Tests
|
|
391
|
-
|
|
392
|
-
Added 4 new tests in `src/plugin.test.ts`:
|
|
393
|
-
- `@ts-ignore + as any` in args → `no-type-suppression` violation detected and injected
|
|
394
|
-
- `catch(e) {}` in args → `no-empty-catch` violation detected and injected
|
|
395
|
-
- Clean code → no violation injected (false-positive guard)
|
|
396
|
-
- `auditToolCalls: false` → audit short-circuits (regression check)
|
|
397
|
-
|
|
398
|
-
### Test & build status
|
|
399
|
-
|
|
400
|
-
- **518/518 tests pass** (up from 514 in v0.17.0 — 4 new audit tests).
|
|
401
|
-
- `bun run typecheck` clean.
|
|
402
|
-
- `bun build.ts` clean (0.34 MB dist).
|
|
403
|
-
|
|
404
|
-
### Migration
|
|
405
|
-
|
|
406
|
-
No user action required. The audit detection now correctly fires when the agent writes forbidden patterns. This means:
|
|
407
|
-
|
|
408
|
-
- **If your agent previously wrote `@ts-ignore` without being flagged**: it will now be flagged with `[GRAVE] no-type-suppression: ...` injected as a synthetic user message.
|
|
409
|
-
- **If you want to disable the audit**: set `protocolEnforcement.auditToolCalls: false` (already supported).
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
## v0.17.2 — Fix escalation dead code + 4 audit gaps
|
|
414
|
-
|
|
415
|
-
v0.17.2 closes 4 gaps discovered during live verification of v0.17.0/v0.17.1. The most important: F5.1 (escalate → Oracle) was effectively dead in production due to two compounding bugs.
|
|
416
|
-
|
|
417
|
-
### Highlights
|
|
418
|
-
|
|
419
|
-
#### Gap C (CRITICAL) — Escalation now actually fires
|
|
420
|
-
|
|
421
|
-
The score formula's `noProgress` and `deviations` inputs were hardcoded as `false` and `[]` in the plugin. This meant the `no-progress-detector` (weight 0.20) and `deviation-detector` (weight 0.20) signals always contributed 0. Combined with default thresholds, the maximum possible score was -0.55 — never reaching `escalateThreshold: 0.6` or `stopThreshold: 0.8`.
|
|
422
|
-
|
|
423
|
-
**Fix:**
|
|
424
|
-
1. **Derive `noProgress`** from the recent tool call window. If the last 5 tool calls contain no `write`/`edit`/`task` (i.e. the agent is only reading/grepping without producing artifacts), `noProgress = true`.
|
|
425
|
-
2. **Derive `deviations`** from accumulated protocol violations. The audit hook now stores violations in `state.accumulatedDeviations` (capped at 5 per session); the orchestrator input reads them.
|
|
426
|
-
3. **Lower default thresholds** to match the new worst-case math:
|
|
427
|
-
- `escalateThreshold`: 0.6 → 0.45
|
|
428
|
-
- `stopThreshold`: 0.8 → 0.55
|
|
429
|
-
|
|
430
|
-
Now worst-case state (no oracle, no progress, 2 grave deviations, iteration at limit, stop-advice lessons) produces score ≈ -0.55 → `stop` action fires.
|
|
431
|
-
|
|
432
|
-
#### Gap Q (HIGH) — File paths threaded through pipeline
|
|
433
|
-
|
|
434
|
-
`orchestrator.ts` was hardcoding `filesChanged: []` instead of `input.filePaths`. This meant lesson extraction never saw the actual changed files, so F7.5's file-basename FTS indexing was empty.
|
|
435
|
-
|
|
436
|
-
**Fix:**
|
|
437
|
-
1. Track `recentWriteFilePaths` in AuditState (alongside existing `recentWriteContents`).
|
|
438
|
-
2. Capture `filePath` from `toolInput.args` on write/edit tool calls.
|
|
439
|
-
3. New `MetaGovernorInput.filePaths?: readonly string[]` passed through to `observeAndLearn`.
|
|
440
|
-
|
|
441
|
-
#### Gap D (HIGH) — Three config fields now actually do something
|
|
442
|
-
|
|
443
|
-
Three fields were in the schema and config projection but NEVER consulted by the logic:
|
|
444
|
-
|
|
445
|
-
- `closedLoop.saveLessons` — parallel to `saveDecisions`. When `false`, lessons are skipped (decision records still save).
|
|
446
|
-
- `intervention.includeDecisionHistory` — when `true`, `messages.transform` prepends recent intervention texts (capped at `maxHistoryMessages`) so the LLM sees its history of decisions.
|
|
447
|
-
- `intervention.maxHistoryMessages` — limit for the above (default 5).
|
|
448
|
-
|
|
449
|
-
**Fix:** All three fields now control behavior. Track `recentInterventionTexts` in AuditState, format them into the injection text.
|
|
450
|
-
|
|
451
|
-
#### Bonus — iteration-budget signal wired (Oracle finding)
|
|
452
|
-
|
|
453
|
-
Oracle flagged a pre-existing gap alongside Gap C: `iteration` was hardcoded `0` in the orchestrator input, making the `iteration-budget` signal (weight 0.15) effectively dead.
|
|
454
|
-
|
|
455
|
-
Fix:
|
|
456
|
-
- Added `iteration: number` to `AuditState`, incremented per tool call.
|
|
457
|
-
- Threaded `iteration: sessionState?.iteration ?? 0` into `MetaGovernorInput`.
|
|
458
|
-
- `maxIterations` now reads from config instead of being hardcoded.
|
|
459
|
-
|
|
460
|
-
Worst-case score math updated: with iteration at 100% (-0.12), all signals bad, no oracle → score = -0.65 → `stop` action fires.
|
|
461
|
-
|
|
462
|
-
#### Gap I (MEDIUM) — `verifyDelivery` return type includes "expired"
|
|
463
|
-
|
|
464
|
-
The TypeScript signature was `Promise<"delivered" | "pending">` but the registry could return `"expired"`. The expired case leaked through as `"pending"` silently.
|
|
465
|
-
|
|
466
|
-
**Fix:** Signature updated to `Promise<"delivered" | "pending" | "expired">`. Bridge tools now distinguish: `"delivered"` (verified), `"pending"` (still polling), `"expired"` (TTL elapsed).
|
|
467
|
-
|
|
468
|
-
### Test & build status
|
|
469
|
-
|
|
470
|
-
- **521/521 tests pass** (up from 518 — 3 new tests for the v0.17.2 fixes).
|
|
471
|
-
- `bun run typecheck` clean.
|
|
472
|
-
- `bun build.ts` clean (0.34 MB dist).
|
|
473
|
-
- `npm pack --dry-run` validated.
|
|
474
|
-
|
|
475
|
-
### Migration
|
|
476
|
-
|
|
477
|
-
No user action required. Two behavior changes:
|
|
478
|
-
|
|
479
|
-
1. **Escalation now fires more aggressively.** If your agent has been producing violations and not making progress, expect to see escalate → Oracle prompts more often. This is the intended behavior; v0.17.0 was incorrectly silent.
|
|
480
|
-
2. **`includeDecisionHistory` and `maxHistoryMessages` are now functional.** If you set them in v0.17.0 expecting them to work, they will now actually take effect.
|
|
481
|
-
|
|
482
|
-
### Audit roadmap (status as of v0.17.2)
|
|
483
|
-
|
|
484
|
-
| Release | Status | Scope |
|
|
485
|
-
|---------|--------|-------|
|
|
486
|
-
| v0.15.1 (F0) | ✅ | Hotfix self-dep |
|
|
487
|
-
| v0.16.0 (F1-F7) | ✅ | Memory hygiene, dead code, tool coverage, CI |
|
|
488
|
-
| v0.17.0 | ✅ | F5.1 escalate, F5.4 cap, F3.6 delivery verify |
|
|
489
|
-
| v0.17.1 | ✅ | Audit args fix |
|
|
490
|
-
| v0.17.2 | ✅ | Gap C (escalation live), Q (file paths), D (config fields), I (delivery expired) |
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
## v0.17.3 — Fix Gap I properly (patch)
|
|
495
|
-
|
|
496
|
-
v0.17.3 is a single-bug patch. During live verification of v0.17.2, Gap I was found to be incompletely fixed.
|
|
497
|
-
|
|
498
|
-
### The bug (v0.17.2 cosmetic fix)
|
|
499
|
-
|
|
500
|
-
The `verifyDelivery` export signature was widened to include `"expired"` in v0.17.2, and the bridge tools' title/output text was updated to handle it. **BUT the underlying `pollForDelivery` helper was still collapsing `"expired"` → `"pending"` silently:**
|
|
501
|
-
|
|
502
|
-
```ts
|
|
503
|
-
// v0.17.2 (BUG):
|
|
504
|
-
return status === "delivered" ? "delivered" : "pending"
|
|
505
|
-
```
|
|
506
|
-
|
|
507
|
-
So bridge tools could never report `"expired"` to the user, even though the registry correctly tracked it. Live verification confirmed: `deliveryStatus` always showed `"pending"`.
|
|
508
|
-
|
|
509
|
-
### The fix (v0.17.3)
|
|
510
|
-
|
|
511
|
-
```ts
|
|
512
|
-
// v0.17.3:
|
|
513
|
-
return await pendingRegistryRef.awaitDelivery({ sessionID, mcpTool, timeoutMs })
|
|
514
|
-
```
|
|
515
|
-
|
|
516
|
-
Now the actual status from the registry propagates through. `"expired"` flows end-to-end to the bridge tool's `metadata.deliveryStatus` and title.
|
|
517
|
-
|
|
518
|
-
### Tests
|
|
519
|
-
|
|
520
|
-
Added 3 RED tests in `src/custom-tools.test.ts`:
|
|
521
|
-
- Returns `"expired"` when registry entry exists past timeout (real registry instance)
|
|
522
|
-
- Returns `"delivered"` when `markDelivered` fires before timeout
|
|
523
|
-
- Returns `"pending"` when no registry is configured
|
|
524
|
-
|
|
525
|
-
### Test & build status
|
|
526
|
-
|
|
527
|
-
- **525/525 tests pass** (up from 522 in v0.17.2 — 3 new tests for pollForDelivery).
|
|
528
|
-
- `bun run typecheck` clean.
|
|
529
|
-
- `bun build.ts` clean (0.34 MB dist).
|
|
530
|
-
|
|
531
|
-
### Migration
|
|
532
|
-
|
|
533
|
-
No user action required. Bridge tools will now correctly distinguish all three delivery states:
|
|
534
|
-
- `"delivered"` — LLM's MCP tool call was observed within 1.5s
|
|
535
|
-
- `"expired"` — TTL elapsed without delivery (entry expires after 10s, but bridge tool sees this immediately as "expired" when polling times out at 1.5s)
|
|
536
|
-
- `"pending"` — no registry configured (graceful degradation for tests/mocks)
|
|
537
|
-
|
|
538
|
-
### Audit roadmap (status as of v0.17.3)
|
|
539
|
-
|
|
540
|
-
| Release | Status | Scope |
|
|
541
|
-
|---------|--------|-------|
|
|
542
|
-
| v0.15.1 → v0.17.2 | ✅ | All audit findings + 5 gap fixes |
|
|
543
|
-
| v0.17.3 | ✅ | Gap I real fix (pollForDelivery returns "expired") |
|
|
544
|
-
|
|
545
|
-
Two remaining gaps documented but require SDK support to fix:
|
|
546
|
-
- `recentTurnTokens: []` — token-predictor signal dead (10% of score); needs per-turn token counts from OpenCode SDK
|
|
547
|
-
- `agentName` defaults to `"unknown"` — cosmetic, no functional impact
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
## v0.18.0 — Audit remediation: 7+ silent config drops + circular ref crash
|
|
322
|
+
### Git hooks
|
|
552
323
|
|
|
553
|
-
|
|
324
|
+
On every `git commit`:
|
|
554
325
|
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|---|-----|----------|-----|
|
|
559
|
-
| 1 | `file-logger.redactData` crashed on circular references with stack overflow | 🔴 CRITICAL | `WeakSet` guard + `try/catch` fallback |
|
|
560
|
-
| 2 | `loadOrchestratorConfig` only projected `closedLoop.saveDecisions` — `enabled`, `minSeverityToLearn`, `maxLessonsPerSession`, `saveLessons` were silently dropped | 🔴 CRITICAL | Project all 5 fields |
|
|
561
|
-
| 3 | `loadOrchestratorConfig` didn't project `decision.warnMessageTemplate`, `escalateMessageTemplate`, `stopMessageTemplate` | 🟠HIGH | Project all 3 templates |
|
|
562
|
-
| 4 | `loadOrchestratorConfig` didn't project `scoring.paralysisThreshold`, `defaultEscalationTarget` | 🟠HIGH | Project all fields |
|
|
563
|
-
| 5 | `loadOrchestratorConfig` had `memory.timeoutMs` field name mismatch (schema said `agentmemoryTimeoutMs`) | 🟠HIGH | Accept both names |
|
|
564
|
-
| 6 | `isMetaGovernorEnabled` only checked top-level `enabled`, not `meta_governor.enabled` (wrapped shape from `opencode.jsonc`) | 🟠HIGH | Check both shapes |
|
|
565
|
-
| 7 | `createMetricsCollector` crashed when called without config (`config.version` on `undefined`) | 🟠HIGH | Accept `Partial<MetricsCollectorConfig>` |
|
|
566
|
-
| 8 | `metrics.inc` crashed on unknown event names (`bucket.count++` on `undefined`) | 🟠HIGH | Guard `if (!bucket) return` |
|
|
567
|
-
| 9 | `isNewerVersion` returned `false` for `installed=null` (no upgrade triggered for fresh installs) | 🟡 MEDIUM | Return `true` when installed is null AND latest is valid |
|
|
568
|
-
|
|
569
|
-
### Test & build status
|
|
570
|
-
|
|
571
|
-
- **557/557 tests pass** (up from 530 in v0.17.3 — 27 new tests for the audit fixes).
|
|
572
|
-
- `bun run typecheck` clean.
|
|
573
|
-
- `bun build.ts` clean (0.34 MB dist).
|
|
574
|
-
- `npm pack --dry-run` validated.
|
|
575
|
-
|
|
576
|
-
### Migration
|
|
577
|
-
|
|
578
|
-
No user action required. The fix to `loadOrchestratorConfig` means **users who were setting `closedLoop.maxLessonsPerSession` or other previously-dropped fields will now see those values actually take effect**. If you had a config like `{ "closedLoop": { "maxLessonsPerSession": 50 } }` before v0.18.0, it was silently being overridden to 20. Starting v0.18.0, the value 50 is now respected.
|
|
326
|
+
- **Primary path** (native git hook): `graphify update` runs in background.
|
|
327
|
+
- **Backup path** (plugin's `tool.execute.after`): detects `git commit`
|
|
328
|
+
in bash commands and runs `codegraph sync -q [path]`.
|
|
579
329
|
|
|
580
|
-
###
|
|
330
|
+
### Process safeguards
|
|
581
331
|
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
332
|
+
Every subprocess the plugin spawns (graphify, codegraph, npx, python,
|
|
333
|
+
npm/pip) is guaranteed to die after use — on success, error, AND
|
|
334
|
+
timeout — including its descendant tree. On Windows this uses
|
|
335
|
+
`taskkill /pid <pid> /T /F` (plain `child.kill()` only kills the direct
|
|
336
|
+
shell, orphaning grandchildren — the confirmed cause of the
|
|
337
|
+
Bun/OpenChamber crashes).
|
|
586
338
|
|
|
587
|
-
|
|
339
|
+
Config: `graphSync.killOrphanedOnInit` (default `true`) — on graph-sync
|
|
340
|
+
init the plugin sweeps orphaned `graphify`/`codegraph` processes left
|
|
341
|
+
by previous crashed runs. Set to `false` to disable the sweep.
|
|
588
342
|
|
|
343
|
+
---
|
|
589
344
|
|
|
590
|
-
##
|
|
345
|
+
## Persistence & observability
|
|
591
346
|
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
1.18.16 npm-package plugins still loaded the module without ever calling
|
|
596
|
-
the factory under `opencode serve`.
|
|
347
|
+
**Lesson storage.** Decisions and lessons persist in **SQLite** at
|
|
348
|
+
`~/.omo-meta-governor/meta-governor.db` with full-text search (FTS5) for
|
|
349
|
+
fast recall. Zero dependencies — uses Bun's built-in `bun:sqlite`.
|
|
597
350
|
|
|
598
|
-
|
|
351
|
+
**Cross-session memory.** The `omo_remember` / `omo_recall_mcp` tools
|
|
352
|
+
bridge to AgentMemory via `session.prompt()` — the LLM receives a
|
|
353
|
+
structured instruction to call the appropriate MCP tool.
|
|
599
354
|
|
|
600
|
-
|
|
601
|
-
**and** a PluginModule:
|
|
355
|
+
**Health JSON** at `~/.config/opencode/meta-governor-health.json`:
|
|
602
356
|
|
|
603
|
-
```
|
|
604
|
-
|
|
605
|
-
_plugin.id = "omo-meta-governor"
|
|
606
|
-
_plugin.server = _plugin
|
|
607
|
-
export default _plugin
|
|
357
|
+
```bash
|
|
358
|
+
cat ~/.config/opencode/meta-governor-health.json
|
|
608
359
|
```
|
|
609
360
|
|
|
610
|
-
|
|
611
|
-
Whichever path opencode picks (`default(input, options)` or
|
|
612
|
-
`default.server(input, options)`), the same callable fires and the hooks
|
|
613
|
-
register.
|
|
614
|
-
|
|
615
|
-
### Verification
|
|
616
|
-
|
|
617
|
-
After restart of OpenChamber, log shows:
|
|
618
|
-
- factory_invoked events (was 0 with v0.19.3)
|
|
619
|
-
- config_loaded events (was 0 with v0.19.3)
|
|
620
|
-
- intervention / violations / persist calls firing normally
|
|
621
|
-
|
|
622
|
-
### Test & build status
|
|
361
|
+
Or invoke `omo_health` directly for a formatted report.
|
|
623
362
|
|
|
624
|
-
|
|
625
|
-
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
### Migration
|
|
630
|
-
|
|
631
|
-
No user action required. If you previously set
|
|
632
|
-
`intervention.persistToSession: false` in your config, that toggle is
|
|
633
|
-
still respected.
|
|
363
|
+
**Structured JSONL logs** at `~/.config/opencode/meta-governor.log` with
|
|
364
|
+
size-based rotation (10MB max, 5 rotated files). Secret redaction layer
|
|
365
|
+
strips JWT, OpenAI keys, Bearer tokens, GitHub PATs, and generic
|
|
366
|
+
`key:value` patterns before writing.
|
|
634
367
|
|
|
635
368
|
---
|
|
636
369
|
|
|
637
|
-
## v0.
|
|
370
|
+
## CI monitor (v0.25.0)
|
|
638
371
|
|
|
639
|
-
|
|
372
|
+
`src/ci-monitor.ts` auto-triggers GitHub Actions on `git push` and
|
|
373
|
+
surfaces failures to the agent:
|
|
640
374
|
|
|
641
|
-
|
|
375
|
+
- Detects `git push` in bash commands via the `tool.execute.after` hook.
|
|
376
|
+
- Polls the GH Actions API for the resulting run (5s initial delay,
|
|
377
|
+
exponential backoff).
|
|
378
|
+
- On failure, injects a synthetic message with the failed logs into the
|
|
379
|
+
agent's context so it can fix and retry.
|
|
642
380
|
|
|
643
|
-
`
|
|
381
|
+
Configurable via `meta_governor.ciMonitor` (disabled by default — opt-in
|
|
382
|
+
feature).
|
|
644
383
|
|
|
645
|
-
|
|
646
|
-
"exports": {
|
|
647
|
-
".": { "types": "./dist/index.d.ts" },
|
|
648
|
-
"./lib": { "types": "./dist/lib.d.ts" }
|
|
649
|
-
}
|
|
650
|
-
```
|
|
384
|
+
---
|
|
651
385
|
|
|
652
|
-
|
|
386
|
+
## Configuration reference
|
|
387
|
+
|
|
388
|
+
All configuration lives under the `meta_governor` key in
|
|
389
|
+
`opencode.jsonc`. Full schema:
|
|
390
|
+
[assets/omo-meta-governor.schema.json](assets/omo-meta-governor.schema.json).
|
|
391
|
+
|
|
392
|
+
### Top-level
|
|
393
|
+
|
|
394
|
+
| Field | Type | Default | Description |
|
|
395
|
+
|-------|------|---------|-------------|
|
|
396
|
+
| `enabled` | boolean | `false` | Master feature flag — must be true to run the orchestrator. |
|
|
397
|
+
| `decision` | object | — | Decision handler tuning. |
|
|
398
|
+
| `memory` | object | — | Memory aggregator config. |
|
|
399
|
+
| `tokenPredictor` | object | — | Token predictor (compact-now / switch-model / delegate recommendations). |
|
|
400
|
+
| `scoring` | object | — | Scoring engine thresholds. |
|
|
401
|
+
| `closedLoop` | object | — | Closed-loop learning (save decisions + lessons). |
|
|
402
|
+
| `modelOverride` | object | — | Model override for MetaGovernor's internal LLM usage. |
|
|
403
|
+
| `intervention` | object | — | Visible decision injection config. |
|
|
404
|
+
| `protocolEnforcement` | object | — | Sisyphus protocol enforcement. |
|
|
405
|
+
| `skillPriming` | object | — | Proactive skill-selection nudge (v0.20.0). |
|
|
406
|
+
| `graphSync` | object | — | Graph synchronization (auto-init codegraph/graphify). |
|
|
407
|
+
|
|
408
|
+
### `decision`
|
|
409
|
+
|
|
410
|
+
| Field | Type | Default | Description |
|
|
411
|
+
|-------|------|---------|-------------|
|
|
412
|
+
| `maxHistoryPerSession` | integer | — | Maximum history entries per session before oldest are trimmed. |
|
|
413
|
+
| `forceContinueAfterStops` | integer | — | How many consecutive stops before forcing continue. |
|
|
414
|
+
|
|
415
|
+
### `memory`
|
|
416
|
+
|
|
417
|
+
| Field | Type | Default | Description |
|
|
418
|
+
|-------|------|---------|-------------|
|
|
419
|
+
| `agentmemoryTimeoutMs` | integer | — | Timeout for agentmemory queries in milliseconds. |
|
|
420
|
+
| `boulderStateTimeoutMs` | integer | — | Timeout for boulder-state queries in milliseconds. |
|
|
421
|
+
| `query` | string | — | Natural-language query for memory recall. |
|
|
422
|
+
|
|
423
|
+
### `tokenPredictor`
|
|
424
|
+
|
|
425
|
+
| Field | Type | Default | Description |
|
|
426
|
+
|-------|------|---------|-------------|
|
|
427
|
+
| `compactBurnRateThreshold` | integer | — | Burn rate (tokens/turn) above which to recommend compact-now. |
|
|
428
|
+
| `compactUsageThreshold` | number | — | Context usage ratio (0..1) above which to recommend compact-now. |
|
|
429
|
+
| `switchModelUsageThreshold` | number | — | Context usage ratio above which to recommend switch-model. |
|
|
430
|
+
| `delegateConsecutiveHighBurn` | integer | — | Max consecutive high-burn turns before recommending delegate. |
|
|
431
|
+
|
|
432
|
+
### `scoring`
|
|
433
|
+
|
|
434
|
+
| Field | Type | Default | Description |
|
|
435
|
+
|-------|------|---------|-------------|
|
|
436
|
+
| `continueThreshold` | number | `0.05` | Score ≥ this → continue silently. |
|
|
437
|
+
| `warnThreshold` | number | `0.3` | Score ≤ -this → warn. |
|
|
438
|
+
| `escalateThreshold` | number | `0.45` | Score ≤ -this → escalate. |
|
|
439
|
+
| `stopThreshold` | number | `0.55` | Score ≤ -this → stop. |
|
|
440
|
+
|
|
441
|
+
### `closedLoop`
|
|
442
|
+
|
|
443
|
+
| Field | Type | Default | Description |
|
|
444
|
+
|-------|------|---------|-------------|
|
|
445
|
+
| `saveDecisions` | boolean | `true` | Whether to save decision records. |
|
|
446
|
+
| `saveLessons` | boolean | `true` | Whether to save lessons. |
|
|
447
|
+
|
|
448
|
+
### `modelOverride`
|
|
449
|
+
|
|
450
|
+
| Field | Type | Default | Description |
|
|
451
|
+
|-------|------|---------|-------------|
|
|
452
|
+
| `providerID` | string | — | Provider ID (e.g. `'openai'`, `'anthropic'`). |
|
|
453
|
+
| `modelID` | string | — | Model ID (e.g. `'gpt-4o-mini'`, `'claude-sonnet-4-20250514'`). |
|
|
454
|
+
| `modelLimit` | integer | — | Context window size for token predictor (min 1000). |
|
|
455
|
+
| `temperature` | number | `0.2` | Sampling temperature (0..2). |
|
|
456
|
+
| `topP` | number | `1` | Top-p nucleus sampling (0..1). |
|
|
457
|
+
| `maxTokens` | integer | — | Max output tokens for internal reasoning. |
|
|
458
|
+
| `reasoning` | boolean | — | Enable extended reasoning / thinking mode. |
|
|
459
|
+
| `verbosity` | enum | — | `'silent'` \| `'minimal'` \| `'verbose'`. |
|
|
460
|
+
|
|
461
|
+
### `intervention`
|
|
462
|
+
|
|
463
|
+
| Field | Type | Default | Description |
|
|
464
|
+
|-------|------|---------|-------------|
|
|
465
|
+
| `mode` | enum | — | `'silent'` \| `'message'` \| `'system'`. |
|
|
466
|
+
| `includeDecisionHistory` | boolean | — | Whether to include recent decision history in injection. |
|
|
467
|
+
| `maxHistoryMessages` | integer | `5` | Max history entries when `includeDecisionHistory: true`. |
|
|
468
|
+
| `minActionForMessage` | enum | — | Minimum action: `'warn'` (all non-continue), `'escalate'`, `'stop'`. |
|
|
469
|
+
| `persistToSession` | boolean | `true` | v0.19.0: when true, intervention messages ALSO persist to the session. |
|
|
470
|
+
| `maxInterventionsPerSession` | integer | `3` | v0.10.0: hard cap before auto-disable. |
|
|
471
|
+
| `respectDoneSignal` | boolean | `true` | Stop injecting once terminal signal + Oracle verified. |
|
|
472
|
+
| `phaseAwareDoneSignal` | boolean | `false` | v0.15.0: split per-phase hint from terminal signal. |
|
|
473
|
+
|
|
474
|
+
### `protocolEnforcement`
|
|
475
|
+
|
|
476
|
+
| Field | Type | Default | Description |
|
|
477
|
+
|-------|------|---------|-------------|
|
|
478
|
+
| `enabled` | boolean | — | Master switch. |
|
|
479
|
+
| `path` | string | — | Path to protocol markdown file. |
|
|
480
|
+
| `injectIntoSystem` | boolean | — | Whether to inject protocol rules into the system prompt. |
|
|
481
|
+
| `auditToolCalls` | boolean | — | Whether to audit tool calls for violations. |
|
|
482
|
+
|
|
483
|
+
### `skillPriming`
|
|
484
|
+
|
|
485
|
+
| Field | Type | Default | Description |
|
|
486
|
+
|-------|------|---------|-------------|
|
|
487
|
+
| `enabled` | boolean | `false` | Master switch. |
|
|
488
|
+
| `trigger` | enum | `'firstImplement'` | `'sessionStart'` (first transform) or `'firstImplement'` (once write-like tool observed). |
|
|
489
|
+
| `router` | enum | `'both'` | `'aas'` \| `'superpowers'` \| `'both'`. |
|
|
490
|
+
|
|
491
|
+
### `graphSync`
|
|
492
|
+
|
|
493
|
+
| Field | Type | Default | Description |
|
|
494
|
+
|-------|------|---------|-------------|
|
|
495
|
+
| `enabled` | boolean | `true` | Enable auto-initialization. |
|
|
496
|
+
| `watch` | boolean | `false` | Enable watch mode (re-index on file changes). |
|
|
497
|
+
| `killOrphanedOnInit` | boolean | `true` | Sweep orphaned processes on init. |
|
|
498
|
+
| `autoUpgrade` | boolean | `true` | **v0.26.0** — auto-upgrade installed codegraph + graphify binaries. |
|
|
499
|
+
| `upgradeCachePath` | string | — | **v0.26.0** — path for the upgrade cache file. |
|
|
500
|
+
| `checkGraphifyNeedsUpdate` | boolean | `true` | **v0.26.0** — run `graphify check-update` after upgrade. |
|
|
653
501
|
|
|
654
|
-
|
|
655
|
-
"exports": {
|
|
656
|
-
".": { "types": "./dist/index.d.ts", "import": "./dist/index.js" },
|
|
657
|
-
"./lib": { "types": "./dist/lib.d.ts", "import": "./dist/lib.js" }
|
|
658
|
-
}
|
|
659
|
-
```
|
|
502
|
+
---
|
|
660
503
|
|
|
661
|
-
|
|
504
|
+
## Architecture overview
|
|
662
505
|
|
|
663
|
-
|
|
506
|
+
The plugin is a single ESM module with five layers wired through opencode
|
|
507
|
+
event hooks:
|
|
664
508
|
|
|
665
|
-
Cheap-shape probes (`@herjarsa/omg-shape-probe2` … `probe7`) with byte-identical Bun-bundles from `dist/index.js` were published to npm and tested under `opencode run` with XDG-isolated config. All probes with `exports."."` containing `"import"` or `"default"` invoked the factory. The probe replicating the exact published shape (types-only exports) failed to invoke. Bundle SHA-256 identical between probes and the real published package:
|
|
666
509
|
```
|
|
667
|
-
|
|
510
|
+
┌─────────────────────────────────────────────────────┐
|
|
511
|
+
│ opencode event hooks │
|
|
512
|
+
│ tool.execute.before tool.execute.after │
|
|
513
|
+
│ chat.messages.transform chat.system.transform │
|
|
514
|
+
└───────────────┬─────────────────────┬────────────────┘
|
|
515
|
+
│ │
|
|
516
|
+
┌───────────────────▼────────┐ ┌──────────▼─────────────┐
|
|
517
|
+
│ AuditStateCache (TTL) │ │ Decision + Scoring │
|
|
518
|
+
│ recentWriteFilePaths │ │ Engine (-1..+1 score) │
|
|
519
|
+
│ accumulatedDeviations │ └──────────┬─────────────┘
|
|
520
|
+
│ recentInterventionTexts │ │
|
|
521
|
+
└───────────────────────────┘ │
|
|
522
|
+
│ │
|
|
523
|
+
┌─────────────────────────▼─────────────────────▼──────────────┐
|
|
524
|
+
│ Governance pipeline │
|
|
525
|
+
│ Protocol Enforcer → Scoring → Decision Handler → │
|
|
526
|
+
│ Intervention │
|
|
527
|
+
└──────────────────────────────────────────────────────────────┘
|
|
528
|
+
│
|
|
529
|
+
│
|
|
530
|
+
┌─────────────────────────▼──────────────────────────────────────┐
|
|
531
|
+
│ Graph sync + tool layer │
|
|
532
|
+
│ codegraph + graphify (auto-init, git hooks, auto-upgrade) │
|
|
533
|
+
│ 12 omo_* tools (search, find, impact, recall, files, etc.) │
|
|
534
|
+
└───────────────────────────────────────────────────────────────┘
|
|
535
|
+
│
|
|
536
|
+
▼
|
|
537
|
+
┌──────────────────────────────────┐
|
|
538
|
+
│ SQLite (bun:sqlite) + AgentMem │
|
|
539
|
+
│ meta-governor.db / decisions │
|
|
540
|
+
│ / lessons / audit state │
|
|
541
|
+
└──────────────────────────────────┘
|
|
668
542
|
```
|
|
669
543
|
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
No source/bundle changes — the bundle was correct all along. The malformed published `package.json` was restored from the repo (`git show HEAD:package.json` has the canonical full exports map with `import`) and only the version was bumped to `0.19.7`. Rebuild with `bun build.ts` (bakes version into the bundle), published, verified.
|
|
673
|
-
|
|
674
|
-
### Verification
|
|
544
|
+
See [ARCHITECTURE.md](ARCHITECTURE.md) for module-level relationships and
|
|
545
|
+
[STRUCTURE.md](STRUCTURE.md) for the file layout.
|
|
675
546
|
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
- v0.19.6 (cache populated): log shows `MetaGovernor plugin loaded` only — **no `factory_invoked`**, intervention never runs.
|
|
679
|
-
- v0.19.7 (cache cleared, reinstalled): log shows full chain:
|
|
680
|
-
```
|
|
681
|
-
[meta-governor] v0.21.1 MetaGovernor plugin loaded
|
|
682
|
-
[meta-governor] v0.21.1 factory_invoked
|
|
683
|
-
[meta-governor] SessionBridge: OpenCode client hydrated — session.prompt() available
|
|
684
|
-
[meta-governor] v0.21.1 config_loaded
|
|
685
|
-
```
|
|
686
|
-
> **Note (v0.21.1+)**: every init log line now prepends `v<DEFAULT_VERSION>` (read from `package.json` at build time by Bun). Use this prefix to confirm which release OpenChamber actually loaded — a stale npm cache could otherwise serve an older bundle silently because `@latest` does not force re-fetch if the cache is still valid.
|
|
687
|
-
|
|
688
|
-
Updated `~/.cache/opencode/packages/@herjarsa/omo-meta-governor@latest/node_modules/@herjarsa/omo-meta-governor/package.json` now reads `exports."."` = `{ types: "./dist/index.d.ts", import: "./dist/index.js" }` and `peerDependencies` = `{ "@opencode-ai/plugin": ">=1.0.0" }`.
|
|
689
|
-
|
|
690
|
-
### Test & build status
|
|
691
|
-
|
|
692
|
-
- `bun run typecheck` clean.
|
|
693
|
-
- `bun build.ts` clean (0.34 MB dist, version 0.19.7 baked in).
|
|
694
|
-
- `npm publish` to registry OK.
|
|
695
|
-
- Empirical harness verification: factory_invoked + config_logged restored.
|
|
547
|
+
---
|
|
696
548
|
|
|
697
|
-
|
|
549
|
+
## Testing
|
|
698
550
|
|
|
699
|
-
No user action required. If you were running v0.19.6 and the plugin appeared silent (no interventions, no metrics), delete your opencode cache:
|
|
700
551
|
```bash
|
|
701
|
-
|
|
552
|
+
bun test # full suite (672+ tests)
|
|
553
|
+
bun test src/upgrade-autofix.test.ts # Wave 1: auto-upgrade regression
|
|
554
|
+
bun test src/custom-tools.test.ts # Wave 2: 12 tools
|
|
702
555
|
```
|
|
703
|
-
Then restart opencode — it will reinstall v0.19.7 from the registry and the pipeline will fire normally.
|
|
704
|
-
|
|
705
|
-
---
|
|
706
|
-
|
|
707
|
-
## v0.19.3 — opencode serve factory invocation + persistSessionMessage wiring
|
|
708
|
-
|
|
709
|
-
This release closes the persistSessionMessage wiring arc (memory #999) and
|
|
710
|
-
loads config from three sources automatically (CLI > project > user).
|
|
711
|
-
The `index.ts` `export default` change was incomplete (see v0.19.4 for
|
|
712
|
-
the proper dual-shape fix that resolves opencode serve invocation).
|
|
713
|
-
|
|
714
|
-
### Highlights
|
|
715
|
-
|
|
716
|
-
- **index.ts**: switched `export default` to call `createMetaGovernorPlugin()`
|
|
717
|
-
directly (function path), abandoning the `PluginModule` wrapper. Was the
|
|
718
|
-
wrong shape — see v0.19.4 for the actual fix.
|
|
719
|
-
- **plugin.ts**: factory now calls `loadMetaGovernorConfig({ projectDir })` so
|
|
720
|
-
config from `.opencode/omo-meta-governor.jsonc` and
|
|
721
|
-
`~/.config/opencode/omo-meta-governor.jsonc` flows in automatically.
|
|
722
|
-
- **session-bridge.ts**: `persistSessionMessage()` — fire-and-forget
|
|
723
|
-
`session.prompt()` helper that records intervention text as a REAL session
|
|
724
|
-
message (visible in TUI and session DB).
|
|
725
|
-
- **types.ts + config.ts + orchestrator.ts**: `persistToSession` defaults to
|
|
726
|
-
true on `InterventionConfig`. Helps users running OpenChamber actually
|
|
727
|
-
SEE interventions in their TUI.
|
|
728
|
-
- **tests**: 16 `createMetaGovernorPlugin()` calls in plugin/v172/v173-gap-d
|
|
729
|
-
tests now pass `graphSync: { enabled: false, autoInstall: false }`
|
|
730
|
-
because user config enables `autoInstall` by default (memory #989).
|
|
731
|
-
|
|
732
|
-
### Test & build status
|
|
733
|
-
|
|
734
|
-
- ~437/437 tests pass (per-file, `graphsink-fix.ts` skipped per known Bun
|
|
735
|
-
Windows integer-overflow crash).
|
|
736
|
-
- `bun run typecheck` clean.
|
|
737
|
-
- `bun build.ts` clean (0.35 MB dist).
|
|
738
|
-
- `npm publish` to registry OK.
|
|
739
|
-
|
|
740
|
-
### Migration
|
|
741
556
|
|
|
742
|
-
|
|
557
|
+
**Coverage highlights (v0.26.0):**
|
|
558
|
+
|
|
559
|
+
- 10 tests in `src/upgrade-autofix.test.ts` (AUT-1..AUT-7) — tiered probe,
|
|
560
|
+
pip `--upgrade` flag, `graphify check-update` integration, cache
|
|
561
|
+
write-once semantics.
|
|
562
|
+
- 7 tests in `src/custom-tools.test.ts` for the new tools
|
|
563
|
+
(FIL-1..3, CAL-1..2, NOD-1..2) plus full coverage of the existing 9.
|
|
564
|
+
- 686+ tests across `decision-store`, `token-predictor`,
|
|
565
|
+
`protocol-enforcer`, `graph-sync`, `skill-priming`, `ci-monitor`,
|
|
566
|
+
`audit-state-cache`, `closed-loop-learning`, `closed-loop`,
|
|
567
|
+
`config-file`, `session-bridge`, `sqlite-backend`, `memory-aggregator`,
|
|
568
|
+
`proc-guard`, `ttl-queue`, `mcp-client`, `scoring-engine`, `v018-fixes`,
|
|
569
|
+
`v172`, `v173-f51`, `v173-gap-d`, `intervention-fix`, `graphsink-fix`,
|
|
570
|
+
`plugin`, `plugin-graphsync`, `plugin-audit-postwave`, `postwave-wire`,
|
|
571
|
+
`postwave-gate`.
|
|
572
|
+
|
|
573
|
+
Known flaky test: `runGuarded > times out` (1 test) — pre-existing,
|
|
574
|
+
unrelated to v0.26.0, confirmed by Oracle audit.
|
|
743
575
|
|
|
744
576
|
---
|
|
745
577
|
|
|
746
|
-
##
|
|
578
|
+
## Migration from earlier versions
|
|
747
579
|
|
|
748
|
-
|
|
749
|
-
added call sites and tightened the test coverage, but the fix was lost in
|
|
750
|
-
stashes and merges until v0.19.3 finally shipped a working version of
|
|
751
|
-
the helper. See v0.19.3 for the user-facing release notes; v0.19.4
|
|
752
|
-
supersedes with the correct dual-shape export.
|
|
753
|
-
## Auto-upgrade (v0.12.0)
|
|
580
|
+
**From v0.24.x → v0.26.0:**
|
|
754
581
|
|
|
755
|
-
On plugin load,
|
|
756
|
-
|
|
757
|
-
|
|
582
|
+
- **Stale-cache detection (v0.24.3):** On plugin load, an async npm
|
|
583
|
+
version check runs in the background. If the loaded version differs
|
|
584
|
+
from the latest published version, a warning is logged with
|
|
585
|
+
cache-clearing instructions. If you see `STALE_CACHE` in
|
|
586
|
+
`meta-governor.log`, run:
|
|
758
587
|
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
#### Background Oracle intervention suppression (v0.24.0)
|
|
764
|
-
|
|
765
|
-
When the agent invokes Oracle via `task(subagent_type="oracle", run_in_background=true)`, the plugin now detects the background task and suppresses all interventions until Oracle returns. Previously, the agent's idle window during Oracle execution triggered noProgress + accumulated deviations → intervention pile-up.
|
|
766
|
-
|
|
767
|
-
New `AuditState` fields:
|
|
768
|
-
- `oracleInFlight: boolean` — true while a background Oracle task is running
|
|
769
|
-
- `signalAtMs: number` — timestamp of the last done/phase signal, used to prevent stale latches from immediately clearing oracleInFlight
|
|
770
|
-
|
|
771
|
-
Detection uses `toolInput.args` (not `toolOutput.output`) to correctly identify background Oracle calls.
|
|
772
|
-
|
|
773
|
-
3-tier clear strategy (Oracle-reviewed):
|
|
774
|
-
1. Promise signal detected AFTER oracleInFlight was set (signal timestamp > oracleInFlightSinceMs)
|
|
775
|
-
2. Timeout safety net (5 minutes since invocation)
|
|
776
|
-
3. Foreground Oracle call (agent explicitly waiting for a new Oracle)
|
|
777
|
-
|
|
778
|
-
#### Memory save directive (v0.24.0)
|
|
779
|
-
|
|
780
|
-
Added explicit negative guidance to the protocol-enforcer memory save directive:
|
|
781
|
-
> "Do NOT save routine operations (file reads, greps, list commands), trivial decisions, or facts already covered by existing memory."
|
|
588
|
+
```bash
|
|
589
|
+
npm cache clean --force && rm -rf ~/.cache/opencode/packages/@herjarsa/omo-meta-governor*
|
|
590
|
+
```
|
|
782
591
|
|
|
783
|
-
|
|
592
|
+
Then restart opencode.
|
|
784
593
|
|
|
785
|
-
|
|
594
|
+
- **Auto-upgrade (v0.26.0):** No user action required. The plugin now
|
|
595
|
+
upgrades codegraph and graphify silently on every load. If you
|
|
596
|
+
previously disabled `graphSync.enabled` to work around the broken
|
|
597
|
+
upgrade, re-enable it.
|
|
786
598
|
|
|
787
|
-
|
|
599
|
+
- **New config fields:** `graphSync.autoUpgrade`,
|
|
600
|
+
`graphSync.upgradeCachePath`, `graphSync.checkGraphifyNeedsUpdate` —
|
|
601
|
+
all default true. Schema is backward-compatible.
|
|
788
602
|
|
|
789
|
-
|
|
603
|
+
**From earlier versions:** no user action required. All changes through
|
|
604
|
+
v0.18.0 were transparent — the audit gaps (config drops, circular refs,
|
|
605
|
+
metrics crashes) only affected edge cases where users set obscure
|
|
606
|
+
fields. See [CHANGELOG.md](CHANGELOG.md) for the full history.
|
|
790
607
|
|
|
791
|
-
|
|
792
|
-
```bash
|
|
793
|
-
npm cache clean --force && rm -rf ~/.cache/opencode/packages/@herjarsa/omo-meta-governor*
|
|
794
|
-
```
|
|
795
|
-
Then restart opencode.
|
|
608
|
+
---
|
|
796
609
|
|
|
797
610
|
## License
|
|
798
611
|
|
|
799
|
-
MIT
|
|
612
|
+
MIT
|