@herjarsa/omo-meta-governor 0.19.4 → 0.19.6

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 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 — USE THIS FIRST |
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 — uses Bun's built-in
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 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
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 — logged, does NOT latch. |
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–v0.14.x users keep working without changes (default
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 — Audit remediation: memory hygiene, dead code, tool coverage, CI
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 — only internal cleanup, dead code removal, and CI hardening.
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`) — 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).
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()` — 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).
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` → proper runtime guard that validates client shape.
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 — canonical is `bun.lock`).
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` → `ARCHITECTURE.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()` — defaults to neutral continue when `iterationRatio` or `ambient.iteration/maxIterations` produce NaN.
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`) — reindexes both codegraph AND graphify backends.
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 — 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.
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 — Wire escalate to Oracle, enforce lesson cap, verify bridge delivery
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 → Oracle), **F5.4** (`maxLessonsPerSession` enforcement), and **F3.6** (bridge tool delivery verification).
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 — Escalate action now fires Oracle (v0.17.0)
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 ≤ -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
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 — `maxLessonsPerSession` is now enforced
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** — when count equals cap, no more lessons are saved
278
+ - **Cap semantics: inclusive** — when count equals cap, no more lessons are saved
279
279
 
280
- #### F3.6 — Bridge tool delivery verification
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 — without verifying the LLM actually called the MCP tool. v0.17.0 adds:
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`) — tracks pending dispatches per session with TTL-based cleanup.
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 — 5 + 4 + 10 new tests across F5.4, F5.1, F3.6).
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 — 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.
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) | ✅ 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 |
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 — Audit args fix (patch)
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 — it didn't receive the `output` parameter that contains the mutable args, even though the SDK provides it.
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 → `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)
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 — 4 new audit tests).
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 — Fix escalation dead code + 4 audit gaps
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 → Oracle) was effectively dead in production due to two compounding bugs.
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) — Escalation now actually fires
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 — never reaching `escalateThreshold: 0.6` or `stopThreshold: 0.8`.
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 → 0.45
396
- - `stopThreshold`: 0.8 → 0.55
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 ≈ -0.55 → `stop` action fires.
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) — File paths threaded through pipeline
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) — Three config fields now actually do something
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` — 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).
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 — iteration-budget signal wired (Oracle finding)
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 → score = -0.65 → `stop` action fires.
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) — `verifyDelivery` return type includes "expired"
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 — 3 new tests for the v0.17.2 fixes).
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 → Oracle prompts more often. This is the intended behavior; v0.17.0 was incorrectly silent.
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) | ✅ | 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) |
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 — Fix Gap I properly (patch)
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"` → `"pending"` silently:**
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 — 3 new tests for pollForDelivery).
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"` — 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)
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 → v0.17.2 | ✅ | All audit findings + 5 gap fixes |
511
- | v0.17.3 | ✅ | Gap I real fix (pollForDelivery returns "expired") |
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: []` — token-predictor signal dead (10% of score); needs per-turn token counts from OpenCode SDK
515
- - `agentName` defaults to `"unknown"` — cosmetic, no functional impact
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 — Audit remediation: 7+ silent config drops + circular ref crash
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 | 🔴 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 |
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 — 27 new tests for the audit fixes).
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 → 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 |
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,41 +1,16 @@
1
+ import type { Hooks, PluginInput, PluginOptions } from "@opencode-ai/plugin";
1
2
  /**
2
- * @sisyphuslabs/omo-meta-governor — Self-judging agent orchestration layer.
3
- *
4
- * Default export is an OpenCode PluginModule that registers a
5
- * `tool.execute.after` hook. The MetaGovernor reads session signals,
6
- * scores them against weighted evidence, and dispatches decisions.
7
- *
8
- * Install:
9
- * npm install @sisyphuslabs/omo-meta-governor
10
- *
11
- * Configure:
12
- * ```jsonc
13
- * {
14
- * "meta_governor": {
15
- * "enabled": true
16
- * }
17
- * }
18
- * ```
3
+ * Plugin function shape: `default(input, options) => Hooks`.
4
+ * Also acts as PluginModule shape via the `.server` self-reference.
19
5
  */
20
- declare const _plugin: import("@opencode-ai/plugin").Plugin;
21
- export default _plugin;
22
- export { createMetaGovernorPlugin, type MetaGovernorPluginDeps } from "./plugin";
23
- export { logToFile } from "./file-logger";
24
- export { runMetaGovernor, buildDecisionContext, defaultOrchestratorConfig, } from "./orchestrator";
25
- export { loadOrchestratorConfig, isMetaGovernorEnabled, type MetaGovernorPluginConfig, } from "./config";
26
- export { score, defaultScoringConfig } from "./scoring-engine";
27
- export { predict, defaultTokenPredictorConfig, calculateBurnRate } from "./token-predictor";
28
- export { handleDecision, defaultDecisionHandlerConfig, trimHistory, countConsecutiveStops } from "./decision-handler";
29
- export { observeAndLearn, defaultClosedLoopConfig } from "./closed-loop-learning";
30
- export { aggregateRead } from "./memory-aggregator";
31
- export { recordRecovery, type RecoveryOutcome } from "./post-repair-recorder";
32
- export { storeDecision, takeDecision, hasDecision, takeAnyDecision, clearAll, } from "./decision-store";
6
+ declare function omoMetaGovernor(input: PluginInput, options?: PluginOptions): Promise<Hooks>;
7
+ export default omoMetaGovernor;
33
8
  export type { Decision, DecisionContext, DecisionHandlerConfig, DecisionHandlerInput, DecisionHandlerOutput, Deviation, Evidence, EvidenceContribution, InterventionConfig, InterventionMode, LearnFromOutcomeInput, LearnFromOutcomeOutput, MemoryRead, MemoryBackends, AgentmemoryWriteBackend, MetaGovernorInput, MetaGovernorOutput, OrchestratorConfig, ScoringConfig, ScoringResult, SlotMemory, TokenPredictorConfig, TokenPredictorInput, TokenPredictorOutput, ClosedLoopConfig, } from "./types";
34
- export { loadProtocol, buildSystemInjection, auditToolCall, DEFAULT_PROTOCOL_PATH, } from "./protocol-enforcer";
35
- export { stripJsoncComments, parseJsonc, loadJsoncFile, deepMerge, loadMetaGovernorConfig, getUserConfigPath, getProjectConfigPath, type ConfigFileSources, type ConfigFileResult, } from "./config-file";
36
- export { runGraphSync, stopWatches, resetInitializedProjects, type GraphSyncConfig, type GraphSyncResult, type GraphSyncCode, type ToolAvailability, } from "./graph-sync";
37
- export { generateSchema, writeSchemaFile, type JsonSchema, type JsonSchemaProperty } from "./generate-schema";
38
- export { SqliteBackend, getDefaultSqliteBackend } from "./sqlite-backend";
39
- export { GraphRetrieval, getDefaultGraphRetrieval, hashQuery, type GraphToolKind, type GraphInvocationResult, type GraphRetrievalConfig, type InvokeOptions } from "./graph-retrieval";
40
- export { loadOrchestratorConfigFromSources } from "./config";
9
+ export type { ConfigFileSources, ConfigFileResult, } from "./config-file";
10
+ export type { GraphSyncConfig, GraphSyncResult, GraphSyncCode, ToolAvailability, } from "./graph-sync";
11
+ export type { JsonSchema, JsonSchemaProperty } from "./generate-schema";
12
+ export type { GraphToolKind, GraphInvocationResult, GraphRetrievalConfig, InvokeOptions } from "./graph-retrieval";
41
13
  export type { ProtocolViolation, ProtocolEnforcementSessionState } from "./types";
14
+ export type { MetaGovernorPluginConfig } from "./config";
15
+ export type { MetaGovernorPluginDeps } from "./plugin";
16
+ export type { RecoveryOutcome } from "./post-repair-recorder";