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.
Files changed (46) hide show
  1. package/README.md +6 -1
  2. package/crates/sks-core/Cargo.lock +1 -1
  3. package/crates/sks-core/Cargo.toml +1 -1
  4. package/dist/cli/command-manifest-lite.js +3 -1
  5. package/dist/cli/command-registry.js +9 -1
  6. package/dist/cli/install-helpers-codex-lb-config.js +14 -4
  7. package/dist/cli/install-helpers-menubar.js +57 -0
  8. package/dist/cli/install-helpers.js +10 -1
  9. package/dist/commands/decision.js +7 -0
  10. package/dist/config/skills-manifest.json +1 -1
  11. package/dist/core/agents/native-worker-backend-router.js +7 -2
  12. package/dist/core/codex-app/menubar/constants.js +2 -0
  13. package/dist/core/codex-lb/desktop-controller-v3/provider-commands.js +9 -0
  14. package/dist/core/decisions/cli.js +324 -0
  15. package/dist/core/decisions/config.js +109 -0
  16. package/dist/core/decisions/evaluation.js +62 -0
  17. package/dist/core/decisions/integration.js +297 -0
  18. package/dist/core/decisions/openrouter.js +270 -0
  19. package/dist/core/decisions/policy.js +393 -0
  20. package/dist/core/decisions/questions.js +215 -0
  21. package/dist/core/decisions/receipt.js +41 -0
  22. package/dist/core/decisions/recovery.js +39 -0
  23. package/dist/core/decisions/routing.js +58 -0
  24. package/dist/core/decisions/state.js +173 -0
  25. package/dist/core/decisions/types.js +69 -0
  26. package/dist/core/feature-fixtures.js +1 -0
  27. package/dist/core/feature-registry.js +1 -0
  28. package/dist/core/hooks-runtime/subagent-context.js +5 -3
  29. package/dist/core/hooks-runtime/subagent-spawn-policy.js +9 -3
  30. package/dist/core/hooks-runtime.js +25 -1
  31. package/dist/core/provider/model-router.js +3 -3
  32. package/dist/core/routes.js +2 -1
  33. package/dist/core/subagents/model-policy.js +15 -0
  34. package/dist/core/subagents/official-subagent-lock.js +15 -0
  35. package/dist/core/subagents/official-subagent-preparation.js +265 -24
  36. package/dist/core/subagents/official-subagent-prompt.js +56 -13
  37. package/dist/core/update/update-migration-state/retired-local-decision.js +203 -0
  38. package/dist/core/update/update-migration-state.js +6 -0
  39. package/dist/core/version.js +1 -1
  40. package/dist/native/sks-menubar/Sources/ControlCenterWindowController.swift +6 -3
  41. package/dist/native/sks-menubar/Sources/LocalDecisionModels.swift +166 -0
  42. package/dist/native/sks-menubar/Sources/LocalDecisionViewController.swift +200 -0
  43. package/dist/native/sks-menubar/Sources/OverviewViewController.swift +4 -0
  44. package/dist/native/sks-menubar/Sources/SidebarItem.swift +2 -0
  45. package/dist/scripts/current-surface-update-e2e-check.js +1 -0
  46. 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
+ }