@jmanuelcorral/openteam 0.2.0 → 0.2.1

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/dist/index.js CHANGED
@@ -692,6 +692,9 @@ function scanReferenceOnly(surfaces) {
692
692
  return { surfacesScanned: surfaces.length, rawFindings };
693
693
  }
694
694
 
695
+ // src/contract/opencode.ts
696
+ var SUPPORTED_OPENCODE_VERSIONS = ["1.17.13", "1.18.18"];
697
+
695
698
  // src/graph/soakLedger.ts
696
699
  import { z as z2 } from "zod";
697
700
  var Sha256Schema = z2.string().regex(/^[0-9a-f]{64}$/);
@@ -1138,14 +1141,14 @@ var SoakPolicySchema = z3.object({
1138
1141
  minimumGenuineObservations: z3.number().int().positive(),
1139
1142
  minimumDistinctDays: z3.number().int().positive(),
1140
1143
  requireGenuineUsageOnAllPlatforms: z3.boolean(),
1141
- supportedOpencodeVersion: z3.string().min(1),
1144
+ supportedOpencodeVersions: z3.array(z3.string().min(1)).min(1),
1142
1145
  criticalDivergenceCodes: z3.array(RecomputedDivergenceCodeSchema).min(1)
1143
1146
  }).strict();
1144
1147
  var DEFAULT_SOAK_POLICY = {
1145
1148
  minimumGenuineObservations: 100,
1146
1149
  minimumDistinctDays: 14,
1147
1150
  requireGenuineUsageOnAllPlatforms: true,
1148
- supportedOpencodeVersion: "1.17.13",
1151
+ supportedOpencodeVersions: [...SUPPORTED_OPENCODE_VERSIONS],
1149
1152
  criticalDivergenceCodes: ["fixes"]
1150
1153
  };
1151
1154
  var SoakPlatformEnumSchema = z3.enum(["linux", "win32", "darwin"]);
