@herjarsa/omo-meta-governor 0.14.3 → 0.17.0
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 +168 -2
- package/dist/audit-state-cache.d.ts +43 -0
- package/dist/config.d.ts +2 -0
- package/dist/custom-tools.d.ts +73 -11
- package/dist/decision-store.d.ts +4 -3
- package/dist/delivery-registry.d.ts +83 -0
- package/dist/graph-retrieval.d.ts +2 -0
- package/dist/graph-sync.d.ts +2 -0
- package/dist/index.js +67 -62
- package/dist/index.js.map +18 -16
- package/dist/metrics.d.ts +2 -1
- package/dist/plugin.d.ts +23 -0
- package/dist/scoring-engine.d.ts +28 -6
- package/dist/session-bridge.d.ts +20 -0
- package/dist/types.d.ts +32 -6
- package/package.json +4 -3
package/README.md
CHANGED
|
@@ -141,7 +141,8 @@ Enabled when `meta_governor.enabled: true` in config.
|
|
|
141
141
|
"mode": "message",
|
|
142
142
|
"minActionForMessage": "warn",
|
|
143
143
|
"maxInterventionsPerSession": 3,
|
|
144
|
-
"respectDoneSignal": true
|
|
144
|
+
"respectDoneSignal": true,
|
|
145
|
+
"phaseAwareDoneSignal": true // v0.15.0: multi-phase plan support
|
|
145
146
|
}
|
|
146
147
|
}
|
|
147
148
|
}
|
|
@@ -154,7 +155,172 @@ Enabled when `meta_governor.enabled: true` in config.
|
|
|
154
155
|
| `mode` | `"message"` | How to inject: `"silent"`, `"message"`, or `"system"` |
|
|
155
156
|
| `minActionForMessage` | `"warn"` | Minimum action: `"warn"`, `"escalate"`, or `"stop"` |
|
|
156
157
|
| `maxInterventionsPerSession` | `3` | Hard cap on injections per session |
|
|
157
|
-
| `respectDoneSignal` | `true` | Stop injecting after
|
|
158
|
+
| `respectDoneSignal` | `true` | Stop injecting after terminal signal + Oracle verified |
|
|
159
|
+
| `phaseAwareDoneSignal` | `false` | **v0.15.0**: when `true`, only `<promise>PLAN-COMPLETE</promise>` latches intervention. DONE/PHASE-N-COMPLETE are per-phase hints. Recommended for multi-phase plans. |
|
|
160
|
+
|
|
161
|
+
### Multi-phase plans (v0.15.0)
|
|
162
|
+
|
|
163
|
+
For work plans with multiple phases (e.g. Sisyphus/Prometheus work plans),
|
|
164
|
+
configure `phaseAwareDoneSignal: true` and emit `<promise>PLAN-COMPLETE</promise>`
|
|
165
|
+
only when the **entire** plan is verified done by Oracle. The new markers:
|
|
166
|
+
|
|
167
|
+
| Marker | Effect |
|
|
168
|
+
|--------|--------|
|
|
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. |
|
|
171
|
+
| `<promise>PLAN-COMPLETE</promise>` | Terminal. Latches intervention when Oracle has verified. |
|
|
172
|
+
|
|
173
|
+
**Migration**: existing v0.10.0–v0.14.x users keep working without changes (default
|
|
174
|
+
`phaseAwareDoneSignal: false` preserves the legacy single-task behavior). Set the
|
|
175
|
+
flag to `true` and switch your terminal marker to `PLAN-COMPLETE` to enable
|
|
176
|
+
multi-phase governance.
|
|
177
|
+
|
|
178
|
+
## v0.16.0 — Audit remediation: memory hygiene, dead code, tool coverage, CI
|
|
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.
|
|
181
|
+
|
|
182
|
+
### Highlights
|
|
183
|
+
|
|
184
|
+
#### Memory hygiene (F1)
|
|
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).
|
|
189
|
+
|
|
190
|
+
#### Dead code elimination (F2)
|
|
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).
|
|
196
|
+
|
|
197
|
+
#### Tool bug fixes (F3)
|
|
198
|
+
|
|
199
|
+
- **AFT checkpoint/undo**: args split on whitespace broke names with spaces. Rewrote arg construction with proper quoting.
|
|
200
|
+
- **AFT subcommand**: now uses `options.projectDir` instead of `process.cwd()`.
|
|
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.
|
|
203
|
+
- **`session-bridge`**: replaced module-level `_client` with `AsyncLocalStorage` for per-request isolation. Concurrent sessions no longer race on the same client reference.
|
|
204
|
+
|
|
205
|
+
#### Test coverage (F4)
|
|
206
|
+
|
|
207
|
+
- 22 tests covering all 15 custom tools (`src/custom-tools.test.ts`). Previously the entire public tool surface had zero test coverage.
|
|
208
|
+
- 12 tests for `decision-store` (previously untested).
|
|
209
|
+
|
|
210
|
+
#### Type/token pipeline (F5)
|
|
211
|
+
|
|
212
|
+
- `token-predictor` refactor: dead code (`delegate`/`switch-model`) removed; output is now informational-only as designed.
|
|
213
|
+
- Type alignment across `types.ts`, `token-predictor.ts`, `orchestrator.ts`.
|
|
214
|
+
|
|
215
|
+
#### CI matrix (F6)
|
|
216
|
+
|
|
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`).
|
|
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`.
|
|
221
|
+
|
|
222
|
+
#### Final refactors (F7)
|
|
223
|
+
|
|
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.
|
|
226
|
+
- `ACTION_SEVERITY` keyed by `DecisionHandlerOutput["action"]` union literal (was bare `Record<string, number>`).
|
|
227
|
+
- `projectHasCodegraph` / `projectHasGraphify` IIFE booleans replaced with lookup-time calls to `graphRetrieval.hasCodegraphDir(cwd)`.
|
|
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.
|
|
230
|
+
|
|
231
|
+
### Test & build status
|
|
232
|
+
|
|
233
|
+
- **495/495 tests pass** (up from 487 in v0.15.0/0.15.1).
|
|
234
|
+
- `bun run typecheck` clean.
|
|
235
|
+
- `bun build.ts` clean (0.34 MB dist).
|
|
236
|
+
- `npm pack --dry-run` validated (no forbidden artifacts).
|
|
237
|
+
|
|
238
|
+
### Migration
|
|
239
|
+
|
|
240
|
+
No user action required. All changes are internal. The default `phaseAwareDoneSignal` is still `false` for backward compatibility; the v0.15.0 multi-phase behavior is preserved when explicitly enabled.
|
|
241
|
+
|
|
242
|
+
### Deferred to v0.17.0
|
|
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.
|
|
247
|
+
|
|
248
|
+
|
|
249
|
+
|
|
250
|
+
|
|
251
|
+
## v0.17.0 — Wire escalate to Oracle, enforce lesson cap, verify bridge delivery
|
|
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).
|
|
254
|
+
|
|
255
|
+
### Highlights
|
|
256
|
+
|
|
257
|
+
#### F5.1 — Escalate action now fires Oracle (v0.17.0)
|
|
258
|
+
|
|
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
|
+
|
|
261
|
+
```ts
|
|
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
|
|
269
|
+
```
|
|
270
|
+
|
|
271
|
+
#### F5.4 — `maxLessonsPerSession` is now enforced
|
|
272
|
+
|
|
273
|
+
The cap (default 20) was a config field that was never enforced. v0.17.0 adds:
|
|
274
|
+
- `currentLessonCount` on `LearnFromOutcomeInput` and `MetaGovernorInput`
|
|
275
|
+
- `lessonCount` tracked in per-session `AuditState`
|
|
276
|
+
- `observeAndLearn()` short-circuits when `currentLessonCount >= maxLessonsPerSession`
|
|
277
|
+
- The orchestrator increments `sessionState.lessonCount` after each successful save
|
|
278
|
+
- **Cap semantics: inclusive** — when count equals cap, no more lessons are saved
|
|
279
|
+
|
|
280
|
+
#### F3.6 — Bridge tool delivery verification
|
|
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:
|
|
283
|
+
|
|
284
|
+
- **New `PendingDeliveryRegistry` module** (`src/delivery-registry.ts`) — tracks pending dispatches per session with TTL-based cleanup.
|
|
285
|
+
- **`tool.execute.after` hook** marks deliveries when a matching MCP tool call is observed.
|
|
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
|
+
- 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.
|
|
288
|
+
|
|
289
|
+
```ts
|
|
290
|
+
// Bridge tool result metadata now includes:
|
|
291
|
+
{
|
|
292
|
+
tool: "omo_remember",
|
|
293
|
+
ok: true,
|
|
294
|
+
deliveryStatus: "delivered" | "pending",
|
|
295
|
+
messageID: "...",
|
|
296
|
+
durationMs: 1234,
|
|
297
|
+
contentLength: 256
|
|
298
|
+
}
|
|
299
|
+
```
|
|
300
|
+
|
|
301
|
+
### Test & build status
|
|
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).
|
|
304
|
+
- `bun run typecheck` clean.
|
|
305
|
+
- `bun build.ts` clean (0.34 MB dist).
|
|
306
|
+
- `npm pack --dry-run` validated.
|
|
307
|
+
|
|
308
|
+
### Migration
|
|
309
|
+
|
|
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.
|
|
314
|
+
|
|
315
|
+
### Audit roadmap (status as of v0.17.0)
|
|
316
|
+
|
|
317
|
+
| Release | Status | Scope |
|
|
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 |
|
|
322
|
+
|
|
323
|
+
All audit findings are now closed. Future work focuses on new features and user-driven feedback.
|
|
158
324
|
|
|
159
325
|
## Auto-upgrade (v0.12.0)
|
|
160
326
|
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* TTL-based + LRU-bounded cache for per-session audit state.
|
|
3
|
+
*
|
|
4
|
+
* v0.15.0: closed the C1/H16 audit findings — `auditSessions` was an
|
|
5
|
+
* unbounded Map that grew indefinitely. Replaced with a class that
|
|
6
|
+
*
|
|
7
|
+
* 1. Caps total entries (default 100, configurable).
|
|
8
|
+
* 2. Evicts the least-recently-accessed entry when the cap is hit.
|
|
9
|
+
* 3. TTLs each entry (default 1 hour, configurable). On read, expired
|
|
10
|
+
* entries are dropped.
|
|
11
|
+
*
|
|
12
|
+
* The cache is intentionally synchronous (Map-backed) — the audit
|
|
13
|
+
* state mutations happen on the plugin's main thread between hooks
|
|
14
|
+
* and are not shared across the event loop, so no locking is needed.
|
|
15
|
+
*
|
|
16
|
+
* v0.16.0 also documents: Bun's runtime is single-threaded, so a read
|
|
17
|
+
* followed by an `await` cannot be interrupted by another write. This
|
|
18
|
+
* means we do NOT need per-session mutex for the audit state. See
|
|
19
|
+
* plugin.ts `// v0.16.0 concurrency model` comment block.
|
|
20
|
+
*/
|
|
21
|
+
export interface AuditStateCacheConfig {
|
|
22
|
+
/** Max number of entries. Default 100. */
|
|
23
|
+
readonly maxEntries?: number;
|
|
24
|
+
/** Time-to-live per entry in milliseconds. Default 3_600_000 (1h). */
|
|
25
|
+
readonly ttlMs?: number;
|
|
26
|
+
/** Optional clock injection for testing. Returns ms since epoch. */
|
|
27
|
+
readonly now?: () => number;
|
|
28
|
+
}
|
|
29
|
+
export declare class AuditStateCache<V> {
|
|
30
|
+
private readonly store;
|
|
31
|
+
private readonly maxEntries;
|
|
32
|
+
private readonly ttlMs;
|
|
33
|
+
private readonly now;
|
|
34
|
+
constructor(config?: AuditStateCacheConfig);
|
|
35
|
+
get(key: string): V | undefined;
|
|
36
|
+
has(key: string): boolean;
|
|
37
|
+
set(key: string, value: V): void;
|
|
38
|
+
delete(key: string): boolean;
|
|
39
|
+
size(): number;
|
|
40
|
+
clear(): void;
|
|
41
|
+
/** Evict the entry with the oldest lastAccessAtMs. No-op if empty. */
|
|
42
|
+
private evictOldest;
|
|
43
|
+
}
|
package/dist/config.d.ts
CHANGED
|
@@ -51,6 +51,8 @@ export interface MetaGovernorPluginConfig {
|
|
|
51
51
|
maxInterventionsPerSession?: number;
|
|
52
52
|
/** v0.10.0: stop injecting after <promise>DONE</promise> + Oracle verified. */
|
|
53
53
|
respectDoneSignal?: boolean;
|
|
54
|
+
/** v0.15.0: split per-phase hint from terminal signal. See types.ts. */
|
|
55
|
+
phaseAwareDoneSignal?: boolean;
|
|
54
56
|
};
|
|
55
57
|
/** Sisyphus protocol enforcement config. */
|
|
56
58
|
protocolEnforcement?: {
|
package/dist/custom-tools.d.ts
CHANGED
|
@@ -23,6 +23,29 @@ import type { SqliteBackend } from "./sqlite-backend";
|
|
|
23
23
|
import type { GraphRetrieval } from "./graph-retrieval";
|
|
24
24
|
import type { MetricsCollector } from "./metrics";
|
|
25
25
|
import { type CodeGraphTools } from "./codegraph-tools";
|
|
26
|
+
/**
|
|
27
|
+
* Module-level reference to the PendingDeliveryRegistry. The plugin
|
|
28
|
+
* factory sets this once at startup. Bridge tools call it via
|
|
29
|
+
* onDispatch and pollForDelivery.
|
|
30
|
+
*/
|
|
31
|
+
declare let pendingRegistryRef: {
|
|
32
|
+
register(input: {
|
|
33
|
+
sessionID: string;
|
|
34
|
+
mcpTool: string;
|
|
35
|
+
mcpArgs: Record<string, unknown>;
|
|
36
|
+
ttlMs?: number;
|
|
37
|
+
}): string;
|
|
38
|
+
awaitDelivery(input: {
|
|
39
|
+
sessionID: string;
|
|
40
|
+
mcpTool: string;
|
|
41
|
+
timeoutMs?: number;
|
|
42
|
+
}): Promise<"delivered" | "expired">;
|
|
43
|
+
} | null;
|
|
44
|
+
/**
|
|
45
|
+
* Called by the plugin factory at startup to inject the delivery registry.
|
|
46
|
+
* Exposed as a setter so we don't need to thread it through every tool deps.
|
|
47
|
+
*/
|
|
48
|
+
export declare function setPendingDeliveryRegistry(registry: typeof pendingRegistryRef): void;
|
|
26
49
|
export interface OmoSearchDeps {
|
|
27
50
|
graphRetrieval: GraphRetrieval;
|
|
28
51
|
cwd: string;
|
|
@@ -111,6 +134,14 @@ export declare function buildOmoImpactTool(deps: OmoImpactDeps): {
|
|
|
111
134
|
}, context: ToolContext): Promise<ToolResult>;
|
|
112
135
|
};
|
|
113
136
|
export interface OmoRememberDeps {
|
|
137
|
+
/** Optional callback invoked after a successful prompt dispatch.
|
|
138
|
+
* Used by the plugin to register the pending delivery in the registry
|
|
139
|
+
* so the bridge tool can verify the LLM actually called the MCP tool. */
|
|
140
|
+
onDispatch?: (input: {
|
|
141
|
+
sessionID: string;
|
|
142
|
+
mcpTool: string;
|
|
143
|
+
mcpArgs: Record<string, unknown>;
|
|
144
|
+
}) => void;
|
|
114
145
|
}
|
|
115
146
|
/**
|
|
116
147
|
* Build the `omo_remember` tool. Persists a fact/observation/lesson to
|
|
@@ -122,18 +153,26 @@ export declare function buildOmoRememberTool(deps: OmoRememberDeps): {
|
|
|
122
153
|
content: import("zod").ZodString;
|
|
123
154
|
concepts: import("zod").ZodOptional<import("zod").ZodArray<import("zod").ZodString>>;
|
|
124
155
|
type: import("zod").ZodOptional<import("zod").ZodEnum<{
|
|
125
|
-
pattern: "pattern";
|
|
126
156
|
fact: "fact";
|
|
127
157
|
observation: "observation";
|
|
158
|
+
pattern: "pattern";
|
|
128
159
|
}>>;
|
|
129
160
|
};
|
|
130
161
|
execute(args: {
|
|
131
162
|
content: string;
|
|
132
163
|
concepts?: string[] | undefined;
|
|
133
|
-
type?: "
|
|
164
|
+
type?: "fact" | "observation" | "pattern" | undefined;
|
|
134
165
|
}, context: ToolContext): Promise<ToolResult>;
|
|
135
166
|
};
|
|
136
167
|
export interface OmoRecallMcpDeps {
|
|
168
|
+
/** Optional callback invoked after a successful prompt dispatch.
|
|
169
|
+
* Used by the plugin to register the pending delivery in the registry
|
|
170
|
+
* so the bridge tool can verify the LLM actually called the MCP tool. */
|
|
171
|
+
onDispatch?: (input: {
|
|
172
|
+
sessionID: string;
|
|
173
|
+
mcpTool: string;
|
|
174
|
+
mcpArgs: Record<string, unknown>;
|
|
175
|
+
}) => void;
|
|
137
176
|
}
|
|
138
177
|
/**
|
|
139
178
|
* Build the `omo_recall_mcp` tool. Searches AgentMemory by sending a
|
|
@@ -155,6 +194,14 @@ export declare function buildOmoRecallMcpTool(deps: OmoRecallMcpDeps): {
|
|
|
155
194
|
}, context: ToolContext): Promise<ToolResult>;
|
|
156
195
|
};
|
|
157
196
|
export interface OmoRuleDeps {
|
|
197
|
+
/** Optional callback invoked after a successful prompt dispatch.
|
|
198
|
+
* Used by the plugin to register the pending delivery in the registry
|
|
199
|
+
* so the bridge tool can verify the LLM actually called the MCP tool. */
|
|
200
|
+
onDispatch?: (input: {
|
|
201
|
+
sessionID: string;
|
|
202
|
+
mcpTool: string;
|
|
203
|
+
mcpArgs: Record<string, unknown>;
|
|
204
|
+
}) => void;
|
|
158
205
|
}
|
|
159
206
|
/**
|
|
160
207
|
* Build the `omo_rule` tool. Saves a durable rule to Magic Context that
|
|
@@ -165,20 +212,28 @@ export declare function buildOmoRuleTool(deps: OmoRuleDeps): {
|
|
|
165
212
|
description: string;
|
|
166
213
|
args: {
|
|
167
214
|
category: import("zod").ZodEnum<{
|
|
168
|
-
PROJECT_RULES: "PROJECT_RULES";
|
|
169
215
|
ARCHITECTURE: "ARCHITECTURE";
|
|
170
|
-
CONSTRAINTS: "CONSTRAINTS";
|
|
171
216
|
CONFIG_VALUES: "CONFIG_VALUES";
|
|
217
|
+
CONSTRAINTS: "CONSTRAINTS";
|
|
172
218
|
NAMING: "NAMING";
|
|
219
|
+
PROJECT_RULES: "PROJECT_RULES";
|
|
173
220
|
}>;
|
|
174
221
|
content: import("zod").ZodString;
|
|
175
222
|
};
|
|
176
223
|
execute(args: {
|
|
177
|
-
category: "
|
|
224
|
+
category: "ARCHITECTURE" | "CONFIG_VALUES" | "CONSTRAINTS" | "NAMING" | "PROJECT_RULES";
|
|
178
225
|
content: string;
|
|
179
226
|
}, context: ToolContext): Promise<ToolResult>;
|
|
180
227
|
};
|
|
181
228
|
export interface OmoHistoryDeps {
|
|
229
|
+
/** Optional callback invoked after a successful prompt dispatch.
|
|
230
|
+
* Used by the plugin to register the pending delivery in the registry
|
|
231
|
+
* so the bridge tool can verify the LLM actually called the MCP tool. */
|
|
232
|
+
onDispatch?: (input: {
|
|
233
|
+
sessionID: string;
|
|
234
|
+
mcpTool: string;
|
|
235
|
+
mcpArgs: Record<string, unknown>;
|
|
236
|
+
}) => void;
|
|
182
237
|
}
|
|
183
238
|
/**
|
|
184
239
|
* Build the `omo_history` tool. Searches git commit history and prior
|
|
@@ -189,16 +244,24 @@ export declare function buildOmoHistoryTool(deps: OmoHistoryDeps): {
|
|
|
189
244
|
args: {
|
|
190
245
|
query: import("zod").ZodString;
|
|
191
246
|
sources: import("zod").ZodOptional<import("zod").ZodArray<import("zod").ZodEnum<{
|
|
192
|
-
message: "message";
|
|
193
247
|
git_commit: "git_commit";
|
|
248
|
+
message: "message";
|
|
194
249
|
}>>>;
|
|
195
250
|
};
|
|
196
251
|
execute(args: {
|
|
197
252
|
query: string;
|
|
198
|
-
sources?: ("
|
|
253
|
+
sources?: ("git_commit" | "message")[] | undefined;
|
|
199
254
|
}, context: ToolContext): Promise<ToolResult>;
|
|
200
255
|
};
|
|
201
256
|
export interface OmoNoteDeps {
|
|
257
|
+
/** Optional callback invoked after a successful prompt dispatch.
|
|
258
|
+
* Used by the plugin to register the pending delivery in the registry
|
|
259
|
+
* so the bridge tool can verify the LLM actually called the MCP tool. */
|
|
260
|
+
onDispatch?: (input: {
|
|
261
|
+
sessionID: string;
|
|
262
|
+
mcpTool: string;
|
|
263
|
+
mcpArgs: Record<string, unknown>;
|
|
264
|
+
}) => void;
|
|
202
265
|
}
|
|
203
266
|
/**
|
|
204
267
|
* Build the `omo_note` tool. Writes a session-scoped working note via
|
|
@@ -266,8 +329,7 @@ export declare function buildOmoOutlineTool(deps: OmoOutlineDeps): {
|
|
|
266
329
|
target: string;
|
|
267
330
|
}, context: ToolContext): Promise<ToolResult>;
|
|
268
331
|
};
|
|
269
|
-
export
|
|
270
|
-
}
|
|
332
|
+
export type OmoCheckpointDeps = Record<string, never>;
|
|
271
333
|
/**
|
|
272
334
|
* Build the `omo_checkpoint` tool. Creates a named AFT checkpoint so the
|
|
273
335
|
* user can revert to a known good state. Uses `aft safety checkpoint --name <name>`.
|
|
@@ -281,8 +343,7 @@ export declare function buildOmoCheckpointTool(_deps: OmoCheckpointDeps): {
|
|
|
281
343
|
name: string;
|
|
282
344
|
}, context: ToolContext): Promise<ToolResult>;
|
|
283
345
|
};
|
|
284
|
-
export
|
|
285
|
-
}
|
|
346
|
+
export type OmoUndoDeps = Record<string, never>;
|
|
286
347
|
/**
|
|
287
348
|
* Build the `omo_undo` tool. Reverts tracked files to the most recent AFT
|
|
288
349
|
* checkpoint. Uses `aft safety undo`.
|
|
@@ -292,3 +353,4 @@ export declare function buildOmoUndoTool(_deps: OmoUndoDeps): {
|
|
|
292
353
|
args: {};
|
|
293
354
|
execute(args: Record<string, never>, context: ToolContext): Promise<ToolResult>;
|
|
294
355
|
};
|
|
356
|
+
export {};
|
package/dist/decision-store.d.ts
CHANGED
|
@@ -25,9 +25,10 @@ export declare function takeDecision(sessionID: string): DecisionHandlerOutput |
|
|
|
25
25
|
*/
|
|
26
26
|
export declare function hasDecision(sessionID: string): boolean;
|
|
27
27
|
/**
|
|
28
|
-
*
|
|
29
|
-
*
|
|
30
|
-
*
|
|
28
|
+
* @deprecated v0.16.0: this function can leak decisions across sessions.
|
|
29
|
+
* Use takeDecision(sessionID) instead — the messages.transform hook now
|
|
30
|
+
* derives the sessionID from the last outgoing message (see plugin.ts).
|
|
31
|
+
* Will be removed in v0.18.0.
|
|
31
32
|
*/
|
|
32
33
|
export declare function takeAnyDecision(): DecisionHandlerOutput | undefined;
|
|
33
34
|
/**
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* v0.17.0 (F3.6): PendingDeliveryRegistry — track bridge tool dispatches
|
|
3
|
+
* and verify they were actually delivered by the LLM via the matching
|
|
4
|
+
* MCP tool call in `tool.execute.after`.
|
|
5
|
+
*
|
|
6
|
+
* Why this exists (v0.14.0 pivot):
|
|
7
|
+
* session-bridge uses `session.prompt()` to instruct the LLM to call an
|
|
8
|
+
* MCP tool (e.g. agentmemory_memory_save). The LLM may or may not follow
|
|
9
|
+
* the instruction. Previously, the bridge tool returned "dispatched" on
|
|
10
|
+
* `session.prompt()` success — but that just means the prompt was queued,
|
|
11
|
+
* not that the MCP tool was actually called. This registry gives us a
|
|
12
|
+
* way to verify delivery within a short window.
|
|
13
|
+
*
|
|
14
|
+
* Design:
|
|
15
|
+
* - Per-session pending entries (Map) — small, bounded, TTL-cleaned.
|
|
16
|
+
* - `register()` when a bridge tool dispatches a prompt.
|
|
17
|
+
* - `markDelivered()` when tool.execute.after sees a matching tool call.
|
|
18
|
+
* - `awaitDelivery()` is a brief async poll (~2-3s) used by bridge tools
|
|
19
|
+
* to surface fast deliveries. Slow deliveries are still tracked.
|
|
20
|
+
*/
|
|
21
|
+
export interface PendingDelivery {
|
|
22
|
+
/** Unique id (randomUUID) so callers can correlate. */
|
|
23
|
+
readonly id: string;
|
|
24
|
+
readonly sessionID: string;
|
|
25
|
+
/** The MCP tool the bridge instructed the LLM to call. */
|
|
26
|
+
readonly mcpTool: string;
|
|
27
|
+
/** Hash of mcpArgs to match the eventual tool call. */
|
|
28
|
+
readonly mcpArgsHash: string;
|
|
29
|
+
/** When registered (ms since epoch). */
|
|
30
|
+
readonly registeredAt: number;
|
|
31
|
+
/** TTL in ms — after this, the entry is considered expired. */
|
|
32
|
+
readonly ttlMs: number;
|
|
33
|
+
}
|
|
34
|
+
export type DeliveryStatus = "pending" | "delivered" | "expired";
|
|
35
|
+
export declare class PendingDeliveryRegistry {
|
|
36
|
+
private readonly entries;
|
|
37
|
+
/** When mcpArgs match is disabled (no mcpArgs available on observed call) */
|
|
38
|
+
private deliveredCount;
|
|
39
|
+
private expiredCount;
|
|
40
|
+
/**
|
|
41
|
+
* Register a pending delivery. Returns a random id for correlation.
|
|
42
|
+
*/
|
|
43
|
+
register(input: {
|
|
44
|
+
sessionID: string;
|
|
45
|
+
mcpTool: string;
|
|
46
|
+
mcpArgs: Record<string, unknown>;
|
|
47
|
+
ttlMs?: number;
|
|
48
|
+
}): string;
|
|
49
|
+
/**
|
|
50
|
+
* Mark a pending delivery as delivered. Returns the matching id if
|
|
51
|
+
* found, or null if no pending entry matches.
|
|
52
|
+
*/
|
|
53
|
+
markDelivered(input: {
|
|
54
|
+
sessionID: string;
|
|
55
|
+
mcpTool: string;
|
|
56
|
+
mcpArgs?: unknown;
|
|
57
|
+
}): string | null;
|
|
58
|
+
/**
|
|
59
|
+
* Brief async poll: wait for the matching delivery, up to `timeoutMs`.
|
|
60
|
+
* Resolves with the status when the delivery is verified or expires.
|
|
61
|
+
*/
|
|
62
|
+
awaitDelivery(input: {
|
|
63
|
+
sessionID: string;
|
|
64
|
+
mcpTool: string;
|
|
65
|
+
timeoutMs?: number;
|
|
66
|
+
}): Promise<DeliveryStatus>;
|
|
67
|
+
/**
|
|
68
|
+
* Return current stats: pending + cumulative delivered + cumulative expired.
|
|
69
|
+
*/
|
|
70
|
+
getStats(): {
|
|
71
|
+
pending: number;
|
|
72
|
+
delivered: number;
|
|
73
|
+
expired: number;
|
|
74
|
+
};
|
|
75
|
+
/**
|
|
76
|
+
* Clear all entries for a session. Useful on session end.
|
|
77
|
+
*/
|
|
78
|
+
clearSession(sessionID: string): void;
|
|
79
|
+
/**
|
|
80
|
+
* Remove expired entries. Called internally on register/mark/await.
|
|
81
|
+
*/
|
|
82
|
+
private cleanup;
|
|
83
|
+
}
|
|
@@ -50,6 +50,8 @@ export interface InvokeOptions {
|
|
|
50
50
|
graphifyBin?: string;
|
|
51
51
|
/** Override timeout for this call. */
|
|
52
52
|
timeoutMs?: number;
|
|
53
|
+
/** v0.16.0: project working directory. Defaults to process.cwd(). */
|
|
54
|
+
projectDir?: string;
|
|
53
55
|
}
|
|
54
56
|
/** Deterministic hash for a query string. Used as cache key suffix. */
|
|
55
57
|
export declare function hashQuery(query: string): string;
|
package/dist/graph-sync.d.ts
CHANGED
|
@@ -129,6 +129,8 @@ export declare function isGraphifyHookInstalled(projectDir: string): Promise<boo
|
|
|
129
129
|
* Best-effort: never throws, returns a structured result.
|
|
130
130
|
*/
|
|
131
131
|
export declare function triggerCodegraphSync(projectDir: string): Promise<GraphSyncResult>;
|
|
132
|
+
import type { LogLevel } from "./file-logger";
|
|
133
|
+
export declare function logToFile(level: LogLevel, msg: string): Promise<void>;
|
|
132
134
|
/**
|
|
133
135
|
* Compare two semver strings. Returns true if `latest` is strictly greater
|
|
134
136
|
* than `installed`. Handles X.Y.Z with optional pre-release suffix (-rc.1,
|