@herjarsa/omo-meta-governor 0.17.2 → 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 +57 -0
- package/dist/index.js +2 -2
- package/dist/index.js.map +3 -3
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -457,6 +457,63 @@ No user action required. Two behavior changes:
|
|
|
457
457
|
| v0.17.1 | ✅ | Audit args fix |
|
|
458
458
|
| v0.17.2 | ✅ | Gap C (escalation live), Q (file paths), D (config fields), I (delivery expired) |
|
|
459
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
|
+
|
|
460
517
|
## Auto-upgrade (v0.12.0)
|
|
461
518
|
|
|
462
519
|
On plugin load, queries npm/pip registries to check whether newer versions
|
package/dist/index.js
CHANGED
|
@@ -126,7 +126,7 @@ After the tool call, briefly confirm what you stored and for which tool.`};try{r
|
|
|
126
126
|
|
|
127
127
|
Please invoke the \`task\` tool with \`subagent_type=oracle\` to perform a verification pass on the current session state. Decision context: ${r.evidenceCount} evidence unit(s). After Oracle returns, you should continue with the recommended action.`;return`[MetaGovernor] Escalation to user required. Reason: ${r.reasoning}
|
|
128
128
|
|
|
129
|
-
Present a clear summary to the user with the deviation(s) detected and your recommended next steps. Wait for explicit user input before proceeding.`}var x=f.schema,m_="0.0.0";try{m_=Z_().version}catch{}async function Ng(r,v,b=1500){if(!R_)return"pending";return await R_.awaitDelivery({sessionID:r,mcpTool:v,timeoutMs:b})
|
|
129
|
+
Present a clear summary to the user with the deviation(s) detected and your recommended next steps. Wait for explicit user input before proceeding.`}var x=f.schema,m_="0.0.0";try{m_=Z_().version}catch{}async function Ng(r,v,b=1500){if(!R_)return"pending";return await R_.awaitDelivery({sessionID:r,mcpTool:v,timeoutMs:b})}var R_=null;function ON(r){R_=r}async function kN(r,v){return await Ng(r,v)}function jN(r){return f({description:"Semantic code search using codegraph/graphify for the current project. USE THIS for architecture questions, finding call sites, understanding module structure. "+"Prefer over grep/glob for high-level understanding — grep is still better for literal text matches.",args:{query:x.string().min(3).describe("Natural language query describing what you're looking for"),maxResults:x.number().int().min(1).max(20).optional().describe("Max results to return (default 10)")},async execute(v,b){let I=Date.now(),$=await r.graphRetrieval.invoke(r.cwd,v.query,{timeoutMs:8000}),U={tool:"omo_search",query:v.query,kind:$.kind,timedOut:$.timedOut,durationMs:$.durationMs,resultSize:$.result?.length??0,sessionID:b.sessionID};if($.timedOut)return{title:"omo_search: timeout",output:`Graph search timed out after ${$.durationMs}ms. No graph tools available at ${r.cwd}, or the query is too expensive. Fall back to grep/glob for direct text matching.`,metadata:U};if(!$.result)return{title:"omo_search: no graph backend",output:`No codegraph or graphify directory found at ${r.cwd}. Run \`npx codegraph init\` or \`graphify . --no-viz\` to build the index, then call omo_search again. Until then, use grep/glob for direct text matching.`,metadata:U};return{title:`omo_search: ${$.kind}`,output:$.result,metadata:U}}})}function gN(r){return f({description:"Search lessons learned in past sessions of this project. Returns ranked lessons (highest confidence first) matching the query. "+"Use before making non-trivial decisions — the answer may already be in memory.",args:{query:x.string().min(2).describe("What kind of lesson you're looking for"),limit:x.number().int().min(1).max(20).optional().describe("Max lessons to return (default 5)")},async execute(v,b){let I=Date.now(),U=(await r.sqlite.smartSearch({query:v.query,limit:v.limit??5})).lessons;if(U.length===0)return{title:"omo_recall: no matches",output:`No past lessons found matching "${v.query}". This is the first time the agent is encountering this question.`,metadata:{tool:"omo_recall",query:v.query,durationMs:Date.now()-I,lessonsFound:0}};let _=U.map((w,z)=>`${z+1}. [${w.id}] confidence=${w.confidence.toFixed(2)}
|
|
130
130
|
${w.title}
|
|
131
131
|
${w.content.slice(0,500)}${w.content.length>500?"...":""}`).join(`
|
|
132
132
|
|
|
@@ -203,5 +203,5 @@ Current decision: ${Ur.message}`;Z.recentInterventionTexts=[...Xr,`[${Ur.action}
|
|
|
203
203
|
`),I=[];for(let $ of b){let U=$.match(/^\s*(\S+)\s+(fail)\s+(.*)$/);if(U){let _=U[1].trim(),w=U[3].trim();I.push(`${v} · ${_}: ${w}`)}}return I}function Mg(r){if(typeof r!=="string"||r.length===0)return!1;let v=r.replace(/\\\n/g," ").replace(/\s*\n\s*/g," ");return/(?:^|[\s;&|])gh\s+pr(?:\s|$)/.test(v)}function Fg(r,v){if(v>=1)return!1;try{return Lg(mN(r,"PLAN.md")),!1}catch{}try{let b=Bg(mN(r,"AGENTS.md"),"utf-8");if(/^##\s+Plan\b/im.test(b))return!1}catch{}return!0}function xg(r){if(typeof r!=="string"||r.length===0)return!1;return/<promise>\s*DONE!?\s*<\/promise>/i.test(r)}function Zg(r){if(typeof r!=="string"||r.length===0)return!1;return/<promise>\s*DONE!?\s*<\/promise>/i.test(r)||/<promise>\s*PHASE-\d+-COMPLETE\s*<\/promise>/i.test(r)}function mg(r){if(typeof r!=="string"||r.length===0)return!1;return/<promise>\s*PLAN-COMPLETE\s*<\/promise>/i.test(r)}J4();function Rg(r){let v={severity:r.success?"leve":"grave",category:`recovery:${r.fixStrategy}`,detail:`${r.errorCode}: ${r.context??"no context"}`};return{action:r.success?"continue":"warn",score:r.success?0.5:-0.5,reasoning:`Recovery ${r.success?"succeeded":"failed"}: ${r.fixStrategy} for ${r.errorCode}`,evidence:[{source:"deviation-detector",value:v.detail,confidence:1,weight:r.success?0.3:0.8}],shouldEscalateTo:r.success?null:"oracle"}}var TN={leve:0,media:1,grave:2};function hN(r,v){let b=TN[v]??0;return r.some((I)=>(TN[I.severity]??0)>=b)}async function Tg(r,v,b){if(!v)return null;let I=b?.config??Fr(),$=Rg(r);if(!I.enabled)return{lessonSaved:null,decisionSaved:null,reason:"closed-loop learning disabled"};let U=[{severity:r.success?"leve":"grave",category:`recovery:${r.fixStrategy}`,detail:`${r.errorCode}: ${r.context??"no context"}`}],_=null,w=null;if(I.saveDecisions){let N={id:`D-${Math.abs(`${r.sessionID}-${$.action}-${Date.now()}`.split("").reduce((k,P)=>(k<<5)-k+P.charCodeAt(0)|0,0)).toString(36)}`,timestampISO:new Date().toISOString(),action:$.action,score:$.score,reasoning:$.reasoning,sessionID:r.sessionID,directory:r.directory,deviations:U.map((k)=>({severity:k.severity,category:k.category,detail:k.detail}))};try{await v.saveMemory({content:`Decision: ${$.action} (score ${$.score.toFixed(2)}). ${$.reasoning}`,concepts:["meta-governor","decision",$.action,...U.map((k)=>k.category)],type:"fact",files:[...r.filesChanged??[]]}),w=N}catch{}}if(hN(U,I.minSeverityToLearn)){let N=[...new Set(U.flatMap((K)=>[K.category,K.severity]))],k=U.map((K)=>`[${K.severity}] ${K.category}: ${K.detail}`).join("; "),P=`Action "${$.action}" (score ${$.score.toFixed(2)}) after deviations: ${k}. Reasoning: ${$.reasoning}`;try{_={id:(await v.saveLesson({content:P,context:`session:${r.sessionID} dir:${r.directory}`,confidence:Math.max(0.3,Math.min(0.8,Math.abs($.score))),tags:N})).id,title:`${$.action} after ${U[0]?.category??"recovery"}`,content:P,type:"pattern",concepts:N,confidence:Math.max(0.3,Math.min(0.8,Math.abs($.score))),files:[...r.filesChanged??[]],sessionID:r.sessionID}}catch{}}let z=[];if(w)z.push("decision saved");if(_)z.push("lesson saved");else if(!hN(U,I.minSeverityToLearn))z.push("severity below threshold");if(!w&&!_&&!z.length)z.push("no saveable content");return{lessonSaved:_,decisionSaved:w,reason:z.join("; ")||"no action taken"}}l_();function CN(){return{$schema:"http://json-schema.org/draft-07/schema#",$id:"https://raw.githubusercontent.com/herjarsa/omo-meta-governor/main/assets/omo-meta-governor.schema.json",title:"omo-meta-governor",description:"Configuration schema for @herjarsa/omo-meta-governor — Self-judging agent orchestration layer for OpenCode.",type:"object",additionalProperties:!1,properties:{$schema:{type:"string",description:"JSON Schema reference for IDE autocompletion."},enabled:{type:"boolean",description:"Master feature flag — must be true to run the orchestrator.",default:!1},decision:{type:"object",description:"Decision handler configuration.",additionalProperties:!1,properties:{maxHistoryPerSession:{type:"integer",description:"Maximum history entries per session before oldest are trimmed.",default:50,minimum:1},forceContinueAfterStops:{type:"integer",description:"How many consecutive stops before forcing continue.",default:3,minimum:1}}},memory:{type:"object",description:"Memory aggregator configuration.",additionalProperties:!1,properties:{agentmemoryTimeoutMs:{type:"integer",description:"Timeout for agentmemory queries in milliseconds.",default:2000,minimum:100},magicContextTimeoutMs:{type:"integer",description:"Timeout for magic-context queries in milliseconds.",default:1000,minimum:100},boulderStateTimeoutMs:{type:"integer",description:"Timeout for boulder-state queries in milliseconds.",default:1000,minimum:100},query:{type:"string",description:"Natural-language query for memory recall.",default:"meta_governor_context"}}},tokenPredictor:{type:"object",description:"Token predictor configuration.",additionalProperties:!1,properties:{compactBurnRateThreshold:{type:"integer",description:"Burn rate threshold (tokens/turn) above which to recommend compact-now.",default:500,minimum:0},compactUsageThreshold:{type:"number",description:"Context usage ratio (0..1) above which to recommend compact-now.",default:0.85,minimum:0,maximum:1},switchModelUsageThreshold:{type:"number",description:"Context usage ratio above which to recommend switch-model.",default:0.95,minimum:0,maximum:1},delegateConsecutiveHighBurn:{type:"integer",description:"Max consecutive high-burn turns before recommending delegate.",default:5,minimum:1}}},scoring:{type:"object",description:"Scoring engine configuration.",additionalProperties:!1,properties:{continueThreshold:{type:"number",description:"Score >= this -> continue silently.",default:0.3,minimum:0,maximum:1},warnThreshold:{type:"number",description:"Score <= -warnThreshold -> warn.",default:0.3,minimum:0,maximum:1},escalateThreshold:{type:"number",description:"Score <= -escalateThreshold -> escalate.",default:0.6,minimum:0,maximum:1},stopThreshold:{type:"number",description:"Score <= -stopThreshold -> stop.",default:0.8,minimum:0,maximum:1}}},closedLoop:{type:"object",description:"Closed-loop learning configuration.",additionalProperties:!1,properties:{saveDecisions:{type:"boolean",description:"Whether to save decision records.",default:!0},saveLessons:{type:"boolean",description:"Whether to save lessons.",default:!0}}},modelOverride:{type:"object",description:"Model override for MetaGovernor internal LLM usage.",additionalProperties:!1,properties:{providerID:{type:"string",description:"Provider ID (e.g. 'openai', 'anthropic')."},modelID:{type:"string",description:"Model ID (e.g. 'gpt-4o-mini', 'claude-sonnet-4-20250514')."},modelLimit:{type:"integer",description:"Context window size for token predictor.",minimum:1000},temperature:{type:"number",description:"Sampling temperature. Default: 0.2.",default:0.2,minimum:0,maximum:2},topP:{type:"number",description:"Top-p nucleus sampling. Default: 1.",default:1,minimum:0,maximum:1},maxTokens:{type:"integer",description:"Max output tokens for internal reasoning.",default:2048,minimum:1},reasoning:{type:"boolean",description:"Enable extended reasoning / thinking mode.",default:!1},verbosity:{type:"string",description:"Verbosity level for internal logging.",enum:["silent","minimal","verbose"],default:"minimal"}}},intervention:{type:"object",description:"Intervention config for visible decision injection.",additionalProperties:!1,properties:{mode:{type:"string",description:"How to inject: 'silent', 'message', or 'system'.",enum:["silent","message","system"],default:"silent"},includeDecisionHistory:{type:"boolean",description:"Whether to include recent decision history.",default:!0},maxHistoryMessages:{type:"integer",description:"Max history entries when includeDecisionHistory is true.",default:5,minimum:1},minActionForMessage:{type:"string",description:"Minimum action: 'warn' (all non-continue), 'escalate', or 'stop'.",enum:["warn","escalate","stop"],default:"warn"}}},protocolEnforcement:{type:"object",description:"Sisyphus protocol enforcement config.",additionalProperties:!1,properties:{enabled:{type:"boolean",description:"Master switch for protocol enforcement.",default:!1},path:{type:"string",description:"Path to protocol markdown file."},injectIntoSystem:{type:"boolean",description:"Whether to inject protocol rules into the system prompt.",default:!1},auditToolCalls:{type:"boolean",description:"Whether to audit tool calls for protocol violations.",default:!1}}},graphSync:{type:"object",description:"Graph synchronization (auto-init codegraph/graphify).",additionalProperties:!1,properties:{enabled:{type:"boolean",description:"Enable auto-initialization of codegraph and graphify.",default:!0},watch:{type:"boolean",description:"Enable watch mode (re-index on file changes).",default:!1}}}},definitions:{verbosity:{type:"string",enum:["silent","minimal","verbose"],description:"Verbosity level."},interventionMode:{type:"string",enum:["silent","message","system"],description:"Intervention injection mode."},minAction:{type:"string",enum:["warn","escalate","stop"],description:"Minimum action threshold."}}}}async function hg(r){let v=CN(),{writeFile:b}=await import("node:fs/promises");await b(r,JSON.stringify(v,null,2)+`
|
|
204
204
|
`,"utf-8")}var Cg={id:"omo-meta-governor",server:s_()},NX=Cg;export{hg as writeSchemaFile,c1 as trimHistory,Mr as takeDecision,Yg as takeAnyDecision,C_ as stripJsoncComments,o_ as storeDecision,w1 as stopWatches,c4 as score,x4 as runMetaGovernor,rv as runGraphSync,U1 as resetInitializedProjects,Tg as recordRecovery,E4 as predict,f_ as parseJsonc,M4 as observeAndLearn,y as logToFile,d_ as loadProtocol,ug as loadOrchestratorConfigFromSources,X4 as loadOrchestratorConfig,xN as loadMetaGovernorConfig,K4 as loadJsoncFile,Wg as isMetaGovernorEnabled,A_ as hashQuery,Qg as hasDecision,D4 as handleDecision,y_ as getUserConfigPath,i_ as getProjectConfigPath,z$ as getDefaultSqliteBackend,jr as getDefaultGraphRetrieval,CN as generateSchema,Y1 as defaultTokenPredictorConfig,$v as defaultScoringConfig,Gw as defaultOrchestratorConfig,bv as defaultDecisionHandlerConfig,Fr as defaultClosedLoopConfig,NX as default,b$ as deepMerge,s_ as createMetaGovernorPlugin,D1 as countConsecutiveStops,Vg as clearAll,uw as calculateBurnRate,p_ as buildSystemInjection,qw as buildDecisionContext,e_ as auditToolCall,B4 as aggregateRead,m4 as SqliteBackend,E_ as GraphRetrieval,W4 as DEFAULT_PROTOCOL_PATH};
|
|
205
205
|
|
|
206
|
-
//# debugId=
|
|
206
|
+
//# debugId=E8D795DE6732239564756E2164756E21
|
|
207
207
|
//# sourceMappingURL=index.js.map
|