@@ -1167,6 +1170,7 @@ var SoakEvidenceSchema = z3.object({
1167
1170
  genuineUsageObservations: z3.number().int().nonnegative(),
1168
1171
  ciSyntheticObservations: z3.number().int().nonnegative(),
1169
1172
  recorderCount: z3.number().int().nonnegative(),
1173
+ ineligibleObservations: z3.number().int().nonnegative(),
1170
1174
  firstTimestamp: z3.string().datetime().nullable(),
1171
1175
  lastTimestamp: z3.string().datetime().nullable(),
1172
1176
  distinctDays: z3.number().int().nonnegative(),
@@ -1247,7 +1251,8 @@ function evaluateSoakGates(evidence, policy) {
1247
1251
  failed.push("os-diversity");
1248
1252
  }
1249
1253
  }
1250
- if (!evidence.opencodeVersionsObserved.includes(policy.supportedOpencodeVersion)) {
1254
+ const supported = new Set(policy.supportedOpencodeVersions);
1255
+ if (evidence.opencodeVersionsObserved.length === 0 || !evidence.opencodeVersionsObserved.every((v) => supported.has(v))) {
1251
1256
  failed.push("opencode-pin");
1252
1257
  }
1253
1258
  return failed;
@@ -1263,7 +1268,7 @@ function canonicalSoakCertificate(certificate) {
1263
1268
  minimumGenuineObservations: pol.minimumGenuineObservations,
1264
1269
  minimumDistinctDays: pol.minimumDistinctDays,
1265
1270
  requireGenuineUsageOnAllPlatforms: pol.requireGenuineUsageOnAllPlatforms,
1266
- supportedOpencodeVersion: pol.supportedOpencodeVersion,
1271
+ supportedOpencodeVersions: [...pol.supportedOpencodeVersions].sort(),
1267
1272
  criticalDivergenceCodes: [...pol.criticalDivergenceCodes].sort()
1268
1273
  },
1269
1274
  verdict: certificate.verdict,
@@ -1274,6 +1279,7 @@ function canonicalSoakCertificate(certificate) {
1274
1279
  genuineUsageObservations: ev.genuineUsageObservations,
1275
1280
  ciSyntheticObservations: ev.ciSyntheticObservations,
1276
1281
  recorderCount: ev.recorderCount,
1282
+ ineligibleObservations: ev.ineligibleObservations,
1277
1283
  firstTimestamp: ev.firstTimestamp,
1278
1284
  lastTimestamp: ev.lastTimestamp,
1279
1285
  distinctDays: ev.distinctDays,
@@ -1292,7 +1298,9 @@ function sameSoakGates(a, b) {
1292
1298
  return a.length === b.length && a.every((gate, index) => gate === b[index]);
1293
1299
  }
1294
1300
  function sameSoakPolicy(a, b) {
1295
- return a.minimumGenuineObservations === b.minimumGenuineObservations && a.minimumDistinctDays === b.minimumDistinctDays && a.requireGenuineUsageOnAllPlatforms === b.requireGenuineUsageOnAllPlatforms && a.supportedOpencodeVersion === b.supportedOpencodeVersion && a.criticalDivergenceCodes.length === b.criticalDivergenceCodes.length && [...a.criticalDivergenceCodes].sort().every((code, i) => code === [...b.criticalDivergenceCodes].sort()[i]);
1301
+ const aVersions = [...a.supportedOpencodeVersions].sort();
1302
+ const bVersions = [...b.supportedOpencodeVersions].sort();
1303
+ return a.minimumGenuineObservations === b.minimumGenuineObservations && a.minimumDistinctDays === b.minimumDistinctDays && a.requireGenuineUsageOnAllPlatforms === b.requireGenuineUsageOnAllPlatforms && aVersions.length === bVersions.length && aVersions.every((v, i) => v === bVersions[i]) && a.criticalDivergenceCodes.length === b.criticalDivergenceCodes.length && [...a.criticalDivergenceCodes].sort().every((code, i) => code === [...b.criticalDivergenceCodes].sort()[i]);
1296
1304
  }
1297
1305
  function parseSoakCertificate(value, expectedPolicy, expectedLedgerDigest) {
1298
1306
  const parsed = SoakCertificateSchema.safeParse(value);
@@ -2959,1578 +2967,1578 @@ function validateGraphSpec(spec) {
2959
2967
  assertConnected(spec.nodes);
2960
2968
  }
2961
2969
 
2962
- // src/capabilities/classify.ts
2963
- var hardKeywords = [
2964
- "security",
2965
- "auth",
2966
- "authentication",
2967
- "authorization",
2968
- "concurrency",
2969
- "race condition",
2970
- "architecture",
2971
- "refactor",
2972
- "migration",
2973
- "debug",
2974
- "root cause"
2975
- ];
2976
- function scoreOverride(override) {
2977
- if (override === "alwaysFrontier") {
2978
- return 30;
2970
+ // src/orchestrator/graphIngress.ts
2971
+ var ACTIVE_INGRESS_BRAND = Symbol("openteam.activeIngress");
2972
+ function gateReason(policy) {
2973
+ if (policy.capability === undefined) {
2974
+ return "gate-closed";
2979
2975
  }
2980
- if (override === "alwaysLocal") {
2981
- return -20;
2976
+ if (policy.graph.killSwitch) {
2977
+ return "kill-switch";
2982
2978
  }
2983
- return 0;
2979
+ return policy.graph.configuredMode === "active" ? undefined : "graph-disabled";
2984
2980
  }
2985
- function tierFromScore(score) {
2986
- if (score <= 15) {
2987
- return "trivial";
2981
+ function decideIngress(policy, taskID) {
2982
+ const blocked = gateReason(policy);
2983
+ if (blocked !== undefined) {
2984
+ return { route: "legacy", reason: blocked };
2988
2985
  }
2989
- if (score <= 35) {
2990
- return "simple";
2986
+ if (!policy.allowList.includes(taskID)) {
2987
+ return { route: "legacy", reason: "not-allow-listed" };
2991
2988
  }
2992
- if (score <= 65) {
2993
- return "moderate";
2989
+ return { route: "graph", taskID };
2990
+ }
2991
+
2992
+ // src/plugin/legacyRunProducer.ts
2993
+ function toObservedNode(node) {
2994
+ return {
2995
+ id: node.id,
2996
+ role: node.role,
2997
+ model: node.model,
2998
+ ok: node.ok,
2999
+ ...node.sessionRef !== undefined ? { sessionRef: node.sessionRef } : {},
3000
+ ...node.errorClass !== undefined ? { errorClass: node.errorClass } : {}
3001
+ };
3002
+ }
3003
+ function buildObservedRun(payload) {
3004
+ return {
3005
+ runID: payload.runID,
3006
+ executed: true,
3007
+ status: payload.status,
3008
+ fixes: payload.fixes,
3009
+ nodes: payload.nodes.map(toObservedNode),
3010
+ ...payload.parentSessionRef !== undefined ? { parentSessionRef: payload.parentSessionRef } : {}
3011
+ };
3012
+ }
3013
+ function crossVerify(payload, tracker) {
3014
+ const unverifiedModels = [];
3015
+ const modelMismatches = [];
3016
+ const unknownSessions = [];
3017
+ for (const node of payload.nodes) {
3018
+ if (node.sessionRef !== undefined) {
3019
+ const mv = tracker.verifyModel(node.sessionRef, node.model);
3020
+ if (!mv.verified) {
3021
+ unverifiedModels.push(node.id);
3022
+ } else if (!mv.match) {
3023
+ modelMismatches.push(node.id);
3024
+ }
3025
+ const sv = tracker.verifySessionRef(node.sessionRef);
3026
+ if (sv.known === false) {
3027
+ unknownSessions.push(node.id);
3028
+ }
3029
+ } else {
3030
+ unverifiedModels.push(node.id);
3031
+ }
2994
3032
  }
2995
- return "hard";
3033
+ return { unverifiedModels, modelMismatches, unknownSessions };
2996
3034
  }
2997
- function confidenceFromScore(score) {
2998
- if (score >= 75 || score <= 10) {
2999
- return 0.9;
3035
+ function formatWarnings(verification) {
3036
+ const warnings = [];
3037
+ if (verification.unverifiedModels.length > 0) {
3038
+ warnings.push(`model not verifiable for nodes: ${verification.unverifiedModels.join(", ")}`);
3000
3039
  }
3001
- if (score >= 30 && score <= 70) {
3002
- return 0.58;
3040
+ if (verification.modelMismatches.length > 0) {
3041
+ warnings.push(`model mismatch for nodes: ${verification.modelMismatches.join(", ")}`);
3003
3042
  }
3004
- return 0.72;
3005
- }
3006
- function addScore(condition, amount, reason, state) {
3007
- if (condition) {
3008
- state.score += amount;
3009
- state.reasons.push(reason);
3043
+ if (verification.unknownSessions.length > 0) {
3044
+ warnings.push(`unknown sessionRef for nodes: ${verification.unknownSessions.join(", ")}`);
3010
3045
  }
3046
+ return warnings;
3011
3047
  }
3012
- function classifyHeuristic(task) {
3013
- const state = { score: scoreOverride(task.explicitOverride), reasons: [] };
3014
- const prompt = task.prompt?.toLowerCase() ?? "";
3015
- const estimatedTokens = (task.estimatedInputTokens ?? 0) + (task.estimatedOutputTokens ?? 0);
3016
- addScore(task.promptChars <= 80 && !task.hasCode && task.requiresTools !== true, -5, "short-text-prompt", state);
3017
- addScore(task.promptChars > 1500 || estimatedTokens > 700, 10, "large-prompt", state);
3018
- addScore(task.promptChars > 5000 || estimatedTokens > 3000, 15, "very-large-context", state);
3019
- addScore(task.hasCode, 15, "code-present", state);
3020
- addScore(task.requiresTools === true, 15, "tools-required", state);
3021
- addScore(task.requiresVision === true, 15, "vision-required", state);
3022
- addScore((task.fileCount ?? 0) > 1, 20, "multi-file-task", state);
3023
- addScore((task.diffHunks ?? 0) > 2, 15, "multi-hunk-diff", state);
3024
- addScore(hardKeywords.some((keyword) => prompt.includes(keyword)), 25, "hard-keyword", state);
3025
- addScore(task.userAskedForQuality === true, 20, "quality-requested", state);
3026
- addScore(task.privacySensitive === true, 10, "privacy-sensitive", state);
3027
- const normalizedScore = Math.max(0, Math.min(100, state.score));
3028
- return {
3029
- tier: tierFromScore(normalizedScore),
3030
- confidence: confidenceFromScore(normalizedScore),
3031
- reasons: state.reasons.length > 0 ? state.reasons : ["no-hard-signals"],
3032
- ambiguous: normalizedScore >= 30 && normalizedScore <= 70
3033
- };
3048
+ function formatResponse(response) {
3049
+ const parts = [`report-run: ${response.result}`];
3050
+ if (response.detail !== undefined) {
3051
+ parts.push(response.detail);
3052
+ }
3053
+ if (response.warnings !== undefined && response.warnings.length > 0) {
3054
+ parts.push(`warnings: ${response.warnings.join("; ")}`);
3055
+ }
3056
+ return parts.join(" ");
3034
3057
  }
3035
3058
 
3036
- // src/capabilities/budget.ts
3037
- var WARNING_UTILIZATION = 0.8;
3038
- function projectedSpend(current, estimatedCostUSD) {
3039
- return Math.max(0, current) + Math.max(0, estimatedCostUSD);
3040
- }
3041
- function budgetExceeded(projected, limit) {
3042
- return limit !== undefined && projected >= limit;
3059
+ // src/plugin/reportRunSchema.ts
3060
+ import { z as z9 } from "zod";
3061
+
3062
+ // src/plugin/graphShadowIngress.ts
3063
+ import { z as z8 } from "zod";
3064
+ var LEGACY_EXECUTION_TRACE_VERSION = 1;
3065
+ var LegacyExecutionStatusSchema = z8.enum([
3066
+ "completed",
3067
+ "failed",
3068
+ "cancelled"
3069
+ ]);
3070
+ var LegacyReviewOutcomeSchema = z8.enum([
3071
+ "approved",
3072
+ "rejected",
3073
+ "inconclusive"
3074
+ ]);
3075
+ var LegacyTraceNodeV1Schema = z8.object({
3076
+ id: NodeIDSchema,
3077
+ role: NodeRoleSchema,
3078
+ model: z8.string().min(1),
3079
+ sessionRef: z8.string().min(1).optional(),
3080
+ errorClass: ErrorClassSchema.optional()
3081
+ }).strict();
3082
+ var LegacyExecutionTraceV1Schema = z8.object({
3083
+ version: z8.literal(LEGACY_EXECUTION_TRACE_VERSION),
3084
+ runID: NodeIDSchema,
3085
+ status: LegacyExecutionStatusSchema,
3086
+ outcome: LegacyReviewOutcomeSchema,
3087
+ fixes: z8.number().int().nonnegative(),
3088
+ nodes: z8.array(LegacyTraceNodeV1Schema).min(1),
3089
+ parentSessionRef: z8.string().min(1).optional()
3090
+ }).strict();
3091
+ function gateReason2(gate) {
3092
+ if (gate === undefined || gate.mode === "off") {
3093
+ return "graph-disabled";
3094
+ }
3095
+ if (gate.killSwitch) {
3096
+ return "kill-switch";
3097
+ }
3098
+ return;
3043
3099
  }
3044
- function budgetNearLimit(projected, limit) {
3045
- return limit !== undefined && projected >= limit * WARNING_UTILIZATION && projected < limit;
3100
+ function deriveOutcome(nodes) {
3101
+ for (let index = nodes.length - 1;index >= 0; index -= 1) {
3102
+ const node = nodes[index];
3103
+ if (node !== undefined && node.role === "reviewer") {
3104
+ return node.ok ? "approved" : "rejected";
3105
+ }
3106
+ }
3107
+ return "inconclusive";
3046
3108
  }
3047
- function exhaustedDecision(budgets, reason) {
3109
+ function toTraceNode(node) {
3048
3110
  return {
3049
- action: budgets.hardStopOnBudgetExhaustion ? "blockFrontier" : "forceLocal",
3050
- reason
3111
+ id: node.id,
3112
+ role: node.role,
3113
+ model: node.model,
3114
+ ...node.sessionRef !== undefined ? { sessionRef: node.sessionRef } : {},
3115
+ ...node.errorClass !== undefined ? { errorClass: node.errorClass } : {}
3051
3116
  };
3052
3117
  }
3053
- function evaluateBudget(state, estimatedCostUSD, budgets) {
3054
- const projectedSessionUSD = projectedSpend(state.sessionUSD, estimatedCostUSD);
3055
- const projectedMonthlyUSD = budgets.monthlyUSD === undefined ? undefined : projectedSpend(state.monthlyUSD ?? 0, estimatedCostUSD);
3056
- if (budgetExceeded(projectedSessionUSD, budgets.sessionUSD)) {
3057
- return exhaustedDecision(budgets, "session-budget-exhausted");
3058
- }
3059
- if (budgetExceeded(projectedMonthlyUSD ?? 0, budgets.monthlyUSD)) {
3060
- return exhaustedDecision(budgets, "monthly-budget-exhausted");
3061
- }
3062
- if (state.frontierTokens !== undefined && budgets.frontierTokensPerSession !== undefined && state.frontierTokens >= budgets.frontierTokensPerSession) {
3063
- return exhaustedDecision(budgets, "frontier-token-budget-exhausted");
3118
+ function ingestLegacyExecution(observation, gate) {
3119
+ const gated = gateReason2(gate);
3120
+ if (gated !== undefined) {
3121
+ return { eligible: false, reason: gated };
3064
3122
  }
3065
- if (budgetNearLimit(projectedSessionUSD, budgets.sessionUSD)) {
3066
- return { action: "warn", reason: "session-budget-near-limit" };
3123
+ if (!observation.executed) {
3124
+ return { eligible: false, reason: "not-executed" };
3067
3125
  }
3068
- if (budgetNearLimit(projectedMonthlyUSD ?? 0, budgets.monthlyUSD)) {
3069
- return { action: "warn", reason: "monthly-budget-near-limit" };
3126
+ if (observation.nodes.length === 0) {
3127
+ return { eligible: false, reason: "no-observation" };
3070
3128
  }
3071
- return { action: "ok" };
3129
+ const trace = {
3130
+ version: LEGACY_EXECUTION_TRACE_VERSION,
3131
+ runID: observation.runID,
3132
+ status: observation.status,
3133
+ outcome: deriveOutcome(observation.nodes),
3134
+ fixes: Math.max(0, Math.trunc(observation.fixes)),
3135
+ nodes: observation.nodes.map(toTraceNode),
3136
+ ...observation.parentSessionRef !== undefined ? { parentSessionRef: observation.parentSessionRef } : {}
3137
+ };
3138
+ assertReferenceOnly(trace);
3139
+ return { eligible: true, trace };
3072
3140
  }
3073
3141
 
3074
- // src/router/modelSelection.ts
3075
- function modelKey2(model) {
3076
- return `${model.providerID}/${model.modelID}`;
3077
- }
3078
- function sameModel(left, right) {
3079
- return left.providerID === right.providerID && left.modelID === right.modelID;
3080
- }
3081
- function compareModels(left, right) {
3082
- return modelKey2(left).localeCompare(modelKey2(right));
3142
+ class LegacyTraceError extends Error {
3143
+ code = "invalid-legacy-trace";
3144
+ issues;
3145
+ constructor(error) {
3146
+ super(`invalid-legacy-trace: ${error.issues.map((issue) => issue.message).join("; ")}`);
3147
+ this.name = "LegacyTraceError";
3148
+ this.issues = error.issues.map((issue) => issue.message);
3149
+ }
3083
3150
  }
3084
- function uniqueModelSelections(models) {
3085
- const byKey = new Map;
3086
- for (const model of models) {
3087
- byKey.set(modelKey2(model), model);
3151
+ function parseLegacyExecutionTrace(input) {
3152
+ const result = LegacyExecutionTraceV1Schema.safeParse(input);
3153
+ if (!result.success) {
3154
+ throw new LegacyTraceError(result.error);
3088
3155
  }
3089
- return [...byKey.values()].sort(compareModels);
3090
- }
3091
- function localDefault(config) {
3092
- return config.local.runtimes.find((runtime) => runtime.enabled)?.defaultModel ?? config.router.localDefault;
3093
- }
3094
- function resolveConfiguredFrontierBaseline(config) {
3095
- if (config.baseline.mode === "pinned" && config.baseline.pinnedModel !== null) {
3096
- return config.baseline.pinnedModel;
3097
- }
3098
- return config.baseline.hardDefault;
3099
- }
3100
- function compareAvailableModels2(left, right) {
3101
- return compareModels(left, right);
3102
- }
3103
- function defaultAvailableModels2(config) {
3104
- return [
3105
- {
3106
- ...localDefault(config),
3107
- kind: "local",
3108
- available: true
3109
- },
3110
- {
3111
- ...resolveConfiguredFrontierBaseline(config),
3112
- kind: "frontier",
3113
- available: true
3114
- }
3115
- ].sort(compareAvailableModels2);
3116
- }
3117
- function availableModels(input) {
3118
- return (input.availableModels ?? defaultAvailableModels2(input.config)).slice().sort(compareAvailableModels2);
3119
- }
3120
- function listedModel(input, model) {
3121
- return availableModels(input).find((candidate) => sameModel(candidate, model));
3122
- }
3123
- function frontierAvailable(input, model) {
3124
- return listedModel(input, model)?.available !== false;
3125
- }
3126
- function localCandidateIsUsable(input, model) {
3127
- return model.kind === "local" && model.available && !(input.task.requiresTools === true && model.supportsTools === false);
3128
- }
3129
- function availableLocalFallbacks(input, selected) {
3130
- return uniqueModelSelections(availableModels(input).filter((model) => localCandidateIsUsable(input, model)).filter((model) => !sameModel(model, selected)).map((model) => ({
3131
- providerID: model.providerID,
3132
- modelID: model.modelID
3133
- })));
3156
+ return result.data;
3134
3157
  }
3135
3158
 
3136
- // src/router/cost.ts
3137
- function modelProfile(input, model) {
3138
- return input.profiles?.find((profile) => sameModel(profile.ref, model));
3139
- }
3140
- function estimatedCostUSD(input, model) {
3141
- const profile = modelProfile(input, model);
3142
- if (profile === undefined) {
3143
- return 0;
3159
+ // src/plugin/reportRunSchema.ts
3160
+ var ReportRunNodeSchema = z9.object({
3161
+ id: NodeIDSchema,
3162
+ role: NodeRoleSchema,
3163
+ model: z9.string().min(1),
3164
+ ok: z9.boolean(),
3165
+ sessionRef: z9.string().min(1).optional(),
3166
+ errorClass: ErrorClassSchema.optional()
3167
+ }).strict();
3168
+ var ReportRunPayloadSchema = z9.object({
3169
+ runID: NodeIDSchema,
3170
+ status: LegacyExecutionStatusSchema,
3171
+ fixes: z9.number().int().nonnegative(),
3172
+ nodes: z9.array(ReportRunNodeSchema).min(1),
3173
+ parentSessionRef: z9.string().min(1).optional()
3174
+ }).strict();
3175
+
3176
+ // src/graph/types.ts
3177
+ var TERMINAL_NODE_STATUSES = new Set([
3178
+ "succeeded",
3179
+ "cancelled"
3180
+ ]);
3181
+ var TERMINAL_RUN_STATUSES = new Set([
3182
+ "completed",
3183
+ "failed",
3184
+ "cancelled"
3185
+ ]);
3186
+
3187
+ // src/graph/reducer.ts
3188
+ class ReducerError extends Error {
3189
+ code;
3190
+ detail;
3191
+ constructor(code, detail) {
3192
+ super(`${code}: ${detail}`);
3193
+ this.name = "ReducerError";
3194
+ this.code = code;
3195
+ this.detail = detail;
3144
3196
  }
3145
- const inputTokens = input.task.estimatedInputTokens ?? 0;
3146
- const outputTokens = input.task.estimatedOutputTokens ?? 0;
3147
- return inputTokens / 1e6 * profile.costPer1M.inputUSD + outputTokens / 1e6 * profile.costPer1M.outputUSD;
3148
3197
  }
3149
- function roundUSD(value) {
3150
- return Math.round(value * 1000000000000) / 1000000000000;
3198
+ function initialState(spec) {
3199
+ const nodes = {};
3200
+ for (const node of spec.nodes) {
3201
+ nodes[node.id] = { status: "pending", attempts: 0 };
3202
+ }
3203
+ return { runID: spec.runID, status: "running", seq: -1, nodes };
3151
3204
  }
3152
-
3153
- // src/capabilities/select.ts
3154
- var BLENDED_COST_INPUT_WEIGHT = 0.75;
3155
- var BLENDED_COST_OUTPUT_WEIGHT = 1 - BLENDED_COST_INPUT_WEIGHT;
3156
- var availabilityRank = {
3157
- available: 0,
3158
- degraded: 1,
3159
- unavailable: 2
3160
- };
3161
- var tierRequirements = {
3162
- trivial: { reasoning: 0, code: 1, context: 8000 },
3163
- simple: { reasoning: 1, code: 2, context: 16000 },
3164
- moderate: { reasoning: 3, code: 3, context: 32000 },
3165
- hard: { reasoning: 4, code: 5, context: 64000 }
3166
- };
3167
- function deriveRequirement(tier, task) {
3168
- const base = tierRequirements[tier];
3169
- const estimatedContext = (task.estimatedInputTokens ?? 0) + (task.estimatedOutputTokens ?? 0);
3170
- const contextFromPrompt = Math.ceil(task.promptChars / 4);
3171
- const minContextWindow = Math.max(base.context, estimatedContext, contextFromPrompt);
3172
- const codeBump = task.hasCode ? 1 : 0;
3205
+ function withNode(state, nodeID, next) {
3173
3206
  return {
3174
- minReasoningTier: base.reasoning,
3175
- minCodeQualityTier: Math.min(5, base.code + codeBump),
3176
- minContextWindow,
3177
- needsTools: task.requiresTools === true,
3178
- needsVision: task.requiresVision === true
3207
+ ...state,
3208
+ nodes: { ...state.nodes, [nodeID]: next },
3209
+ seq: state.seq
3179
3210
  };
3180
3211
  }
3181
- function blendedCostPer1M(profile) {
3182
- return profile.costPer1M.inputUSD * BLENDED_COST_INPUT_WEIGHT + profile.costPer1M.outputUSD * BLENDED_COST_OUTPUT_WEIGHT;
3183
- }
3184
- function modelKey3(profile) {
3185
- return `${profile.ref.providerID}/${profile.ref.modelID}`;
3212
+ function specNode(spec, nodeID) {
3213
+ return spec.nodes.find((node) => node.id === nodeID);
3186
3214
  }
3187
- function compareCapableFrontier(req, left, right) {
3188
- const costDelta = blendedCostPer1M(left) - blendedCostPer1M(right);
3189
- if (costDelta !== 0) {
3190
- return costDelta;
3191
- }
3192
- const availabilityDelta = availabilityRank[left.availability] - availabilityRank[right.availability];
3193
- if (availabilityDelta !== 0) {
3194
- return availabilityDelta;
3195
- }
3196
- const reasoningWasteDelta = left.reasoningTier - req.minReasoningTier - (right.reasoningTier - req.minReasoningTier);
3197
- if (reasoningWasteDelta !== 0) {
3198
- return reasoningWasteDelta;
3215
+ function applyRunStarted(state, seq, specDigest) {
3216
+ if (state.specDigest !== undefined) {
3217
+ if (state.specDigest === specDigest) {
3218
+ return state;
3219
+ }
3220
+ throw new ReducerError("run-started-conflict", specDigest);
3199
3221
  }
3200
- return modelKey3(left).localeCompare(modelKey3(right));
3201
- }
3202
- function satisfiesRequirement(req, profile) {
3203
- return profile.kind === "frontier" && profile.availability !== "unavailable" && profile.contextWindow >= req.minContextWindow && profile.reasoningTier >= req.minReasoningTier && profile.codeQualityTier >= req.minCodeQualityTier && (!req.needsTools || profile.supportsToolCalling) && (!req.needsVision || profile.supportsVision);
3204
- }
3205
- function selectCheapestCapableFrontier(req, profiles) {
3206
- const selected = profiles.filter((profile) => satisfiesRequirement(req, profile)).sort((left, right) => compareCapableFrontier(req, left, right))[0];
3207
- return selected?.ref ?? null;
3222
+ return { ...state, specDigest, seq };
3208
3223
  }
3209
-
3210
- // src/router/frontierBaseline.ts
3211
- function resolveFrontierBaseline(input, tier) {
3212
- if (input.config.baseline.mode === "pinned" && input.config.baseline.pinnedModel !== null) {
3213
- return { model: input.config.baseline.pinnedModel, rationale: [] };
3224
+ function applyDispatched(spec, state, event) {
3225
+ const node = specNode(spec, event.nodeID);
3226
+ const current = state.nodes[event.nodeID];
3227
+ if (node === undefined || current === undefined) {
3228
+ throw new ReducerError("unknown-node", event.nodeID);
3214
3229
  }
3215
- if (input.profiles !== undefined) {
3216
- const selected = selectCheapestCapableFrontier(deriveRequirement(tier, input.task), input.profiles);
3217
- if (selected !== null) {
3218
- return {
3219
- model: selected,
3220
- rationale: ["auto-cheapest-capable-frontier"]
3221
- };
3230
+ for (const dep of node.dependsOn) {
3231
+ if (state.nodes[dep]?.status !== "succeeded") {
3232
+ throw new ReducerError("dependency-not-satisfied", `${event.nodeID} <- ${dep}`);
3222
3233
  }
3223
- return {
3224
- model: input.config.baseline.hardDefault,
3225
- rationale: ["auto-cheapest-capable-unavailable-hard-default"]
3226
- };
3227
3234
  }
3228
- return { model: input.config.baseline.hardDefault, rationale: [] };
3229
- }
3230
-
3231
- // src/router/chooseModel.ts
3232
- function localStatus(input, model) {
3233
- const listed = listedModel(input, model);
3234
- return {
3235
- available: input.availableModels === undefined ? listed?.available !== false : listed?.available === true,
3236
- missingTools: input.task.requiresTools === true && listed?.supportsTools === false
3235
+ const running = {
3236
+ status: "running",
3237
+ attempts: current.attempts + 1,
3238
+ operationID: event.operationID,
3239
+ attemptID: event.attemptID
3237
3240
  };
3238
- }
3239
- function buildFallbackChain(input, selected, frontier, allowFrontier) {
3240
- const chain = availableLocalFallbacks(input, selected);
3241
- if (allowFrontier && !sameModel(frontier, selected) && frontierAvailable(input, frontier)) {
3242
- chain.push(frontier);
3241
+ if (current.status === "pending") {
3242
+ return withNode({ ...state, seq: event.seq }, event.nodeID, running);
3243
3243
  }
3244
- return chain;
3245
- }
3246
- function inferRouteKind(config, selected, listed) {
3247
- if (listed !== undefined) {
3248
- return listed.kind;
3244
+ if (current.status === "failed") {
3245
+ if (current.operationID !== event.operationID) {
3246
+ throw new ReducerError("dispatch-conflict", event.nodeID);
3247
+ }
3248
+ return withNode({ ...state, seq: event.seq }, event.nodeID, running);
3249
3249
  }
3250
- return config.local.runtimes.some((runtime) => sameModel(runtime.defaultModel, selected)) ? "local" : "frontier";
3251
- }
3252
- function localFallbackReason(status) {
3253
- return status.missingTools ? "local-missing-tools-fallback" : "local-unavailable-fallback";
3254
- }
3255
- function decision(selected, routeKind, rationale, fallbackChain) {
3256
- return {
3257
- selected,
3258
- routeKind,
3259
- rationale,
3260
- fallbackChain
3261
- };
3250
+ if (current.status === "running") {
3251
+ if (current.operationID === event.operationID && current.attemptID === event.attemptID) {
3252
+ return state;
3253
+ }
3254
+ throw new ReducerError("dispatch-conflict", event.nodeID);
3255
+ }
3256
+ throw new ReducerError("illegal-transition", `dispatch ${current.status}`);
3262
3257
  }
3263
- function resolveLocalPrimary(input, primary, frontier, options) {
3264
- const status = localStatus(input, primary);
3265
- if (status.available && !status.missingTools) {
3266
- return decision(primary, "local", options.baseRationale, buildFallbackChain(input, primary, frontier, options.allowFrontier));
3258
+ function applySucceeded(state, event) {
3259
+ const current = state.nodes[event.nodeID];
3260
+ if (current === undefined) {
3261
+ throw new ReducerError("unknown-node", event.nodeID);
3267
3262
  }
3268
- const fallbackReason = localFallbackReason(status);
3269
- const nextLocal = availableLocalFallbacks(input, primary)[0];
3270
- if (nextLocal !== undefined) {
3271
- return decision(nextLocal, "local", [...options.baseRationale, fallbackReason], buildFallbackChain(input, nextLocal, frontier, options.allowFrontier));
3263
+ if (current.status === "succeeded") {
3264
+ if (current.operationID === event.operationID && current.artifactSha256 === event.artifact.sha256) {
3265
+ return state;
3266
+ }
3267
+ throw new ReducerError("receipt-conflict", event.nodeID);
3272
3268
  }
3273
- if (!options.allowFrontier) {
3274
- return decision(primary, "local", [...options.baseRationale, fallbackReason, options.noLocalRationale], []);
3269
+ if (current.status !== "running") {
3270
+ throw new ReducerError("illegal-transition", `succeed ${current.status}`);
3275
3271
  }
3276
- if (frontierAvailable(input, frontier)) {
3277
- return decision(frontier, "frontier", [...options.baseRationale, fallbackReason, "no-local-available-frontier"], []);
3278
- }
3279
- return decision(primary, "local", [...options.baseRationale, fallbackReason, "frontier-unavailable"], []);
3280
- }
3281
- function resolveFrontierPrimary(input, frontier, rationale) {
3282
- if (frontierAvailable(input, frontier)) {
3283
- return decision(frontier, "frontier", rationale, []);
3284
- }
3285
- const nextLocal = availableLocalFallbacks(input, frontier)[0];
3286
- if (nextLocal !== undefined) {
3287
- return decision(nextLocal, "local", [...rationale, "frontier-unavailable-fallback"], buildFallbackChain(input, nextLocal, frontier, false));
3272
+ if (current.operationID !== event.operationID || current.attemptID !== event.attemptID) {
3273
+ throw new ReducerError("receipt-conflict", event.nodeID);
3288
3274
  }
3289
- return decision(frontier, "frontier", [...rationale, "frontier-unavailable"], []);
3290
- }
3291
- function tierForInput(input) {
3292
- return input.tier ?? classifyHeuristic(input.task).tier;
3293
- }
3294
- function finalizeDecision(input, tier, frontier, budgetAction, core) {
3295
- const selectedCostUSD = estimatedCostUSD(input, core.selected);
3296
- const baselineCostUSD = estimatedCostUSD(input, frontier.model);
3297
- const savingsUSD = core.routeKind === "frontier" && sameModel(core.selected, frontier.model) ? 0 : baselineCostUSD - selectedCostUSD;
3298
- return {
3299
- ...core,
3300
- tier,
3301
- rationale: [...frontier.rationale, ...core.rationale],
3302
- estimatedCostUSD: roundUSD(selectedCostUSD),
3303
- baselineCostUSD: roundUSD(baselineCostUSD),
3304
- estimatedSavingsUSD: roundUSD(savingsUSD),
3305
- budgetAction
3306
- };
3275
+ return withNode({ ...state, seq: event.seq }, event.nodeID, {
3276
+ status: "succeeded",
3277
+ attempts: current.attempts,
3278
+ operationID: event.operationID,
3279
+ attemptID: event.attemptID,
3280
+ artifactSha256: event.artifact.sha256
3281
+ });
3307
3282
  }
3308
- function chooseModel(input) {
3309
- const tier = tierForInput(input);
3310
- const local = localDefault(input.config);
3311
- const frontier = resolveFrontierBaseline(input, tier);
3312
- const frontierCostUSD = estimatedCostUSD(input, frontier.model);
3313
- const budgetAction = input.budgetState === undefined ? { action: "ok" } : evaluateBudget(input.budgetState, frontierCostUSD, input.config.budgets);
3314
- const override = input.task.explicitOverride;
3315
- if (input.task.privacySensitive === true && input.config.privacyMode === "forceLocalOnSensitive") {
3316
- return finalizeDecision(input, tier, frontier, budgetAction, resolveLocalPrimary(input, local, frontier.model, {
3317
- baseRationale: ["privacy-force-local"],
3318
- allowFrontier: false,
3319
- noLocalRationale: "privacy-force-local-unavailable"
3320
- }));
3283
+ function applyFailed(state, event) {
3284
+ const current = state.nodes[event.nodeID];
3285
+ if (current === undefined) {
3286
+ throw new ReducerError("unknown-node", event.nodeID);
3321
3287
  }
3322
- if (budgetAction.action === "forceLocal" || budgetAction.action === "blockFrontier") {
3323
- return finalizeDecision(input, tier, frontier, budgetAction, resolveLocalPrimary(input, local, frontier.model, {
3324
- baseRationale: [`budget-${budgetAction.action}`],
3325
- allowFrontier: false,
3326
- noLocalRationale: "budget-local-unavailable"
3327
- }));
3288
+ if (current.status === "failed") {
3289
+ if (current.operationID === event.operationID && current.attemptID === event.attemptID) {
3290
+ return state;
3291
+ }
3292
+ throw new ReducerError("receipt-conflict", event.nodeID);
3328
3293
  }
3329
- if (typeof override === "object") {
3330
- return finalizeDecision(input, tier, frontier, budgetAction, decision(override, inferRouteKind(input.config, override, listedModel(input, override)), ["explicit-model-override"], buildFallbackChain(input, override, frontier.model, true)));
3294
+ if (current.status !== "running") {
3295
+ throw new ReducerError("illegal-transition", `fail ${current.status}`);
3331
3296
  }
3332
- if (override === "alwaysLocal") {
3333
- return finalizeDecision(input, tier, frontier, budgetAction, resolveLocalPrimary(input, local, frontier.model, {
3334
- baseRationale: ["explicit-always-local"],
3335
- allowFrontier: false,
3336
- noLocalRationale: "forced-local-unavailable"
3337
- }));
3297
+ if (current.operationID !== event.operationID || current.attemptID !== event.attemptID) {
3298
+ throw new ReducerError("receipt-conflict", event.nodeID);
3338
3299
  }
3339
- if (override === "alwaysFrontier") {
3340
- return finalizeDecision(input, tier, frontier, budgetAction, decision(frontier.model, "frontier", ["explicit-always-frontier"], []));
3300
+ return withNode({ ...state, seq: event.seq }, event.nodeID, {
3301
+ status: "failed",
3302
+ attempts: current.attempts,
3303
+ operationID: event.operationID,
3304
+ attemptID: event.attemptID
3305
+ });
3306
+ }
3307
+ function applyCancelled(state, event) {
3308
+ const current = state.nodes[event.nodeID];
3309
+ if (current === undefined) {
3310
+ throw new ReducerError("unknown-node", event.nodeID);
3341
3311
  }
3342
- if (input.config.router.frontierOnly) {
3343
- return finalizeDecision(input, tier, frontier, budgetAction, decision(frontier.model, "frontier", ["router-frontier-only"], []));
3312
+ if (current.status === "cancelled") {
3313
+ return state;
3344
3314
  }
3345
- const shortEnoughForLocal = input.task.promptChars <= input.config.router.trivialPromptMaxChars;
3346
- const largeEnoughForFrontier = input.task.promptChars >= input.config.router.frontierPromptMinChars;
3347
- if (!input.task.hasCode && shortEnoughForLocal && !largeEnoughForFrontier) {
3348
- return finalizeDecision(input, tier, frontier, budgetAction, resolveLocalPrimary(input, local, frontier.model, {
3349
- baseRationale: ["trivial-short-no-code"],
3350
- allowFrontier: true,
3351
- noLocalRationale: "forced-local-unavailable"
3352
- }));
3315
+ if (current.status === "succeeded") {
3316
+ throw new ReducerError("illegal-transition", "cancel succeeded");
3353
3317
  }
3354
- return finalizeDecision(input, tier, frontier, budgetAction, resolveFrontierPrimary(input, frontier.model, [
3355
- input.task.hasCode ? "code-detected" : "large-or-nontrivial-prompt"
3356
- ]));
3357
- }
3358
-
3359
- // src/telemetry/cost.ts
3360
- function routeKind(decision2) {
3361
- return decision2.routeKind === "local" ? "local" : "frontier";
3318
+ return withNode({ ...state, seq: event.seq }, event.nodeID, {
3319
+ ...current,
3320
+ status: "cancelled"
3321
+ });
3362
3322
  }
3363
- function budgetAction(decision2) {
3364
- const reason = decision2.budgetAction.reason;
3365
- return reason === undefined ? decision2.budgetAction.action : `${decision2.budgetAction.action}:${reason}`;
3323
+ function applyRunCompleted(state, seq) {
3324
+ for (const node of Object.values(state.nodes)) {
3325
+ if (node.status !== "succeeded" && node.status !== "cancelled") {
3326
+ throw new ReducerError("incomplete-run", node.status);
3327
+ }
3328
+ }
3329
+ return { ...state, status: "completed", seq };
3366
3330
  }
3367
- function toCostRecord(decision2, context) {
3368
- const record = {
3369
- ts: context.ts,
3370
- promptHash: context.promptHash,
3371
- promptChars: context.promptChars,
3372
- tier: decision2.tier,
3373
- routeKind: routeKind(decision2),
3374
- selected: decision2.selected,
3375
- rationale: decision2.rationale.join(","),
3376
- estimatedCostUSD: decision2.estimatedCostUSD,
3377
- baselineCostUSD: decision2.baselineCostUSD,
3378
- estimatedSavingsUSD: decision2.estimatedSavingsUSD,
3379
- budgetAction: budgetAction(decision2)
3380
- };
3381
- if (context.sessionID !== undefined) {
3382
- record.sessionID = context.sessionID;
3331
+ function applyEvent(spec, state, event) {
3332
+ if (event.runID !== state.runID) {
3333
+ throw new ReducerError("run-mismatch", event.runID);
3383
3334
  }
3384
- if (context.tokensIn !== undefined) {
3385
- record.tokensIn = context.tokensIn;
3335
+ if (TERMINAL_RUN_STATUSES.has(state.status)) {
3336
+ if (event.type === "run.completed" && state.status === "completed" || event.type === "run.failed" && state.status === "failed" || event.type === "run.cancelled" && state.status === "cancelled") {
3337
+ return state;
3338
+ }
3339
+ throw new ReducerError("post-terminal", event.type);
3386
3340
  }
3387
- if (context.tokensOut !== undefined) {
3388
- record.tokensOut = context.tokensOut;
3341
+ switch (event.type) {
3342
+ case "run.started":
3343
+ return applyRunStarted(state, event.seq, event.specDigest);
3344
+ case "node.dispatched":
3345
+ return applyDispatched(spec, state, event);
3346
+ case "node.succeeded":
3347
+ return applySucceeded(state, event);
3348
+ case "node.failed":
3349
+ return applyFailed(state, event);
3350
+ case "node.cancelled":
3351
+ return applyCancelled(state, event);
3352
+ case "run.completed":
3353
+ return applyRunCompleted(state, event.seq);
3354
+ case "run.failed":
3355
+ return { ...state, status: "failed", seq: event.seq };
3356
+ case "run.cancelled":
3357
+ return { ...state, status: "cancelled", seq: event.seq };
3389
3358
  }
3390
- return record;
3391
3359
  }
3392
3360
 
3393
- // src/telemetry/types.ts
3394
- import { z as z8 } from "zod";
3395
- var CostRecordSchema = z8.object({
3396
- ts: z8.number().finite(),
3397
- sessionID: z8.string().min(1).optional(),
3398
- promptHash: z8.string().min(1),
3399
- promptChars: z8.number().int().min(0),
3400
- tier: ComplexityTierSchema,
3401
- routeKind: z8.enum(["local", "frontier"]),
3402
- selected: ModelRefSchema,
3403
- rationale: z8.string(),
3404
- estimatedCostUSD: z8.number().finite().min(0),
3405
- baselineCostUSD: z8.number().finite().min(0),
3406
- estimatedSavingsUSD: z8.number().finite(),
3407
- budgetAction: z8.string().min(1),
3408
- tokensIn: z8.number().int().min(0).optional(),
3409
- tokensOut: z8.number().int().min(0).optional()
3410
- });
3411
-
3412
- // src/telemetry/read.ts
3413
- var DEFAULT_TELEMETRY_PATH = ".opencode/openteam-telemetry.jsonl";
3414
- function parseCostRecordsJsonl(text) {
3415
- const records = [];
3416
- for (const line of text.split(`
3417
- `)) {
3418
- const trimmed = line.trim();
3419
- if (trimmed.length === 0) {
3420
- continue;
3421
- }
3422
- let candidate;
3423
- try {
3424
- candidate = JSON.parse(trimmed);
3425
- } catch {
3426
- continue;
3427
- }
3428
- const parsed = CostRecordSchema.safeParse(candidate);
3429
- if (parsed.success) {
3430
- records.push(parsed.data);
3431
- }
3361
+ // src/orchestrator/graphShadow.ts
3362
+ class ShadowMirrorError extends Error {
3363
+ code;
3364
+ detail;
3365
+ constructor(code, detail) {
3366
+ super(`${code}: ${detail}`);
3367
+ this.name = "ShadowMirrorError";
3368
+ this.code = code;
3369
+ this.detail = detail;
3432
3370
  }
3433
- return records;
3434
3371
  }
3435
-
3436
- // src/telemetry/eventLog.ts
3437
- var DEFAULT_SESSIONS_DIR = ".opencode/openteam/sessions";
3438
- var LEGACY_SESSION_ID = "legacy";
3439
- function sessionFileName(sessionID) {
3440
- const safe = sessionID.replace(/[^A-Za-z0-9._-]/g, "_");
3441
- return `${safe}.jsonl`;
3372
+ function traceAnchorDigest(trace) {
3373
+ return sha256Hex(JSON.stringify({
3374
+ version: trace.version,
3375
+ runID: trace.runID,
3376
+ nodes: trace.nodes.map((node) => [node.id, node.role])
3377
+ }));
3442
3378
  }
3443
- function createEventLogSink(deps) {
3444
- return {
3445
- emit: async (event) => {
3446
- try {
3447
- const parsed = OpenTeamEventSchema.parse(event);
3448
- const path = joinVirtualPath(deps.dir, sessionFileName(parsed.sessionID));
3449
- await deps.storage.append(path, `${JSON.stringify(parsed)}
3450
- `);
3451
- } catch (error) {
3452
- deps.onError?.(error);
3453
- }
3379
+ function compileShadowSpec(trace) {
3380
+ const anchor = { taskID: trace.runID, specDigest: traceAnchorDigest(trace) };
3381
+ const nodes = [];
3382
+ let previousID;
3383
+ let lastImplementerID;
3384
+ for (const node of trace.nodes) {
3385
+ const dependsOn = previousID === undefined ? [] : [previousID];
3386
+ if (node.role === "implementer") {
3387
+ nodes.push({ id: node.id, role: "implementer", dependsOn, anchor });
3388
+ lastImplementerID = node.id;
3389
+ } else {
3390
+ nodes.push({
3391
+ id: node.id,
3392
+ role: "reviewer",
3393
+ dependsOn,
3394
+ anchor,
3395
+ ...lastImplementerID === undefined ? {} : { reviews: lastImplementerID }
3396
+ });
3454
3397
  }
3455
- };
3456
- }
3457
- function createNullEventSink() {
3458
- return { emit: () => {} };
3459
- }
3460
- function parseEventsJsonl(text) {
3461
- const events = [];
3462
- for (const line of text.split(`
3463
- `)) {
3464
- const trimmed = line.trim();
3465
- if (trimmed.length === 0) {
3466
- continue;
3398
+ previousID = node.id;
3399
+ }
3400
+ let spec;
3401
+ try {
3402
+ spec = GraphSpecV1Schema.parse({ version: 1, runID: trace.runID, nodes });
3403
+ validateGraphSpec(spec);
3404
+ } catch (error) {
3405
+ throw new ShadowMirrorError("invalid-spec", error instanceof Error ? error.message : String(error));
3406
+ }
3407
+ assertReferenceOnly(spec);
3408
+ return spec;
3409
+ }
3410
+ var TERMINAL_EVENT = {
3411
+ completed: "run.completed",
3412
+ failed: "run.failed",
3413
+ cancelled: "run.cancelled"
3414
+ };
3415
+ function shadowArtifact(runID, nodeID) {
3416
+ return {
3417
+ uri: `shadow://${runID}/${nodeID}`,
3418
+ sha256: sha256Hex(`shadow-artifact\x00${runID}\x00${nodeID}`),
3419
+ bytes: 0
3420
+ };
3421
+ }
3422
+ function mirrorJournal(spec, trace) {
3423
+ const runID = trace.runID;
3424
+ const events = [
3425
+ {
3426
+ v: 1,
3427
+ seq: 0,
3428
+ runID,
3429
+ type: "run.started",
3430
+ specDigest: graphSpecDigest(spec)
3467
3431
  }
3468
- let candidate;
3469
- try {
3470
- candidate = JSON.parse(trimmed);
3471
- } catch {
3432
+ ];
3433
+ for (const node of trace.nodes) {
3434
+ const operation = operationID(runID, node.id);
3435
+ const attempt = attemptID(operation, 0);
3436
+ events.push({
3437
+ v: 1,
3438
+ seq: events.length,
3439
+ runID,
3440
+ type: "node.dispatched",
3441
+ nodeID: node.id,
3442
+ operationID: operation,
3443
+ attemptID: attempt
3444
+ });
3445
+ if (node.errorClass === undefined) {
3446
+ events.push({
3447
+ v: 1,
3448
+ seq: events.length,
3449
+ runID,
3450
+ type: "node.succeeded",
3451
+ nodeID: node.id,
3452
+ operationID: operation,
3453
+ attemptID: attempt,
3454
+ artifact: shadowArtifact(runID, node.id)
3455
+ });
3472
3456
  continue;
3473
3457
  }
3474
- const parsed = OpenTeamEventSchema.safeParse(candidate);
3475
- if (parsed.success) {
3476
- events.push(parsed.data);
3458
+ if (node.errorClass === "cancelled") {
3459
+ events.push({
3460
+ v: 1,
3461
+ seq: events.length,
3462
+ runID,
3463
+ type: "node.cancelled",
3464
+ nodeID: node.id
3465
+ });
3466
+ continue;
3477
3467
  }
3468
+ events.push({
3469
+ v: 1,
3470
+ seq: events.length,
3471
+ runID,
3472
+ type: "node.failed",
3473
+ nodeID: node.id,
3474
+ operationID: operation,
3475
+ attemptID: attempt,
3476
+ errorClass: node.errorClass
3477
+ });
3478
3478
  }
3479
+ events.push({
3480
+ v: 1,
3481
+ seq: events.length,
3482
+ runID,
3483
+ type: TERMINAL_EVENT[trace.status]
3484
+ });
3479
3485
  return events;
3480
3486
  }
3481
- function costRecordToRouteEvent(record) {
3482
- const event = {
3483
- v: EVENT_SCHEMA_VERSION,
3484
- type: "route",
3485
- ts: record.ts,
3486
- sessionID: record.sessionID ?? LEGACY_SESSION_ID,
3487
- promptHash: record.promptHash,
3488
- promptChars: record.promptChars,
3489
- tier: record.tier,
3490
- routeKind: record.routeKind,
3491
- selected: record.selected,
3492
- rationale: record.rationale,
3493
- estimatedCostUSD: record.estimatedCostUSD,
3494
- baselineCostUSD: record.baselineCostUSD,
3495
- estimatedSavingsUSD: record.estimatedSavingsUSD,
3496
- budgetAction: record.budgetAction
3497
- };
3498
- if (record.tokensIn !== undefined) {
3499
- event.tokensIn = record.tokensIn;
3500
- }
3501
- if (record.tokensOut !== undefined) {
3502
- event.tokensOut = record.tokensOut;
3487
+ function reduceMirror(spec, journal) {
3488
+ let state = initialState(spec);
3489
+ try {
3490
+ for (const event of journal) {
3491
+ state = applyEvent(spec, state, event);
3492
+ }
3493
+ } catch (error) {
3494
+ throw new ShadowMirrorError("illegal-sequence", error instanceof ReducerError ? `${error.code}: ${error.detail}` : String(error));
3503
3495
  }
3504
- return event;
3496
+ return state;
3505
3497
  }
3506
- function routeEventToCostRecord(event) {
3507
- const record = {
3508
- ts: event.ts,
3509
- sessionID: event.sessionID,
3510
- promptHash: event.promptHash,
3511
- promptChars: event.promptChars,
3512
- tier: event.tier,
3513
- routeKind: event.routeKind,
3514
- selected: event.selected,
3515
- rationale: event.rationale,
3516
- estimatedCostUSD: event.estimatedCostUSD,
3517
- baselineCostUSD: event.baselineCostUSD,
3518
- estimatedSavingsUSD: event.estimatedSavingsUSD,
3519
- budgetAction: event.budgetAction
3498
+ function projectLegacySummary(trace) {
3499
+ return {
3500
+ runID: trace.runID,
3501
+ status: trace.status,
3502
+ outcome: trace.outcome,
3503
+ fixes: trace.fixes,
3504
+ nodes: trace.nodes.map((node) => ({
3505
+ id: node.id,
3506
+ role: node.role,
3507
+ model: node.model
3508
+ }))
3520
3509
  };
3521
- if (event.tokensIn !== undefined) {
3522
- record.tokensIn = event.tokensIn;
3523
- }
3524
- if (event.tokensOut !== undefined) {
3525
- record.tokensOut = event.tokensOut;
3526
- }
3527
- return record;
3528
3510
  }
3529
- async function readRouteCostRecords(dir, deps) {
3530
- const events = await readSessionEvents(dir, deps);
3531
- const records = [];
3532
- for (const event of events) {
3533
- if (event.type === "route") {
3534
- records.push(routeEventToCostRecord(event));
3535
- }
3536
- }
3537
- return records;
3511
+ function projectShadowSummary(spec, trace) {
3512
+ const implementers = spec.nodes.filter((node) => node.role === "implementer").length;
3513
+ return {
3514
+ runID: spec.runID,
3515
+ status: trace.status,
3516
+ outcome: trace.outcome,
3517
+ fixes: implementers - 1,
3518
+ nodes: spec.nodes.map((node, index) => ({
3519
+ id: node.id,
3520
+ role: node.role,
3521
+ model: trace.nodes[index].model
3522
+ }))
3523
+ };
3538
3524
  }
3539
- async function readSessionEvents(dir, deps) {
3540
- const files = (await deps.storage.list(dir)).filter((file) => file.endsWith(".jsonl"));
3541
- const perFile = await Promise.all(files.map(async (file) => {
3542
- const text = await deps.storage.read(joinVirtualPath(dir, file));
3543
- return text === undefined ? [] : parseEventsJsonl(text);
3544
- }));
3545
- const events = perFile.flat();
3546
- if (deps.legacyTelemetryPath !== undefined) {
3547
- const legacyText = await deps.storage.read(deps.legacyTelemetryPath);
3548
- if (legacyText !== undefined) {
3549
- for (const record of parseCostRecordsJsonl(legacyText)) {
3550
- events.push(costRecordToRouteEvent(record));
3551
- }
3525
+ function mirrorLegacyExecution(trace) {
3526
+ const spec = compileShadowSpec(trace);
3527
+ const journal = mirrorJournal(spec, trace);
3528
+ const state = reduceMirror(spec, journal);
3529
+ const summary = projectShadowSummary(spec, trace);
3530
+ assertReferenceOnly(summary);
3531
+ return {
3532
+ spec,
3533
+ specDigest: graphSpecDigest(spec),
3534
+ journal,
3535
+ state,
3536
+ summary
3537
+ };
3538
+ }
3539
+
3540
+ // src/orchestrator/graphFacade.ts
3541
+ function mirrorLegacyTrace(trace) {
3542
+ try {
3543
+ return {
3544
+ ok: true,
3545
+ mirror: mirrorLegacyExecution(parseLegacyExecutionTrace(trace))
3546
+ };
3547
+ } catch (error) {
3548
+ if (error instanceof ShadowMirrorError) {
3549
+ return { ok: false, code: error.code, detail: error.detail };
3550
+ }
3551
+ if (error instanceof LegacyTraceError) {
3552
+ return {
3553
+ ok: false,
3554
+ code: "invalid-trace",
3555
+ detail: error.issues.join("; ")
3556
+ };
3552
3557
  }
3558
+ return {
3559
+ ok: false,
3560
+ code: "mirror-error",
3561
+ detail: error instanceof Error ? error.message : String(error)
3562
+ };
3553
3563
  }
3554
- return events.sort((a, b) => a.ts - b.ts);
3555
3564
  }
3556
3565
 
3557
- // src/telemetry/hash.ts
3558
- var FNV_OFFSET_BASIS = 2166136261;
3559
- var FNV_PRIME = 16777619;
3560
- function hashPrompt(prompt) {
3561
- let hash = FNV_OFFSET_BASIS;
3562
- for (let index = 0;index < prompt.length; index += 1) {
3563
- hash ^= prompt.charCodeAt(index);
3564
- hash = Math.imul(hash, FNV_PRIME);
3566
+ // src/orchestrator/shadowComparator.ts
3567
+ function sequenceEqual(a, b) {
3568
+ if (a.length !== b.length) {
3569
+ return false;
3565
3570
  }
3566
- return `fnv1a32:${(hash >>> 0).toString(16).padStart(8, "0")}`;
3571
+ return a.every((value, index) => value === b[index]);
3567
3572
  }
3568
-
3569
- // src/orchestrator/graphIngress.ts
3570
- var ACTIVE_INGRESS_BRAND = Symbol("openteam.activeIngress");
3571
- function gateReason(policy) {
3572
- if (policy.capability === undefined) {
3573
- return "gate-closed";
3573
+ function compareShadowRun(legacy, shadow) {
3574
+ if (legacy === undefined || shadow === undefined) {
3575
+ return { verdict: "inconclusive", divergences: [] };
3574
3576
  }
3575
- if (policy.graph.killSwitch) {
3576
- return "kill-switch";
3577
+ const divergences = [];
3578
+ if (legacy.status !== shadow.status) {
3579
+ divergences.push("status");
3577
3580
  }
3578
- return policy.graph.configuredMode === "active" ? undefined : "graph-disabled";
3579
- }
3580
- function decideIngress(policy, taskID) {
3581
- const blocked = gateReason(policy);
3582
- if (blocked !== undefined) {
3583
- return { route: "legacy", reason: blocked };
3581
+ if (!sequenceEqual(legacy.nodes.map((node) => node.id), shadow.nodes.map((node) => node.id))) {
3582
+ divergences.push("order");
3584
3583
  }
3585
- if (!policy.allowList.includes(taskID)) {
3586
- return { route: "legacy", reason: "not-allow-listed" };
3584
+ if (!sequenceEqual(legacy.nodes.map((node) => node.role), shadow.nodes.map((node) => node.role))) {
3585
+ divergences.push("roles");
3586
+ }
3587
+ if (!sequenceEqual(legacy.nodes.map((node) => node.model), shadow.nodes.map((node) => node.model))) {
3588
+ divergences.push("models");
3589
+ }
3590
+ if (legacy.fixes !== shadow.fixes) {
3591
+ divergences.push("fixes");
3592
+ }
3593
+ if (legacy.outcome !== shadow.outcome) {
3594
+ divergences.push("outcome");
3587
3595
  }
3588
- return { route: "graph", taskID };
3589
- }
3590
-
3591
- // src/plugin/legacyRunProducer.ts
3592
- function toObservedNode(node) {
3593
- return {
3594
- id: node.id,
3595
- role: node.role,
3596
- model: node.model,
3597
- ok: node.ok,
3598
- ...node.sessionRef !== undefined ? { sessionRef: node.sessionRef } : {},
3599
- ...node.errorClass !== undefined ? { errorClass: node.errorClass } : {}
3600
- };
3601
- }
3602
- function buildObservedRun(payload) {
3603
3596
  return {
3604
- runID: payload.runID,
3605
- executed: true,
3606
- status: payload.status,
3607
- fixes: payload.fixes,
3608
- nodes: payload.nodes.map(toObservedNode),
3609
- ...payload.parentSessionRef !== undefined ? { parentSessionRef: payload.parentSessionRef } : {}
3597
+ verdict: divergences.length === 0 ? "match" : "divergent",
3598
+ divergences
3610
3599
  };
3611
3600
  }
3612
- function crossVerify(payload, tracker) {
3613
- const unverifiedModels = [];
3614
- const modelMismatches = [];
3615
- const unknownSessions = [];
3616
- for (const node of payload.nodes) {
3617
- if (node.sessionRef !== undefined) {
3618
- const mv = tracker.verifyModel(node.sessionRef, node.model);
3619
- if (!mv.verified) {
3620
- unverifiedModels.push(node.id);
3621
- } else if (!mv.match) {
3622
- modelMismatches.push(node.id);
3623
- }
3624
- const sv = tracker.verifySessionRef(node.sessionRef);
3625
- if (sv.known === false) {
3626
- unknownSessions.push(node.id);
3627
- }
3628
- } else {
3629
- unverifiedModels.push(node.id);
3601
+
3602
+ // src/storage/graph/soakRecorder.ts
3603
+ async function ensureRecorderId(ports, basePath) {
3604
+ const idPath = `${basePath}/soak-recorder-id`;
3605
+ if (await ports.fs.exists(idPath)) {
3606
+ const id = (await ports.fs.readFile(idPath)).trim();
3607
+ if (/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/.test(id)) {
3608
+ return id;
3630
3609
  }
3631
3610
  }
3632
- return { unverifiedModels, modelMismatches, unknownSessions };
3611
+ const newId = ports.id.randomUUID();
3612
+ await ports.fs.writeFile(idPath, newId);
3613
+ return newId;
3633
3614
  }
3634
- function formatWarnings(verification) {
3635
- const warnings = [];
3636
- if (verification.unverifiedModels.length > 0) {
3637
- warnings.push(`model not verifiable for nodes: ${verification.unverifiedModels.join(", ")}`);
3638
- }
3639
- if (verification.modelMismatches.length > 0) {
3640
- warnings.push(`model mismatch for nodes: ${verification.modelMismatches.join(", ")}`);
3615
+ async function readAllChains(ports, evidenceDir) {
3616
+ if (!await ports.fs.exists(evidenceDir)) {
3617
+ return [];
3641
3618
  }
3642
- if (verification.unknownSessions.length > 0) {
3643
- warnings.push(`unknown sessionRef for nodes: ${verification.unknownSessions.join(", ")}`);
3619
+ const files = await ports.fs.readDir(evidenceDir);
3620
+ const chains = [];
3621
+ for (const file of files) {
3622
+ if (!file.endsWith(".jsonl")) {
3623
+ continue;
3624
+ }
3625
+ const content = await ports.fs.readFile(`${evidenceDir}/${file}`);
3626
+ const lines = content.split(`
3627
+ `).filter((l) => l.trim().length > 0);
3628
+ const observations = [];
3629
+ for (const line of lines) {
3630
+ const parsed = SoakObservationSchema.safeParse(JSON.parse(line));
3631
+ if (parsed.success) {
3632
+ observations.push(parsed.data);
3633
+ }
3634
+ }
3635
+ if (observations.length > 0) {
3636
+ chains.push(observations);
3637
+ }
3644
3638
  }
3645
- return warnings;
3639
+ return chains;
3646
3640
  }
3647
- function formatResponse(response) {
3648
- const parts = [`report-run: ${response.result}`];
3649
- if (response.detail !== undefined) {
3650
- parts.push(response.detail);
3641
+ function canonicalObservationPreimage2(obs) {
3642
+ return JSON.stringify({
3643
+ version: obs.version,
3644
+ seq: obs.seq,
3645
+ timestamp: obs.timestamp,
3646
+ platform: obs.platform,
3647
+ opencodeVersion: obs.opencodeVersion,
3648
+ provenance: obs.provenance,
3649
+ traceDigest: obs.traceDigest,
3650
+ criticalDivergences: obs.criticalDivergences,
3651
+ privacy: obs.privacy,
3652
+ duplicateEffects: obs.duplicateEffects,
3653
+ modelVerification: obs.modelVerification
3654
+ });
3655
+ }
3656
+ async function appendObservation(ports, evidenceDir, recorderId, input) {
3657
+ await ports.fs.mkdir(evidenceDir);
3658
+ const chainPath = `${evidenceDir}/${recorderId}.jsonl`;
3659
+ let seq = 0;
3660
+ let prevChainDigest = "0".repeat(64);
3661
+ if (await ports.fs.exists(chainPath)) {
3662
+ const content = await ports.fs.readFile(chainPath);
3663
+ const lines = content.split(`
3664
+ `).filter((l) => l.trim().length > 0);
3665
+ if (lines.length > 0) {
3666
+ const lastLine = lines[lines.length - 1];
3667
+ let rawParsed;
3668
+ try {
3669
+ rawParsed = JSON.parse(lastLine);
3670
+ } catch {
3671
+ throw new Error("corrupt chain tail: invalid JSON");
3672
+ }
3673
+ const parsed = SoakObservationSchema.safeParse(rawParsed);
3674
+ if (!parsed.success) {
3675
+ const detail = parsed.error.issues.map((i) => `${i.path.join(".")}: ${i.code}`).join("; ");
3676
+ throw new Error(`corrupt chain tail: ${detail}`);
3677
+ }
3678
+ seq = parsed.data.seq + 1;
3679
+ prevChainDigest = parsed.data.chainDigest;
3680
+ }
3651
3681
  }
3652
- if (response.warnings !== undefined && response.warnings.length > 0) {
3653
- parts.push(`warnings: ${response.warnings.join("; ")}`);
3682
+ const timestamp = ports.clock.now();
3683
+ const base = {
3684
+ version: 1,
3685
+ seq,
3686
+ timestamp,
3687
+ platform: input.platform,
3688
+ opencodeVersion: input.opencodeVersion,
3689
+ provenance: input.provenance,
3690
+ traceDigest: input.traceDigest,
3691
+ criticalDivergences: input.criticalDivergences,
3692
+ privacy: input.privacy,
3693
+ duplicateEffects: input.duplicateEffects,
3694
+ modelVerification: input.modelVerification
3695
+ };
3696
+ const preimage = canonicalObservationPreimage2(base);
3697
+ const chainDigest = sha256Hex(prevChainDigest + preimage);
3698
+ const observation = { ...base, chainDigest };
3699
+ assertReferenceOnly(observation);
3700
+ const line = JSON.stringify(observation);
3701
+ if (await ports.fs.exists(chainPath)) {
3702
+ const existing = await ports.fs.readFile(chainPath);
3703
+ await ports.fs.writeFile(chainPath, `${existing}
3704
+ ${line}`);
3705
+ } else {
3706
+ await ports.fs.writeFile(chainPath, line);
3654
3707
  }
3655
- return parts.join(" — ");
3708
+ return observation;
3656
3709
  }
3657
3710
 
3658
- // src/plugin/reportRunSchema.ts
3659
- import { z as z10 } from "zod";
3660
-
3661
- // src/plugin/graphShadowIngress.ts
3662
- import { z as z9 } from "zod";
3663
- var LEGACY_EXECUTION_TRACE_VERSION = 1;
3664
- var LegacyExecutionStatusSchema = z9.enum([
3665
- "completed",
3666
- "failed",
3667
- "cancelled"
3668
- ]);
3669
- var LegacyReviewOutcomeSchema = z9.enum([
3670
- "approved",
3671
- "rejected",
3672
- "inconclusive"
3673
- ]);
3674
- var LegacyTraceNodeV1Schema = z9.object({
3675
- id: NodeIDSchema,
3676
- role: NodeRoleSchema,
3677
- model: z9.string().min(1),
3678
- sessionRef: z9.string().min(1).optional(),
3679
- errorClass: ErrorClassSchema.optional()
3680
- }).strict();
3681
- var LegacyExecutionTraceV1Schema = z9.object({
3682
- version: z9.literal(LEGACY_EXECUTION_TRACE_VERSION),
3683
- runID: NodeIDSchema,
3684
- status: LegacyExecutionStatusSchema,
3685
- outcome: LegacyReviewOutcomeSchema,
3686
- fixes: z9.number().int().nonnegative(),
3687
- nodes: z9.array(LegacyTraceNodeV1Schema).min(1),
3688
- parentSessionRef: z9.string().min(1).optional()
3689
- }).strict();
3690
- function gateReason2(gate) {
3691
- if (gate === undefined || gate.mode === "off") {
3692
- return "graph-disabled";
3693
- }
3694
- if (gate.killSwitch) {
3695
- return "kill-switch";
3696
- }
3697
- return;
3711
+ // src/plugin/soakObserver.ts
3712
+ function resolvePlatform(platform) {
3713
+ if (platform === "win32")
3714
+ return "win32";
3715
+ if (platform === "darwin")
3716
+ return "darwin";
3717
+ if (platform === "linux")
3718
+ return "linux";
3719
+ return null;
3698
3720
  }
3699
- function deriveOutcome(nodes) {
3700
- for (let index = nodes.length - 1;index >= 0; index -= 1) {
3701
- const node = nodes[index];
3702
- if (node !== undefined && node.role === "reviewer") {
3703
- return node.ok ? "approved" : "rejected";
3704
- }
3705
- }
3706
- return "inconclusive";
3721
+ function countCriticalDivergences(parity, criticalCodes) {
3722
+ if (parity === undefined)
3723
+ return null;
3724
+ if (criticalCodes.length === 0)
3725
+ return null;
3726
+ const criticalSet = new Set(criticalCodes);
3727
+ return parity.divergences.filter((code) => criticalSet.has(code)).length;
3707
3728
  }
3708
- function toTraceNode(node) {
3729
+ function scanTracePrivacy(trace) {
3730
+ const result = scanReferenceOnly([trace]);
3709
3731
  return {
3710
- id: node.id,
3711
- role: node.role,
3712
- model: node.model,
3713
- ...node.sessionRef !== undefined ? { sessionRef: node.sessionRef } : {},
3714
- ...node.errorClass !== undefined ? { errorClass: node.errorClass } : {}
3732
+ surfacesScanned: result.surfacesScanned,
3733
+ rawFindings: result.rawFindings
3715
3734
  };
3716
3735
  }
3717
- function ingestLegacyExecution(observation, gate) {
3718
- const gated = gateReason2(gate);
3719
- if (gated !== undefined) {
3720
- return { eligible: false, reason: gated };
3721
- }
3722
- if (!observation.executed) {
3723
- return { eligible: false, reason: "not-executed" };
3724
- }
3725
- if (observation.nodes.length === 0) {
3726
- return { eligible: false, reason: "no-observation" };
3736
+ function detectDuplicateEffects(trace) {
3737
+ const nodes = trace.nodes;
3738
+ if (nodes.length === 0)
3739
+ return null;
3740
+ const seen = new Set;
3741
+ let duplicates = 0;
3742
+ for (const node of nodes) {
3743
+ if (seen.has(node.id)) {
3744
+ duplicates++;
3745
+ } else {
3746
+ seen.add(node.id);
3747
+ }
3727
3748
  }
3728
- const trace = {
3729
- version: LEGACY_EXECUTION_TRACE_VERSION,
3730
- runID: observation.runID,
3731
- status: observation.status,
3732
- outcome: deriveOutcome(observation.nodes),
3733
- fixes: Math.max(0, Math.trunc(observation.fixes)),
3734
- nodes: observation.nodes.map(toTraceNode),
3735
- ...observation.parentSessionRef !== undefined ? { parentSessionRef: observation.parentSessionRef } : {}
3736
- };
3737
- assertReferenceOnly(trace);
3738
- return { eligible: true, trace };
3749
+ return { effectsExamined: nodes.length, duplicatesFound: duplicates };
3739
3750
  }
3740
-
3741
- class LegacyTraceError extends Error {
3742
- code = "invalid-legacy-trace";
3743
- issues;
3744
- constructor(error) {
3745
- super(`invalid-legacy-trace: ${error.issues.map((issue) => issue.message).join("; ")}`);
3746
- this.name = "LegacyTraceError";
3747
- this.issues = error.issues.map((issue) => issue.message);
3748
- }
3751
+ function traceToObservationInput(trace, opencodeVersion, parity, criticalCodes, modelVerification, platformOverride) {
3752
+ const platform = resolvePlatform(platformOverride ?? process.platform);
3753
+ if (platform === null)
3754
+ return null;
3755
+ const traceDigest = sha256Hex(JSON.stringify(trace));
3756
+ return {
3757
+ platform,
3758
+ opencodeVersion,
3759
+ provenance: "genuine-usage",
3760
+ traceDigest,
3761
+ criticalDivergences: countCriticalDivergences(parity, criticalCodes),
3762
+ privacy: scanTracePrivacy(trace),
3763
+ duplicateEffects: detectDuplicateEffects(trace),
3764
+ modelVerification
3765
+ };
3749
3766
  }
3750
- function parseLegacyExecutionTrace(input) {
3751
- const result = LegacyExecutionTraceV1Schema.safeParse(input);
3752
- if (!result.success) {
3753
- throw new LegacyTraceError(result.error);
3754
- }
3755
- return result.data;
3767
+ async function recordSoakObservation(ports, evidenceDir, recorderId, trace, opencodeVersion, parity, criticalCodes, modelVerification, platformOverride) {
3768
+ const input = traceToObservationInput(trace, opencodeVersion, parity, criticalCodes, modelVerification, platformOverride);
3769
+ if (input === null)
3770
+ return false;
3771
+ await appendObservation(ports, evidenceDir, recorderId, input);
3772
+ return true;
3756
3773
  }
3757
3774
 
3758
- // src/plugin/reportRunSchema.ts
3759
- var ReportRunNodeSchema = z10.object({
3760
- id: NodeIDSchema,
3761
- role: NodeRoleSchema,
3762
- model: z10.string().min(1),
3763
- ok: z10.boolean(),
3764
- sessionRef: z10.string().min(1).optional(),
3765
- errorClass: ErrorClassSchema.optional()
3766
- }).strict();
3767
- var ReportRunPayloadSchema = z10.object({
3768
- runID: NodeIDSchema,
3769
- status: LegacyExecutionStatusSchema,
3770
- fixes: z10.number().int().nonnegative(),
3771
- nodes: z10.array(ReportRunNodeSchema).min(1),
3772
- parentSessionRef: z10.string().min(1).optional()
3773
- }).strict();
3774
-
3775
- // src/graph/types.ts
3776
- var TERMINAL_NODE_STATUSES = new Set([
3777
- "succeeded",
3778
- "cancelled"
3779
- ]);
3780
- var TERMINAL_RUN_STATUSES = new Set([
3781
- "completed",
3782
- "failed",
3783
- "cancelled"
3784
- ]);
3775
+ // src/plugin/shadowPipeline.ts
3776
+ function createShadowPipeline(deps) {
3777
+ return async (observation, modelVerification) => {
3778
+ try {
3779
+ const ingested = ingestLegacyExecution(observation, deps.gate);
3780
+ if (!ingested.eligible) {
3781
+ return { kind: "ineligible", reason: ingested.reason };
3782
+ }
3783
+ const mirror = mirrorLegacyTrace(ingested.trace);
3784
+ let parity;
3785
+ if (mirror.ok) {
3786
+ const legacySummary = projectLegacySummary(ingested.trace);
3787
+ const report = compareShadowRun(legacySummary, mirror.mirror.summary);
3788
+ parity = { divergences: [...report.divergences] };
3789
+ }
3790
+ const recorded = await recordSoakObservation(deps.ports, deps.evidenceDir, deps.recorderId, ingested.trace, deps.opencodeVersion, parity, deps.criticalCodes, modelVerification ?? null, deps.platformOverride);
3791
+ if (!recorded) {
3792
+ return {
3793
+ kind: "observation-rejected",
3794
+ reason: "unrecognized-platform"
3795
+ };
3796
+ }
3797
+ return { kind: "observed" };
3798
+ } catch (error) {
3799
+ return {
3800
+ kind: "contained-failure",
3801
+ detail: error instanceof Error ? error.message : String(error)
3802
+ };
3803
+ }
3804
+ };
3805
+ }
3785
3806
 
3786
- // src/graph/reducer.ts
3787
- class ReducerError extends Error {
3788
- code;
3789
- detail;
3790
- constructor(code, detail) {
3791
- super(`${code}: ${detail}`);
3792
- this.name = "ReducerError";
3793
- this.code = code;
3794
- this.detail = detail;
3807
+ // src/plugin/graphTool.ts
3808
+ function describeDecision(decision) {
3809
+ if (decision.route === "graph") {
3810
+ return `graph: la tarea ${decision.taskID} se enrutaría al runtime activo.`;
3795
3811
  }
3796
- }
3797
- function initialState(spec) {
3798
- const nodes = {};
3799
- for (const node of spec.nodes) {
3800
- nodes[node.id] = { status: "pending", attempts: 0 };
3812
+ switch (decision.reason) {
3813
+ case "gate-closed":
3814
+ return "legacy: gate-closed — el ingress activo no es alcanzable por configuración en esta versión.";
3815
+ case "kill-switch":
3816
+ return "legacy: kill-switch apagado de emergencia activo.";
3817
+ case "graph-disabled":
3818
+ return "legacy: graph-disabled — graph.mode no es 'active'.";
3819
+ case "not-allow-listed":
3820
+ return "legacy: not-allow-listed — la tarea no está en la allow-list del ingress.";
3801
3821
  }
3802
- return { runID: spec.runID, status: "running", seq: -1, nodes };
3803
3822
  }
3804
- function withNode(state, nodeID, next) {
3805
- return {
3806
- ...state,
3807
- nodes: { ...state.nodes, [nodeID]: next },
3808
- seq: state.seq
3809
- };
3823
+ function describeOutcome(outcome) {
3824
+ switch (outcome.kind) {
3825
+ case "legacy":
3826
+ return describeDecision({ route: "legacy", reason: outcome.reason });
3827
+ case "accepted":
3828
+ return `accepted: run ${outcome.runID}, paso ${outcome.step.kind}.`;
3829
+ case "revision":
3830
+ return `revision: run ${outcome.runID}, plan ${outcome.plan.kind}.`;
3831
+ case "reassigned":
3832
+ return `reassigned: run ${outcome.runID}, reviewer ${outcome.reviewerID}.`;
3833
+ case "cancelled":
3834
+ return `cancelled: run ${outcome.runID}, ${outcome.cancelledNodeIDs.length} nodo(s) cancelado(s).`;
3835
+ case "error":
3836
+ return `error: ${outcome.code}.`;
3837
+ }
3810
3838
  }
3811
- function specNode(spec, nodeID) {
3812
- return spec.nodes.find((node) => node.id === nodeID);
3839
+ function unavailableReason(deps, taskID) {
3840
+ const decision = decideIngress(deps.policy, taskID);
3841
+ return decision.route === "legacy" ? describeDecision(decision) : "unavailable: el ejecutor de efectos del runtime activo no está enchufado.";
3813
3842
  }
3814
- function applyRunStarted(state, seq, specDigest) {
3815
- if (state.specDigest !== undefined) {
3816
- if (state.specDigest === specDigest) {
3817
- return state;
3843
+ function createGraphTool(deps) {
3844
+ const observe = deps.shadow !== undefined ? createShadowPipeline(deps.shadow) : async () => ({
3845
+ kind: "ineligible",
3846
+ reason: "shadow-not-configured"
3847
+ });
3848
+ const definition = tool2({
3849
+ description: "Ingress activo de SDD de openteam (GE-050). En esta versión la puerta interna está cerrada: informa del estado de enrutado y no ejecuta runs. La acción report-run registra una observación shadow de la ejecución legacy.",
3850
+ args: {
3851
+ action: tool2.schema.enum(["status", "start", "cancel", "report-run"]).describe("Acción a ejecutar"),
3852
+ taskID: tool2.schema.string().optional().describe("Identificador de la tarea SDD"),
3853
+ runID: tool2.schema.string().optional().describe("Identificador del run (para action=cancel o report-run)"),
3854
+ status: tool2.schema.enum(["completed", "failed", "cancelled"]).optional().describe("Estado terminal del run (solo action=report-run)"),
3855
+ fixes: tool2.schema.number().optional().describe("Número de iteraciones de fix (solo action=report-run)"),
3856
+ nodes: tool2.schema.array(tool2.schema.object({
3857
+ id: tool2.schema.string().describe("ID del nodo"),
3858
+ role: tool2.schema.enum(["implementer", "reviewer"]).describe("Rol del nodo"),
3859
+ model: tool2.schema.string().describe("Modelo utilizado por el nodo"),
3860
+ ok: tool2.schema.boolean().describe("Éxito terminal del nodo"),
3861
+ sessionRef: tool2.schema.string().optional().describe("ID de sesión de opencode del nodo"),
3862
+ errorClass: tool2.schema.enum(["transient", "permanent", "exhausted"]).optional().describe("Clase de error si el nodo falló")
3863
+ })).optional().describe("Nodos de la ejecución (solo action=report-run)"),
3864
+ parentSessionRef: tool2.schema.string().optional().describe("Sesión padre del run (solo action=report-run)")
3865
+ },
3866
+ async execute(args) {
3867
+ if (args.action === "report-run") {
3868
+ return handleReportRun(args, observe, deps.tracker);
3869
+ }
3870
+ const taskID = args.taskID ?? "";
3871
+ if (args.action === "status") {
3872
+ return describeDecision(decideIngress(deps.policy, taskID));
3873
+ }
3874
+ const ingress = deps.ingress;
3875
+ if (ingress === undefined) {
3876
+ return unavailableReason(deps, taskID);
3877
+ }
3878
+ if (args.action === "cancel") {
3879
+ return describeOutcome(await ingress.cancel(args.runID ?? ""));
3880
+ }
3881
+ return describeOutcome(await ingress.start({
3882
+ id: taskID,
3883
+ implementerRoleID: "linus",
3884
+ title: taskID,
3885
+ brief: taskID,
3886
+ task: {
3887
+ promptChars: 0,
3888
+ hasCode: false,
3889
+ estimatedInputTokens: 0,
3890
+ estimatedOutputTokens: 0
3891
+ }
3892
+ }));
3818
3893
  }
3819
- throw new ReducerError("run-started-conflict", specDigest);
3820
- }
3821
- return { ...state, specDigest, seq };
3894
+ });
3895
+ return { definition, observeLegacyExecution: observe };
3822
3896
  }
3823
- function applyDispatched(spec, state, event) {
3824
- const node = specNode(spec, event.nodeID);
3825
- const current = state.nodes[event.nodeID];
3826
- if (node === undefined || current === undefined) {
3827
- throw new ReducerError("unknown-node", event.nodeID);
3828
- }
3829
- for (const dep of node.dependsOn) {
3830
- if (state.nodes[dep]?.status !== "succeeded") {
3831
- throw new ReducerError("dependency-not-satisfied", `${event.nodeID} <- ${dep}`);
3832
- }
3897
+ async function handleReportRun(args, observe, tracker) {
3898
+ const parsed = ReportRunPayloadSchema.safeParse({
3899
+ runID: args.runID,
3900
+ status: args.status,
3901
+ fixes: args.fixes,
3902
+ nodes: args.nodes,
3903
+ ...args.parentSessionRef !== undefined ? { parentSessionRef: args.parentSessionRef } : {}
3904
+ });
3905
+ if (!parsed.success) {
3906
+ const issues = parsed.error.issues.map((issue) => issue.message).join("; ");
3907
+ return formatResponse({
3908
+ result: "ineligible",
3909
+ detail: `validation: ${issues}`
3910
+ });
3833
3911
  }
3834
- const running = {
3835
- status: "running",
3836
- attempts: current.attempts + 1,
3837
- operationID: event.operationID,
3838
- attemptID: event.attemptID
3912
+ const verification = crossVerify(parsed.data, tracker);
3913
+ const warnings = formatWarnings(verification);
3914
+ const verificationPair = {
3915
+ nodesChecked: parsed.data.nodes.length,
3916
+ unverified: verification.unverifiedModels.length,
3917
+ mismatched: verification.modelMismatches.length
3839
3918
  };
3840
- if (current.status === "pending") {
3841
- return withNode({ ...state, seq: event.seq }, event.nodeID, running);
3842
- }
3843
- if (current.status === "failed") {
3844
- if (current.operationID !== event.operationID) {
3845
- throw new ReducerError("dispatch-conflict", event.nodeID);
3846
- }
3847
- return withNode({ ...state, seq: event.seq }, event.nodeID, running);
3848
- }
3849
- if (current.status === "running") {
3850
- if (current.operationID === event.operationID && current.attemptID === event.attemptID) {
3851
- return state;
3852
- }
3853
- throw new ReducerError("dispatch-conflict", event.nodeID);
3919
+ const run = buildObservedRun(parsed.data);
3920
+ try {
3921
+ const result = await observe(run, verificationPair);
3922
+ const base = { result: result.kind };
3923
+ const detail = result.kind === "ineligible" ? result.reason : result.kind === "observation-rejected" ? result.reason : result.kind === "contained-failure" ? result.detail : null;
3924
+ return formatResponse({
3925
+ ...base,
3926
+ ...detail !== null ? { detail } : {},
3927
+ ...warnings.length > 0 ? { warnings } : {}
3928
+ });
3929
+ } catch (error) {
3930
+ return formatResponse({
3931
+ result: "contained-failure",
3932
+ detail: error instanceof Error ? error.message : String(error)
3933
+ });
3854
3934
  }
3855
- throw new ReducerError("illegal-transition", `dispatch ${current.status}`);
3856
3935
  }
3857
- function applySucceeded(state, event) {
3858
- const current = state.nodes[event.nodeID];
3859
- if (current === undefined) {
3860
- throw new ReducerError("unknown-node", event.nodeID);
3861
- }
3862
- if (current.status === "succeeded") {
3863
- if (current.operationID === event.operationID && current.artifactSha256 === event.artifact.sha256) {
3864
- return state;
3865
- }
3866
- throw new ReducerError("receipt-conflict", event.nodeID);
3936
+
3937
+ // src/capabilities/budget.ts
3938
+ var WARNING_UTILIZATION = 0.8;
3939
+ function projectedSpend(current, estimatedCostUSD) {
3940
+ return Math.max(0, current) + Math.max(0, estimatedCostUSD);
3941
+ }
3942
+ function budgetExceeded(projected, limit) {
3943
+ return limit !== undefined && projected >= limit;
3944
+ }
3945
+ function budgetNearLimit(projected, limit) {
3946
+ return limit !== undefined && projected >= limit * WARNING_UTILIZATION && projected < limit;
3947
+ }
3948
+ function exhaustedDecision(budgets, reason) {
3949
+ return {
3950
+ action: budgets.hardStopOnBudgetExhaustion ? "blockFrontier" : "forceLocal",
3951
+ reason
3952
+ };
3953
+ }
3954
+ function evaluateBudget(state, estimatedCostUSD, budgets) {
3955
+ const projectedSessionUSD = projectedSpend(state.sessionUSD, estimatedCostUSD);
3956
+ const projectedMonthlyUSD = budgets.monthlyUSD === undefined ? undefined : projectedSpend(state.monthlyUSD ?? 0, estimatedCostUSD);
3957
+ if (budgetExceeded(projectedSessionUSD, budgets.sessionUSD)) {
3958
+ return exhaustedDecision(budgets, "session-budget-exhausted");
3867
3959
  }
3868
- if (current.status !== "running") {
3869
- throw new ReducerError("illegal-transition", `succeed ${current.status}`);
3960
+ if (budgetExceeded(projectedMonthlyUSD ?? 0, budgets.monthlyUSD)) {
3961
+ return exhaustedDecision(budgets, "monthly-budget-exhausted");
3870
3962
  }
3871
- if (current.operationID !== event.operationID || current.attemptID !== event.attemptID) {
3872
- throw new ReducerError("receipt-conflict", event.nodeID);
3963
+ if (state.frontierTokens !== undefined && budgets.frontierTokensPerSession !== undefined && state.frontierTokens >= budgets.frontierTokensPerSession) {
3964
+ return exhaustedDecision(budgets, "frontier-token-budget-exhausted");
3873
3965
  }
3874
- return withNode({ ...state, seq: event.seq }, event.nodeID, {
3875
- status: "succeeded",
3876
- attempts: current.attempts,
3877
- operationID: event.operationID,
3878
- attemptID: event.attemptID,
3879
- artifactSha256: event.artifact.sha256
3880
- });
3881
- }
3882
- function applyFailed(state, event) {
3883
- const current = state.nodes[event.nodeID];
3884
- if (current === undefined) {
3885
- throw new ReducerError("unknown-node", event.nodeID);
3966
+ if (budgetNearLimit(projectedSessionUSD, budgets.sessionUSD)) {
3967
+ return { action: "warn", reason: "session-budget-near-limit" };
3886
3968
  }
3887
- if (current.status === "failed") {
3888
- if (current.operationID === event.operationID && current.attemptID === event.attemptID) {
3889
- return state;
3890
- }
3891
- throw new ReducerError("receipt-conflict", event.nodeID);
3969
+ if (budgetNearLimit(projectedMonthlyUSD ?? 0, budgets.monthlyUSD)) {
3970
+ return { action: "warn", reason: "monthly-budget-near-limit" };
3892
3971
  }
3893
- if (current.status !== "running") {
3894
- throw new ReducerError("illegal-transition", `fail ${current.status}`);
3972
+ return { action: "ok" };
3973
+ }
3974
+
3975
+ // src/capabilities/classify.ts
3976
+ var hardKeywords = [
3977
+ "security",
3978
+ "auth",
3979
+ "authentication",
3980
+ "authorization",
3981
+ "concurrency",
3982
+ "race condition",
3983
+ "architecture",
3984
+ "refactor",
3985
+ "migration",
3986
+ "debug",
3987
+ "root cause"
3988
+ ];
3989
+ function scoreOverride(override) {
3990
+ if (override === "alwaysFrontier") {
3991
+ return 30;
3895
3992
  }
3896
- if (current.operationID !== event.operationID || current.attemptID !== event.attemptID) {
3897
- throw new ReducerError("receipt-conflict", event.nodeID);
3993
+ if (override === "alwaysLocal") {
3994
+ return -20;
3898
3995
  }
3899
- return withNode({ ...state, seq: event.seq }, event.nodeID, {
3900
- status: "failed",
3901
- attempts: current.attempts,
3902
- operationID: event.operationID,
3903
- attemptID: event.attemptID
3904
- });
3996
+ return 0;
3905
3997
  }
3906
- function applyCancelled(state, event) {
3907
- const current = state.nodes[event.nodeID];
3908
- if (current === undefined) {
3909
- throw new ReducerError("unknown-node", event.nodeID);
3910
- }
3911
- if (current.status === "cancelled") {
3912
- return state;
3998
+ function tierFromScore(score) {
3999
+ if (score <= 15) {
4000
+ return "trivial";
3913
4001
  }
3914
- if (current.status === "succeeded") {
3915
- throw new ReducerError("illegal-transition", "cancel succeeded");
4002
+ if (score <= 35) {
4003
+ return "simple";
3916
4004
  }
3917
- return withNode({ ...state, seq: event.seq }, event.nodeID, {
3918
- ...current,
3919
- status: "cancelled"
3920
- });
3921
- }
3922
- function applyRunCompleted(state, seq) {
3923
- for (const node of Object.values(state.nodes)) {
3924
- if (node.status !== "succeeded" && node.status !== "cancelled") {
3925
- throw new ReducerError("incomplete-run", node.status);
3926
- }
4005
+ if (score <= 65) {
4006
+ return "moderate";
3927
4007
  }
3928
- return { ...state, status: "completed", seq };
4008
+ return "hard";
3929
4009
  }
3930
- function applyEvent(spec, state, event) {
3931
- if (event.runID !== state.runID) {
3932
- throw new ReducerError("run-mismatch", event.runID);
4010
+ function confidenceFromScore(score) {
4011
+ if (score >= 75 || score <= 10) {
4012
+ return 0.9;
3933
4013
  }
3934
- if (TERMINAL_RUN_STATUSES.has(state.status)) {
3935
- if (event.type === "run.completed" && state.status === "completed" || event.type === "run.failed" && state.status === "failed" || event.type === "run.cancelled" && state.status === "cancelled") {
3936
- return state;
3937
- }
3938
- throw new ReducerError("post-terminal", event.type);
4014
+ if (score >= 30 && score <= 70) {
4015
+ return 0.58;
3939
4016
  }
3940
- switch (event.type) {
3941
- case "run.started":
3942
- return applyRunStarted(state, event.seq, event.specDigest);
3943
- case "node.dispatched":
3944
- return applyDispatched(spec, state, event);
3945
- case "node.succeeded":
3946
- return applySucceeded(state, event);
3947
- case "node.failed":
3948
- return applyFailed(state, event);
3949
- case "node.cancelled":
3950
- return applyCancelled(state, event);
3951
- case "run.completed":
3952
- return applyRunCompleted(state, event.seq);
3953
- case "run.failed":
3954
- return { ...state, status: "failed", seq: event.seq };
3955
- case "run.cancelled":
3956
- return { ...state, status: "cancelled", seq: event.seq };
4017
+ return 0.72;
4018
+ }
4019
+ function addScore(condition, amount, reason, state) {
4020
+ if (condition) {
4021
+ state.score += amount;
4022
+ state.reasons.push(reason);
3957
4023
  }
3958
4024
  }
4025
+ function classifyHeuristic(task) {
4026
+ const state = { score: scoreOverride(task.explicitOverride), reasons: [] };
4027
+ const prompt = task.prompt?.toLowerCase() ?? "";
4028
+ const estimatedTokens = (task.estimatedInputTokens ?? 0) + (task.estimatedOutputTokens ?? 0);
4029
+ addScore(task.promptChars <= 80 && !task.hasCode && task.requiresTools !== true, -5, "short-text-prompt", state);
4030
+ addScore(task.promptChars > 1500 || estimatedTokens > 700, 10, "large-prompt", state);
4031
+ addScore(task.promptChars > 5000 || estimatedTokens > 3000, 15, "very-large-context", state);
4032
+ addScore(task.hasCode, 15, "code-present", state);
4033
+ addScore(task.requiresTools === true, 15, "tools-required", state);
4034
+ addScore(task.requiresVision === true, 15, "vision-required", state);
4035
+ addScore((task.fileCount ?? 0) > 1, 20, "multi-file-task", state);
4036
+ addScore((task.diffHunks ?? 0) > 2, 15, "multi-hunk-diff", state);
4037
+ addScore(hardKeywords.some((keyword) => prompt.includes(keyword)), 25, "hard-keyword", state);
4038
+ addScore(task.userAskedForQuality === true, 20, "quality-requested", state);
4039
+ addScore(task.privacySensitive === true, 10, "privacy-sensitive", state);
4040
+ const normalizedScore = Math.max(0, Math.min(100, state.score));
4041
+ return {
4042
+ tier: tierFromScore(normalizedScore),
4043
+ confidence: confidenceFromScore(normalizedScore),
4044
+ reasons: state.reasons.length > 0 ? state.reasons : ["no-hard-signals"],
4045
+ ambiguous: normalizedScore >= 30 && normalizedScore <= 70
4046
+ };
4047
+ }
3959
4048
 
3960
- // src/orchestrator/graphShadow.ts
3961
- class ShadowMirrorError extends Error {
3962
- code;
3963
- detail;
3964
- constructor(code, detail) {
3965
- super(`${code}: ${detail}`);
3966
- this.name = "ShadowMirrorError";
3967
- this.code = code;
3968
- this.detail = detail;
3969
- }
4049
+ // src/router/modelSelection.ts
4050
+ function modelKey2(model) {
4051
+ return `${model.providerID}/${model.modelID}`;
3970
4052
  }
3971
- function traceAnchorDigest(trace) {
3972
- return sha256Hex(JSON.stringify({
3973
- version: trace.version,
3974
- runID: trace.runID,
3975
- nodes: trace.nodes.map((node) => [node.id, node.role])
3976
- }));
4053
+ function sameModel(left, right) {
4054
+ return left.providerID === right.providerID && left.modelID === right.modelID;
3977
4055
  }
3978
- function compileShadowSpec(trace) {
3979
- const anchor = { taskID: trace.runID, specDigest: traceAnchorDigest(trace) };
3980
- const nodes = [];
3981
- let previousID;
3982
- let lastImplementerID;
3983
- for (const node of trace.nodes) {
3984
- const dependsOn = previousID === undefined ? [] : [previousID];
3985
- if (node.role === "implementer") {
3986
- nodes.push({ id: node.id, role: "implementer", dependsOn, anchor });
3987
- lastImplementerID = node.id;
3988
- } else {
3989
- nodes.push({
3990
- id: node.id,
3991
- role: "reviewer",
3992
- dependsOn,
3993
- anchor,
3994
- ...lastImplementerID === undefined ? {} : { reviews: lastImplementerID }
3995
- });
3996
- }
3997
- previousID = node.id;
4056
+ function compareModels(left, right) {
4057
+ return modelKey2(left).localeCompare(modelKey2(right));
4058
+ }
4059
+ function uniqueModelSelections(models) {
4060
+ const byKey = new Map;
4061
+ for (const model of models) {
4062
+ byKey.set(modelKey2(model), model);
3998
4063
  }
3999
- let spec;
4000
- try {
4001
- spec = GraphSpecV1Schema.parse({ version: 1, runID: trace.runID, nodes });
4002
- validateGraphSpec(spec);
4003
- } catch (error) {
4004
- throw new ShadowMirrorError("invalid-spec", error instanceof Error ? error.message : String(error));
4064
+ return [...byKey.values()].sort(compareModels);
4065
+ }
4066
+ function localDefault(config) {
4067
+ return config.local.runtimes.find((runtime) => runtime.enabled)?.defaultModel ?? config.router.localDefault;
4068
+ }
4069
+ function resolveConfiguredFrontierBaseline(config) {
4070
+ if (config.baseline.mode === "pinned" && config.baseline.pinnedModel !== null) {
4071
+ return config.baseline.pinnedModel;
4005
4072
  }
4006
- assertReferenceOnly(spec);
4007
- return spec;
4073
+ return config.baseline.hardDefault;
4008
4074
  }
4009
- var TERMINAL_EVENT = {
4010
- completed: "run.completed",
4011
- failed: "run.failed",
4012
- cancelled: "run.cancelled"
4013
- };
4014
- function shadowArtifact(runID, nodeID) {
4015
- return {
4016
- uri: `shadow://${runID}/${nodeID}`,
4017
- sha256: sha256Hex(`shadow-artifact\x00${runID}\x00${nodeID}`),
4018
- bytes: 0
4019
- };
4075
+ function compareAvailableModels2(left, right) {
4076
+ return compareModels(left, right);
4020
4077
  }
4021
- function mirrorJournal(spec, trace) {
4022
- const runID = trace.runID;
4023
- const events = [
4078
+ function defaultAvailableModels2(config) {
4079
+ return [
4024
4080
  {
4025
- v: 1,
4026
- seq: 0,
4027
- runID,
4028
- type: "run.started",
4029
- specDigest: graphSpecDigest(spec)
4030
- }
4031
- ];
4032
- for (const node of trace.nodes) {
4033
- const operation = operationID(runID, node.id);
4034
- const attempt = attemptID(operation, 0);
4035
- events.push({
4036
- v: 1,
4037
- seq: events.length,
4038
- runID,
4039
- type: "node.dispatched",
4040
- nodeID: node.id,
4041
- operationID: operation,
4042
- attemptID: attempt
4043
- });
4044
- if (node.errorClass === undefined) {
4045
- events.push({
4046
- v: 1,
4047
- seq: events.length,
4048
- runID,
4049
- type: "node.succeeded",
4050
- nodeID: node.id,
4051
- operationID: operation,
4052
- attemptID: attempt,
4053
- artifact: shadowArtifact(runID, node.id)
4054
- });
4055
- continue;
4056
- }
4057
- if (node.errorClass === "cancelled") {
4058
- events.push({
4059
- v: 1,
4060
- seq: events.length,
4061
- runID,
4062
- type: "node.cancelled",
4063
- nodeID: node.id
4064
- });
4065
- continue;
4081
+ ...localDefault(config),
4082
+ kind: "local",
4083
+ available: true
4084
+ },
4085
+ {
4086
+ ...resolveConfiguredFrontierBaseline(config),
4087
+ kind: "frontier",
4088
+ available: true
4066
4089
  }
4067
- events.push({
4068
- v: 1,
4069
- seq: events.length,
4070
- runID,
4071
- type: "node.failed",
4072
- nodeID: node.id,
4073
- operationID: operation,
4074
- attemptID: attempt,
4075
- errorClass: node.errorClass
4076
- });
4077
- }
4078
- events.push({
4079
- v: 1,
4080
- seq: events.length,
4081
- runID,
4082
- type: TERMINAL_EVENT[trace.status]
4083
- });
4084
- return events;
4090
+ ].sort(compareAvailableModels2);
4091
+ }
4092
+ function availableModels(input) {
4093
+ return (input.availableModels ?? defaultAvailableModels2(input.config)).slice().sort(compareAvailableModels2);
4094
+ }
4095
+ function listedModel(input, model) {
4096
+ return availableModels(input).find((candidate) => sameModel(candidate, model));
4085
4097
  }
4086
- function reduceMirror(spec, journal) {
4087
- let state = initialState(spec);
4088
- try {
4089
- for (const event of journal) {
4090
- state = applyEvent(spec, state, event);
4091
- }
4092
- } catch (error) {
4093
- throw new ShadowMirrorError("illegal-sequence", error instanceof ReducerError ? `${error.code}: ${error.detail}` : String(error));
4098
+ function frontierAvailable(input, model) {
4099
+ return listedModel(input, model)?.available !== false;
4100
+ }
4101
+ function localCandidateIsUsable(input, model) {
4102
+ return model.kind === "local" && model.available && !(input.task.requiresTools === true && model.supportsTools === false);
4103
+ }
4104
+ function availableLocalFallbacks(input, selected) {
4105
+ return uniqueModelSelections(availableModels(input).filter((model) => localCandidateIsUsable(input, model)).filter((model) => !sameModel(model, selected)).map((model) => ({
4106
+ providerID: model.providerID,
4107
+ modelID: model.modelID
4108
+ })));
4109
+ }
4110
+
4111
+ // src/router/cost.ts
4112
+ function modelProfile(input, model) {
4113
+ return input.profiles?.find((profile) => sameModel(profile.ref, model));
4114
+ }
4115
+ function estimatedCostUSD(input, model) {
4116
+ const profile = modelProfile(input, model);
4117
+ if (profile === undefined) {
4118
+ return 0;
4094
4119
  }
4095
- return state;
4120
+ const inputTokens = input.task.estimatedInputTokens ?? 0;
4121
+ const outputTokens = input.task.estimatedOutputTokens ?? 0;
4122
+ return inputTokens / 1e6 * profile.costPer1M.inputUSD + outputTokens / 1e6 * profile.costPer1M.outputUSD;
4096
4123
  }
4097
- function projectLegacySummary(trace) {
4098
- return {
4099
- runID: trace.runID,
4100
- status: trace.status,
4101
- outcome: trace.outcome,
4102
- fixes: trace.fixes,
4103
- nodes: trace.nodes.map((node) => ({
4104
- id: node.id,
4105
- role: node.role,
4106
- model: node.model
4107
- }))
4108
- };
4124
+ function roundUSD(value) {
4125
+ return Math.round(value * 1000000000000) / 1000000000000;
4109
4126
  }
4110
- function projectShadowSummary(spec, trace) {
4111
- const implementers = spec.nodes.filter((node) => node.role === "implementer").length;
4127
+
4128
+ // src/capabilities/select.ts
4129
+ var BLENDED_COST_INPUT_WEIGHT = 0.75;
4130
+ var BLENDED_COST_OUTPUT_WEIGHT = 1 - BLENDED_COST_INPUT_WEIGHT;
4131
+ var availabilityRank = {
4132
+ available: 0,
4133
+ degraded: 1,
4134
+ unavailable: 2
4135
+ };
4136
+ var tierRequirements = {
4137
+ trivial: { reasoning: 0, code: 1, context: 8000 },
4138
+ simple: { reasoning: 1, code: 2, context: 16000 },
4139
+ moderate: { reasoning: 3, code: 3, context: 32000 },
4140
+ hard: { reasoning: 4, code: 5, context: 64000 }
4141
+ };
4142
+ function deriveRequirement(tier, task) {
4143
+ const base = tierRequirements[tier];
4144
+ const estimatedContext = (task.estimatedInputTokens ?? 0) + (task.estimatedOutputTokens ?? 0);
4145
+ const contextFromPrompt = Math.ceil(task.promptChars / 4);
4146
+ const minContextWindow = Math.max(base.context, estimatedContext, contextFromPrompt);
4147
+ const codeBump = task.hasCode ? 1 : 0;
4112
4148
  return {
4113
- runID: spec.runID,
4114
- status: trace.status,
4115
- outcome: trace.outcome,
4116
- fixes: implementers - 1,
4117
- nodes: spec.nodes.map((node, index) => ({
4118
- id: node.id,
4119
- role: node.role,
4120
- model: trace.nodes[index].model
4121
- }))
4149
+ minReasoningTier: base.reasoning,
4150
+ minCodeQualityTier: Math.min(5, base.code + codeBump),
4151
+ minContextWindow,
4152
+ needsTools: task.requiresTools === true,
4153
+ needsVision: task.requiresVision === true
4122
4154
  };
4123
4155
  }
4124
- function mirrorLegacyExecution(trace) {
4125
- const spec = compileShadowSpec(trace);
4126
- const journal = mirrorJournal(spec, trace);
4127
- const state = reduceMirror(spec, journal);
4128
- const summary = projectShadowSummary(spec, trace);
4129
- assertReferenceOnly(summary);
4130
- return {
4131
- spec,
4132
- specDigest: graphSpecDigest(spec),
4133
- journal,
4134
- state,
4135
- summary
4136
- };
4156
+ function blendedCostPer1M(profile) {
4157
+ return profile.costPer1M.inputUSD * BLENDED_COST_INPUT_WEIGHT + profile.costPer1M.outputUSD * BLENDED_COST_OUTPUT_WEIGHT;
4158
+ }
4159
+ function modelKey3(profile) {
4160
+ return `${profile.ref.providerID}/${profile.ref.modelID}`;
4161
+ }
4162
+ function compareCapableFrontier(req, left, right) {
4163
+ const costDelta = blendedCostPer1M(left) - blendedCostPer1M(right);
4164
+ if (costDelta !== 0) {
4165
+ return costDelta;
4166
+ }
4167
+ const availabilityDelta = availabilityRank[left.availability] - availabilityRank[right.availability];
4168
+ if (availabilityDelta !== 0) {
4169
+ return availabilityDelta;
4170
+ }
4171
+ const reasoningWasteDelta = left.reasoningTier - req.minReasoningTier - (right.reasoningTier - req.minReasoningTier);
4172
+ if (reasoningWasteDelta !== 0) {
4173
+ return reasoningWasteDelta;
4174
+ }
4175
+ return modelKey3(left).localeCompare(modelKey3(right));
4176
+ }
4177
+ function satisfiesRequirement(req, profile) {
4178
+ return profile.kind === "frontier" && profile.availability !== "unavailable" && profile.contextWindow >= req.minContextWindow && profile.reasoningTier >= req.minReasoningTier && profile.codeQualityTier >= req.minCodeQualityTier && (!req.needsTools || profile.supportsToolCalling) && (!req.needsVision || profile.supportsVision);
4179
+ }
4180
+ function selectCheapestCapableFrontier(req, profiles) {
4181
+ const selected = profiles.filter((profile) => satisfiesRequirement(req, profile)).sort((left, right) => compareCapableFrontier(req, left, right))[0];
4182
+ return selected?.ref ?? null;
4137
4183
  }
4138
4184
 
4139
- // src/orchestrator/graphFacade.ts
4140
- function mirrorLegacyTrace(trace) {
4141
- try {
4142
- return {
4143
- ok: true,
4144
- mirror: mirrorLegacyExecution(parseLegacyExecutionTrace(trace))
4145
- };
4146
- } catch (error) {
4147
- if (error instanceof ShadowMirrorError) {
4148
- return { ok: false, code: error.code, detail: error.detail };
4149
- }
4150
- if (error instanceof LegacyTraceError) {
4185
+ // src/router/frontierBaseline.ts
4186
+ function resolveFrontierBaseline(input, tier) {
4187
+ if (input.config.baseline.mode === "pinned" && input.config.baseline.pinnedModel !== null) {
4188
+ return { model: input.config.baseline.pinnedModel, rationale: [] };
4189
+ }
4190
+ if (input.profiles !== undefined) {
4191
+ const selected = selectCheapestCapableFrontier(deriveRequirement(tier, input.task), input.profiles);
4192
+ if (selected !== null) {
4151
4193
  return {
4152
- ok: false,
4153
- code: "invalid-trace",
4154
- detail: error.issues.join("; ")
4194
+ model: selected,
4195
+ rationale: ["auto-cheapest-capable-frontier"]
4155
4196
  };
4156
4197
  }
4157
4198
  return {
4158
- ok: false,
4159
- code: "mirror-error",
4160
- detail: error instanceof Error ? error.message : String(error)
4199
+ model: input.config.baseline.hardDefault,
4200
+ rationale: ["auto-cheapest-capable-unavailable-hard-default"]
4161
4201
  };
4162
4202
  }
4203
+ return { model: input.config.baseline.hardDefault, rationale: [] };
4163
4204
  }
4164
4205
 
4165
- // src/orchestrator/shadowComparator.ts
4166
- function sequenceEqual(a, b) {
4167
- if (a.length !== b.length) {
4168
- return false;
4206
+ // src/router/chooseModel.ts
4207
+ function localStatus(input, model) {
4208
+ const listed = listedModel(input, model);
4209
+ return {
4210
+ available: input.availableModels === undefined ? listed?.available !== false : listed?.available === true,
4211
+ missingTools: input.task.requiresTools === true && listed?.supportsTools === false
4212
+ };
4213
+ }
4214
+ function buildFallbackChain(input, selected, frontier, allowFrontier) {
4215
+ const chain = availableLocalFallbacks(input, selected);
4216
+ if (allowFrontier && !sameModel(frontier, selected) && frontierAvailable(input, frontier)) {
4217
+ chain.push(frontier);
4169
4218
  }
4170
- return a.every((value, index) => value === b[index]);
4219
+ return chain;
4171
4220
  }
4172
- function compareShadowRun(legacy, shadow) {
4173
- if (legacy === undefined || shadow === undefined) {
4174
- return { verdict: "inconclusive", divergences: [] };
4221
+ function inferRouteKind(config, selected, listed) {
4222
+ if (listed !== undefined) {
4223
+ return listed.kind;
4175
4224
  }
4176
- const divergences = [];
4177
- if (legacy.status !== shadow.status) {
4178
- divergences.push("status");
4225
+ return config.local.runtimes.some((runtime) => sameModel(runtime.defaultModel, selected)) ? "local" : "frontier";
4226
+ }
4227
+ function localFallbackReason(status) {
4228
+ return status.missingTools ? "local-missing-tools-fallback" : "local-unavailable-fallback";
4229
+ }
4230
+ function decision(selected, routeKind, rationale, fallbackChain) {
4231
+ return {
4232
+ selected,
4233
+ routeKind,
4234
+ rationale,
4235
+ fallbackChain
4236
+ };
4237
+ }
4238
+ function resolveLocalPrimary(input, primary, frontier, options) {
4239
+ const status = localStatus(input, primary);
4240
+ if (status.available && !status.missingTools) {
4241
+ return decision(primary, "local", options.baseRationale, buildFallbackChain(input, primary, frontier, options.allowFrontier));
4242
+ }
4243
+ const fallbackReason = localFallbackReason(status);
4244
+ const nextLocal = availableLocalFallbacks(input, primary)[0];
4245
+ if (nextLocal !== undefined) {
4246
+ return decision(nextLocal, "local", [...options.baseRationale, fallbackReason], buildFallbackChain(input, nextLocal, frontier, options.allowFrontier));
4247
+ }
4248
+ if (!options.allowFrontier) {
4249
+ return decision(primary, "local", [...options.baseRationale, fallbackReason, options.noLocalRationale], []);
4250
+ }
4251
+ if (frontierAvailable(input, frontier)) {
4252
+ return decision(frontier, "frontier", [...options.baseRationale, fallbackReason, "no-local-available-frontier"], []);
4253
+ }
4254
+ return decision(primary, "local", [...options.baseRationale, fallbackReason, "frontier-unavailable"], []);
4255
+ }
4256
+ function resolveFrontierPrimary(input, frontier, rationale) {
4257
+ if (frontierAvailable(input, frontier)) {
4258
+ return decision(frontier, "frontier", rationale, []);
4259
+ }
4260
+ const nextLocal = availableLocalFallbacks(input, frontier)[0];
4261
+ if (nextLocal !== undefined) {
4262
+ return decision(nextLocal, "local", [...rationale, "frontier-unavailable-fallback"], buildFallbackChain(input, nextLocal, frontier, false));
4263
+ }
4264
+ return decision(frontier, "frontier", [...rationale, "frontier-unavailable"], []);
4265
+ }
4266
+ function tierForInput(input) {
4267
+ return input.tier ?? classifyHeuristic(input.task).tier;
4268
+ }
4269
+ function finalizeDecision(input, tier, frontier, budgetAction, core) {
4270
+ const selectedCostUSD = estimatedCostUSD(input, core.selected);
4271
+ const baselineCostUSD = estimatedCostUSD(input, frontier.model);
4272
+ const savingsUSD = core.routeKind === "frontier" && sameModel(core.selected, frontier.model) ? 0 : baselineCostUSD - selectedCostUSD;
4273
+ return {
4274
+ ...core,
4275
+ tier,
4276
+ rationale: [...frontier.rationale, ...core.rationale],
4277
+ estimatedCostUSD: roundUSD(selectedCostUSD),
4278
+ baselineCostUSD: roundUSD(baselineCostUSD),
4279
+ estimatedSavingsUSD: roundUSD(savingsUSD),
4280
+ budgetAction
4281
+ };
4282
+ }
4283
+ function chooseModel(input) {
4284
+ const tier = tierForInput(input);
4285
+ const local = localDefault(input.config);
4286
+ const frontier = resolveFrontierBaseline(input, tier);
4287
+ const frontierCostUSD = estimatedCostUSD(input, frontier.model);
4288
+ const budgetAction = input.budgetState === undefined ? { action: "ok" } : evaluateBudget(input.budgetState, frontierCostUSD, input.config.budgets);
4289
+ const override = input.task.explicitOverride;
4290
+ if (input.task.privacySensitive === true && input.config.privacyMode === "forceLocalOnSensitive") {
4291
+ return finalizeDecision(input, tier, frontier, budgetAction, resolveLocalPrimary(input, local, frontier.model, {
4292
+ baseRationale: ["privacy-force-local"],
4293
+ allowFrontier: false,
4294
+ noLocalRationale: "privacy-force-local-unavailable"
4295
+ }));
4296
+ }
4297
+ if (budgetAction.action === "forceLocal" || budgetAction.action === "blockFrontier") {
4298
+ return finalizeDecision(input, tier, frontier, budgetAction, resolveLocalPrimary(input, local, frontier.model, {
4299
+ baseRationale: [`budget-${budgetAction.action}`],
4300
+ allowFrontier: false,
4301
+ noLocalRationale: "budget-local-unavailable"
4302
+ }));
4179
4303
  }
4180
- if (!sequenceEqual(legacy.nodes.map((node) => node.id), shadow.nodes.map((node) => node.id))) {
4181
- divergences.push("order");
4304
+ if (typeof override === "object") {
4305
+ return finalizeDecision(input, tier, frontier, budgetAction, decision(override, inferRouteKind(input.config, override, listedModel(input, override)), ["explicit-model-override"], buildFallbackChain(input, override, frontier.model, true)));
4182
4306
  }
4183
- if (!sequenceEqual(legacy.nodes.map((node) => node.role), shadow.nodes.map((node) => node.role))) {
4184
- divergences.push("roles");
4307
+ if (override === "alwaysLocal") {
4308
+ return finalizeDecision(input, tier, frontier, budgetAction, resolveLocalPrimary(input, local, frontier.model, {
4309
+ baseRationale: ["explicit-always-local"],
4310
+ allowFrontier: false,
4311
+ noLocalRationale: "forced-local-unavailable"
4312
+ }));
4185
4313
  }
4186
- if (!sequenceEqual(legacy.nodes.map((node) => node.model), shadow.nodes.map((node) => node.model))) {
4187
- divergences.push("models");
4314
+ if (override === "alwaysFrontier") {
4315
+ return finalizeDecision(input, tier, frontier, budgetAction, decision(frontier.model, "frontier", ["explicit-always-frontier"], []));
4188
4316
  }
4189
- if (legacy.fixes !== shadow.fixes) {
4190
- divergences.push("fixes");
4317
+ if (input.config.router.frontierOnly) {
4318
+ return finalizeDecision(input, tier, frontier, budgetAction, decision(frontier.model, "frontier", ["router-frontier-only"], []));
4191
4319
  }
4192
- if (legacy.outcome !== shadow.outcome) {
4193
- divergences.push("outcome");
4320
+ const shortEnoughForLocal = input.task.promptChars <= input.config.router.trivialPromptMaxChars;
4321
+ const largeEnoughForFrontier = input.task.promptChars >= input.config.router.frontierPromptMinChars;
4322
+ if (!input.task.hasCode && shortEnoughForLocal && !largeEnoughForFrontier) {
4323
+ return finalizeDecision(input, tier, frontier, budgetAction, resolveLocalPrimary(input, local, frontier.model, {
4324
+ baseRationale: ["trivial-short-no-code"],
4325
+ allowFrontier: true,
4326
+ noLocalRationale: "forced-local-unavailable"
4327
+ }));
4194
4328
  }
4195
- return {
4196
- verdict: divergences.length === 0 ? "match" : "divergent",
4197
- divergences
4198
- };
4329
+ return finalizeDecision(input, tier, frontier, budgetAction, resolveFrontierPrimary(input, frontier.model, [
4330
+ input.task.hasCode ? "code-detected" : "large-or-nontrivial-prompt"
4331
+ ]));
4199
4332
  }
4200
4333
 
4201
- // src/storage/graph/soakRecorder.ts
4202
- async function ensureRecorderId(ports, basePath) {
4203
- const idPath = `${basePath}/soak-recorder-id`;
4204
- if (await ports.fs.exists(idPath)) {
4205
- const id = (await ports.fs.readFile(idPath)).trim();
4206
- if (/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/.test(id)) {
4207
- return id;
4208
- }
4209
- }
4210
- const newId = ports.id.randomUUID();
4211
- await ports.fs.writeFile(idPath, newId);
4212
- return newId;
4334
+ // src/telemetry/cost.ts
4335
+ function routeKind(decision2) {
4336
+ return decision2.routeKind === "local" ? "local" : "frontier";
4213
4337
  }
4214
- async function readAllChains(ports, evidenceDir) {
4215
- if (!await ports.fs.exists(evidenceDir)) {
4216
- return [];
4338
+ function budgetAction(decision2) {
4339
+ const reason = decision2.budgetAction.reason;
4340
+ return reason === undefined ? decision2.budgetAction.action : `${decision2.budgetAction.action}:${reason}`;
4341
+ }
4342
+ function toCostRecord(decision2, context) {
4343
+ const record = {
4344
+ ts: context.ts,
4345
+ promptHash: context.promptHash,
4346
+ promptChars: context.promptChars,
4347
+ tier: decision2.tier,
4348
+ routeKind: routeKind(decision2),
4349
+ selected: decision2.selected,
4350
+ rationale: decision2.rationale.join(","),
4351
+ estimatedCostUSD: decision2.estimatedCostUSD,
4352
+ baselineCostUSD: decision2.baselineCostUSD,
4353
+ estimatedSavingsUSD: decision2.estimatedSavingsUSD,
4354
+ budgetAction: budgetAction(decision2)
4355
+ };
4356
+ if (context.sessionID !== undefined) {
4357
+ record.sessionID = context.sessionID;
4217
4358
  }
4218
- const files = await ports.fs.readDir(evidenceDir);
4219
- const chains = [];
4220
- for (const file of files) {
4221
- if (!file.endsWith(".jsonl")) {
4359
+ if (context.tokensIn !== undefined) {
4360
+ record.tokensIn = context.tokensIn;
4361
+ }
4362
+ if (context.tokensOut !== undefined) {
4363
+ record.tokensOut = context.tokensOut;
4364
+ }
4365
+ return record;
4366
+ }
4367
+
4368
+ // src/telemetry/types.ts
4369
+ import { z as z10 } from "zod";
4370
+ var CostRecordSchema = z10.object({
4371
+ ts: z10.number().finite(),
4372
+ sessionID: z10.string().min(1).optional(),
4373
+ promptHash: z10.string().min(1),
4374
+ promptChars: z10.number().int().min(0),
4375
+ tier: ComplexityTierSchema,
4376
+ routeKind: z10.enum(["local", "frontier"]),
4377
+ selected: ModelRefSchema,
4378
+ rationale: z10.string(),
4379
+ estimatedCostUSD: z10.number().finite().min(0),
4380
+ baselineCostUSD: z10.number().finite().min(0),
4381
+ estimatedSavingsUSD: z10.number().finite(),
4382
+ budgetAction: z10.string().min(1),
4383
+ tokensIn: z10.number().int().min(0).optional(),
4384
+ tokensOut: z10.number().int().min(0).optional()
4385
+ });
4386
+
4387
+ // src/telemetry/read.ts
4388
+ var DEFAULT_TELEMETRY_PATH = ".opencode/openteam-telemetry.jsonl";
4389
+ function parseCostRecordsJsonl(text) {
4390
+ const records = [];
4391
+ for (const line of text.split(`
4392
+ `)) {
4393
+ const trimmed = line.trim();
4394
+ if (trimmed.length === 0) {
4222
4395
  continue;
4223
4396
  }
4224
- const content = await ports.fs.readFile(`${evidenceDir}/${file}`);
4225
- const lines = content.split(`
4226
- `).filter((l) => l.trim().length > 0);
4227
- const observations = [];
4228
- for (const line of lines) {
4229
- const parsed = SoakObservationSchema.safeParse(JSON.parse(line));
4230
- if (parsed.success) {
4231
- observations.push(parsed.data);
4232
- }
4233
- }
4234
- if (observations.length > 0) {
4235
- chains.push(observations);
4397
+ let candidate;
4398
+ try {
4399
+ candidate = JSON.parse(trimmed);
4400
+ } catch {
4401
+ continue;
4236
4402
  }
4237
- }
4238
- return chains;
4239
- }
4240
- function canonicalObservationPreimage2(obs) {
4241
- return JSON.stringify({
4242
- version: obs.version,
4243
- seq: obs.seq,
4244
- timestamp: obs.timestamp,
4245
- platform: obs.platform,
4246
- opencodeVersion: obs.opencodeVersion,
4247
- provenance: obs.provenance,
4248
- traceDigest: obs.traceDigest,
4249
- criticalDivergences: obs.criticalDivergences,
4250
- privacy: obs.privacy,
4251
- duplicateEffects: obs.duplicateEffects,
4252
- modelVerification: obs.modelVerification
4253
- });
4254
- }
4255
- async function appendObservation(ports, evidenceDir, recorderId, input) {
4256
- await ports.fs.mkdir(evidenceDir);
4257
- const chainPath = `${evidenceDir}/${recorderId}.jsonl`;
4258
- let seq = 0;
4259
- let prevChainDigest = "0".repeat(64);
4260
- if (await ports.fs.exists(chainPath)) {
4261
- const content = await ports.fs.readFile(chainPath);
4262
- const lines = content.split(`
4263
- `).filter((l) => l.trim().length > 0);
4264
- if (lines.length > 0) {
4265
- const lastLine = lines[lines.length - 1];
4266
- let rawParsed;
4267
- try {
4268
- rawParsed = JSON.parse(lastLine);
4269
- } catch {
4270
- throw new Error("corrupt chain tail: invalid JSON");
4271
- }
4272
- const parsed = SoakObservationSchema.safeParse(rawParsed);
4273
- if (!parsed.success) {
4274
- const detail = parsed.error.issues.map((i) => `${i.path.join(".")}: ${i.code}`).join("; ");
4275
- throw new Error(`corrupt chain tail: ${detail}`);
4276
- }
4277
- seq = parsed.data.seq + 1;
4278
- prevChainDigest = parsed.data.chainDigest;
4403
+ const parsed = CostRecordSchema.safeParse(candidate);
4404
+ if (parsed.success) {
4405
+ records.push(parsed.data);
4279
4406
  }
4280
4407
  }
4281
- const timestamp = ports.clock.now();
4282
- const base = {
4283
- version: 1,
4284
- seq,
4285
- timestamp,
4286
- platform: input.platform,
4287
- opencodeVersion: input.opencodeVersion,
4288
- provenance: input.provenance,
4289
- traceDigest: input.traceDigest,
4290
- criticalDivergences: input.criticalDivergences,
4291
- privacy: input.privacy,
4292
- duplicateEffects: input.duplicateEffects,
4293
- modelVerification: input.modelVerification
4294
- };
4295
- const preimage = canonicalObservationPreimage2(base);
4296
- const chainDigest = sha256Hex(prevChainDigest + preimage);
4297
- const observation = { ...base, chainDigest };
4298
- assertReferenceOnly(observation);
4299
- const line = JSON.stringify(observation);
4300
- if (await ports.fs.exists(chainPath)) {
4301
- const existing = await ports.fs.readFile(chainPath);
4302
- await ports.fs.writeFile(chainPath, `${existing}
4303
- ${line}`);
4304
- } else {
4305
- await ports.fs.writeFile(chainPath, line);
4306
- }
4307
- return observation;
4408
+ return records;
4308
4409
  }
4309
4410
 
4310
- // src/plugin/soakObserver.ts
4311
- function resolvePlatform(platform) {
4312
- if (platform === "win32")
4313
- return "win32";
4314
- if (platform === "darwin")
4315
- return "darwin";
4316
- if (platform === "linux")
4317
- return "linux";
4318
- return null;
4319
- }
4320
- function countCriticalDivergences(parity, criticalCodes) {
4321
- if (parity === undefined)
4322
- return null;
4323
- if (criticalCodes.length === 0)
4324
- return null;
4325
- const criticalSet = new Set(criticalCodes);
4326
- return parity.divergences.filter((code) => criticalSet.has(code)).length;
4327
- }
4328
- function scanTracePrivacy(trace) {
4329
- const result = scanReferenceOnly([trace]);
4330
- return {
4331
- surfacesScanned: result.surfacesScanned,
4332
- rawFindings: result.rawFindings
4333
- };
4334
- }
4335
- function detectDuplicateEffects(trace) {
4336
- const nodes = trace.nodes;
4337
- if (nodes.length === 0)
4338
- return null;
4339
- const seen = new Set;
4340
- let duplicates = 0;
4341
- for (const node of nodes) {
4342
- if (seen.has(node.id)) {
4343
- duplicates++;
4344
- } else {
4345
- seen.add(node.id);
4346
- }
4347
- }
4348
- return { effectsExamined: nodes.length, duplicatesFound: duplicates };
4411
+ // src/telemetry/eventLog.ts
4412
+ var DEFAULT_SESSIONS_DIR = ".opencode/openteam/sessions";
4413
+ var LEGACY_SESSION_ID = "legacy";
4414
+ function sessionFileName(sessionID) {
4415
+ const safe = sessionID.replace(/[^A-Za-z0-9._-]/g, "_");
4416
+ return `${safe}.jsonl`;
4349
4417
  }
4350
- function traceToObservationInput(trace, opencodeVersion, parity, criticalCodes, modelVerification, platformOverride) {
4351
- const platform = resolvePlatform(platformOverride ?? process.platform);
4352
- if (platform === null)
4353
- return null;
4354
- const traceDigest = sha256Hex(JSON.stringify(trace));
4355
- return {
4356
- platform,
4357
- opencodeVersion,
4358
- provenance: "genuine-usage",
4359
- traceDigest,
4360
- criticalDivergences: countCriticalDivergences(parity, criticalCodes),
4361
- privacy: scanTracePrivacy(trace),
4362
- duplicateEffects: detectDuplicateEffects(trace),
4363
- modelVerification
4418
+ function createEventLogSink(deps) {
4419
+ return {
4420
+ emit: async (event) => {
4421
+ try {
4422
+ const parsed = OpenTeamEventSchema.parse(event);
4423
+ const path = joinVirtualPath(deps.dir, sessionFileName(parsed.sessionID));
4424
+ await deps.storage.append(path, `${JSON.stringify(parsed)}
4425
+ `);
4426
+ } catch (error) {
4427
+ deps.onError?.(error);
4428
+ }
4429
+ }
4364
4430
  };
4365
4431
  }
4366
- async function recordSoakObservation(ports, evidenceDir, recorderId, trace, opencodeVersion, parity, criticalCodes, modelVerification, platformOverride) {
4367
- const input = traceToObservationInput(trace, opencodeVersion, parity, criticalCodes, modelVerification, platformOverride);
4368
- if (input === null)
4369
- return false;
4370
- await appendObservation(ports, evidenceDir, recorderId, input);
4371
- return true;
4432
+ function createNullEventSink() {
4433
+ return { emit: () => {} };
4372
4434
  }
4373
-
4374
- // src/plugin/shadowPipeline.ts
4375
- function createShadowPipeline(deps) {
4376
- return async (observation, modelVerification) => {
4435
+ function parseEventsJsonl(text) {
4436
+ const events = [];
4437
+ for (const line of text.split(`
4438
+ `)) {
4439
+ const trimmed = line.trim();
4440
+ if (trimmed.length === 0) {
4441
+ continue;
4442
+ }
4443
+ let candidate;
4377
4444
  try {
4378
- const ingested = ingestLegacyExecution(observation, deps.gate);
4379
- if (!ingested.eligible) {
4380
- return { kind: "ineligible", reason: ingested.reason };
4381
- }
4382
- const mirror = mirrorLegacyTrace(ingested.trace);
4383
- let parity;
4384
- if (mirror.ok) {
4385
- const legacySummary = projectLegacySummary(ingested.trace);
4386
- const report = compareShadowRun(legacySummary, mirror.mirror.summary);
4387
- parity = { divergences: [...report.divergences] };
4388
- }
4389
- const recorded = await recordSoakObservation(deps.ports, deps.evidenceDir, deps.recorderId, ingested.trace, deps.opencodeVersion, parity, deps.criticalCodes, modelVerification ?? null, deps.platformOverride);
4390
- if (!recorded) {
4391
- return {
4392
- kind: "observation-rejected",
4393
- reason: "unrecognized-platform"
4394
- };
4395
- }
4396
- return { kind: "observed" };
4397
- } catch (error) {
4398
- return {
4399
- kind: "contained-failure",
4400
- detail: error instanceof Error ? error.message : String(error)
4401
- };
4445
+ candidate = JSON.parse(trimmed);
4446
+ } catch {
4447
+ continue;
4402
4448
  }
4403
- };
4449
+ const parsed = OpenTeamEventSchema.safeParse(candidate);
4450
+ if (parsed.success) {
4451
+ events.push(parsed.data);
4452
+ }
4453
+ }
4454
+ return events;
4404
4455
  }
4405
-
4406
- // src/plugin/graphTool.ts
4407
- function describeDecision(decision2) {
4408
- if (decision2.route === "graph") {
4409
- return `graph: la tarea ${decision2.taskID} se enrutaría al runtime activo.`;
4456
+ function costRecordToRouteEvent(record) {
4457
+ const event = {
4458
+ v: EVENT_SCHEMA_VERSION,
4459
+ type: "route",
4460
+ ts: record.ts,
4461
+ sessionID: record.sessionID ?? LEGACY_SESSION_ID,
4462
+ promptHash: record.promptHash,
4463
+ promptChars: record.promptChars,
4464
+ tier: record.tier,
4465
+ routeKind: record.routeKind,
4466
+ selected: record.selected,
4467
+ rationale: record.rationale,
4468
+ estimatedCostUSD: record.estimatedCostUSD,
4469
+ baselineCostUSD: record.baselineCostUSD,
4470
+ estimatedSavingsUSD: record.estimatedSavingsUSD,
4471
+ budgetAction: record.budgetAction
4472
+ };
4473
+ if (record.tokensIn !== undefined) {
4474
+ event.tokensIn = record.tokensIn;
4410
4475
  }
4411
- switch (decision2.reason) {
4412
- case "gate-closed":
4413
- return "legacy: gate-closed — el ingress activo no es alcanzable por configuración en esta versión.";
4414
- case "kill-switch":
4415
- return "legacy: kill-switch — apagado de emergencia activo.";
4416
- case "graph-disabled":
4417
- return "legacy: graph-disabled — graph.mode no es 'active'.";
4418
- case "not-allow-listed":
4419
- return "legacy: not-allow-listed — la tarea no está en la allow-list del ingress.";
4476
+ if (record.tokensOut !== undefined) {
4477
+ event.tokensOut = record.tokensOut;
4420
4478
  }
4479
+ return event;
4421
4480
  }
4422
- function describeOutcome(outcome) {
4423
- switch (outcome.kind) {
4424
- case "legacy":
4425
- return describeDecision({ route: "legacy", reason: outcome.reason });
4426
- case "accepted":
4427
- return `accepted: run ${outcome.runID}, paso ${outcome.step.kind}.`;
4428
- case "revision":
4429
- return `revision: run ${outcome.runID}, plan ${outcome.plan.kind}.`;
4430
- case "reassigned":
4431
- return `reassigned: run ${outcome.runID}, reviewer ${outcome.reviewerID}.`;
4432
- case "cancelled":
4433
- return `cancelled: run ${outcome.runID}, ${outcome.cancelledNodeIDs.length} nodo(s) cancelado(s).`;
4434
- case "error":
4435
- return `error: ${outcome.code}.`;
4481
+ function routeEventToCostRecord(event) {
4482
+ const record = {
4483
+ ts: event.ts,
4484
+ sessionID: event.sessionID,
4485
+ promptHash: event.promptHash,
4486
+ promptChars: event.promptChars,
4487
+ tier: event.tier,
4488
+ routeKind: event.routeKind,
4489
+ selected: event.selected,
4490
+ rationale: event.rationale,
4491
+ estimatedCostUSD: event.estimatedCostUSD,
4492
+ baselineCostUSD: event.baselineCostUSD,
4493
+ estimatedSavingsUSD: event.estimatedSavingsUSD,
4494
+ budgetAction: event.budgetAction
4495
+ };
4496
+ if (event.tokensIn !== undefined) {
4497
+ record.tokensIn = event.tokensIn;
4498
+ }
4499
+ if (event.tokensOut !== undefined) {
4500
+ record.tokensOut = event.tokensOut;
4436
4501
  }
4502
+ return record;
4437
4503
  }
4438
- function unavailableReason(deps, taskID) {
4439
- const decision2 = decideIngress(deps.policy, taskID);
4440
- return decision2.route === "legacy" ? describeDecision(decision2) : "unavailable: el ejecutor de efectos del runtime activo no está enchufado.";
4504
+ async function readRouteCostRecords(dir, deps) {
4505
+ const events = await readSessionEvents(dir, deps);
4506
+ const records = [];
4507
+ for (const event of events) {
4508
+ if (event.type === "route") {
4509
+ records.push(routeEventToCostRecord(event));
4510
+ }
4511
+ }
4512
+ return records;
4441
4513
  }
4442
- function createGraphTool(deps) {
4443
- const observe = deps.shadow !== undefined ? createShadowPipeline(deps.shadow) : async () => ({
4444
- kind: "ineligible",
4445
- reason: "shadow-not-configured"
4446
- });
4447
- const definition = tool2({
4448
- description: "Ingress activo de SDD de openteam (GE-050). En esta versión la puerta interna está cerrada: informa del estado de enrutado y no ejecuta runs. La acción report-run registra una observación shadow de la ejecución legacy.",
4449
- args: {
4450
- action: tool2.schema.enum(["status", "start", "cancel", "report-run"]).describe("Acción a ejecutar"),
4451
- taskID: tool2.schema.string().optional().describe("Identificador de la tarea SDD"),
4452
- runID: tool2.schema.string().optional().describe("Identificador del run (para action=cancel o report-run)"),
4453
- status: tool2.schema.enum(["completed", "failed", "cancelled"]).optional().describe("Estado terminal del run (solo action=report-run)"),
4454
- fixes: tool2.schema.number().optional().describe("Número de iteraciones de fix (solo action=report-run)"),
4455
- nodes: tool2.schema.array(tool2.schema.object({
4456
- id: tool2.schema.string().describe("ID del nodo"),
4457
- role: tool2.schema.enum(["implementer", "reviewer"]).describe("Rol del nodo"),
4458
- model: tool2.schema.string().describe("Modelo utilizado por el nodo"),
4459
- ok: tool2.schema.boolean().describe("Éxito terminal del nodo"),
4460
- sessionRef: tool2.schema.string().optional().describe("ID de sesión de opencode del nodo"),
4461
- errorClass: tool2.schema.enum(["transient", "permanent", "exhausted"]).optional().describe("Clase de error si el nodo falló")
4462
- })).optional().describe("Nodos de la ejecución (solo action=report-run)"),
4463
- parentSessionRef: tool2.schema.string().optional().describe("Sesión padre del run (solo action=report-run)")
4464
- },
4465
- async execute(args) {
4466
- if (args.action === "report-run") {
4467
- return handleReportRun(args, observe, deps.tracker);
4468
- }
4469
- const taskID = args.taskID ?? "";
4470
- if (args.action === "status") {
4471
- return describeDecision(decideIngress(deps.policy, taskID));
4472
- }
4473
- const ingress = deps.ingress;
4474
- if (ingress === undefined) {
4475
- return unavailableReason(deps, taskID);
4476
- }
4477
- if (args.action === "cancel") {
4478
- return describeOutcome(await ingress.cancel(args.runID ?? ""));
4514
+ async function readSessionEvents(dir, deps) {
4515
+ const files = (await deps.storage.list(dir)).filter((file) => file.endsWith(".jsonl"));
4516
+ const perFile = await Promise.all(files.map(async (file) => {
4517
+ const text = await deps.storage.read(joinVirtualPath(dir, file));
4518
+ return text === undefined ? [] : parseEventsJsonl(text);
4519
+ }));
4520
+ const events = perFile.flat();
4521
+ if (deps.legacyTelemetryPath !== undefined) {
4522
+ const legacyText = await deps.storage.read(deps.legacyTelemetryPath);
4523
+ if (legacyText !== undefined) {
4524
+ for (const record of parseCostRecordsJsonl(legacyText)) {
4525
+ events.push(costRecordToRouteEvent(record));
4479
4526
  }
4480
- return describeOutcome(await ingress.start({
4481
- id: taskID,
4482
- implementerRoleID: "linus",
4483
- title: taskID,
4484
- brief: taskID,
4485
- task: {
4486
- promptChars: 0,
4487
- hasCode: false,
4488
- estimatedInputTokens: 0,
4489
- estimatedOutputTokens: 0
4490
- }
4491
- }));
4492
4527
  }
4493
- });
4494
- return { definition, observeLegacyExecution: observe };
4495
- }
4496
- async function handleReportRun(args, observe, tracker) {
4497
- const parsed = ReportRunPayloadSchema.safeParse({
4498
- runID: args.runID,
4499
- status: args.status,
4500
- fixes: args.fixes,
4501
- nodes: args.nodes,
4502
- ...args.parentSessionRef !== undefined ? { parentSessionRef: args.parentSessionRef } : {}
4503
- });
4504
- if (!parsed.success) {
4505
- const issues = parsed.error.issues.map((issue) => issue.message).join("; ");
4506
- return formatResponse({
4507
- result: "ineligible",
4508
- detail: `validation: ${issues}`
4509
- });
4510
4528
  }
4511
- const verification = crossVerify(parsed.data, tracker);
4512
- const warnings = formatWarnings(verification);
4513
- const verificationPair = {
4514
- nodesChecked: parsed.data.nodes.length,
4515
- unverified: verification.unverifiedModels.length,
4516
- mismatched: verification.modelMismatches.length
4517
- };
4518
- const run = buildObservedRun(parsed.data);
4519
- try {
4520
- const result = await observe(run, verificationPair);
4521
- const base = { result: result.kind };
4522
- const detail = result.kind === "ineligible" ? result.reason : result.kind === "observation-rejected" ? result.reason : result.kind === "contained-failure" ? result.detail : null;
4523
- return formatResponse({
4524
- ...base,
4525
- ...detail !== null ? { detail } : {},
4526
- ...warnings.length > 0 ? { warnings } : {}
4527
- });
4528
- } catch (error) {
4529
- return formatResponse({
4530
- result: "contained-failure",
4531
- detail: error instanceof Error ? error.message : String(error)
4532
- });
4529
+ return events.sort((a, b) => a.ts - b.ts);
4530
+ }
4531
+
4532
+ // src/telemetry/hash.ts
4533
+ var FNV_OFFSET_BASIS = 2166136261;
4534
+ var FNV_PRIME = 16777619;
4535
+ function hashPrompt(prompt) {
4536
+ let hash = FNV_OFFSET_BASIS;
4537
+ for (let index = 0;index < prompt.length; index += 1) {
4538
+ hash ^= prompt.charCodeAt(index);
4539
+ hash = Math.imul(hash, FNV_PRIME);
4533
4540
  }
4541
+ return `fnv1a32:${(hash >>> 0).toString(16).padStart(8, "0")}`;
4534
4542
  }
4535
4543
 
4536
4544
  // src/plugin/hooks.ts