File size: 3,075 Bytes
fc93158 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 | import { describe, expect, it } from "vitest";
import { RicciGraphAnalytics } from "./graph-analytics.js";
import type { OmegaSelfTimeKernelState } from "./self-time-kernel.js";
function makeKernel(
files: OmegaSelfTimeKernelState["causalGraph"]["files"],
edges: OmegaSelfTimeKernelState["causalGraph"]["edges"],
): OmegaSelfTimeKernelState {
return {
revision: 2,
sessionKey: "agent:test:main",
turnCount: 4,
identity: {
continuityId: "cont-1",
firstSeenAt: 1,
lastSeenAt: 4,
},
world: {
lastObservedChangedFiles: [],
},
goals: [],
tension: {
openGoalCount: 0,
staleGoalCount: 0,
failureStreak: 0,
repeatedFailureKinds: [],
pendingCorrection: false,
},
causalGraph: {
files,
edges,
},
updatedAt: 4,
};
}
describe("RicciGraphAnalytics", () => {
it("prioritizes low-success bottlenecks over busy but mostly successful files", () => {
const kernel = makeKernel(
[
{ path: "src/busy.ts", writeCount: 6, failureCount: 2 },
{ path: "src/bottleneck.ts", writeCount: 0, failureCount: 1 },
],
[
{
goalId: "g1",
filePath: "src/busy.ts",
relation: "goal_targets_file",
updatedAt: 1,
updatedTurn: 1,
},
{
goalId: "g2",
filePath: "src/busy.ts",
relation: "goal_failed_on_file",
updatedAt: 2,
updatedTurn: 2,
},
{
goalId: "g3",
filePath: "src/bottleneck.ts",
relation: "goal_failed_on_file",
updatedAt: 3,
updatedTurn: 3,
},
],
);
const recommendation = RicciGraphAnalytics.getFocusRecommendation(kernel);
expect(recommendation).toContain("src/bottleneck.ts");
});
it("returns null when no file crosses the bottleneck threshold", () => {
const kernel = makeKernel(
[
{ path: "src/stable.ts", writeCount: 4, failureCount: 0 },
{ path: "src/healthy.ts", writeCount: 3, failureCount: 0 },
],
[
{
goalId: "g1",
filePath: "src/stable.ts",
relation: "goal_wrote_file",
updatedAt: 1,
updatedTurn: 1,
},
],
);
const recommendation = RicciGraphAnalytics.getFocusRecommendation(kernel);
expect(recommendation).toBeNull();
});
it("sorts the most negative-curvature file first", () => {
const kernel = makeKernel(
[
{ path: "src/stable.ts", writeCount: 3, failureCount: 0 },
{ path: "src/failing.ts", writeCount: 0, failureCount: 1 },
],
[
{
goalId: "g1",
filePath: "src/failing.ts",
relation: "goal_failed_on_file",
updatedAt: 1,
updatedTurn: 1,
},
],
);
const analysis = RicciGraphAnalytics.analyze(kernel);
expect(analysis[0]?.path).toBe("src/failing.ts");
expect((analysis[0]?.curvature ?? 0) < (analysis[1]?.curvature ?? 0)).toBe(true);
});
});
|