sneakoscope 10.2.0 → 10.3.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/README.md +6 -1
- package/crates/sks-core/Cargo.lock +1 -1
- package/crates/sks-core/Cargo.toml +1 -1
- package/dist/cli/command-manifest-lite.js +3 -1
- package/dist/cli/command-registry.js +9 -1
- package/dist/cli/install-helpers-codex-lb-config.js +14 -4
- package/dist/cli/install-helpers-menubar.js +57 -0
- package/dist/cli/install-helpers.js +10 -1
- package/dist/commands/decision.js +7 -0
- package/dist/config/skills-manifest.json +1 -1
- package/dist/core/agents/native-worker-backend-router.js +7 -2
- package/dist/core/codex-app/menubar/constants.js +2 -0
- package/dist/core/codex-lb/desktop-controller-v3/provider-commands.js +9 -0
- package/dist/core/decisions/cli.js +324 -0
- package/dist/core/decisions/config.js +109 -0
- package/dist/core/decisions/evaluation.js +62 -0
- package/dist/core/decisions/integration.js +297 -0
- package/dist/core/decisions/openrouter.js +270 -0
- package/dist/core/decisions/policy.js +393 -0
- package/dist/core/decisions/questions.js +215 -0
- package/dist/core/decisions/receipt.js +41 -0
- package/dist/core/decisions/recovery.js +39 -0
- package/dist/core/decisions/routing.js +58 -0
- package/dist/core/decisions/state.js +173 -0
- package/dist/core/decisions/types.js +69 -0
- package/dist/core/feature-fixtures.js +1 -0
- package/dist/core/feature-registry.js +1 -0
- package/dist/core/hooks-runtime/subagent-context.js +5 -3
- package/dist/core/hooks-runtime/subagent-spawn-policy.js +9 -3
- package/dist/core/hooks-runtime.js +25 -1
- package/dist/core/provider/model-router.js +3 -3
- package/dist/core/routes.js +2 -1
- package/dist/core/subagents/model-policy.js +15 -0
- package/dist/core/subagents/official-subagent-lock.js +15 -0
- package/dist/core/subagents/official-subagent-preparation.js +265 -24
- package/dist/core/subagents/official-subagent-prompt.js +56 -13
- package/dist/core/update/update-migration-state/retired-local-decision.js +203 -0
- package/dist/core/update/update-migration-state.js +6 -0
- package/dist/core/version.js +1 -1
- package/dist/native/sks-menubar/Sources/ControlCenterWindowController.swift +6 -3
- package/dist/native/sks-menubar/Sources/LocalDecisionModels.swift +166 -0
- package/dist/native/sks-menubar/Sources/LocalDecisionViewController.swift +200 -0
- package/dist/native/sks-menubar/Sources/OverviewViewController.swift +4 -0
- package/dist/native/sks-menubar/Sources/SidebarItem.swift +2 -0
- package/dist/scripts/current-surface-update-e2e-check.js +1 -0
- package/package.json +1 -1
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
import fsp from 'node:fs/promises';
|
|
2
|
+
import os from 'node:os';
|
|
3
|
+
import path from 'node:path';
|
|
4
|
+
import { nowIso, readJson, writeJsonAtomic } from '../fsx.js';
|
|
5
|
+
import { ensureConfinedDirectory, inspectConfinedPath, ManagedPathSafetyError } from '../managed-path-safety.js';
|
|
6
|
+
import { DESIGN_DEFAULTS } from './types.js';
|
|
7
|
+
export const DECISION_CONFIG_SCHEMA = 'sks.jev-decision-config.v1';
|
|
8
|
+
const CONFIG_DIRNAME = 'decisions';
|
|
9
|
+
export function decisionPaths(env = process.env) {
|
|
10
|
+
const sksHome = path.resolve(env.SKS_HOME || path.join(env.HOME || os.homedir(), '.sneakoscope'));
|
|
11
|
+
const configDir = path.join(sksHome, CONFIG_DIRNAME);
|
|
12
|
+
return {
|
|
13
|
+
sksHome,
|
|
14
|
+
configDir,
|
|
15
|
+
configPath: path.join(configDir, 'config.json')
|
|
16
|
+
};
|
|
17
|
+
}
|
|
18
|
+
export function defaultDecisionConfig() {
|
|
19
|
+
return {
|
|
20
|
+
schema: DECISION_CONFIG_SCHEMA,
|
|
21
|
+
mode: DESIGN_DEFAULTS.mode,
|
|
22
|
+
provider: 'openrouter',
|
|
23
|
+
model: DESIGN_DEFAULTS.model,
|
|
24
|
+
consentCloud: false,
|
|
25
|
+
consentAt: null,
|
|
26
|
+
capabilities: {
|
|
27
|
+
context: capability(false, false, 'not_enabled'),
|
|
28
|
+
plan: capability(false, false, 'not_enabled'),
|
|
29
|
+
recovery: capability(false, false, 'unsupported_no_sks_handler')
|
|
30
|
+
},
|
|
31
|
+
updatedAt: null
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
export async function readDecisionConfig(env = process.env) {
|
|
35
|
+
const paths = decisionPaths(env);
|
|
36
|
+
const current = await readJson(paths.configPath, null).catch(() => null);
|
|
37
|
+
return current ? normalizeConfig(current) : defaultDecisionConfig();
|
|
38
|
+
}
|
|
39
|
+
export async function writeDecisionConfig(patch, env = process.env) {
|
|
40
|
+
const paths = decisionPaths(env);
|
|
41
|
+
const current = await readDecisionConfig(env);
|
|
42
|
+
const next = {
|
|
43
|
+
...current,
|
|
44
|
+
...(patch.mode === undefined ? {} : { mode: patch.mode }),
|
|
45
|
+
...(patch.model === undefined ? {} : { model: patch.model }),
|
|
46
|
+
...(patch.consentCloud === undefined ? {} : { consentCloud: patch.consentCloud }),
|
|
47
|
+
...(patch.consentAt === undefined ? {} : { consentAt: patch.consentAt }),
|
|
48
|
+
capabilities: {
|
|
49
|
+
context: patch.capabilities?.context || current.capabilities.context,
|
|
50
|
+
plan: patch.capabilities?.plan || current.capabilities.plan,
|
|
51
|
+
recovery: current.capabilities.recovery
|
|
52
|
+
},
|
|
53
|
+
updatedAt: nowIso()
|
|
54
|
+
};
|
|
55
|
+
if (next.mode !== 'off' && next.mode !== 'jev')
|
|
56
|
+
throw new Error(`invalid_decision_mode:${String(next.mode)}`);
|
|
57
|
+
if (next.mode === 'jev' && next.consentCloud !== true)
|
|
58
|
+
throw new Error('jev_cloud_consent_required');
|
|
59
|
+
if (next.model !== DESIGN_DEFAULTS.model)
|
|
60
|
+
throw new Error(`unsupported_decision_model:${next.model}`);
|
|
61
|
+
await fsp.mkdir(paths.sksHome, { recursive: true });
|
|
62
|
+
await ensureConfinedDirectory(paths.sksHome, paths.configDir);
|
|
63
|
+
const inspected = await inspectConfinedPath(paths.sksHome, paths.configPath);
|
|
64
|
+
if (inspected.leafSymlink) {
|
|
65
|
+
throw new ManagedPathSafetyError('managed_path_leaf_symlink_refused', inspected.path);
|
|
66
|
+
}
|
|
67
|
+
await writeJsonAtomic(inspected.path, next, { mode: 0o600 });
|
|
68
|
+
return next;
|
|
69
|
+
}
|
|
70
|
+
export function jevEnabled(config) {
|
|
71
|
+
return config.mode === 'jev' && config.consentCloud === true;
|
|
72
|
+
}
|
|
73
|
+
function normalizeConfig(raw) {
|
|
74
|
+
const fallback = defaultDecisionConfig();
|
|
75
|
+
if (!isRecord(raw) || raw.schema !== DECISION_CONFIG_SCHEMA)
|
|
76
|
+
return fallback;
|
|
77
|
+
const mode = raw.mode === 'jev' ? 'jev' : 'off';
|
|
78
|
+
const consentCloud = raw.consentCloud === true;
|
|
79
|
+
return {
|
|
80
|
+
schema: DECISION_CONFIG_SCHEMA,
|
|
81
|
+
mode: mode === 'jev' && consentCloud ? 'jev' : 'off',
|
|
82
|
+
provider: 'openrouter',
|
|
83
|
+
model: typeof raw.model === 'string' && raw.model.trim() ? raw.model.trim() : DESIGN_DEFAULTS.model,
|
|
84
|
+
consentCloud,
|
|
85
|
+
consentAt: typeof raw.consentAt === 'string' ? raw.consentAt : null,
|
|
86
|
+
capabilities: {
|
|
87
|
+
context: normalizeCapability(raw.capabilities, 'context', fallback.capabilities.context),
|
|
88
|
+
plan: normalizeCapability(raw.capabilities, 'plan', fallback.capabilities.plan),
|
|
89
|
+
recovery: capability(false, false, 'unsupported_no_sks_handler')
|
|
90
|
+
},
|
|
91
|
+
updatedAt: typeof raw.updatedAt === 'string' ? raw.updatedAt : null
|
|
92
|
+
};
|
|
93
|
+
}
|
|
94
|
+
function normalizeCapability(raw, key, fallback) {
|
|
95
|
+
if (!isRecord(raw) || !isRecord(raw[key]))
|
|
96
|
+
return fallback;
|
|
97
|
+
const row = raw[key];
|
|
98
|
+
return {
|
|
99
|
+
ready: row.ready === true,
|
|
100
|
+
promoted: row.promoted === true,
|
|
101
|
+
reason: typeof row.reason === 'string' ? row.reason : fallback.reason
|
|
102
|
+
};
|
|
103
|
+
}
|
|
104
|
+
function capability(ready, promoted, reason) {
|
|
105
|
+
return { ready, promoted, reason };
|
|
106
|
+
}
|
|
107
|
+
function isRecord(value) {
|
|
108
|
+
return Boolean(value) && typeof value === 'object' && !Array.isArray(value);
|
|
109
|
+
}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
export function percentile(values, p) {
|
|
2
|
+
const sorted = values.filter((value) => Number.isFinite(value)).sort((left, right) => left - right);
|
|
3
|
+
if (!sorted.length)
|
|
4
|
+
return null;
|
|
5
|
+
const rank = Math.min(sorted.length - 1, Math.max(0, Math.ceil((p / 100) * sorted.length) - 1));
|
|
6
|
+
return sorted[rank] ?? null;
|
|
7
|
+
}
|
|
8
|
+
export const EVALUATION_SCHEMA = 'sks.jev-evaluation.v1';
|
|
9
|
+
export function buildEvaluationReport(input) {
|
|
10
|
+
const unavailable = [];
|
|
11
|
+
const rows = [...input.rows];
|
|
12
|
+
if (rows.length === 0)
|
|
13
|
+
unavailable.push('no_labeled_tasks');
|
|
14
|
+
const success = rows.map((row) => row.success).filter((value) => value !== null);
|
|
15
|
+
const escaped = rows.map((row) => row.escapedFailure).filter((value) => value !== null);
|
|
16
|
+
const wall = rows.map((row) => row.wallClockMs).filter((value) => Number.isFinite(value));
|
|
17
|
+
const overhead = rows.map((row) => row.jevOverheadMs).filter((value) => Number.isFinite(value));
|
|
18
|
+
const tokenKnown = rows.every((row) => row.tokenEvidence === 'provider_response');
|
|
19
|
+
if (!tokenKnown)
|
|
20
|
+
unavailable.push('token_savings_unavailable');
|
|
21
|
+
const inputTokens = tokenKnown
|
|
22
|
+
? sum(rows.map((row) => row.inputTokens))
|
|
23
|
+
: null;
|
|
24
|
+
const outputTokens = tokenKnown
|
|
25
|
+
? sum(rows.map((row) => row.outputTokens))
|
|
26
|
+
: null;
|
|
27
|
+
const cost = rows.some((row) => row.reportedCost === null)
|
|
28
|
+
? null
|
|
29
|
+
: sum(rows.map((row) => row.reportedCost));
|
|
30
|
+
if (cost === null)
|
|
31
|
+
unavailable.push('cost_unavailable');
|
|
32
|
+
const successes = rows.filter((row) => row.success === true).length;
|
|
33
|
+
const costPerSuccess = cost === null || successes === 0 ? null : cost / successes;
|
|
34
|
+
const coverage = rows.filter((row) => row.coveragePreserved).length;
|
|
35
|
+
return {
|
|
36
|
+
schema: EVALUATION_SCHEMA,
|
|
37
|
+
evidenceLevel: input.evidenceLevel || 'synthetic',
|
|
38
|
+
live: input.live === true,
|
|
39
|
+
arms: [...new Set(rows.map((row) => row.arm))],
|
|
40
|
+
taskCount: rows.length,
|
|
41
|
+
metrics: {
|
|
42
|
+
taskSuccessRate: success.length ? success.filter(Boolean).length / success.length : null,
|
|
43
|
+
escapedFailureRate: escaped.length ? escaped.filter(Boolean).length / escaped.length : null,
|
|
44
|
+
wallClockP50Ms: percentile(wall, 50),
|
|
45
|
+
wallClockP95Ms: percentile(wall, 95),
|
|
46
|
+
jevOverheadP50Ms: percentile(overhead, 50),
|
|
47
|
+
llmRejudgeCalls: rows.reduce((sumValue, row) => sumValue + row.llmRejudgeCalls, 0),
|
|
48
|
+
inputTokens,
|
|
49
|
+
outputTokens,
|
|
50
|
+
reportedCost: cost,
|
|
51
|
+
costPerSuccessfulTask: costPerSuccess,
|
|
52
|
+
coveragePreservedRate: rows.length ? coverage / rows.length : null
|
|
53
|
+
},
|
|
54
|
+
unavailableReasons: [...unavailable],
|
|
55
|
+
receipts: [...(input.receipts || [])]
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
function sum(values) {
|
|
59
|
+
if (values.some((value) => value === null || !Number.isFinite(value)))
|
|
60
|
+
return null;
|
|
61
|
+
return values.reduce((total, value) => total + (value || 0), 0);
|
|
62
|
+
}
|
|
@@ -0,0 +1,297 @@
|
|
|
1
|
+
import { sha256 } from '../fsx.js';
|
|
2
|
+
import { resolveOpenRouterApiKey } from '../providers/openrouter/openrouter-secret-store.js';
|
|
3
|
+
import { jevEnabled, readDecisionConfig } from './config.js';
|
|
4
|
+
import { requestOpenRouterDecision } from './openrouter.js';
|
|
5
|
+
import { compileDecision } from './policy.js';
|
|
6
|
+
import { buildDecisionBundle, validatePlanCoverage } from './questions.js';
|
|
7
|
+
import { applyRecoveryEffect, listProductionRecoveryCandidates } from './recovery.js';
|
|
8
|
+
import { assembleRoutingSelection, buildRoutingCandidates } from './routing.js';
|
|
9
|
+
import { buildDecisionReceipt } from './receipt.js';
|
|
10
|
+
import { applyOptionalContextSelection, graphFileDigest, hydrateContextCandidates, sourceSnapshotDigest } from './state.js';
|
|
11
|
+
import { DESIGN_DEFAULTS, POLICY_REVISION, UNKNOWN_USAGE } from './types.js';
|
|
12
|
+
let testOverrides = null;
|
|
13
|
+
const appliedEffects = new Set();
|
|
14
|
+
export function setDecisionTestOverrides(overrides) {
|
|
15
|
+
testOverrides = overrides;
|
|
16
|
+
}
|
|
17
|
+
function activeOverrides() {
|
|
18
|
+
return process.env.SKS_JEV_DECISION_TEST_OVERRIDES === '1' ? testOverrides : null;
|
|
19
|
+
}
|
|
20
|
+
export async function decideOfficialSubagentPreparation(input) {
|
|
21
|
+
const started = Date.now();
|
|
22
|
+
try {
|
|
23
|
+
return await decideOfficialSubagentPreparationInner(input, started);
|
|
24
|
+
}
|
|
25
|
+
catch (error) {
|
|
26
|
+
if (error instanceof Error && error.name === 'AssertionError')
|
|
27
|
+
throw error;
|
|
28
|
+
return keep(input, 'transport_error', started);
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
async function decideOfficialSubagentPreparationInner(input, started) {
|
|
32
|
+
const overrides = activeOverrides();
|
|
33
|
+
const env = input.env || process.env;
|
|
34
|
+
const config = overrides?.config ?? await readDecisionConfig(env);
|
|
35
|
+
const baseline = keep(input, 'off', started);
|
|
36
|
+
if (!jevEnabled(config)) {
|
|
37
|
+
overrides?.observe?.({ mode: config.mode, eligible: false, compiled: baseline.compiled, receipt: baseline.receipt });
|
|
38
|
+
return baseline;
|
|
39
|
+
}
|
|
40
|
+
const resolved = await resolveOpenRouterApiKey({ env });
|
|
41
|
+
if (!resolved.key) {
|
|
42
|
+
const missing = keep(input, 'missing_key', started);
|
|
43
|
+
overrides?.observe?.({ mode: config.mode, eligible: false, compiled: missing.compiled, receipt: missing.receipt });
|
|
44
|
+
return missing;
|
|
45
|
+
}
|
|
46
|
+
const contextCandidates = config.capabilities.context.ready
|
|
47
|
+
? await hydrateContextCandidates(input.root, input.attention, input.changedPaths || [])
|
|
48
|
+
: [];
|
|
49
|
+
const planCandidates = config.capabilities.plan.ready && input.requestedSource === 'automatic'
|
|
50
|
+
? buildAutomaticPlanCandidates(input)
|
|
51
|
+
: [];
|
|
52
|
+
const routingCandidates = input.requestedSource === 'automatic'
|
|
53
|
+
? buildRoutingCandidates({ roles: input.routingRoles || [] })
|
|
54
|
+
: [];
|
|
55
|
+
const recoveryCandidates = config.capabilities.recovery.ready
|
|
56
|
+
? [...listProductionRecoveryCandidates()]
|
|
57
|
+
: [];
|
|
58
|
+
const optionalContext = contextCandidates.filter((row) => !row.pinned && row.excerpt);
|
|
59
|
+
const eligible = planCandidates.length > 1 || routingCandidates.length > 0 || optionalContext.length > 0 || recoveryCandidates.length > 0;
|
|
60
|
+
if (!eligible) {
|
|
61
|
+
const compiled = keep(input, 'no_alternative', started);
|
|
62
|
+
overrides?.observe?.({ mode: config.mode, eligible: false, compiled: compiled.compiled, receipt: compiled.receipt });
|
|
63
|
+
return compiled;
|
|
64
|
+
}
|
|
65
|
+
const sourceDigest = await sourceSnapshotDigest(input.root);
|
|
66
|
+
const graphDigest = input.attention?.snapshot_hash || await graphFileDigest(input.root);
|
|
67
|
+
const bundle = buildDecisionBundle({
|
|
68
|
+
projectId: sha256(input.root).slice(0, 32),
|
|
69
|
+
workflowRunId: input.workflowRunId,
|
|
70
|
+
workflowRevision: input.workflowRevision,
|
|
71
|
+
sourceDigest,
|
|
72
|
+
graphDigest,
|
|
73
|
+
goal: input.goal,
|
|
74
|
+
planCandidates,
|
|
75
|
+
contextCandidates,
|
|
76
|
+
recoveryCandidates,
|
|
77
|
+
routingCandidates,
|
|
78
|
+
baselinePlanId: planCandidates[0]?.id ?? null,
|
|
79
|
+
requiredSliceIds: planCandidates[0]?.sliceIds ?? input.slices.map((slice) => slice.id),
|
|
80
|
+
requiredVerificationIds: ['review_coverage']
|
|
81
|
+
});
|
|
82
|
+
const fetchImpl = input.fetchImpl || overrides?.fetchImpl;
|
|
83
|
+
const transport = await requestOpenRouterDecision(bundle, {
|
|
84
|
+
env,
|
|
85
|
+
deadlineMs: input.deadlineMs ?? DESIGN_DEFAULTS.deadlineMs,
|
|
86
|
+
...(fetchImpl ? { fetchImpl } : {}),
|
|
87
|
+
...(input.signal ? { signal: input.signal } : {})
|
|
88
|
+
});
|
|
89
|
+
const compiled = transport.ok
|
|
90
|
+
? compileDecision(bundle, transport.response)
|
|
91
|
+
: {
|
|
92
|
+
kind: 'keep_baseline',
|
|
93
|
+
binding: bundle.binding,
|
|
94
|
+
reason: transport.reason,
|
|
95
|
+
usage: transport.usage
|
|
96
|
+
};
|
|
97
|
+
const applied = compiled.kind === 'apply'
|
|
98
|
+
? applyEffects(input.attention, contextCandidates, planCandidates, compiled)
|
|
99
|
+
: {
|
|
100
|
+
attention: input.attention,
|
|
101
|
+
selectedPlan: null,
|
|
102
|
+
selectedRouting: null,
|
|
103
|
+
selectedContextIds: null,
|
|
104
|
+
consumptionEvidence: null
|
|
105
|
+
};
|
|
106
|
+
const receipt = buildDecisionReceipt({
|
|
107
|
+
binding: bundle.binding,
|
|
108
|
+
compiled,
|
|
109
|
+
result: compiled.kind === 'apply' ? 'applied' : 'kept_baseline',
|
|
110
|
+
reason: compiled.kind === 'apply' ? compiled.effects.map((effect) => effect.kind).join(',') : compiled.reason,
|
|
111
|
+
elapsedMs: Date.now() - started,
|
|
112
|
+
cacheHit: transport.ok && transport.cacheHit,
|
|
113
|
+
resolvedModel: transport.ok ? transport.resolvedModel : null,
|
|
114
|
+
responseId: transport.ok ? transport.responseId : null,
|
|
115
|
+
consumptionEvidence: applied.consumptionEvidence,
|
|
116
|
+
env
|
|
117
|
+
});
|
|
118
|
+
const result = {
|
|
119
|
+
compiled,
|
|
120
|
+
receipt,
|
|
121
|
+
attention: applied.attention,
|
|
122
|
+
selectedPlan: applied.selectedPlan,
|
|
123
|
+
selectedRouting: applied.selectedRouting,
|
|
124
|
+
selectedContextIds: applied.selectedContextIds,
|
|
125
|
+
llmRejudgeCalls: 0,
|
|
126
|
+
bundle
|
|
127
|
+
};
|
|
128
|
+
overrides?.observe?.({ mode: config.mode, eligible: true, compiled, receipt });
|
|
129
|
+
return result;
|
|
130
|
+
}
|
|
131
|
+
export async function consultJevTurnModel(input) {
|
|
132
|
+
const overrides = activeOverrides();
|
|
133
|
+
const env = input.env || process.env;
|
|
134
|
+
const config = overrides?.config ?? await readDecisionConfig(env);
|
|
135
|
+
if (!jevEnabled(config))
|
|
136
|
+
return { called: false, model: null, reason: 'off' };
|
|
137
|
+
const resolved = await resolveOpenRouterApiKey({ env });
|
|
138
|
+
if (!resolved.key)
|
|
139
|
+
return { called: false, model: null, reason: 'missing_key' };
|
|
140
|
+
const prompt = String(input.prompt || '').trim();
|
|
141
|
+
if (!prompt)
|
|
142
|
+
return { called: false, model: null, reason: 'empty_prompt' };
|
|
143
|
+
const bundle = buildDecisionBundle({
|
|
144
|
+
projectId: sha256(input.root).slice(0, 32),
|
|
145
|
+
workflowRunId: 'turn',
|
|
146
|
+
workflowRevision: 'turn',
|
|
147
|
+
sourceDigest: 'turn',
|
|
148
|
+
graphDigest: null,
|
|
149
|
+
goal: prompt,
|
|
150
|
+
routingCandidates: [{ id: 'turn', summary: prompt.slice(0, 240) }]
|
|
151
|
+
});
|
|
152
|
+
const transport = await requestOpenRouterDecision(bundle, {
|
|
153
|
+
env,
|
|
154
|
+
deadlineMs: DESIGN_DEFAULTS.deadlineMs,
|
|
155
|
+
...(overrides?.fetchImpl ? { fetchImpl: overrides.fetchImpl } : {})
|
|
156
|
+
});
|
|
157
|
+
if (!transport.ok)
|
|
158
|
+
return { called: true, model: null, reason: transport.reason };
|
|
159
|
+
const compiled = compileDecision(bundle, transport.response);
|
|
160
|
+
if (compiled.kind !== 'apply')
|
|
161
|
+
return { called: true, model: null, reason: compiled.reason };
|
|
162
|
+
const selected = assembleRoutingSelection(compiled.effects.flatMap((effect) => (effect.kind === 'select_routing' ? [{ roleId: effect.roleId, model: effect.model }] : [])));
|
|
163
|
+
const model = selected?.models.turn || null;
|
|
164
|
+
return { called: true, model, reason: model ? 'applied' : 'keep_baseline' };
|
|
165
|
+
}
|
|
166
|
+
export function effectAlreadyConsumed(identity) {
|
|
167
|
+
return appliedEffects.has(identity);
|
|
168
|
+
}
|
|
169
|
+
export function markEffectConsumed(identity) {
|
|
170
|
+
if (appliedEffects.has(identity))
|
|
171
|
+
return false;
|
|
172
|
+
if (appliedEffects.size >= 256) {
|
|
173
|
+
const oldest = appliedEffects.values().next().value;
|
|
174
|
+
if (oldest !== undefined)
|
|
175
|
+
appliedEffects.delete(oldest);
|
|
176
|
+
}
|
|
177
|
+
appliedEffects.add(identity);
|
|
178
|
+
return true;
|
|
179
|
+
}
|
|
180
|
+
export async function dispatchBoundRecovery(input) {
|
|
181
|
+
if (!markEffectConsumed(input.consumptionIdentity)) {
|
|
182
|
+
return { invoked: false, reason: 'duplicate_delivery', consumptionEvidence: null };
|
|
183
|
+
}
|
|
184
|
+
const result = await applyRecoveryEffect(input);
|
|
185
|
+
if (!result.ok)
|
|
186
|
+
return { invoked: false, reason: result.reason, consumptionEvidence: null };
|
|
187
|
+
return { invoked: true, reason: 'applied', consumptionEvidence: result.consumptionEvidence };
|
|
188
|
+
}
|
|
189
|
+
function applyEffects(attention, contextCandidates, planCandidates, compiled) {
|
|
190
|
+
let nextAttention = attention;
|
|
191
|
+
let selectedPlan = null;
|
|
192
|
+
let selectedContextIds = null;
|
|
193
|
+
const evidence = [];
|
|
194
|
+
const routingEffects = [];
|
|
195
|
+
for (const effect of compiled.effects) {
|
|
196
|
+
if (effect.kind === 'select_optional_context') {
|
|
197
|
+
nextAttention = applyOptionalContextSelection(attention, contextCandidates, effect.keepIds);
|
|
198
|
+
selectedContextIds = effect.keepIds;
|
|
199
|
+
evidence.push(`context:${effect.keepIds.join(',')}`);
|
|
200
|
+
}
|
|
201
|
+
if (effect.kind === 'select_plan') {
|
|
202
|
+
selectedPlan = planCandidates.find((row) => row.id === effect.planId) || null;
|
|
203
|
+
if (selectedPlan)
|
|
204
|
+
evidence.push(`plan:${selectedPlan.id}`);
|
|
205
|
+
}
|
|
206
|
+
if (effect.kind === 'select_routing') {
|
|
207
|
+
routingEffects.push({ roleId: effect.roleId, model: effect.model });
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
const selectedRouting = assembleRoutingSelection(routingEffects);
|
|
211
|
+
if (selectedRouting) {
|
|
212
|
+
evidence.push(...Object.entries(selectedRouting.models).map(([roleId, model]) => `routing:${roleId}=${model}`));
|
|
213
|
+
}
|
|
214
|
+
return {
|
|
215
|
+
attention: nextAttention,
|
|
216
|
+
selectedPlan,
|
|
217
|
+
selectedRouting,
|
|
218
|
+
selectedContextIds,
|
|
219
|
+
consumptionEvidence: evidence.length ? evidence.join('|') : null
|
|
220
|
+
};
|
|
221
|
+
}
|
|
222
|
+
function buildAutomaticPlanCandidates(input) {
|
|
223
|
+
const slices = input.slices.filter((slice) => slice.id);
|
|
224
|
+
const sliceIds = slices.map((slice) => slice.id);
|
|
225
|
+
const workerCount = Math.max(1, input.requestedSubagents);
|
|
226
|
+
if (workerCount < 2)
|
|
227
|
+
return [];
|
|
228
|
+
const verification = ['review_coverage'];
|
|
229
|
+
const covered = sliceIds.length > 0 ? sliceIds : ['parent_owned_decomposition'];
|
|
230
|
+
const baselineGroups = slices.length > 0
|
|
231
|
+
? slices.map((slice, index) => ({
|
|
232
|
+
id: `G${index + 1}`,
|
|
233
|
+
sliceIds: [slice.id],
|
|
234
|
+
role: slice.agent || (slice.kind === 'expert' ? 'expert' : 'worker'),
|
|
235
|
+
effort: slice.kind === 'expert' ? 'max' : 'low'
|
|
236
|
+
}))
|
|
237
|
+
: [{ id: 'G1', sliceIds: covered, role: 'expert', effort: 'max' }];
|
|
238
|
+
const baseline = {
|
|
239
|
+
id: 'baseline',
|
|
240
|
+
summary: sliceIds.length > 0
|
|
241
|
+
? `Execute every required slice with ${workerCount} permitted workers.`
|
|
242
|
+
: `Execute the automatic parent-owned work with ${workerCount} permitted workers. The parent still decomposes slices.`,
|
|
243
|
+
sliceIds: covered,
|
|
244
|
+
groups: baselineGroups,
|
|
245
|
+
workerCount,
|
|
246
|
+
requiredVerificationIds: verification
|
|
247
|
+
};
|
|
248
|
+
const grouped = {
|
|
249
|
+
id: 'grouped',
|
|
250
|
+
summary: sliceIds.length > 0
|
|
251
|
+
? 'Execute every required slice in one permitted worker group, preserving full coverage.'
|
|
252
|
+
: 'Execute the automatic parent-owned work in one permitted worker group. The parent still decomposes slices.',
|
|
253
|
+
sliceIds: covered,
|
|
254
|
+
groups: [{ id: 'G1', sliceIds: covered, role: 'expert', effort: 'max' }],
|
|
255
|
+
workerCount: 1,
|
|
256
|
+
requiredVerificationIds: verification
|
|
257
|
+
};
|
|
258
|
+
const candidates = [baseline, grouped].filter((candidate) => validatePlanCoverage(covered, candidate).length === 0);
|
|
259
|
+
const workerCounts = new Set(candidates.map((candidate) => candidate.workerCount));
|
|
260
|
+
if (candidates.length < 2 || workerCounts.size < 2)
|
|
261
|
+
return [];
|
|
262
|
+
return candidates;
|
|
263
|
+
}
|
|
264
|
+
function keep(input, reason, started) {
|
|
265
|
+
const compiled = {
|
|
266
|
+
kind: 'keep_baseline',
|
|
267
|
+
binding: {
|
|
268
|
+
projectId: sha256(input.root).slice(0, 32),
|
|
269
|
+
workflowRunId: input.workflowRunId,
|
|
270
|
+
workflowRevision: input.workflowRevision,
|
|
271
|
+
sourceDigest: 'uncomputed',
|
|
272
|
+
graphDigest: input.attention?.snapshot_hash ?? null,
|
|
273
|
+
candidateDigest: 'none',
|
|
274
|
+
questionDigest: 'none',
|
|
275
|
+
policyRevision: POLICY_REVISION,
|
|
276
|
+
requestedModel: DESIGN_DEFAULTS.model
|
|
277
|
+
},
|
|
278
|
+
reason,
|
|
279
|
+
usage: { ...UNKNOWN_USAGE }
|
|
280
|
+
};
|
|
281
|
+
return {
|
|
282
|
+
compiled,
|
|
283
|
+
receipt: buildDecisionReceipt({
|
|
284
|
+
binding: compiled.binding,
|
|
285
|
+
compiled,
|
|
286
|
+
result: 'kept_baseline',
|
|
287
|
+
reason,
|
|
288
|
+
elapsedMs: Date.now() - started
|
|
289
|
+
}),
|
|
290
|
+
attention: input.attention,
|
|
291
|
+
selectedPlan: null,
|
|
292
|
+
selectedRouting: null,
|
|
293
|
+
selectedContextIds: null,
|
|
294
|
+
llmRejudgeCalls: 0,
|
|
295
|
+
bundle: null
|
|
296
|
+
};
|
|
297
|
+
}
|