sneakoscope 10.3.1 → 10.3.2
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 +1 -1
- package/crates/sks-core/Cargo.lock +1 -1
- package/crates/sks-core/Cargo.toml +1 -1
- package/dist/config/skills-manifest.json +1 -1
- package/dist/core/decisions/integration.js +24 -12
- package/dist/core/decisions/policy.js +11 -1
- package/dist/core/decisions/questions.js +14 -0
- package/dist/core/decisions/types.js +1 -0
- package/dist/core/hooks-runtime/hook-io.js +3 -1
- package/dist/core/hooks-runtime/jev-spawn-routing.js +50 -0
- package/dist/core/hooks-runtime.js +14 -4
- package/dist/core/routes.js +3 -0
- package/dist/core/subagents/official-subagent-preparation.js +8 -1
- package/dist/core/subagents/official-subagent-prompt.js +2 -0
- package/dist/core/version.js +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
Sneakoscope Codex (`sks`) is an open-source trust layer for Codex CLI and ChatGPT Desktop. It coordinates bounded AI coding agents, records machine-verifiable evidence, preserves project memory, and blocks release claims that are not supported by current tests or artifacts. Search visibility outcomes are measured separately; SKS does not promise rankings or traffic.
|
|
17
17
|
<!-- END SKS SEARCH VISIBILITY MARKETING -->
|
|
18
18
|
|
|
19
|
-
Current package: **SKS 10.3.
|
|
19
|
+
Current package: **SKS 10.3.2**. Install the latest stable release from npm.
|
|
20
20
|
|
|
21
21
|
[Quick start](#install-in-one-command) · [Commands](#everyday-commands) · [SKS Center](#sks-center-macos) · [Documentation](#documentation) · [Changelog](CHANGELOG.md)
|
|
22
22
|
|
|
@@ -8,7 +8,7 @@ import { applyRecoveryEffect, listProductionRecoveryCandidates } from './recover
|
|
|
8
8
|
import { assembleRoutingSelection, buildRoutingCandidates } from './routing.js';
|
|
9
9
|
import { buildDecisionReceipt } from './receipt.js';
|
|
10
10
|
import { applyOptionalContextSelection, graphFileDigest, hydrateContextCandidates, sourceSnapshotDigest } from './state.js';
|
|
11
|
-
import { DESIGN_DEFAULTS, POLICY_REVISION, UNKNOWN_USAGE } from './types.js';
|
|
11
|
+
import { DESIGN_DEFAULTS, POLICY_REVISION, UNKNOWN_USAGE, sealedRoutingModel } from './types.js';
|
|
12
12
|
let testOverrides = null;
|
|
13
13
|
const appliedEffects = new Set();
|
|
14
14
|
export function setDecisionTestOverrides(overrides) {
|
|
@@ -101,6 +101,7 @@ async function decideOfficialSubagentPreparationInner(input, started) {
|
|
|
101
101
|
selectedPlan: null,
|
|
102
102
|
selectedRouting: null,
|
|
103
103
|
selectedContextIds: null,
|
|
104
|
+
omittedRoutingRoles: [],
|
|
104
105
|
consumptionEvidence: null
|
|
105
106
|
};
|
|
106
107
|
const receipt = buildDecisionReceipt({
|
|
@@ -122,6 +123,7 @@ async function decideOfficialSubagentPreparationInner(input, started) {
|
|
|
122
123
|
selectedPlan: applied.selectedPlan,
|
|
123
124
|
selectedRouting: applied.selectedRouting,
|
|
124
125
|
selectedContextIds: applied.selectedContextIds,
|
|
126
|
+
omittedRoutingRoles: applied.omittedRoutingRoles,
|
|
125
127
|
llmRejudgeCalls: 0,
|
|
126
128
|
bundle
|
|
127
129
|
};
|
|
@@ -132,22 +134,24 @@ export async function consultJevTurnModel(input) {
|
|
|
132
134
|
const overrides = activeOverrides();
|
|
133
135
|
const env = input.env || process.env;
|
|
134
136
|
const config = overrides?.config ?? await readDecisionConfig(env);
|
|
137
|
+
const none = (reason) => ({ called: false, model: null, effort: null, reason });
|
|
135
138
|
if (!jevEnabled(config))
|
|
136
|
-
return
|
|
139
|
+
return none('off');
|
|
137
140
|
const resolved = await resolveOpenRouterApiKey({ env });
|
|
138
141
|
if (!resolved.key)
|
|
139
|
-
return
|
|
142
|
+
return none('missing_key');
|
|
140
143
|
const prompt = String(input.prompt || '').trim();
|
|
141
144
|
if (!prompt)
|
|
142
|
-
return
|
|
145
|
+
return none('empty_prompt');
|
|
146
|
+
const roleId = input.roleId === 'spawn' ? 'spawn' : 'turn';
|
|
143
147
|
const bundle = buildDecisionBundle({
|
|
144
148
|
projectId: sha256(input.root).slice(0, 32),
|
|
145
|
-
workflowRunId:
|
|
146
|
-
workflowRevision:
|
|
147
|
-
sourceDigest:
|
|
149
|
+
workflowRunId: roleId,
|
|
150
|
+
workflowRevision: roleId,
|
|
151
|
+
sourceDigest: roleId,
|
|
148
152
|
graphDigest: null,
|
|
149
153
|
goal: prompt,
|
|
150
|
-
routingCandidates: [{ id:
|
|
154
|
+
routingCandidates: [{ id: roleId, summary: prompt.slice(0, 240) }]
|
|
151
155
|
});
|
|
152
156
|
const transport = await requestOpenRouterDecision(bundle, {
|
|
153
157
|
env,
|
|
@@ -155,13 +159,14 @@ export async function consultJevTurnModel(input) {
|
|
|
155
159
|
...(overrides?.fetchImpl ? { fetchImpl: overrides.fetchImpl } : {})
|
|
156
160
|
});
|
|
157
161
|
if (!transport.ok)
|
|
158
|
-
return { called: true, model: null, reason: transport.reason };
|
|
162
|
+
return { called: true, model: null, effort: null, reason: transport.reason };
|
|
159
163
|
const compiled = compileDecision(bundle, transport.response);
|
|
160
164
|
if (compiled.kind !== 'apply')
|
|
161
|
-
return { called: true, model: null, reason: compiled.reason };
|
|
165
|
+
return { called: true, model: null, effort: null, reason: compiled.reason };
|
|
162
166
|
const selected = assembleRoutingSelection(compiled.effects.flatMap((effect) => (effect.kind === 'select_routing' ? [{ roleId: effect.roleId, model: effect.model }] : [])));
|
|
163
|
-
const model = selected?.models
|
|
164
|
-
|
|
167
|
+
const model = selected?.models[roleId] || null;
|
|
168
|
+
const sealed = model ? sealedRoutingModel(model) : null;
|
|
169
|
+
return { called: true, model: sealed?.id || null, effort: sealed?.effort || null, reason: sealed ? 'applied' : 'keep_baseline' };
|
|
165
170
|
}
|
|
166
171
|
export function effectAlreadyConsumed(identity) {
|
|
167
172
|
return appliedEffects.has(identity);
|
|
@@ -192,6 +197,7 @@ function applyEffects(attention, contextCandidates, planCandidates, compiled) {
|
|
|
192
197
|
let selectedContextIds = null;
|
|
193
198
|
const evidence = [];
|
|
194
199
|
const routingEffects = [];
|
|
200
|
+
const omittedRoutingRoles = [];
|
|
195
201
|
for (const effect of compiled.effects) {
|
|
196
202
|
if (effect.kind === 'select_optional_context') {
|
|
197
203
|
nextAttention = applyOptionalContextSelection(attention, contextCandidates, effect.keepIds);
|
|
@@ -206,6 +212,10 @@ function applyEffects(attention, contextCandidates, planCandidates, compiled) {
|
|
|
206
212
|
if (effect.kind === 'select_routing') {
|
|
207
213
|
routingEffects.push({ roleId: effect.roleId, model: effect.model });
|
|
208
214
|
}
|
|
215
|
+
if (effect.kind === 'omit_role') {
|
|
216
|
+
omittedRoutingRoles.push(effect.roleId);
|
|
217
|
+
evidence.push(`omit:${effect.roleId}`);
|
|
218
|
+
}
|
|
209
219
|
}
|
|
210
220
|
const selectedRouting = assembleRoutingSelection(routingEffects);
|
|
211
221
|
if (selectedRouting) {
|
|
@@ -216,6 +226,7 @@ function applyEffects(attention, contextCandidates, planCandidates, compiled) {
|
|
|
216
226
|
selectedPlan,
|
|
217
227
|
selectedRouting,
|
|
218
228
|
selectedContextIds,
|
|
229
|
+
omittedRoutingRoles,
|
|
219
230
|
consumptionEvidence: evidence.length ? evidence.join('|') : null
|
|
220
231
|
};
|
|
221
232
|
}
|
|
@@ -291,6 +302,7 @@ function keep(input, reason, started) {
|
|
|
291
302
|
selectedPlan: null,
|
|
292
303
|
selectedRouting: null,
|
|
293
304
|
selectedContextIds: null,
|
|
305
|
+
omittedRoutingRoles: [],
|
|
294
306
|
llmRejudgeCalls: 0,
|
|
295
307
|
bundle: null
|
|
296
308
|
};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { CHOICE_MIN_CONFIDENCE, CHOICE_MIN_PROBABILITY, CONTEXT_DROP_NOUL_MAX, DISTRIBUTION_SUM_TOLERANCE, KEEP_BASELINE_CHOICE, NEEDS_EVIDENCE_CHOICE, POLICY_REVISION, ROUTING_RISK_NOUL_MIN, UNKNOWN_USAGE, sealedRoutingModel } from './types.js';
|
|
1
|
+
import { CHOICE_MIN_CONFIDENCE, CHOICE_MIN_PROBABILITY, CONTEXT_DROP_NOUL_MAX, DISTRIBUTION_SUM_TOLERANCE, KEEP_BASELINE_CHOICE, NEEDS_EVIDENCE_CHOICE, POLICY_REVISION, ROUTING_RISK_NOUL_MIN, ROUTING_ROLE_OMIT_NOUL_MAX, UNKNOWN_USAGE, sealedRoutingModel } from './types.js';
|
|
2
2
|
export function compileDecision(bundle, response) {
|
|
3
3
|
const usage = usageFromWire(response.usage);
|
|
4
4
|
const decoded = decodeWireResponse(bundle, response);
|
|
@@ -151,6 +151,16 @@ function compileRouting(bundle, answers) {
|
|
|
151
151
|
else if (!reason)
|
|
152
152
|
reason = compiled.reason;
|
|
153
153
|
}
|
|
154
|
+
for (const [questionId, binding] of Object.entries(bundle.questionBindings)) {
|
|
155
|
+
if (binding.kind !== 'routing_needed')
|
|
156
|
+
continue;
|
|
157
|
+
const answer = answers[questionId];
|
|
158
|
+
if (!answer || answer.type !== 'noul')
|
|
159
|
+
continue;
|
|
160
|
+
if (answer.noul <= ROUTING_ROLE_OMIT_NOUL_MAX) {
|
|
161
|
+
effects.push({ kind: 'omit_role', roleId: binding.roleId });
|
|
162
|
+
}
|
|
163
|
+
}
|
|
154
164
|
return { effects, reason };
|
|
155
165
|
}
|
|
156
166
|
function compileRoleRouting(bundle, answers, roleId) {
|
|
@@ -210,6 +210,20 @@ function appendRoutingSpeculation(roles, questions, bindings, recoverySlot) {
|
|
|
210
210
|
}
|
|
211
211
|
};
|
|
212
212
|
bindings[riskId] = { kind: 'routing_risk', roleId: role.id };
|
|
213
|
+
if (questionRoom(questions, recoverySlot) < 1)
|
|
214
|
+
break;
|
|
215
|
+
const neededId = `needed_${role.id}`;
|
|
216
|
+
const neededInstructions = redactDecisionText(`Does state.task require routing.roles.${role.id} as its own child agent? Omit the role when another listed role already covers the work.`);
|
|
217
|
+
assertIndependentQuestion(neededInstructions);
|
|
218
|
+
questions[neededId] = {
|
|
219
|
+
type: 'noul',
|
|
220
|
+
instructions: neededInstructions,
|
|
221
|
+
criteria: {
|
|
222
|
+
true: 'This role must be spawned to finish the task.',
|
|
223
|
+
false: 'This role is unnecessary. The parent should not spawn it.'
|
|
224
|
+
}
|
|
225
|
+
};
|
|
226
|
+
bindings[neededId] = { kind: 'routing_needed', roleId: role.id };
|
|
213
227
|
}
|
|
214
228
|
}
|
|
215
229
|
export { QUESTION_REVISION };
|
|
@@ -27,6 +27,7 @@ export const ROUTING_DIFFICULTY_RUBRIC = Object.freeze([
|
|
|
27
27
|
'Judgment, architecture, ambiguity, security, or other high-stakes work.'
|
|
28
28
|
]);
|
|
29
29
|
export const ROUTING_RISK_NOUL_MIN = 0.70;
|
|
30
|
+
export const ROUTING_ROLE_OMIT_NOUL_MAX = 0.35;
|
|
30
31
|
export function sealedRoutingModel(model) {
|
|
31
32
|
const match = SEALED_ROUTING_MODELS.find((row) => row.id === model);
|
|
32
33
|
return match ? { id: match.id, effort: match.effort } : null;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { IMAGEGEN_MODEL } from '../imagegen/imagegen-model-policy.js';
|
|
2
2
|
import { readStdin } from '../fsx.js';
|
|
3
|
-
import { buildCompactContinue, buildPermissionRequestAllow, buildPermissionRequestDeny, buildPostToolUseBlock, buildPostToolUseContinue, buildPreToolUseContinue, buildPreToolUseDeny, buildSessionStartContinue, buildStopBlock, buildStopContinue, buildSubagentStartContinue, buildSubagentStopBlock, buildSubagentStopContinue, buildUserPromptSubmitBlock, buildUserPromptSubmitContinue } from '../codex-compat/codex-hook-output-builders.js';
|
|
3
|
+
import { buildCompactContinue, buildPermissionRequestAllow, buildPermissionRequestDeny, buildPostToolUseBlock, buildPostToolUseContinue, buildPreToolUseAllowRewrite, buildPreToolUseContinue, buildPreToolUseDeny, buildSessionStartContinue, buildStopBlock, buildStopContinue, buildSubagentStartContinue, buildSubagentStopBlock, buildSubagentStopContinue, buildUserPromptSubmitBlock, buildUserPromptSubmitContinue } from '../codex-compat/codex-hook-output-builders.js';
|
|
4
4
|
export async function loadHookPayload() {
|
|
5
5
|
const raw = await readStdin();
|
|
6
6
|
try {
|
|
@@ -33,6 +33,8 @@ export function normalizeHookResult(name, result = {}) {
|
|
|
33
33
|
if (out.decision === 'block' || out.permissionDecision === 'deny' || out.decision === 'deny') {
|
|
34
34
|
return buildPreToolUseDeny(reason, { systemMessage });
|
|
35
35
|
}
|
|
36
|
+
if (out.updatedInput)
|
|
37
|
+
return buildPreToolUseAllowRewrite(out.updatedInput, { systemMessage });
|
|
36
38
|
return buildPreToolUseContinue({ additionalContext: out.additionalContext, systemMessage });
|
|
37
39
|
}
|
|
38
40
|
if (eventName === 'PermissionRequest') {
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { consultJevTurnModel } from '../decisions/integration.js';
|
|
2
|
+
import { readRoleModelPreferences } from '../subagents/role-model-preferences.js';
|
|
3
|
+
const SPAWN_TOOLS = new Set(['spawn_agent', 'collaboration.spawn_agent', 'functions.spawn_agent']);
|
|
4
|
+
function spawnInput(payload) {
|
|
5
|
+
const name = String(payload?.tool_name || payload?.toolName || payload?.tool?.name || '');
|
|
6
|
+
if (!SPAWN_TOOLS.has(name))
|
|
7
|
+
return null;
|
|
8
|
+
const input = payload?.tool_input || payload?.toolInput || payload?.tool?.input;
|
|
9
|
+
if (!input || typeof input !== 'object' || Array.isArray(input))
|
|
10
|
+
return null;
|
|
11
|
+
return { ...input };
|
|
12
|
+
}
|
|
13
|
+
function narutoParent(state) {
|
|
14
|
+
const mode = String(state?.mode || '').toUpperCase();
|
|
15
|
+
const route = String(state?.route || state?.route_command || '').replace(/^\$/, '').toUpperCase();
|
|
16
|
+
return mode === 'NARUTO' || route === 'NARUTO' || state?.subagents_required === true;
|
|
17
|
+
}
|
|
18
|
+
function spawnTask(input) {
|
|
19
|
+
return [input.message, input.prompt, input.task, input.agent_type, input.agentType]
|
|
20
|
+
.map((value) => String(value || '').trim())
|
|
21
|
+
.filter(Boolean)
|
|
22
|
+
.join('\n')
|
|
23
|
+
.slice(0, 1200);
|
|
24
|
+
}
|
|
25
|
+
export async function jevSpawnModelRewrite(root, state, payload) {
|
|
26
|
+
if (!narutoParent(state))
|
|
27
|
+
return null;
|
|
28
|
+
const input = spawnInput(payload);
|
|
29
|
+
if (!input)
|
|
30
|
+
return null;
|
|
31
|
+
const agent = String(input.agent_type || input.agentType || '').trim();
|
|
32
|
+
if (agent) {
|
|
33
|
+
const preferences = await readRoleModelPreferences().catch(() => null);
|
|
34
|
+
if (preferences?.store.roles[agent])
|
|
35
|
+
return null;
|
|
36
|
+
}
|
|
37
|
+
const task = spawnTask(input);
|
|
38
|
+
if (!task)
|
|
39
|
+
return null;
|
|
40
|
+
const decision = await consultJevTurnModel({ root, prompt: task, roleId: 'spawn' }).catch(() => null);
|
|
41
|
+
if (!decision?.model || !decision.effort)
|
|
42
|
+
return null;
|
|
43
|
+
if (input.model === decision.model && input.reasoning_effort === decision.effort)
|
|
44
|
+
return null;
|
|
45
|
+
return {
|
|
46
|
+
...input,
|
|
47
|
+
model: decision.model,
|
|
48
|
+
reasoning_effort: decision.effort
|
|
49
|
+
};
|
|
50
|
+
}
|
|
@@ -30,6 +30,7 @@ import { activeNarutoParentLaunchMissionId, claimStandaloneParentHostCapabilityR
|
|
|
30
30
|
import { classifyTaskProfile } from './runtime/task-profile.js';
|
|
31
31
|
import { resolveSubagentThreadBudget } from './subagents/thread-budget.js';
|
|
32
32
|
import { readOfficialSubagentConfig } from './subagents/official-subagent-config.js';
|
|
33
|
+
import { jevSpawnModelRewrite } from './hooks-runtime/jev-spawn-routing.js';
|
|
33
34
|
import { subagentSpawnPolicyBlockReason } from './hooks-runtime/subagent-spawn-policy.js';
|
|
34
35
|
import { withFileLock } from './locks/file-lock.js';
|
|
35
36
|
import { ensureConfinedDirectory, inspectConfinedPath, removeManagedPathVerified } from './managed-path-safety.js';
|
|
@@ -596,7 +597,11 @@ async function consumeActiveOfficialWorkflowQueue(root, missionId, workflowRunId
|
|
|
596
597
|
}
|
|
597
598
|
}
|
|
598
599
|
async function hookPreTool(root, state, payload, noQuestion, sessionKey = null) {
|
|
599
|
-
const
|
|
600
|
+
const jevSpawnInput = await jevSpawnModelRewrite(root, state, payload).catch(() => null);
|
|
601
|
+
const spawnPayload = jevSpawnInput
|
|
602
|
+
? { ...payload, tool_input: jevSpawnInput, toolInput: jevSpawnInput }
|
|
603
|
+
: payload;
|
|
604
|
+
const spawnPolicyBlock = subagentSpawnPolicyBlockReason(spawnPayload);
|
|
600
605
|
if (spawnPolicyBlock)
|
|
601
606
|
return { decision: 'block', permissionDecision: 'deny', reason: spawnPolicyBlock };
|
|
602
607
|
const artifactDir = officialSubagentArtifactDir(root, state, sessionKey);
|
|
@@ -665,15 +670,20 @@ async function hookPreTool(root, state, payload, noQuestion, sessionKey = null)
|
|
|
665
670
|
const waveGuidance = await parentWaveGuidanceContext(root, state, sessionKey).catch(() => '');
|
|
666
671
|
const additionalContext = [skillRefresh.context, waveGuidance].filter(Boolean).join('\n\n');
|
|
667
672
|
if (additionalContext) {
|
|
668
|
-
return {
|
|
673
|
+
return withJevSpawnRewrite({
|
|
669
674
|
continue: true,
|
|
670
675
|
additionalContext,
|
|
671
676
|
...(waveGuidance
|
|
672
677
|
? { systemMessage: visibleHookMessage('pre-tool', 'SKS Naruto wave lifecycle requires root-parent follow-up.') }
|
|
673
678
|
: { silent: true })
|
|
674
|
-
};
|
|
679
|
+
}, jevSpawnInput);
|
|
675
680
|
}
|
|
676
|
-
return { continue: true };
|
|
681
|
+
return withJevSpawnRewrite({ continue: true }, jevSpawnInput);
|
|
682
|
+
}
|
|
683
|
+
function withJevSpawnRewrite(result, updatedInput) {
|
|
684
|
+
if (!updatedInput || result?.decision === 'block' || result?.permissionDecision === 'deny')
|
|
685
|
+
return result;
|
|
686
|
+
return { ...result, permissionDecision: 'allow', updatedInput };
|
|
677
687
|
}
|
|
678
688
|
async function parentWaveGuidanceContext(root, state = {}, sessionKey = null) {
|
|
679
689
|
if (!state?.mission_id && !state?.official_subagent_run_id)
|
package/dist/core/routes.js
CHANGED
|
@@ -1211,6 +1211,9 @@ export function narutoDecisionForRoute(route, prompt = '', profile = classifyTas
|
|
|
1211
1211
|
return narutoRouteDecision('none', routeId, profile, `task_profile_${profile}_bypass`, true);
|
|
1212
1212
|
}
|
|
1213
1213
|
if (profile === 'bounded-work') {
|
|
1214
|
+
if (routeId === 'Naruto') {
|
|
1215
|
+
return narutoRouteDecision('generic_naruto', routeId, profile, 'naruto_parent_orchestrates', false);
|
|
1216
|
+
}
|
|
1214
1217
|
return narutoRouteDecision('none', routeId, profile, 'task_profile_bounded_work_parent_owned', false);
|
|
1215
1218
|
}
|
|
1216
1219
|
if (profile === 'parallel-read' || profile === 'parallel-write' || profile === 'high-risk') {
|
|
@@ -461,6 +461,12 @@ function applyOfficialSubagentDecision(derived, decided) {
|
|
|
461
461
|
: { ...derived.fanoutPolicy };
|
|
462
462
|
if (selectedRouting)
|
|
463
463
|
fanoutPolicy = { ...fanoutPolicy, jev_selected_routing: selectedRouting.id };
|
|
464
|
+
const omitted = new Set(decided.omittedRoutingRoles || []);
|
|
465
|
+
if (omitted.size)
|
|
466
|
+
fanoutPolicy = { ...fanoutPolicy, jev_omitted_roles: [...omitted] };
|
|
467
|
+
const recommendedAgents = omitted.size > 0 && derived.suggestedAgents.some((name) => !omitted.has(name))
|
|
468
|
+
? derived.suggestedAgents.filter((name) => !omitted.has(name))
|
|
469
|
+
: derived.suggestedAgents;
|
|
464
470
|
const routingPreferences = selectedRouting
|
|
465
471
|
? Object.fromEntries(Object.entries(selectedRouting.efforts)
|
|
466
472
|
.filter(([name]) => !derived.roleModelPreferences.store.roles[name])
|
|
@@ -483,7 +489,7 @@ function applyOfficialSubagentDecision(derived, decided) {
|
|
|
483
489
|
waveCount: budget.waveCount,
|
|
484
490
|
capacity: budget.capacity,
|
|
485
491
|
triwikiAttention: attention,
|
|
486
|
-
recommendedAgents
|
|
492
|
+
recommendedAgents,
|
|
487
493
|
roleModelPreferences: {
|
|
488
494
|
...derived.roleModelPreferences.store.roles,
|
|
489
495
|
...routingPreferences
|
|
@@ -519,6 +525,7 @@ function applyOfficialSubagentDecision(derived, decided) {
|
|
|
519
525
|
}),
|
|
520
526
|
triwiki_attention: attention,
|
|
521
527
|
agents,
|
|
528
|
+
suggested_agents: recommendedAgents,
|
|
522
529
|
fanout_policy: fanoutPolicy,
|
|
523
530
|
capacity_controller: budget.capacity,
|
|
524
531
|
jev_decision: decided.receipt,
|
|
@@ -53,6 +53,8 @@ export function buildOfficialSubagentPrompt(input) {
|
|
|
53
53
|
const spawnModelRouting = renderSpawnModelRouting(narutoChildren);
|
|
54
54
|
const childModelRules = narutoChildren
|
|
55
55
|
? [
|
|
56
|
+
'- the parent orchestrates only: decompose the goal, assign disjoint slices, spawn children, and integrate their results',
|
|
57
|
+
'- do not implement the assigned slice work in the parent thread',
|
|
56
58
|
'- use the model and reasoning_effort named in each slice spawn contract',
|
|
57
59
|
'- sealed child models are gpt-5.6-luna, gpt-5.6-sol, gpt-5.6-terra, and gpt-6-astra',
|
|
58
60
|
'- keep a stored user role-model preference for that role'
|
package/dist/core/version.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export const PACKAGE_VERSION = '10.3.
|
|
1
|
+
export const PACKAGE_VERSION = '10.3.2';
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "sneakoscope",
|
|
3
3
|
"displayName": "ㅅㅋㅅ",
|
|
4
|
-
"version": "10.3.
|
|
4
|
+
"version": "10.3.2",
|
|
5
5
|
"description": "Sneakoscope Codex (`sks`) is an open-source trust layer for Codex CLI and ChatGPT Desktop. It coordinates bounded AI coding agents, records machine-verifiable evidence, preserves project memory, and blocks release claims that are not supported by current tests or artifacts. Search visibility outcomes are measured separately; SKS does not promise rankings or traffic.",
|
|
6
6
|
"type": "module",
|
|
7
7
|
"homepage": "https://github.com/mandarange/Sneakoscope-Codex#readme",
|