@herjarsa/omo-meta-governor 0.17.1 → 0.17.3
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 +138 -0
- package/dist/custom-tools.d.ts +10 -0
- package/dist/index.js +51 -45
- package/dist/index.js.map +7 -7
- package/dist/types.d.ts +7 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -376,6 +376,144 @@ No user action required. The audit detection now correctly fires when the agent
|
|
|
376
376
|
- **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.
|
|
377
377
|
- **If you want to disable the audit**: set `protocolEnforcement.auditToolCalls: false` (already supported).
|
|
378
378
|
|
|
379
|
+
|
|
380
|
+
|
|
381
|
+
## v0.17.2 — Fix escalation dead code + 4 audit gaps
|
|
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.
|
|
384
|
+
|
|
385
|
+
### Highlights
|
|
386
|
+
|
|
387
|
+
#### Gap C (CRITICAL) — Escalation now actually fires
|
|
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`.
|
|
390
|
+
|
|
391
|
+
**Fix:**
|
|
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
|
+
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
|
+
3. **Lower default thresholds** to match the new worst-case math:
|
|
395
|
+
- `escalateThreshold`: 0.6 → 0.45
|
|
396
|
+
- `stopThreshold`: 0.8 → 0.55
|
|
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.
|
|
399
|
+
|
|
400
|
+
#### Gap Q (HIGH) — File paths threaded through pipeline
|
|
401
|
+
|
|
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
|
+
|
|
404
|
+
**Fix:**
|
|
405
|
+
1. Track `recentWriteFilePaths` in AuditState (alongside existing `recentWriteContents`).
|
|
406
|
+
2. Capture `filePath` from `toolInput.args` on write/edit tool calls.
|
|
407
|
+
3. New `MetaGovernorInput.filePaths?: readonly string[]` passed through to `observeAndLearn`.
|
|
408
|
+
|
|
409
|
+
#### Gap D (HIGH) — Three config fields now actually do something
|
|
410
|
+
|
|
411
|
+
Three fields were in the schema and config projection but NEVER consulted by the logic:
|
|
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).
|
|
416
|
+
|
|
417
|
+
**Fix:** All three fields now control behavior. Track `recentInterventionTexts` in AuditState, format them into the injection text.
|
|
418
|
+
|
|
419
|
+
#### Bonus — iteration-budget signal wired (Oracle finding)
|
|
420
|
+
|
|
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
|
+
|
|
423
|
+
Fix:
|
|
424
|
+
- Added `iteration: number` to `AuditState`, incremented per tool call.
|
|
425
|
+
- Threaded `iteration: sessionState?.iteration ?? 0` into `MetaGovernorInput`.
|
|
426
|
+
- `maxIterations` now reads from config instead of being hardcoded.
|
|
427
|
+
|
|
428
|
+
Worst-case score math updated: with iteration at 100% (-0.12), all signals bad, no oracle → score = -0.65 → `stop` action fires.
|
|
429
|
+
|
|
430
|
+
#### Gap I (MEDIUM) — `verifyDelivery` return type includes "expired"
|
|
431
|
+
|
|
432
|
+
The TypeScript signature was `Promise<"delivered" | "pending">` but the registry could return `"expired"`. The expired case leaked through as `"pending"` silently.
|
|
433
|
+
|
|
434
|
+
**Fix:** Signature updated to `Promise<"delivered" | "pending" | "expired">`. Bridge tools now distinguish: `"delivered"` (verified), `"pending"` (still polling), `"expired"` (TTL elapsed).
|
|
435
|
+
|
|
436
|
+
### Test & build status
|
|
437
|
+
|
|
438
|
+
- **521/521 tests pass** (up from 518 — 3 new tests for the v0.17.2 fixes).
|
|
439
|
+
- `bun run typecheck` clean.
|
|
440
|
+
- `bun build.ts` clean (0.34 MB dist).
|
|
441
|
+
- `npm pack --dry-run` validated.
|
|
442
|
+
|
|
443
|
+
### Migration
|
|
444
|
+
|
|
445
|
+
No user action required. Two behavior changes:
|
|
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.
|
|
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
|
+
|
|
450
|
+
### Audit roadmap (status as of v0.17.2)
|
|
451
|
+
|
|
452
|
+
| Release | Status | Scope |
|
|
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) |
|
|
459
|
+
|
|
460
|
+
|
|
461
|
+
|
|
462
|
+
## v0.17.3 — Fix Gap I properly (patch)
|
|
463
|
+
|
|
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
|
+
|
|
466
|
+
### The bug (v0.17.2 cosmetic fix)
|
|
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:**
|
|
469
|
+
|
|
470
|
+
```ts
|
|
471
|
+
// v0.17.2 (BUG):
|
|
472
|
+
return status === "delivered" ? "delivered" : "pending"
|
|
473
|
+
```
|
|
474
|
+
|
|
475
|
+
So bridge tools could never report `"expired"` to the user, even though the registry correctly tracked it. Live verification confirmed: `deliveryStatus` always showed `"pending"`.
|
|
476
|
+
|
|
477
|
+
### The fix (v0.17.3)
|
|
478
|
+
|
|
479
|
+
```ts
|
|
480
|
+
// v0.17.3:
|
|
481
|
+
return await pendingRegistryRef.awaitDelivery({ sessionID, mcpTool, timeoutMs })
|
|
482
|
+
```
|
|
483
|
+
|
|
484
|
+
Now the actual status from the registry propagates through. `"expired"` flows end-to-end to the bridge tool's `metadata.deliveryStatus` and title.
|
|
485
|
+
|
|
486
|
+
### Tests
|
|
487
|
+
|
|
488
|
+
Added 3 RED tests in `src/custom-tools.test.ts`:
|
|
489
|
+
- Returns `"expired"` when registry entry exists past timeout (real registry instance)
|
|
490
|
+
- Returns `"delivered"` when `markDelivered` fires before timeout
|
|
491
|
+
- Returns `"pending"` when no registry is configured
|
|
492
|
+
|
|
493
|
+
### Test & build status
|
|
494
|
+
|
|
495
|
+
- **525/525 tests pass** (up from 522 in v0.17.2 — 3 new tests for pollForDelivery).
|
|
496
|
+
- `bun run typecheck` clean.
|
|
497
|
+
- `bun build.ts` clean (0.34 MB dist).
|
|
498
|
+
|
|
499
|
+
### Migration
|
|
500
|
+
|
|
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)
|
|
505
|
+
|
|
506
|
+
### Audit roadmap (status as of v0.17.3)
|
|
507
|
+
|
|
508
|
+
| Release | Status | Scope |
|
|
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") |
|
|
512
|
+
|
|
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
|
|
516
|
+
|
|
379
517
|
## Auto-upgrade (v0.12.0)
|
|
380
518
|
|
|
381
519
|
On plugin load, queries npm/pip registries to check whether newer versions
|
package/dist/custom-tools.d.ts
CHANGED
|
@@ -46,6 +46,16 @@ declare let pendingRegistryRef: {
|
|
|
46
46
|
* Exposed as a setter so we don't need to thread it through every tool deps.
|
|
47
47
|
*/
|
|
48
48
|
export declare function setPendingDeliveryRegistry(registry: typeof pendingRegistryRef): void;
|
|
49
|
+
/**
|
|
50
|
+
* v0.17.2 (Gap I): Updated return type to include "expired" so the bridge
|
|
51
|
+
* tools can distinguish between "LLM hasn't called yet" (pending) and
|
|
52
|
+
* "TTL elapsed without delivery" (expired).
|
|
53
|
+
*
|
|
54
|
+
* Returns "delivered" if the LLM's MCP tool call was observed within the
|
|
55
|
+
* timeout, "expired" if the pending entry's TTL elapsed without delivery,
|
|
56
|
+
* "pending" otherwise (poll still active, no result yet).
|
|
57
|
+
*/
|
|
58
|
+
export declare function verifyDelivery(sessionID: string, mcpTool: string): Promise<"delivered" | "pending" | "expired">;
|
|
49
59
|
export interface OmoSearchDeps {
|
|
50
60
|
graphRetrieval: GraphRetrieval;
|
|
51
61
|
cwd: string;
|