fix(uok-gate-runner): use correct getRelevantMemoriesRanked API
The "Memory enrichment failed for gate test: DB error" warning in test output was a real API mismatch, not a benign degradation. The previous code called getRelevantMemoriesRanked(embedding, "gotcha", 2) but the canonical signature is getRelevantMemoriesRanked(query, limit). Replace the embedding-based call with a query-string built from gateId + failureClass + rationale, and pass limit=2. The embedding helper (computeGateEmbedding) is removed entirely since the memory store does its own embedding internally. Also switch the enrichment-failure log from logWarning to debugLog — gate enrichment is best-effort and must not affect gates, so the failure path should not surface as a warning to operators. Test fixture updated to assert against the new API call shape. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
6851869c00
commit
f038f2a072
2 changed files with 33 additions and 50 deletions
|
|
@ -101,15 +101,21 @@ describe("Gate Context Enrichment (Phase 3)", () => {
|
|||
expect(similarFailure.content.length).toBeLessThanOrEqual(100);
|
||||
});
|
||||
|
||||
it("queries_for_gotcha_category", async () => {
|
||||
it("queries_with_gate_failure_context", async () => {
|
||||
memoryStore.getRelevantMemoriesRanked.mockResolvedValueOnce([]);
|
||||
|
||||
const result = { outcome: "fail" };
|
||||
const result = {
|
||||
outcome: "fail",
|
||||
failureClass: "timeout",
|
||||
rationale: "Command exceeded limit",
|
||||
};
|
||||
|
||||
await enrichGateResultWithMemory(result, "test-gate");
|
||||
|
||||
const callArgs = memoryStore.getRelevantMemoriesRanked.mock.calls[0];
|
||||
expect(callArgs[1]).toBe("gotcha");
|
||||
expect(callArgs[0]).toContain("uok gate failure test-gate");
|
||||
expect(callArgs[0]).toContain("timeout");
|
||||
expect(callArgs[0]).toContain("Command exceeded limit");
|
||||
});
|
||||
|
||||
it("limits_similar_failures_to_2", async () => {
|
||||
|
|
@ -120,7 +126,7 @@ describe("Gate Context Enrichment (Phase 3)", () => {
|
|||
await enrichGateResultWithMemory(result, "test-gate");
|
||||
|
||||
const callArgs = memoryStore.getRelevantMemoriesRanked.mock.calls[0];
|
||||
expect(callArgs[2]).toBe(2); // limit: 2
|
||||
expect(callArgs[1]).toBe(2); // limit: 2
|
||||
});
|
||||
|
||||
it("degrades_gracefully_when_db_unavailable", async () => {
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
import { debugLog } from "../debug-logger.js";
|
||||
import { getErrorMessage } from "../error-utils.js";
|
||||
import { getRelevantMemoriesRanked } from "../memory-store.js";
|
||||
import {
|
||||
|
|
@ -7,7 +8,6 @@ import {
|
|||
isDbAvailable,
|
||||
updateGateCircuitBreaker,
|
||||
} from "../sf-db.js";
|
||||
import { logWarning } from "../workflow-logger.js";
|
||||
import { buildAuditEnvelope, emitUokAuditEvent } from "./audit.js";
|
||||
import { validateGate } from "./contracts.js";
|
||||
import { appendTraceEvent } from "./trace-writer.js";
|
||||
|
|
@ -87,60 +87,37 @@ export async function enrichGateResultWithMemory(gateResult, gateId) {
|
|||
try {
|
||||
// Query: "Have we seen failures like this before?"
|
||||
const gateIdNorm = String(gateId || "unknown").toLowerCase();
|
||||
const embedding = await computeGateEmbedding(gateIdNorm);
|
||||
const failureClass = gateResult?.failureClass
|
||||
? ` ${gateResult.failureClass}`
|
||||
: "";
|
||||
const rationale = gateResult?.rationale ? ` ${gateResult.rationale}` : "";
|
||||
const query = `uok gate failure ${gateIdNorm}${failureClass}${rationale}`;
|
||||
const memories = await getRelevantMemoriesRanked(query, 2);
|
||||
|
||||
if (embedding) {
|
||||
const memories = await getRelevantMemoriesRanked(
|
||||
embedding,
|
||||
"gotcha", // Gate failures are often 'gotchas'
|
||||
2, // Top 2 similar failures
|
||||
);
|
||||
|
||||
if (memories.length > 0) {
|
||||
return {
|
||||
...gateResult,
|
||||
memoryContext: {
|
||||
hasHistoricalPattern: true,
|
||||
similarFailures: memories.map((m) => ({
|
||||
id: m.id,
|
||||
confidence: m.confidence,
|
||||
content: m.content.substring(0, 100), // First 100 chars
|
||||
})),
|
||||
},
|
||||
};
|
||||
}
|
||||
if (memories.length > 0) {
|
||||
return {
|
||||
...gateResult,
|
||||
memoryContext: {
|
||||
hasHistoricalPattern: true,
|
||||
similarFailures: memories.map((m) => ({
|
||||
id: m.id,
|
||||
confidence: m.confidence,
|
||||
content: m.content.substring(0, 100), // First 100 chars
|
||||
})),
|
||||
},
|
||||
};
|
||||
}
|
||||
} catch (err) {
|
||||
// Degrade gracefully - memory enrichment never changes gate result
|
||||
logWarning(
|
||||
"gate-runner",
|
||||
`Memory enrichment failed for gate ${gateId}: ${getErrorMessage(err)}`,
|
||||
);
|
||||
debugLog("gate-memory-enrichment-failed", {
|
||||
gateId,
|
||||
error: getErrorMessage(err),
|
||||
});
|
||||
}
|
||||
|
||||
return gateResult;
|
||||
}
|
||||
|
||||
/**
|
||||
* Compute embedding for a gate ID.
|
||||
*/
|
||||
async function computeGateEmbedding(gateId) {
|
||||
try {
|
||||
const gateNorm = String(gateId || "unknown")
|
||||
.toLowerCase()
|
||||
.trim();
|
||||
const embedding = new Array(64).fill(0);
|
||||
for (let i = 0; i < gateNorm.length; i++) {
|
||||
const charCode = gateNorm.charCodeAt(i);
|
||||
embedding[i % 64] += Math.sin(charCode * (i + 1)) * 0.1;
|
||||
}
|
||||
const norm = Math.sqrt(embedding.reduce((sum, x) => sum + x * x, 0));
|
||||
return norm > 0 ? embedding.map((x) => x / norm) : embedding;
|
||||
} catch (_err) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
export class UokGateRunner {
|
||||
registry = new Map();
|
||||
register(gate) {
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue