openskynet / src /skynet /runtime-observer /trajectory-builder.ts
Darochin's picture
Mirror OpenSkyNet workspace snapshot from Git HEAD
fc93158 verified
import type {
SkynetCausalEpisode,
SkynetCausalValenceLabel,
} from "../causal-valence/episode-ledger.js";
import { deriveSkynetWorldTransitionFeatures } from "../causal-valence/world-transition.js";
export type SkynetRuntimeTrajectorySample = {
id: string;
sessionKey: string;
recordedAt: number;
lookbackCount: number;
historyEpisodes: SkynetCausalEpisode[];
currentEpisode: SkynetCausalEpisode;
targetLabel: SkynetCausalValenceLabel;
};
export type SkynetRuntimeTrajectoryFeatures = {
historyCount: number;
historyProgressRatio: number;
historyReliefRatio: number;
historyStallRatio: number;
historyFrustrationRatio: number;
historyDamageRatio: number;
historyOkRatio: number;
historyErrorRatio: number;
historyEnvironmentalFailureRatio: number;
historyCognitiveFailureRatio: number;
historyMixedFailureRatio: number;
historyMutationRatio: number;
historyAverageRecoveryBurden: number;
historyAverageCollateralDamage: number;
currentOperationCount: number;
currentUniquePathCount: number;
currentCreateRatio: number;
currentEditRatio: number;
currentDeleteRatio: number;
currentRenameRatio: number;
currentNoopRatio: number;
currentTargetCoverage: number;
currentCollateralRatio: number;
currentFailureStreak: number;
currentValidationIntensity: number;
currentFreshRatio: number;
currentAgingRatio: number;
currentStaleRatio: number;
currentMissingRatio: number;
currentOkRatio: number;
currentErrorRatio: number;
currentTimeoutRatio: number;
currentEnvironmentalFailure: number;
currentCognitiveFailure: number;
currentMixedFailure: number;
currentTargetSatisfied: number;
currentValidationPassed: number;
currentContinuityDelta: number;
currentRecoveryBurden: number;
};
function clamp01(value: number): number {
return Math.max(0, Math.min(1, value));
}
function ratio(count: number, total: number): number {
return total > 0 ? clamp01(count / total) : 0;
}
export function buildSkynetRuntimeTrajectorySamples(params: {
episodes: SkynetCausalEpisode[];
lookback?: number;
}): SkynetRuntimeTrajectorySample[] {
const lookback = Math.max(1, Math.min(8, params.lookback ?? 3));
const sortedEpisodes = [...params.episodes].sort((left, right) => {
if (left.sessionKey !== right.sessionKey) {
return left.sessionKey.localeCompare(right.sessionKey);
}
return left.recordedAt - right.recordedAt;
});
const bySession = new Map<string, SkynetCausalEpisode[]>();
for (const episode of sortedEpisodes) {
const bucket = bySession.get(episode.sessionKey) ?? [];
bucket.push(episode);
bySession.set(episode.sessionKey, bucket);
}
const samples: SkynetRuntimeTrajectorySample[] = [];
for (const [sessionKey, sessionEpisodes] of bySession) {
for (let index = 1; index < sessionEpisodes.length; index += 1) {
const historyStart = Math.max(0, index - lookback);
const historyEpisodes = sessionEpisodes.slice(historyStart, index);
const currentEpisode = sessionEpisodes[index];
samples.push({
id: `${sessionKey}:${currentEpisode.id}`,
sessionKey,
recordedAt: currentEpisode.recordedAt,
lookbackCount: historyEpisodes.length,
historyEpisodes,
currentEpisode,
targetLabel: currentEpisode.bootstrapLabel,
});
}
}
return samples;
}
export function deriveSkynetRuntimeTrajectoryFeatureSummary(
sample: SkynetRuntimeTrajectorySample,
): SkynetRuntimeTrajectoryFeatures {
const historyEpisodes = sample.historyEpisodes;
const historyCount = historyEpisodes.length;
const labelCount = (label: SkynetCausalValenceLabel): number =>
historyEpisodes.filter((episode) => episode.bootstrapLabel === label).length;
const okCount = historyEpisodes.filter((episode) => episode.outcome.status === "ok").length;
const errorCount = historyEpisodes.filter((episode) => episode.outcome.status !== "ok").length;
const environmentalFailureCount = historyEpisodes.filter(
(episode) => episode.outcome.failureDomain === "environmental",
).length;
const cognitiveFailureCount = historyEpisodes.filter(
(episode) => episode.outcome.failureDomain === "cognitive",
).length;
const mixedFailureCount = historyEpisodes.filter(
(episode) => episode.outcome.failureDomain === "mixed",
).length;
const mutationCount = historyEpisodes.filter((episode) =>
episode.transition.operations.some((operation) => operation.kind !== "noop"),
).length;
const averageRecoveryBurden =
historyCount > 0
? historyEpisodes.reduce((sum, episode) => sum + episode.outcome.recoveryBurden, 0) /
historyCount
: 0;
const averageCollateralDamage =
historyCount > 0
? historyEpisodes.reduce((sum, episode) => sum + episode.outcome.collateralDamage, 0) /
historyCount
: 0;
const currentTransition = deriveSkynetWorldTransitionFeatures(sample.currentEpisode.transition);
return {
historyCount,
historyProgressRatio: ratio(labelCount("progress"), historyCount),
historyReliefRatio: ratio(labelCount("relief"), historyCount),
historyStallRatio: ratio(labelCount("stall"), historyCount),
historyFrustrationRatio: ratio(labelCount("frustration"), historyCount),
historyDamageRatio: ratio(labelCount("damage"), historyCount),
historyOkRatio: ratio(okCount, historyCount),
historyErrorRatio: ratio(errorCount, historyCount),
historyEnvironmentalFailureRatio: ratio(environmentalFailureCount, historyCount),
historyCognitiveFailureRatio: ratio(cognitiveFailureCount, historyCount),
historyMixedFailureRatio: ratio(mixedFailureCount, historyCount),
historyMutationRatio: ratio(mutationCount, historyCount),
historyAverageRecoveryBurden: clamp01(averageRecoveryBurden),
historyAverageCollateralDamage: clamp01(averageCollateralDamage),
currentOperationCount: currentTransition.operationCount,
currentUniquePathCount: currentTransition.uniquePathCount,
currentCreateRatio: currentTransition.createRatio,
currentEditRatio: currentTransition.editRatio,
currentDeleteRatio: currentTransition.deleteRatio,
currentRenameRatio: currentTransition.renameRatio,
currentNoopRatio: currentTransition.noopRatio,
currentTargetCoverage: currentTransition.targetCoverage,
currentCollateralRatio: currentTransition.collateralRatio,
currentFailureStreak: sample.currentEpisode.context.failureStreak,
currentValidationIntensity: sample.currentEpisode.context.validationIntensity,
currentFreshRatio: sample.currentEpisode.context.continuityFreshness === "fresh" ? 1 : 0,
currentAgingRatio: sample.currentEpisode.context.continuityFreshness === "aging" ? 1 : 0,
currentStaleRatio: sample.currentEpisode.context.continuityFreshness === "stale" ? 1 : 0,
currentMissingRatio: sample.currentEpisode.context.continuityFreshness === "missing" ? 1 : 0,
currentOkRatio: sample.currentEpisode.outcome.status === "ok" ? 1 : 0,
currentErrorRatio: sample.currentEpisode.outcome.status === "error" ? 1 : 0,
currentTimeoutRatio: sample.currentEpisode.outcome.status === "timeout" ? 1 : 0,
currentEnvironmentalFailure:
sample.currentEpisode.outcome.failureDomain === "environmental" ? 1 : 0,
currentCognitiveFailure: sample.currentEpisode.outcome.failureDomain === "cognitive" ? 1 : 0,
currentMixedFailure: sample.currentEpisode.outcome.failureDomain === "mixed" ? 1 : 0,
currentTargetSatisfied: sample.currentEpisode.outcome.targetSatisfied ? 1 : 0,
currentValidationPassed: sample.currentEpisode.outcome.validationPassed ? 1 : 0,
currentContinuityDelta: clamp01(sample.currentEpisode.outcome.continuityDelta),
currentRecoveryBurden: clamp01(sample.currentEpisode.outcome.recoveryBurden),
};
}
export function encodeSkynetRuntimeTrajectoryFeatures(
sample: SkynetRuntimeTrajectorySample,
): number[] {
const summary = deriveSkynetRuntimeTrajectoryFeatureSummary(sample);
return [
clamp01(Math.min(summary.historyCount, 4) / 4),
summary.historyProgressRatio,
summary.historyReliefRatio,
summary.historyStallRatio,
summary.historyFrustrationRatio,
summary.historyDamageRatio,
summary.historyOkRatio,
summary.historyErrorRatio,
summary.historyEnvironmentalFailureRatio,
summary.historyCognitiveFailureRatio,
summary.historyMixedFailureRatio,
summary.historyMutationRatio,
summary.historyAverageRecoveryBurden,
summary.historyAverageCollateralDamage,
clamp01(Math.min(summary.currentOperationCount, 8) / 8),
clamp01(Math.min(summary.currentUniquePathCount, 8) / 8),
summary.currentCreateRatio,
summary.currentEditRatio,
summary.currentDeleteRatio,
summary.currentRenameRatio,
summary.currentNoopRatio,
summary.currentTargetCoverage,
summary.currentCollateralRatio,
clamp01(Math.min(summary.currentFailureStreak, 4) / 4),
clamp01(summary.currentValidationIntensity),
summary.currentFreshRatio,
summary.currentAgingRatio,
summary.currentStaleRatio,
summary.currentMissingRatio,
summary.currentOkRatio,
summary.currentErrorRatio,
summary.currentTimeoutRatio,
summary.currentEnvironmentalFailure,
summary.currentCognitiveFailure,
summary.currentMixedFailure,
summary.currentTargetSatisfied,
summary.currentValidationPassed,
summary.currentContinuityDelta,
summary.currentRecoveryBurden,
];
}