@herjarsa/omo-meta-governor 0.19.3 → 0.19.5
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 +190 -96
- package/dist/index.d.ts +20 -17
- package/dist/index.js +47 -47
- package/dist/index.js.map +5 -5
- package/dist/plugin.d.ts +2 -2
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -43,7 +43,7 @@ The plugin registers 15 tools the LLM can invoke. All available immediately on i
|
|
|
43
43
|
|
|
44
44
|
| Tool | What it does | Use case |
|
|
45
45
|
|------|-------------|----------|
|
|
46
|
-
| `omo_search` | Semantic code search via codegraph/graphify with AFT fallback | Architecture questions, finding features
|
|
46
|
+
| `omo_search` | Semantic code search via codegraph/graphify with AFT fallback | Architecture questions, finding features — USE THIS FIRST |
|
|
47
47
|
| `omo_find` | Exact symbol lookup (definition + direct callers) via codegraph node | "Find the function `validateToken`" |
|
|
48
48
|
| `omo_impact` | Impact analysis: callers, transitive callers, test files, doc files | Run BEFORE modifying a function |
|
|
49
49
|
| `omo_path` | Shortest conceptual path between two concepts via graphify | "How does auth connect to database?" |
|
|
@@ -90,11 +90,11 @@ Structured JSONL logs at `~/.config/opencode/meta-governor.log` with size-based
|
|
|
90
90
|
## Persistence
|
|
91
91
|
|
|
92
92
|
Lessons learned by the plugin persist in **SQLite** at `~/.omo-meta-governor/meta-governor.db`
|
|
93
|
-
with full-text search (FTS5) for fast recall. Zero dependencies needed
|
|
93
|
+
with full-text search (FTS5) for fast recall. Zero dependencies needed — uses Bun's built-in
|
|
94
94
|
`bun:sqlite`.
|
|
95
95
|
|
|
96
|
-
Optionally, the
|
|
97
|
-
`omo_note`) can bridge to AgentMemory and Magic Context via `session.prompt()`
|
|
96
|
+
Optionally, the Opción A tools (`omo_remember`, `omo_recall_mcp`, `omo_rule`, `omo_history`,
|
|
97
|
+
`omo_note`) can bridge to AgentMemory and Magic Context via `session.prompt()` — the LLM
|
|
98
98
|
receives a structured instruction to call the appropriate MCP tool.
|
|
99
99
|
|
|
100
100
|
## Graph Sync (v0.11.0)
|
|
@@ -167,39 +167,39 @@ only when the **entire** plan is verified done by Oracle. The new markers:
|
|
|
167
167
|
| Marker | Effect |
|
|
168
168
|
|--------|--------|
|
|
169
169
|
| `<promise>DONE</promise>` | Per-phase hint. Logged but does NOT latch intervention (when `phaseAwareDoneSignal: true`). |
|
|
170
|
-
| `<promise>PHASE-N-COMPLETE</promise>` | Per-phase hint (e.g. `<promise>PHASE-1-COMPLETE</promise>`). Same as DONE
|
|
170
|
+
| `<promise>PHASE-N-COMPLETE</promise>` | Per-phase hint (e.g. `<promise>PHASE-1-COMPLETE</promise>`). Same as DONE — logged, does NOT latch. |
|
|
171
171
|
| `<promise>PLAN-COMPLETE</promise>` | Terminal. Latches intervention when Oracle has verified. |
|
|
172
172
|
|
|
173
|
-
**Migration**: existing v0.10.0
|
|
173
|
+
**Migration**: existing v0.10.0–v0.14.x users keep working without changes (default
|
|
174
174
|
`phaseAwareDoneSignal: false` preserves the legacy single-task behavior). Set the
|
|
175
175
|
flag to `true` and switch your terminal marker to `PLAN-COMPLETE` to enable
|
|
176
176
|
multi-phase governance.
|
|
177
177
|
|
|
178
|
-
## v0.16.0
|
|
178
|
+
## v0.16.0 — Audit remediation: memory hygiene, dead code, tool coverage, CI
|
|
179
179
|
|
|
180
|
-
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
|
|
180
|
+
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.
|
|
181
181
|
|
|
182
182
|
### Highlights
|
|
183
183
|
|
|
184
184
|
#### Memory hygiene (F1)
|
|
185
185
|
|
|
186
|
-
- **`AuditStateCache`** (`src/audit-state-cache.ts`)
|
|
187
|
-
- **`TTLQueue`** (`src/ttl-queue.ts`)
|
|
188
|
-
- Removed dynamic `require("node:fs")` inside `shouldInjectPlanReminder`
|
|
186
|
+
- **`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.
|
|
187
|
+
- **`TTLQueue`** (`src/ttl-queue.ts`) — TTL-based expiration for `pendingBotFeedback` and `pendingViolations` queues. Previously unbounded.
|
|
188
|
+
- Removed dynamic `require("node:fs")` inside `shouldInjectPlanReminder` — replaced with static ESM imports (no more runtime module resolution failures).
|
|
189
189
|
|
|
190
190
|
#### Dead code elimination (F2)
|
|
191
191
|
|
|
192
|
-
- `takeAnyDecision()`
|
|
193
|
-
- `systemInjection`
|
|
194
|
-
- `logToFile` in `graph-sync.ts`
|
|
195
|
-
- Plugin version
|
|
192
|
+
- `takeAnyDecision()` — deprecated; removed from the active governance pipeline.
|
|
193
|
+
- `systemInjection` — now awaited eagerly instead of fire-and-forget, eliminating a silent failure route.
|
|
194
|
+
- `logToFile` in `graph-sync.ts` — wired to the real JSONL file logger (was a no-op stub).
|
|
195
|
+
- 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).
|
|
196
196
|
|
|
197
197
|
#### Tool bug fixes (F3)
|
|
198
198
|
|
|
199
199
|
- **AFT checkpoint/undo**: args split on whitespace broke names with spaces. Rewrote arg construction with proper quoting.
|
|
200
200
|
- **AFT subcommand**: now uses `options.projectDir` instead of `process.cwd()`.
|
|
201
201
|
- **graphify binary override**: `omo_path` / `omo_explain` honored the `graphifyBin` option (was hardcoded).
|
|
202
|
-
- **`as never` cast** on `setClient`
|
|
202
|
+
- **`as never` cast** on `setClient` → proper runtime guard that validates client shape.
|
|
203
203
|
- **`session-bridge`**: replaced module-level `_client` with `AsyncLocalStorage` for per-request isolation. Concurrent sessions no longer race on the same client reference.
|
|
204
204
|
|
|
205
205
|
#### Test coverage (F4)
|
|
@@ -215,18 +215,18 @@ v0.16.0 closes the 50+ findings from the multi-front audit at `.omo/ulw-research
|
|
|
215
215
|
#### CI matrix (F6)
|
|
216
216
|
|
|
217
217
|
- `bun run typecheck` now runs on **macos-latest** and **windows-latest** (was Ubuntu-only).
|
|
218
|
-
- Removed `package-lock.json` (bun project
|
|
218
|
+
- Removed `package-lock.json` (bun project — canonical is `bun.lock`).
|
|
219
219
|
- Secret redaction layer in `logToFile` (JWT, OpenAI keys, Bearer tokens, GitHub PATs, generic key:value patterns).
|
|
220
|
-
- Implementation plan renamed `IMPLEMENTATION_PLAN.md`
|
|
220
|
+
- Implementation plan renamed `IMPLEMENTATION_PLAN.md` → `ARCHITECTURE.md`.
|
|
221
221
|
|
|
222
222
|
#### Final refactors (F7)
|
|
223
223
|
|
|
224
224
|
- Score formula documented (header doc with full formula spec).
|
|
225
|
-
- **NaN guard** in `score()`
|
|
225
|
+
- **NaN guard** in `score()` — defaults to neutral continue when `iterationRatio` or `ambient.iteration/maxIterations` produce NaN.
|
|
226
226
|
- `ACTION_SEVERITY` keyed by `DecisionHandlerOutput["action"]` union literal (was bare `Record<string, number>`).
|
|
227
227
|
- `projectHasCodegraph` / `projectHasGraphify` IIFE booleans replaced with lookup-time calls to `graphRetrieval.hasCodegraphDir(cwd)`.
|
|
228
228
|
- `extractConcepts` includes file basename for FTS lookup by tool/file name.
|
|
229
|
-
- Backup graph-sync uses `triggerReindex` (was `triggerCodegraphSync`)
|
|
229
|
+
- Backup graph-sync uses `triggerReindex` (was `triggerCodegraphSync`) — reindexes both codegraph AND graphify backends.
|
|
230
230
|
|
|
231
231
|
### Test & build status
|
|
232
232
|
|
|
@@ -241,47 +241,47 @@ No user action required. All changes are internal. The default `phaseAwareDoneSi
|
|
|
241
241
|
|
|
242
242
|
### Deferred to v0.17.0
|
|
243
243
|
|
|
244
|
-
- F5.1
|
|
245
|
-
- F5.4
|
|
246
|
-
- F3.6
|
|
244
|
+
- F5.1 — wiring `escalate` action to a real dispatcher (Oracle is recommended but not yet wired).
|
|
245
|
+
- F5.4 — `maxLessonsPerSession` enforcement (config field exists but is not enforced).
|
|
246
|
+
- 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.
|
|
247
247
|
|
|
248
248
|
|
|
249
249
|
|
|
250
250
|
|
|
251
|
-
## v0.17.0
|
|
251
|
+
## v0.17.0 — Wire escalate to Oracle, enforce lesson cap, verify bridge delivery
|
|
252
252
|
|
|
253
|
-
v0.17.0 closes the 3 deferred items from the v0.16.0 audit: **F5.1** (escalate
|
|
253
|
+
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).
|
|
254
254
|
|
|
255
255
|
### Highlights
|
|
256
256
|
|
|
257
|
-
#### F5.1
|
|
257
|
+
#### F5.1 — Escalate action now fires Oracle (v0.17.0)
|
|
258
258
|
|
|
259
259
|
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.
|
|
260
260
|
|
|
261
261
|
```ts
|
|
262
262
|
// Decision flow when score lands in escalate band:
|
|
263
|
-
score
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
263
|
+
score ≤ -escalateThreshold (default -0.6)
|
|
264
|
+
→ decision.action = "escalate"
|
|
265
|
+
→ decision.shouldEscalateTo = "oracle" (or "user" for grave deviations)
|
|
266
|
+
→ plugin fires session.prompt with buildEscalationPrompt(...)
|
|
267
|
+
→ LLM invokes Oracle (or summarizes for user)
|
|
268
|
+
→ Oracle verifies → oracleInvoked=true → governance continues
|
|
269
269
|
```
|
|
270
270
|
|
|
271
|
-
#### F5.4
|
|
271
|
+
#### F5.4 — `maxLessonsPerSession` is now enforced
|
|
272
272
|
|
|
273
273
|
The cap (default 20) was a config field that was never enforced. v0.17.0 adds:
|
|
274
274
|
- `currentLessonCount` on `LearnFromOutcomeInput` and `MetaGovernorInput`
|
|
275
275
|
- `lessonCount` tracked in per-session `AuditState`
|
|
276
276
|
- `observeAndLearn()` short-circuits when `currentLessonCount >= maxLessonsPerSession`
|
|
277
277
|
- The orchestrator increments `sessionState.lessonCount` after each successful save
|
|
278
|
-
- **Cap semantics: inclusive**
|
|
278
|
+
- **Cap semantics: inclusive** — when count equals cap, no more lessons are saved
|
|
279
279
|
|
|
280
|
-
#### F3.6
|
|
280
|
+
#### F3.6 — Bridge tool delivery verification
|
|
281
281
|
|
|
282
|
-
The 5 bridge tools (`omo_remember`, `omo_recall_mcp`, `omo_rule`, `omo_history`, `omo_note`) previously returned "dispatched" after the `session.prompt()` was queued
|
|
282
|
+
The 5 bridge tools (`omo_remember`, `omo_recall_mcp`, `omo_rule`, `omo_history`, `omo_note`) previously returned "dispatched" after the `session.prompt()` was queued — without verifying the LLM actually called the MCP tool. v0.17.0 adds:
|
|
283
283
|
|
|
284
|
-
- **New `PendingDeliveryRegistry` module** (`src/delivery-registry.ts`)
|
|
284
|
+
- **New `PendingDeliveryRegistry` module** (`src/delivery-registry.ts`) — tracks pending dispatches per session with TTL-based cleanup.
|
|
285
285
|
- **`tool.execute.after` hook** marks deliveries when a matching MCP tool call is observed.
|
|
286
286
|
- **All 5 bridge tools** now report `deliveryStatus: "delivered" | "pending"` in their tool result and metadata, and briefly poll (1.5s) for fast deliveries.
|
|
287
287
|
- When the LLM follows the prompt, the tool returns immediately with `"delivered"`. When it doesn't, the tool returns `"pending"` and the entry expires silently after 10s.
|
|
@@ -300,7 +300,7 @@ The 5 bridge tools (`omo_remember`, `omo_recall_mcp`, `omo_rule`, `omo_history`,
|
|
|
300
300
|
|
|
301
301
|
### Test & build status
|
|
302
302
|
|
|
303
|
-
- **514/514 tests pass** (up from 495 in v0.16.0
|
|
303
|
+
- **514/514 tests pass** (up from 495 in v0.16.0 — 5 + 4 + 10 new tests across F5.4, F5.1, F3.6).
|
|
304
304
|
- `bun run typecheck` clean.
|
|
305
305
|
- `bun build.ts` clean (0.34 MB dist).
|
|
306
306
|
- `npm pack --dry-run` validated.
|
|
@@ -308,23 +308,23 @@ The 5 bridge tools (`omo_remember`, `omo_recall_mcp`, `omo_rule`, `omo_history`,
|
|
|
308
308
|
### Migration
|
|
309
309
|
|
|
310
310
|
No user action required. All changes are internal or additive:
|
|
311
|
-
- `deliveryStatus` is an additive metadata field
|
|
312
|
-
- `maxLessonsPerSession` is now actually enforced
|
|
313
|
-
- `escalate` action now actively fires Oracle
|
|
311
|
+
- `deliveryStatus` is an additive metadata field — existing consumers ignore it.
|
|
312
|
+
- `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.
|
|
313
|
+
- `escalate` action now actively fires Oracle — this is the first version where Oracle is auto-invoked, not just manually invoked by the LLM.
|
|
314
314
|
|
|
315
315
|
### Audit roadmap (status as of v0.17.0)
|
|
316
316
|
|
|
317
317
|
| Release | Status | Scope |
|
|
318
318
|
|---------|--------|-------|
|
|
319
|
-
| v0.15.1 (F0) |
|
|
320
|
-
| v0.16.0 (F1-F7) |
|
|
321
|
-
| v0.17.0 (deferred) |
|
|
319
|
+
| v0.15.1 (F0) | ✅ Shipped | Hotfix self-dep + npm pack gate |
|
|
320
|
+
| v0.16.0 (F1-F7) | ✅ Shipped | Memory hygiene, dead code, tool coverage, CI |
|
|
321
|
+
| v0.17.0 (deferred) | ✅ Shipped | F5.1 escalate, F5.4 cap, F3.6 delivery verify |
|
|
322
322
|
|
|
323
323
|
All audit findings are now closed. Future work focuses on new features and user-driven feedback.
|
|
324
324
|
|
|
325
325
|
|
|
326
326
|
|
|
327
|
-
## v0.17.1
|
|
327
|
+
## v0.17.1 — Audit args fix (patch)
|
|
328
328
|
|
|
329
329
|
v0.17.1 is a single-bug patch release. The fix addresses an issue discovered during v0.17.0 verification:
|
|
330
330
|
|
|
@@ -336,7 +336,7 @@ The `tool.execute.before` hook passed an empty `{}` object as the second argumen
|
|
|
336
336
|
- `as any` type assertions
|
|
337
337
|
- `catch(e) {}` empty catch blocks
|
|
338
338
|
|
|
339
|
-
The hook signature was also incomplete
|
|
339
|
+
The hook signature was also incomplete — it didn't receive the `output` parameter that contains the mutable args, even though the SDK provides it.
|
|
340
340
|
|
|
341
341
|
### The fix
|
|
342
342
|
|
|
@@ -358,14 +358,14 @@ Two changes in `src/plugin.ts`:
|
|
|
358
358
|
### Tests
|
|
359
359
|
|
|
360
360
|
Added 4 new tests in `src/plugin.test.ts`:
|
|
361
|
-
- `@ts-ignore + as any` in args
|
|
362
|
-
- `catch(e) {}` in args
|
|
363
|
-
- Clean code
|
|
364
|
-
- `auditToolCalls: false`
|
|
361
|
+
- `@ts-ignore + as any` in args → `no-type-suppression` violation detected and injected
|
|
362
|
+
- `catch(e) {}` in args → `no-empty-catch` violation detected and injected
|
|
363
|
+
- Clean code → no violation injected (false-positive guard)
|
|
364
|
+
- `auditToolCalls: false` → audit short-circuits (regression check)
|
|
365
365
|
|
|
366
366
|
### Test & build status
|
|
367
367
|
|
|
368
|
-
- **518/518 tests pass** (up from 514 in v0.17.0
|
|
368
|
+
- **518/518 tests pass** (up from 514 in v0.17.0 — 4 new audit tests).
|
|
369
369
|
- `bun run typecheck` clean.
|
|
370
370
|
- `bun build.ts` clean (0.34 MB dist).
|
|
371
371
|
|
|
@@ -378,26 +378,26 @@ No user action required. The audit detection now correctly fires when the agent
|
|
|
378
378
|
|
|
379
379
|
|
|
380
380
|
|
|
381
|
-
## v0.17.2
|
|
381
|
+
## v0.17.2 — Fix escalation dead code + 4 audit gaps
|
|
382
382
|
|
|
383
|
-
v0.17.2 closes 4 gaps discovered during live verification of v0.17.0/v0.17.1. The most important: F5.1 (escalate
|
|
383
|
+
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.
|
|
384
384
|
|
|
385
385
|
### Highlights
|
|
386
386
|
|
|
387
|
-
#### Gap C (CRITICAL)
|
|
387
|
+
#### Gap C (CRITICAL) — Escalation now actually fires
|
|
388
388
|
|
|
389
|
-
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
|
|
389
|
+
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`.
|
|
390
390
|
|
|
391
391
|
**Fix:**
|
|
392
392
|
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`.
|
|
393
393
|
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.
|
|
394
394
|
3. **Lower default thresholds** to match the new worst-case math:
|
|
395
|
-
- `escalateThreshold`: 0.6
|
|
396
|
-
- `stopThreshold`: 0.8
|
|
395
|
+
- `escalateThreshold`: 0.6 → 0.45
|
|
396
|
+
- `stopThreshold`: 0.8 → 0.55
|
|
397
397
|
|
|
398
|
-
Now worst-case state (no oracle, no progress, 2 grave deviations, iteration at limit, stop-advice lessons) produces score
|
|
398
|
+
Now worst-case state (no oracle, no progress, 2 grave deviations, iteration at limit, stop-advice lessons) produces score ≈ -0.55 → `stop` action fires.
|
|
399
399
|
|
|
400
|
-
#### Gap Q (HIGH)
|
|
400
|
+
#### Gap Q (HIGH) — File paths threaded through pipeline
|
|
401
401
|
|
|
402
402
|
`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.
|
|
403
403
|
|
|
@@ -406,17 +406,17 @@ Now worst-case state (no oracle, no progress, 2 grave deviations, iteration at l
|
|
|
406
406
|
2. Capture `filePath` from `toolInput.args` on write/edit tool calls.
|
|
407
407
|
3. New `MetaGovernorInput.filePaths?: readonly string[]` passed through to `observeAndLearn`.
|
|
408
408
|
|
|
409
|
-
#### Gap D (HIGH)
|
|
409
|
+
#### Gap D (HIGH) — Three config fields now actually do something
|
|
410
410
|
|
|
411
411
|
Three fields were in the schema and config projection but NEVER consulted by the logic:
|
|
412
412
|
|
|
413
|
-
- `closedLoop.saveLessons`
|
|
414
|
-
- `intervention.includeDecisionHistory`
|
|
415
|
-
- `intervention.maxHistoryMessages`
|
|
413
|
+
- `closedLoop.saveLessons` — parallel to `saveDecisions`. When `false`, lessons are skipped (decision records still save).
|
|
414
|
+
- `intervention.includeDecisionHistory` — when `true`, `messages.transform` prepends recent intervention texts (capped at `maxHistoryMessages`) so the LLM sees its history of decisions.
|
|
415
|
+
- `intervention.maxHistoryMessages` — limit for the above (default 5).
|
|
416
416
|
|
|
417
417
|
**Fix:** All three fields now control behavior. Track `recentInterventionTexts` in AuditState, format them into the injection text.
|
|
418
418
|
|
|
419
|
-
#### Bonus
|
|
419
|
+
#### Bonus — iteration-budget signal wired (Oracle finding)
|
|
420
420
|
|
|
421
421
|
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.
|
|
422
422
|
|
|
@@ -425,9 +425,9 @@ Fix:
|
|
|
425
425
|
- Threaded `iteration: sessionState?.iteration ?? 0` into `MetaGovernorInput`.
|
|
426
426
|
- `maxIterations` now reads from config instead of being hardcoded.
|
|
427
427
|
|
|
428
|
-
Worst-case score math updated: with iteration at 100% (-0.12), all signals bad, no oracle
|
|
428
|
+
Worst-case score math updated: with iteration at 100% (-0.12), all signals bad, no oracle → score = -0.65 → `stop` action fires.
|
|
429
429
|
|
|
430
|
-
#### Gap I (MEDIUM)
|
|
430
|
+
#### Gap I (MEDIUM) — `verifyDelivery` return type includes "expired"
|
|
431
431
|
|
|
432
432
|
The TypeScript signature was `Promise<"delivered" | "pending">` but the registry could return `"expired"`. The expired case leaked through as `"pending"` silently.
|
|
433
433
|
|
|
@@ -435,7 +435,7 @@ The TypeScript signature was `Promise<"delivered" | "pending">` but the registry
|
|
|
435
435
|
|
|
436
436
|
### Test & build status
|
|
437
437
|
|
|
438
|
-
- **521/521 tests pass** (up from 518
|
|
438
|
+
- **521/521 tests pass** (up from 518 — 3 new tests for the v0.17.2 fixes).
|
|
439
439
|
- `bun run typecheck` clean.
|
|
440
440
|
- `bun build.ts` clean (0.34 MB dist).
|
|
441
441
|
- `npm pack --dry-run` validated.
|
|
@@ -444,28 +444,28 @@ The TypeScript signature was `Promise<"delivered" | "pending">` but the registry
|
|
|
444
444
|
|
|
445
445
|
No user action required. Two behavior changes:
|
|
446
446
|
|
|
447
|
-
1. **Escalation now fires more aggressively.** If your agent has been producing violations and not making progress, expect to see escalate
|
|
447
|
+
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.
|
|
448
448
|
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.
|
|
449
449
|
|
|
450
450
|
### Audit roadmap (status as of v0.17.2)
|
|
451
451
|
|
|
452
452
|
| Release | Status | Scope |
|
|
453
453
|
|---------|--------|-------|
|
|
454
|
-
| v0.15.1 (F0) |
|
|
455
|
-
| v0.16.0 (F1-F7) |
|
|
456
|
-
| v0.17.0 |
|
|
457
|
-
| v0.17.1 |
|
|
458
|
-
| v0.17.2 |
|
|
454
|
+
| v0.15.1 (F0) | ✅ | Hotfix self-dep |
|
|
455
|
+
| v0.16.0 (F1-F7) | ✅ | Memory hygiene, dead code, tool coverage, CI |
|
|
456
|
+
| v0.17.0 | ✅ | F5.1 escalate, F5.4 cap, F3.6 delivery verify |
|
|
457
|
+
| v0.17.1 | ✅ | Audit args fix |
|
|
458
|
+
| v0.17.2 | ✅ | Gap C (escalation live), Q (file paths), D (config fields), I (delivery expired) |
|
|
459
459
|
|
|
460
460
|
|
|
461
461
|
|
|
462
|
-
## v0.17.3
|
|
462
|
+
## v0.17.3 — Fix Gap I properly (patch)
|
|
463
463
|
|
|
464
464
|
v0.17.3 is a single-bug patch. During live verification of v0.17.2, Gap I was found to be incompletely fixed.
|
|
465
465
|
|
|
466
466
|
### The bug (v0.17.2 cosmetic fix)
|
|
467
467
|
|
|
468
|
-
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"`
|
|
468
|
+
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:**
|
|
469
469
|
|
|
470
470
|
```ts
|
|
471
471
|
// v0.17.2 (BUG):
|
|
@@ -492,31 +492,31 @@ Added 3 RED tests in `src/custom-tools.test.ts`:
|
|
|
492
492
|
|
|
493
493
|
### Test & build status
|
|
494
494
|
|
|
495
|
-
- **525/525 tests pass** (up from 522 in v0.17.2
|
|
495
|
+
- **525/525 tests pass** (up from 522 in v0.17.2 — 3 new tests for pollForDelivery).
|
|
496
496
|
- `bun run typecheck` clean.
|
|
497
497
|
- `bun build.ts` clean (0.34 MB dist).
|
|
498
498
|
|
|
499
499
|
### Migration
|
|
500
500
|
|
|
501
501
|
No user action required. Bridge tools will now correctly distinguish all three delivery states:
|
|
502
|
-
- `"delivered"`
|
|
503
|
-
- `"expired"`
|
|
504
|
-
- `"pending"`
|
|
502
|
+
- `"delivered"` — LLM's MCP tool call was observed within 1.5s
|
|
503
|
+
- `"expired"` — TTL elapsed without delivery (entry expires after 10s, but bridge tool sees this immediately as "expired" when polling times out at 1.5s)
|
|
504
|
+
- `"pending"` — no registry configured (graceful degradation for tests/mocks)
|
|
505
505
|
|
|
506
506
|
### Audit roadmap (status as of v0.17.3)
|
|
507
507
|
|
|
508
508
|
| Release | Status | Scope |
|
|
509
509
|
|---------|--------|-------|
|
|
510
|
-
| v0.15.1
|
|
511
|
-
| v0.17.3 |
|
|
510
|
+
| v0.15.1 → v0.17.2 | ✅ | All audit findings + 5 gap fixes |
|
|
511
|
+
| v0.17.3 | ✅ | Gap I real fix (pollForDelivery returns "expired") |
|
|
512
512
|
|
|
513
513
|
Two remaining gaps documented but require SDK support to fix:
|
|
514
|
-
- `recentTurnTokens: []`
|
|
515
|
-
- `agentName` defaults to `"unknown"`
|
|
514
|
+
- `recentTurnTokens: []` — token-predictor signal dead (10% of score); needs per-turn token counts from OpenCode SDK
|
|
515
|
+
- `agentName` defaults to `"unknown"` — cosmetic, no functional impact
|
|
516
516
|
|
|
517
517
|
|
|
518
518
|
|
|
519
|
-
## v0.18.0
|
|
519
|
+
## v0.18.0 — Audit remediation: 7+ silent config drops + circular ref crash
|
|
520
520
|
|
|
521
521
|
v0.18.0 is a thorough-audit patch release. Each fix addresses a bug found by testing every public function with edge cases and adversarial inputs.
|
|
522
522
|
|
|
@@ -524,19 +524,19 @@ v0.18.0 is a thorough-audit patch release. Each fix addresses a bug found by tes
|
|
|
524
524
|
|
|
525
525
|
| # | Bug | Severity | Fix |
|
|
526
526
|
|---|-----|----------|-----|
|
|
527
|
-
| 1 | `file-logger.redactData` crashed on circular references with stack overflow |
|
|
528
|
-
| 2 | `loadOrchestratorConfig` only projected `closedLoop.saveDecisions`
|
|
529
|
-
| 3 | `loadOrchestratorConfig` didn't project `decision.warnMessageTemplate`, `escalateMessageTemplate`, `stopMessageTemplate` |
|
|
530
|
-
| 4 | `loadOrchestratorConfig` didn't project `scoring.paralysisThreshold`, `defaultEscalationTarget` |
|
|
531
|
-
| 5 | `loadOrchestratorConfig` had `memory.timeoutMs` field name mismatch (schema said `agentmemoryTimeoutMs`) |
|
|
532
|
-
| 6 | `isMetaGovernorEnabled` only checked top-level `enabled`, not `meta_governor.enabled` (wrapped shape from `opencode.jsonc`) |
|
|
533
|
-
| 7 | `createMetricsCollector` crashed when called without config (`config.version` on `undefined`) |
|
|
534
|
-
| 8 | `metrics.inc` crashed on unknown event names (`bucket.count++` on `undefined`) |
|
|
535
|
-
| 9 | `isNewerVersion` returned `false` for `installed=null` (no upgrade triggered for fresh installs) |
|
|
527
|
+
| 1 | `file-logger.redactData` crashed on circular references with stack overflow | 🔴 CRITICAL | `WeakSet` guard + `try/catch` fallback |
|
|
528
|
+
| 2 | `loadOrchestratorConfig` only projected `closedLoop.saveDecisions` — `enabled`, `minSeverityToLearn`, `maxLessonsPerSession`, `saveLessons` were silently dropped | 🔴 CRITICAL | Project all 5 fields |
|
|
529
|
+
| 3 | `loadOrchestratorConfig` didn't project `decision.warnMessageTemplate`, `escalateMessageTemplate`, `stopMessageTemplate` | 🟠HIGH | Project all 3 templates |
|
|
530
|
+
| 4 | `loadOrchestratorConfig` didn't project `scoring.paralysisThreshold`, `defaultEscalationTarget` | 🟠HIGH | Project all fields |
|
|
531
|
+
| 5 | `loadOrchestratorConfig` had `memory.timeoutMs` field name mismatch (schema said `agentmemoryTimeoutMs`) | 🟠HIGH | Accept both names |
|
|
532
|
+
| 6 | `isMetaGovernorEnabled` only checked top-level `enabled`, not `meta_governor.enabled` (wrapped shape from `opencode.jsonc`) | 🟠HIGH | Check both shapes |
|
|
533
|
+
| 7 | `createMetricsCollector` crashed when called without config (`config.version` on `undefined`) | 🟠HIGH | Accept `Partial<MetricsCollectorConfig>` |
|
|
534
|
+
| 8 | `metrics.inc` crashed on unknown event names (`bucket.count++` on `undefined`) | 🟠HIGH | Guard `if (!bucket) return` |
|
|
535
|
+
| 9 | `isNewerVersion` returned `false` for `installed=null` (no upgrade triggered for fresh installs) | 🟡 MEDIUM | Return `true` when installed is null AND latest is valid |
|
|
536
536
|
|
|
537
537
|
### Test & build status
|
|
538
538
|
|
|
539
|
-
- **557/557 tests pass** (up from 530 in v0.17.3
|
|
539
|
+
- **557/557 tests pass** (up from 530 in v0.17.3 — 27 new tests for the audit fixes).
|
|
540
540
|
- `bun run typecheck` clean.
|
|
541
541
|
- `bun build.ts` clean (0.34 MB dist).
|
|
542
542
|
- `npm pack --dry-run` validated.
|
|
@@ -549,11 +549,105 @@ No user action required. The fix to `loadOrchestratorConfig` means **users who w
|
|
|
549
549
|
|
|
550
550
|
| Release | Status | Scope |
|
|
551
551
|
|---------|--------|-------|
|
|
552
|
-
| v0.15.1
|
|
553
|
-
| v0.18.0 |
|
|
552
|
+
| v0.15.1 → v0.17.3 | ✅ | All audit findings + deferred items + audit args fix + gap fixes |
|
|
553
|
+
| v0.18.0 | ✅ | 7 silent config drops + circular ref crash + metrics crashes + upgrade trigger |
|
|
554
554
|
|
|
555
555
|
This release closes the final round of gaps found by a thorough function-by-function audit. The plugin now correctly projects **all** user configuration, handles **all** circular reference cases, and fails safely on **all** missing-input scenarios.
|
|
556
556
|
|
|
557
|
+
|
|
558
|
+
## v0.19.4 — Dual-shape default export: opencode 1.18.x loader compat (patch)
|
|
559
|
+
|
|
560
|
+
v0.19.3 shipped a function-only default export hoping to fix the opencode
|
|
561
|
+
serve factory-not-invoked bug. Empirical verification (reading
|
|
562
|
+
`~/.config/opencode/meta-governor.log`) showed it didn''t help: opencode
|
|
563
|
+
1.18.16 npm-package plugins still loaded the module without ever calling
|
|
564
|
+
the factory under `opencode serve`.
|
|
565
|
+
|
|
566
|
+
### The fix
|
|
567
|
+
|
|
568
|
+
`src/index.ts` now exports an object that is **both** a Plugin function
|
|
569
|
+
**and** a PluginModule:
|
|
570
|
+
|
|
571
|
+
```ts
|
|
572
|
+
const _plugin = createMetaGovernorPlugin()
|
|
573
|
+
_plugin.id = "omo-meta-governor"
|
|
574
|
+
_plugin.server = _plugin
|
|
575
|
+
export default _plugin
|
|
576
|
+
```
|
|
577
|
+
|
|
578
|
+
Bundled as `var u4=IN(); u4.id="omo-meta-governor"; u4.server=u4; export{...JX=u4...}`.
|
|
579
|
+
Whichever path opencode picks (`default(input, options)` or
|
|
580
|
+
`default.server(input, options)`), the same callable fires and the hooks
|
|
581
|
+
register.
|
|
582
|
+
|
|
583
|
+
### Verification
|
|
584
|
+
|
|
585
|
+
After restart of OpenChamber, log shows:
|
|
586
|
+
- factory_invoked events (was 0 with v0.19.3)
|
|
587
|
+
- config_loaded events (was 0 with v0.19.3)
|
|
588
|
+
- intervention / violations / persist calls firing normally
|
|
589
|
+
|
|
590
|
+
### Test & build status
|
|
591
|
+
|
|
592
|
+
- 4/4 new tests in `src/index.test.ts` lock down the dual-shape contract.
|
|
593
|
+
- `bun run typecheck` clean.
|
|
594
|
+
- `bun build.ts` clean (0.35 MB dist).
|
|
595
|
+
- `npm publish` to registry OK.
|
|
596
|
+
|
|
597
|
+
### Migration
|
|
598
|
+
|
|
599
|
+
No user action required. If you previously set
|
|
600
|
+
`intervention.persistToSession: false` in your config, that toggle is
|
|
601
|
+
still respected.
|
|
602
|
+
|
|
603
|
+
---
|
|
604
|
+
|
|
605
|
+
## v0.19.3 — opencode serve factory invocation + persistSessionMessage wiring
|
|
606
|
+
|
|
607
|
+
This release closes the persistSessionMessage wiring arc (memory #999) and
|
|
608
|
+
loads config from three sources automatically (CLI > project > user).
|
|
609
|
+
The `index.ts` `export default` change was incomplete (see v0.19.4 for
|
|
610
|
+
the proper dual-shape fix that resolves opencode serve invocation).
|
|
611
|
+
|
|
612
|
+
### Highlights
|
|
613
|
+
|
|
614
|
+
- **index.ts**: switched `export default` to call `createMetaGovernorPlugin()`
|
|
615
|
+
directly (function path), abandoning the `PluginModule` wrapper. Was the
|
|
616
|
+
wrong shape — see v0.19.4 for the actual fix.
|
|
617
|
+
- **plugin.ts**: factory now calls `loadMetaGovernorConfig({ projectDir })` so
|
|
618
|
+
config from `.opencode/omo-meta-governor.jsonc` and
|
|
619
|
+
`~/.config/opencode/omo-meta-governor.jsonc` flows in automatically.
|
|
620
|
+
- **session-bridge.ts**: `persistSessionMessage()` — fire-and-forget
|
|
621
|
+
`session.prompt()` helper that records intervention text as a REAL session
|
|
622
|
+
message (visible in TUI and session DB).
|
|
623
|
+
- **types.ts + config.ts + orchestrator.ts**: `persistToSession` defaults to
|
|
624
|
+
true on `InterventionConfig`. Helps users running OpenChamber actually
|
|
625
|
+
SEE interventions in their TUI.
|
|
626
|
+
- **tests**: 16 `createMetaGovernorPlugin()` calls in plugin/v172/v173-gap-d
|
|
627
|
+
tests now pass `graphSync: { enabled: false, autoInstall: false }`
|
|
628
|
+
because user config enables `autoInstall` by default (memory #989).
|
|
629
|
+
|
|
630
|
+
### Test & build status
|
|
631
|
+
|
|
632
|
+
- ~437/437 tests pass (per-file, `graphsink-fix.ts` skipped per known Bun
|
|
633
|
+
Windows integer-overflow crash).
|
|
634
|
+
- `bun run typecheck` clean.
|
|
635
|
+
- `bun build.ts` clean (0.35 MB dist).
|
|
636
|
+
- `npm publish` to registry OK.
|
|
637
|
+
|
|
638
|
+
### Migration
|
|
639
|
+
|
|
640
|
+
No user action required.
|
|
641
|
+
|
|
642
|
+
---
|
|
643
|
+
|
|
644
|
+
## v0.19.0–v0.19.2 — Internal persistSessionMessage wiring arc (memory #999)
|
|
645
|
+
|
|
646
|
+
Three iterations on the persistSessionMessage wiring arc. Each iteration
|
|
647
|
+
added call sites and tightened the test coverage, but the fix was lost in
|
|
648
|
+
stashes and merges until v0.19.3 finally shipped a working version of
|
|
649
|
+
the helper. See v0.19.3 for the user-facing release notes; v0.19.4
|
|
650
|
+
supersedes with the correct dual-shape export.
|
|
557
651
|
## Auto-upgrade (v0.12.0)
|
|
558
652
|
|
|
559
653
|
On plugin load, queries npm/pip registries to check whether newer versions
|
package/dist/index.d.ts
CHANGED
|
@@ -1,24 +1,27 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
2
|
+
* Dual-shape export for opencode plugin loader compatibility.
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
4
|
+
* The default export is simultaneously:
|
|
5
|
+
* - a Plugin function: `default(input, options) => Promise<Hooks>`
|
|
6
|
+
* - a PluginModule: `default.id`, `default.server(input, options)`
|
|
7
7
|
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
*
|
|
18
|
-
*
|
|
8
|
+
* `.server` points to the same callable as the default, so whichever
|
|
9
|
+
* shape the opencode loader resolves, the factory fires exactly once.
|
|
10
|
+
*/
|
|
11
|
+
export declare const _pluginDual: Plugin & {
|
|
12
|
+
id: string;
|
|
13
|
+
server: Plugin;
|
|
14
|
+
};
|
|
15
|
+
export default _pluginDual;
|
|
16
|
+
/**
|
|
17
|
+
* Named alias of the dual-shape export. Some opencode plugin loaders
|
|
18
|
+
* resolve plugins by named export rather than default — exposing both
|
|
19
|
+
* covers that third hypothetical path with zero cost.
|
|
19
20
|
*/
|
|
20
|
-
declare const
|
|
21
|
-
|
|
21
|
+
export declare const plugin: Plugin & {
|
|
22
|
+
id: string;
|
|
23
|
+
server: Plugin;
|
|
24
|
+
};
|
|
22
25
|
export { createMetaGovernorPlugin, type MetaGovernorPluginDeps } from "./plugin";
|
|
23
26
|
export { logToFile } from "./file-logger";
|
|
24
27
|
export { runMetaGovernor, buildDecisionContext, defaultOrchestratorConfig, } from "./orchestrator";
|