File size: 2,831 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
import { describe, expect, it } from "vitest";
import type { SkynetCausalEpisode } from "../causal-valence/episode-ledger.js";
import {
  buildSkynetRuntimeTrajectorySamples,
  encodeSkynetRuntimeTrajectoryFeatures,
} from "./trajectory-builder.js";
import {
  predictSkynetRuntimeObserverLabel,
  trainSkynetRuntimeObserverModel,
} from "./trajectory-learner.js";

function buildEpisode(
  index: number,
  sessionKey: string,
  bootstrapLabel: SkynetCausalEpisode["bootstrapLabel"],
  kind: "noop" | "edit" | "delete",
): SkynetCausalEpisode {
  const success = bootstrapLabel !== "damage";
  return {
    id: `${sessionKey}-${index}`,
    sessionKey,
    recordedAt: index,
    context: {
      continuityFreshness: bootstrapLabel === "stall" ? "aging" : "fresh",
      failureStreak: bootstrapLabel === "damage" ? 2 : bootstrapLabel === "relief" ? 1 : 0,
      targetCount: 1,
      validationIntensity: kind === "noop" ? 0.2 : 0.9,
    },
    transition: {
      targetPaths: ["src/app.ts"],
      operations: [{ path: "src/app.ts", kind, isTarget: true }],
    },
    outcome: {
      status: success ? "ok" : "error",
      failureDomain: success ? "none" : "cognitive",
      failureClass: success ? "none" : "validation_error",
      targetSatisfied: bootstrapLabel === "progress" || bootstrapLabel === "relief",
      validationPassed: success,
      continuityDelta: bootstrapLabel === "progress" || bootstrapLabel === "relief" ? 0.7 : 0.05,
      recoveryBurden: bootstrapLabel === "damage" ? 0.8 : 0.1,
      collateralDamage: bootstrapLabel === "damage" ? 0.5 : 0,
    },
    bootstrapLabel,
  };
}

describe("skynet runtime trajectory learner", () => {
  it("encodes non-empty history-aware vectors", () => {
    const samples = buildSkynetRuntimeTrajectorySamples({
      episodes: [buildEpisode(1, "s", "stall", "noop"), buildEpisode(2, "s", "progress", "edit")],
    });

    expect(encodeSkynetRuntimeTrajectoryFeatures(samples[0]!).length).toBeGreaterThan(10);
  });

  it("predicts labels from a separable synthetic sequence dataset", () => {
    const samples = buildSkynetRuntimeTrajectorySamples({
      episodes: [
        buildEpisode(1, "a", "stall", "noop"),
        buildEpisode(2, "a", "progress", "edit"),
        buildEpisode(3, "a", "stall", "noop"),
        buildEpisode(4, "a", "progress", "edit"),
        buildEpisode(10, "b", "damage", "delete"),
        buildEpisode(11, "b", "stall", "noop"),
        buildEpisode(12, "b", "damage", "delete"),
        buildEpisode(13, "b", "stall", "noop"),
      ],
    });
    const model = trainSkynetRuntimeObserverModel(samples)!;
    const prediction = predictSkynetRuntimeObserverLabel(model, samples[0]!);

    expect(model.labels.length).toBeGreaterThanOrEqual(2);
    expect(["progress", "stall", "damage"]).toContain(prediction.label);
  });
});