sneakoscope 2.0.1 → 2.0.4
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 +26 -5
- package/crates/sks-core/Cargo.lock +1 -1
- package/crates/sks-core/Cargo.toml +1 -1
- package/crates/sks-core/src/main.rs +1 -1
- package/dist/.sks-build-stamp.json +4 -4
- package/dist/bin/sks.js +1 -1
- package/dist/build-manifest.json +28 -8
- package/dist/cli/command-registry.js +2 -0
- package/dist/commands/doctor.js +29 -3
- package/dist/core/agents/agent-command-surface.js +13 -3
- package/dist/core/agents/agent-orchestrator.js +92 -4
- package/dist/core/agents/agent-output-validator.js +2 -1
- package/dist/core/agents/agent-patch-proof.js +5 -0
- package/dist/core/agents/agent-patch-schema.js +2 -1
- package/dist/core/agents/agent-proof-evidence.js +26 -0
- package/dist/core/agents/agent-roster.js +1 -1
- package/dist/core/agents/agent-runner-ollama.js +411 -0
- package/dist/core/agents/agent-schema.js +1 -1
- package/dist/core/agents/intelligent-work-graph.js +45 -3
- package/dist/core/agents/native-cli-session-swarm.js +8 -1
- package/dist/core/agents/native-cli-worker.js +1 -1
- package/dist/core/agents/native-worker-backend-router.js +44 -2
- package/dist/core/agents/ollama-worker-config.js +118 -0
- package/dist/core/auto-review.js +39 -6
- package/dist/core/codex-app/codex-app-fast-ui-repair.js +42 -3
- package/dist/core/codex-control/codex-fake-sdk-adapter.js +20 -0
- package/dist/core/codex-control/codex-output-schemas.js +5 -1
- package/dist/core/codex-control/gpt-final-arbiter.js +160 -0
- package/dist/core/codex-control/gpt-final-context-compressor.js +17 -0
- package/dist/core/codex-control/gpt-final-proof-pack.js +120 -0
- package/dist/core/codex-control/gpt-final-review-schema.js +71 -0
- package/dist/core/commands/basic-cli.js +36 -1
- package/dist/core/commands/local-model-command.js +120 -0
- package/dist/core/commands/mad-sks-command.js +58 -9
- package/dist/core/commands/naruto-command.js +77 -5
- package/dist/core/commands/run-command.js +33 -1
- package/dist/core/commands/team-command.js +31 -2
- package/dist/core/doctor/doctor-readiness-matrix.js +19 -0
- package/dist/core/feature-fixtures.js +5 -0
- package/dist/core/fsx.js +1 -1
- package/dist/core/git-simple.js +143 -4
- package/dist/core/hooks-runtime.js +1 -1
- package/dist/core/init.js +2 -0
- package/dist/core/local-llm/local-collaboration-policy.js +93 -0
- package/dist/core/local-llm/local-llm-config.js +15 -0
- package/dist/core/pipeline/final-gpt-patch-stage.js +31 -0
- package/dist/core/pipeline/final-gpt-review-stage.js +5 -0
- package/dist/core/provider/provider-context.js +72 -9
- package/dist/core/retention.js +11 -0
- package/dist/core/routes.js +21 -1
- package/dist/core/safety/mutation-guard.js +2 -0
- package/dist/core/team-live.js +7 -1
- package/dist/core/update-check.js +215 -25
- package/dist/core/verification/verification-worker-pool.js +12 -0
- package/dist/core/version.js +1 -1
- package/dist/core/zellij/zellij-worker-pane-manager.js +19 -2
- package/dist/scripts/agent-ast-aware-work-graph-check.js +1 -1
- package/dist/scripts/codex-sdk-team-naruto-agent-pipeline-check.js +2 -1
- package/dist/scripts/doctor-fixes-codex-app-fast-ui-check.js +12 -2
- package/dist/scripts/gpt-final-arbiter-check.js +63 -0
- package/dist/scripts/gpt-final-arbiter-performance-check.js +36 -0
- package/dist/scripts/local-collab-gpt-final-availability-check.js +58 -0
- package/dist/scripts/local-collab-no-local-only-final-check.js +27 -0
- package/dist/scripts/local-collab-policy-check.js +17 -0
- package/dist/scripts/mad-sks-app-ui-no-mutation-check.js +92 -0
- package/dist/scripts/mad-sks-zellij-default-pane-worker-check.js +37 -0
- package/dist/scripts/mad-sks-zellij-launch-check.js +2 -1
- package/dist/scripts/provider-context-config-toml-check.js +63 -0
- package/dist/scripts/release-gate-existence-audit.js +4 -0
- package/dist/scripts/runtime-no-mjs-scripts-check.js +3 -2
- package/dist/scripts/zellij-worker-pane-manager-check.js +3 -0
- package/dist/scripts/zellij-worker-pane-manager-single-owner-check.js +39 -0
- package/package.json +13 -4
- package/schemas/local-llm/local-collaboration-policy.schema.json +57 -0
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
import { nowIso } from '../fsx.js';
|
|
2
|
+
export const LOCAL_COLLABORATION_POLICY_SCHEMA = 'sks.local-collaboration-policy.v1';
|
|
3
|
+
export const LOCAL_COLLABORATION_FINAL_GATE_SCHEMA = 'sks.local-collaboration-final-gate.v1';
|
|
4
|
+
export const DEFAULT_LOCAL_COLLABORATION_MODE = 'local-parallel-gpt-final';
|
|
5
|
+
export const LOCAL_COLLABORATION_MODES = [
|
|
6
|
+
'disabled',
|
|
7
|
+
'local-draft-gpt-final',
|
|
8
|
+
'local-worker-gpt-orchestrator',
|
|
9
|
+
'local-parallel-gpt-final',
|
|
10
|
+
'local-only-draft'
|
|
11
|
+
];
|
|
12
|
+
export function resolveLocalCollaborationPolicy(input = {}) {
|
|
13
|
+
const env = input.env || process.env;
|
|
14
|
+
const requested = firstText(input.mode, env.SKS_LOCAL_COLLAB_MODE, DEFAULT_LOCAL_COLLABORATION_MODE);
|
|
15
|
+
const mode = normalizeLocalCollaborationMode(requested);
|
|
16
|
+
const invalid = mode ? [] : [`invalid_local_collaboration_mode:${requested}`];
|
|
17
|
+
const resolvedMode = mode || DEFAULT_LOCAL_COLLABORATION_MODE;
|
|
18
|
+
return {
|
|
19
|
+
schema: LOCAL_COLLABORATION_POLICY_SCHEMA,
|
|
20
|
+
generated_at: nowIso(),
|
|
21
|
+
mode: resolvedMode,
|
|
22
|
+
default_mode: DEFAULT_LOCAL_COLLABORATION_MODE,
|
|
23
|
+
local_llm_role: resolvedMode === 'disabled' ? 'disabled' : 'draft_worker',
|
|
24
|
+
gpt_final_required: resolvedMode !== 'disabled' && resolvedMode !== 'local-only-draft',
|
|
25
|
+
gpt_final_backend_must_be_remote: resolvedMode !== 'disabled',
|
|
26
|
+
local_only_draft: resolvedMode === 'local-only-draft',
|
|
27
|
+
final_accepted_statuses: ['approved', 'modified'],
|
|
28
|
+
final_patch_source_when_enabled: 'gpt_final_arbiter',
|
|
29
|
+
blockers: [
|
|
30
|
+
...invalid,
|
|
31
|
+
...(resolvedMode === 'local-only-draft' ? ['needs_gpt_final_review'] : [])
|
|
32
|
+
]
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
export function evaluateLocalCollaborationFinalGate(input = {}) {
|
|
36
|
+
const policy = input.policy || resolveLocalCollaborationPolicy(input.mode === undefined ? {} : { mode: input.mode });
|
|
37
|
+
const localParticipated = input.localParticipated !== false && policy.mode !== 'disabled';
|
|
38
|
+
const status = normalizeGptFinalStatus(input.gptFinalStatus);
|
|
39
|
+
const requiresGptFinal = policy.gpt_final_required && localParticipated;
|
|
40
|
+
const gptBackend = String(input.gptFinalBackend || '');
|
|
41
|
+
const remoteBackendOk = !gptBackend || !isLocalBackendName(gptBackend);
|
|
42
|
+
const blockers = [
|
|
43
|
+
...policy.blockers,
|
|
44
|
+
...(requiresGptFinal && input.gptFinalAvailable === false ? ['gpt_final_arbiter_unavailable'] : []),
|
|
45
|
+
...(requiresGptFinal && !status ? ['gpt_final_arbiter_missing'] : []),
|
|
46
|
+
...(requiresGptFinal && status && !policy.final_accepted_statuses.includes(status) ? [`gpt_final_status_not_accepted:${status}`] : []),
|
|
47
|
+
...(requiresGptFinal && !remoteBackendOk ? ['gpt_final_backend_must_not_be_local_llm'] : []),
|
|
48
|
+
...(policy.local_only_draft && input.applyPatches === true ? ['local_only_draft_apply_blocked'] : [])
|
|
49
|
+
];
|
|
50
|
+
const accepted = blockers.length === 0 && (!requiresGptFinal || status === 'approved' || status === 'modified');
|
|
51
|
+
return {
|
|
52
|
+
schema: LOCAL_COLLABORATION_FINAL_GATE_SCHEMA,
|
|
53
|
+
generated_at: nowIso(),
|
|
54
|
+
ok: accepted,
|
|
55
|
+
mode: policy.mode,
|
|
56
|
+
local_participated: localParticipated,
|
|
57
|
+
gpt_final_required: requiresGptFinal,
|
|
58
|
+
gpt_final_status: status,
|
|
59
|
+
gpt_final_backend: gptBackend || null,
|
|
60
|
+
final_status: accepted ? 'accepted' : policy.local_only_draft ? 'draft_only' : 'blocked',
|
|
61
|
+
apply_allowed: accepted && policy.local_only_draft !== true,
|
|
62
|
+
release_proof_allowed: accepted,
|
|
63
|
+
final_patch_source: accepted && policy.mode !== 'disabled' ? policy.final_patch_source_when_enabled : 'not_applicable',
|
|
64
|
+
blockers
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
export function localCollaborationParticipated(results = []) {
|
|
68
|
+
return results.some((result) => {
|
|
69
|
+
const backend = String(result?.backend_router_report?.selected_backend || result?.backend || '').toLowerCase();
|
|
70
|
+
return backend === 'ollama' || backend === 'local-llm' || backend === 'local_llm';
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
export function normalizeLocalCollaborationMode(value) {
|
|
74
|
+
const text = String(value ?? '').trim();
|
|
75
|
+
return LOCAL_COLLABORATION_MODES.includes(text) ? text : null;
|
|
76
|
+
}
|
|
77
|
+
export function normalizeGptFinalStatus(value) {
|
|
78
|
+
const text = String(value ?? '').trim();
|
|
79
|
+
return text === 'approved' || text === 'modified' || text === 'rejected' || text === 'needs_more_work' ? text : null;
|
|
80
|
+
}
|
|
81
|
+
function firstText(...values) {
|
|
82
|
+
for (const value of values) {
|
|
83
|
+
const text = String(value ?? '').trim();
|
|
84
|
+
if (text)
|
|
85
|
+
return text;
|
|
86
|
+
}
|
|
87
|
+
return '';
|
|
88
|
+
}
|
|
89
|
+
function isLocalBackendName(value) {
|
|
90
|
+
const text = value.toLowerCase();
|
|
91
|
+
return text === 'ollama' || text === 'local-llm' || text === 'local_llm';
|
|
92
|
+
}
|
|
93
|
+
//# sourceMappingURL=local-collaboration-policy.js.map
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { resolveOllamaWorkerConfig } from '../agents/ollama-worker-config.js';
|
|
2
|
+
export async function resolveLocalLlmConfig(input = {}) {
|
|
3
|
+
const config = await resolveOllamaWorkerConfig(input);
|
|
4
|
+
return {
|
|
5
|
+
schema: 'sks.local-llm-config.v1',
|
|
6
|
+
ok: config.ok,
|
|
7
|
+
enabled: config.enabled,
|
|
8
|
+
provider: config.provider,
|
|
9
|
+
model: config.model,
|
|
10
|
+
base_url: config.base_url,
|
|
11
|
+
worker_only: true,
|
|
12
|
+
blockers: config.blockers
|
|
13
|
+
};
|
|
14
|
+
}
|
|
15
|
+
//# sourceMappingURL=local-llm-config.js.map
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
export function selectFinalGptPatchSource(gptFinal, localPatchEnvelopes = []) {
|
|
2
|
+
const status = String(gptFinal?.result?.status || gptFinal?.status || '');
|
|
3
|
+
if (status === 'modified') {
|
|
4
|
+
return {
|
|
5
|
+
schema: 'sks.final-gpt-patch-stage.v1',
|
|
6
|
+
ok: true,
|
|
7
|
+
final_patch_source: 'gpt_final_arbiter',
|
|
8
|
+
patch_envelopes: Array.isArray(gptFinal?.result?.modified_patch_envelopes) ? gptFinal.result.modified_patch_envelopes : [],
|
|
9
|
+
blockers: []
|
|
10
|
+
};
|
|
11
|
+
}
|
|
12
|
+
if (status === 'approved') {
|
|
13
|
+
return {
|
|
14
|
+
schema: 'sks.final-gpt-patch-stage.v1',
|
|
15
|
+
ok: true,
|
|
16
|
+
final_patch_source: 'gpt_final_arbiter',
|
|
17
|
+
patch_envelopes: Array.isArray(gptFinal?.result?.accepted_patch_envelopes) && gptFinal.result.accepted_patch_envelopes.length
|
|
18
|
+
? gptFinal.result.accepted_patch_envelopes
|
|
19
|
+
: localPatchEnvelopes,
|
|
20
|
+
blockers: []
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
return {
|
|
24
|
+
schema: 'sks.final-gpt-patch-stage.v1',
|
|
25
|
+
ok: false,
|
|
26
|
+
final_patch_source: 'blocked',
|
|
27
|
+
patch_envelopes: [],
|
|
28
|
+
blockers: ['gpt_final_not_approved']
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
//# sourceMappingURL=final-gpt-patch-stage.js.map
|
|
@@ -1,15 +1,22 @@
|
|
|
1
1
|
import path from 'node:path';
|
|
2
|
-
import { exists, nowIso, readJson, writeJsonAtomic } from '../fsx.js';
|
|
2
|
+
import { exists, nowIso, readJson, readText, writeJsonAtomic } from '../fsx.js';
|
|
3
3
|
export const PROVIDER_CONTEXT_SCHEMA = 'sks.provider-context.v1';
|
|
4
4
|
export async function resolveProviderContext(input = {}) {
|
|
5
5
|
const env = input.env || process.env;
|
|
6
6
|
const root = path.resolve(input.root || process.cwd());
|
|
7
7
|
const codexHome = path.resolve(String(input.codexHome || env.CODEX_HOME || path.join(env.HOME || '', '.codex')));
|
|
8
|
+
const configText = await readText(path.join(codexHome, 'config.toml'), '').catch(() => '');
|
|
9
|
+
const configModelProvider = readTopLevelTomlString(configText, 'model_provider');
|
|
10
|
+
const codexLbProviderBlockPresent = hasCodexLbProviderBlock(configText);
|
|
11
|
+
const codexLbEnvKey = codexLbProviderEnvKey(configText) || (codexLbProviderBlockPresent ? 'CODEX_LB_API_KEY' : null);
|
|
12
|
+
const codexLbRequiresOpenAiAuth = codexLbProviderRequiresOpenAiAuth(configText);
|
|
13
|
+
const codexLbProviderValid = codexLbProviderBlockPresent && (codexLbRequiresOpenAiAuth === false || codexLbRequiresOpenAiAuth == null);
|
|
8
14
|
const openaiKey = Boolean(String(env.OPENAI_API_KEY || '').trim());
|
|
9
|
-
const lbKey = Boolean(String(env.CODEX_LB_API_KEY || '').trim());
|
|
15
|
+
const lbKey = Boolean(String((codexLbEnvKey ? env[codexLbEnvKey] : env.CODEX_LB_API_KEY) || env.CODEX_LB_API_KEY || '').trim());
|
|
10
16
|
const envProvider = String(env.SKS_MODEL_PROVIDER || env.CODEX_MODEL_PROVIDER || env.OPENAI_MODEL_PROVIDER || '').trim();
|
|
11
|
-
const modelProvider = String(input.modelProvider || envProvider || '').trim() || null;
|
|
12
|
-
const
|
|
17
|
+
const modelProvider = String(input.modelProvider || envProvider || configModelProvider || '').trim() || null;
|
|
18
|
+
const envLbExplicit = env.SKS_PROVIDER === 'codex-lb' || env.SKS_USE_CODEX_LB === '1';
|
|
19
|
+
const lbExplicit = modelProvider === 'codex-lb' || envLbExplicit;
|
|
13
20
|
const auth = await readJson(path.join(codexHome, 'auth.json'), null).catch(() => null);
|
|
14
21
|
const appAuthPresent = Boolean(auth) || await exists(path.join(codexHome, 'auth.json'));
|
|
15
22
|
const conflict = (lbKey && openaiKey && !lbExplicit && !modelProvider) || (modelProvider === 'codex-lb' && !lbKey && openaiKey);
|
|
@@ -17,17 +24,23 @@ export async function resolveProviderContext(input = {}) {
|
|
|
17
24
|
let authMode = 'unknown';
|
|
18
25
|
let source = 'unknown';
|
|
19
26
|
let confidence = 'low';
|
|
20
|
-
if (
|
|
27
|
+
if (envLbExplicit && lbKey) {
|
|
21
28
|
provider = 'codex-lb';
|
|
22
29
|
authMode = 'codex_lb_key';
|
|
23
30
|
source = 'codex_lb';
|
|
24
31
|
confidence = 'high';
|
|
25
32
|
}
|
|
26
|
-
else if (modelProvider === 'codex-lb') {
|
|
33
|
+
else if (modelProvider === 'codex-lb' && codexLbProviderValid && lbKey) {
|
|
27
34
|
provider = 'codex-lb';
|
|
28
|
-
authMode =
|
|
35
|
+
authMode = 'codex_lb_key';
|
|
29
36
|
source = 'config';
|
|
30
|
-
confidence =
|
|
37
|
+
confidence = 'high';
|
|
38
|
+
}
|
|
39
|
+
else if (modelProvider === 'codex-lb' && codexLbProviderValid) {
|
|
40
|
+
provider = 'codex-lb';
|
|
41
|
+
authMode = 'unknown';
|
|
42
|
+
source = 'config';
|
|
43
|
+
confidence = 'low';
|
|
31
44
|
}
|
|
32
45
|
else if (openaiKey) {
|
|
33
46
|
provider = 'openai';
|
|
@@ -43,6 +56,7 @@ export async function resolveProviderContext(input = {}) {
|
|
|
43
56
|
}
|
|
44
57
|
const warnings = [
|
|
45
58
|
...(conflict ? ['provider_conflict'] : []),
|
|
59
|
+
...(modelProvider === 'codex-lb' && !codexLbProviderValid && !envLbExplicit ? ['codex_lb_provider_config_missing_or_invalid'] : []),
|
|
46
60
|
...(provider === 'codex-lb' && !lbKey ? ['codex_lb_selected_without_key'] : [])
|
|
47
61
|
];
|
|
48
62
|
return {
|
|
@@ -61,7 +75,11 @@ export async function resolveProviderContext(input = {}) {
|
|
|
61
75
|
codex_lb_key_present: lbKey,
|
|
62
76
|
codex_lb_explicit: lbExplicit,
|
|
63
77
|
codex_app_auth_present: appAuthPresent,
|
|
64
|
-
model_provider: modelProvider
|
|
78
|
+
model_provider: modelProvider,
|
|
79
|
+
codex_lb_provider_block_present: codexLbProviderBlockPresent,
|
|
80
|
+
codex_lb_env_key: codexLbEnvKey,
|
|
81
|
+
codex_lb_requires_openai_auth: codexLbRequiresOpenAiAuth,
|
|
82
|
+
codex_lb_available: codexLbProviderValid && lbKey
|
|
65
83
|
}
|
|
66
84
|
};
|
|
67
85
|
}
|
|
@@ -79,4 +97,49 @@ function normalizeServiceTier(value) {
|
|
|
79
97
|
return 'standard';
|
|
80
98
|
return 'unknown';
|
|
81
99
|
}
|
|
100
|
+
export function readTopLevelTomlString(text, key) {
|
|
101
|
+
const lines = String(text || '').split(/\r?\n/);
|
|
102
|
+
for (const line of lines) {
|
|
103
|
+
if (/^\s*\[/.test(line))
|
|
104
|
+
break;
|
|
105
|
+
const match = line.match(new RegExp(`^\\s*${escapeRegExp(key)}\\s*=\\s*"([^"]*)"\\s*(?:#.*)?$`));
|
|
106
|
+
if (match?.[1] != null)
|
|
107
|
+
return match[1];
|
|
108
|
+
}
|
|
109
|
+
return null;
|
|
110
|
+
}
|
|
111
|
+
export function hasCodexLbProviderBlock(text) {
|
|
112
|
+
return codexLbProviderBody(text) != null;
|
|
113
|
+
}
|
|
114
|
+
export function codexLbProviderEnvKey(text) {
|
|
115
|
+
const body = codexLbProviderBody(text);
|
|
116
|
+
return body == null ? null : readTopLevelTomlString(body, 'env_key');
|
|
117
|
+
}
|
|
118
|
+
export function codexLbProviderRequiresOpenAiAuth(text) {
|
|
119
|
+
const body = codexLbProviderBody(text);
|
|
120
|
+
if (body == null)
|
|
121
|
+
return null;
|
|
122
|
+
const match = body.match(/^\s*requires_openai_auth\s*=\s*(true|false)\s*(?:#.*)?$/m);
|
|
123
|
+
return match?.[1] === 'true' ? true : match?.[1] === 'false' ? false : null;
|
|
124
|
+
}
|
|
125
|
+
function codexLbProviderBody(text) {
|
|
126
|
+
const lines = String(text || '').split(/\r?\n/);
|
|
127
|
+
const out = [];
|
|
128
|
+
let inTable = false;
|
|
129
|
+
for (const line of lines) {
|
|
130
|
+
const table = line.match(/^\s*\[([^\]]+)\]\s*(?:#.*)?$/)?.[1]?.trim();
|
|
131
|
+
if (table) {
|
|
132
|
+
if (inTable)
|
|
133
|
+
break;
|
|
134
|
+
inTable = table === 'model_providers.codex-lb' || table === 'model_providers."codex-lb"' || table === '"model_providers"."codex-lb"';
|
|
135
|
+
continue;
|
|
136
|
+
}
|
|
137
|
+
if (inTable)
|
|
138
|
+
out.push(line);
|
|
139
|
+
}
|
|
140
|
+
return inTable ? out.join('\n') : null;
|
|
141
|
+
}
|
|
142
|
+
function escapeRegExp(value) {
|
|
143
|
+
return value.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
144
|
+
}
|
|
82
145
|
//# sourceMappingURL=provider-context.js.map
|
package/dist/core/retention.js
CHANGED
|
@@ -52,6 +52,10 @@ const DISPOSABLE_MISSION_DIRS = Object.freeze([
|
|
|
52
52
|
'research/cycles',
|
|
53
53
|
'research/tmp'
|
|
54
54
|
]);
|
|
55
|
+
const DISPOSABLE_MISSION_FILES = Object.freeze([
|
|
56
|
+
'agents/agent-intelligent-work-graph.json',
|
|
57
|
+
'agents/agent-intelligent-work-graph-v2.json'
|
|
58
|
+
]);
|
|
55
59
|
const MISSION_CLOSE_GATES = Object.freeze([
|
|
56
60
|
'team-gate.json',
|
|
57
61
|
'reflection-gate.json',
|
|
@@ -235,6 +239,9 @@ async function compactClosedMissionWorkdirs(root, policy, dryRun, actions, opts
|
|
|
235
239
|
const target = path.join(mission.path, rel);
|
|
236
240
|
await removePath('remove_closed_mission_workdir', target, dryRun, actions, { mission: mission.id, rel, reason: 'closed_mission_disposable_workdir' });
|
|
237
241
|
}
|
|
242
|
+
for (const rel of DISPOSABLE_MISSION_FILES) {
|
|
243
|
+
await removePath('remove_closed_mission_large_file', path.join(mission.path, rel), dryRun, actions, { mission: mission.id, rel, reason: 'closed_mission_disposable_large_file' });
|
|
244
|
+
}
|
|
238
245
|
await pruneMissionDisposableLogs(mission, dryRun, actions);
|
|
239
246
|
}
|
|
240
247
|
}
|
|
@@ -272,6 +279,9 @@ async function compactOldMissionWithDurableArtifacts(mission, dryRun, actions, r
|
|
|
272
279
|
for (const rel of DISPOSABLE_MISSION_DIRS) {
|
|
273
280
|
await removePath('remove_old_mission_workdir', path.join(mission.path, rel), dryRun, actions, { mission: mission.id, rel, reason });
|
|
274
281
|
}
|
|
282
|
+
for (const rel of DISPOSABLE_MISSION_FILES) {
|
|
283
|
+
await removePath('remove_old_mission_large_file', path.join(mission.path, rel), dryRun, actions, { mission: mission.id, rel, reason });
|
|
284
|
+
}
|
|
275
285
|
await pruneMissionDisposableLogs(mission, dryRun, actions);
|
|
276
286
|
}
|
|
277
287
|
async function canCompactActiveMission(mission, opts = {}) {
|
|
@@ -545,6 +555,7 @@ export async function enforceRetention(root, opts = {}) {
|
|
|
545
555
|
action_count: actions.length,
|
|
546
556
|
protected_durable_context: DURABLE_RETENTION_CLASSES,
|
|
547
557
|
disposable_mission_dirs: DISPOSABLE_MISSION_DIRS,
|
|
558
|
+
disposable_mission_files: DISPOSABLE_MISSION_FILES,
|
|
548
559
|
prune_report_logs: Boolean(opts.pruneReportLogs || policy.prune_disposable_report_logs),
|
|
549
560
|
completed_mission_id: opts.completedMissionId || null,
|
|
550
561
|
actions
|
package/dist/core/routes.js
CHANGED
|
@@ -335,6 +335,22 @@ export const ROUTES = [
|
|
|
335
335
|
cliEntrypoint: 'sks fast-mode on|off|status|clear [--json]',
|
|
336
336
|
examples: ['$Fast-On', '$Fast-Off', '$Fast-Mode status']
|
|
337
337
|
},
|
|
338
|
+
{
|
|
339
|
+
id: 'LocalModel',
|
|
340
|
+
command: '$with-local-llm-on',
|
|
341
|
+
mode: 'LOCAL_MODEL',
|
|
342
|
+
route: 'local Ollama worker toggle',
|
|
343
|
+
description: 'Turn the optional local Ollama worker backend on or off. Default off keeps SKS GPT-only; enabled mode lets eligible simple code/collection worker slices use Ollama while GPT/Codex owns strategy, design, review, verification, and integration.',
|
|
344
|
+
requiredSkills: ['with-local-llm-on', 'honest-mode'],
|
|
345
|
+
dollarAliases: ['$with-local-llm-off'],
|
|
346
|
+
appSkillAliases: ['with-local-llm-off'],
|
|
347
|
+
lifecycle: ['global_local_model_toggle', 'worker_only_policy_status', 'honest_mode'],
|
|
348
|
+
context7Policy: 'not_required',
|
|
349
|
+
reasoningPolicy: 'low',
|
|
350
|
+
stopGate: 'none',
|
|
351
|
+
cliEntrypoint: 'sks with-local-llm on|off|status|set-model [--json]',
|
|
352
|
+
examples: ['$with-local-llm-on', '$with-local-llm-off', 'sks with-local-llm status --json']
|
|
353
|
+
},
|
|
338
354
|
{
|
|
339
355
|
id: 'Team',
|
|
340
356
|
command: '$Team',
|
|
@@ -534,7 +550,7 @@ export const ROUTES = [
|
|
|
534
550
|
requiredSkills: ['mad-sks', 'db-safety-guard', 'pipeline-runner', 'context7-docs', REFLECTION_SKILL_NAME, 'honest-mode'],
|
|
535
551
|
lifecycle: ['explicit_invocation', 'auto_sealed_permission_scope', 'scoped_permission_override', 'catastrophic_guard', 'permission_deactivation', 'post_route_reflection', 'honest_mode'],
|
|
536
552
|
context7Policy: 'required',
|
|
537
|
-
reasoningPolicy: '
|
|
553
|
+
reasoningPolicy: 'xhigh',
|
|
538
554
|
stopGate: 'mad-sks-gate.json',
|
|
539
555
|
cliEntrypoint: 'Codex App prompt route only: $MAD-SKS <task>',
|
|
540
556
|
examples: ['$MAD-SKS $Team target project maintenance with package/service/file and DB scopes', '$DB Supabase 점검 $MAD-SKS']
|
|
@@ -607,6 +623,7 @@ export const COMMAND_CATALOG = [
|
|
|
607
623
|
{ name: 'quickstart', usage: 'sks quickstart', description: 'Show the shortest safe setup and verification flow.' },
|
|
608
624
|
{ name: 'bootstrap', usage: 'sks bootstrap [--install-scope global|project] [--local-only] [--json]', description: 'Initialize the current project, install SKS Codex App files/skills, check Context7/Codex App/Zellij, and print ready true/false.' },
|
|
609
625
|
{ name: 'root', usage: 'sks root [--json]', description: 'Show whether SKS is using a project root or the per-user global SKS runtime root.' },
|
|
626
|
+
{ name: 'update', usage: 'sks update check|now [--version <version>] [--json] [--dry-run]', description: 'Check for SKS updates or install the requested package version through npm global mode.' },
|
|
610
627
|
{ name: 'deps', usage: 'sks deps check [--json] [--yes]', description: 'Check Node/npm, Codex CLI, and Zellij readiness; pass --yes to repair missing Codex CLI/Zellij tooling when supported.' },
|
|
611
628
|
{ name: 'codex', usage: 'sks codex compatibility|version|doctor|schema [--json]', description: 'Check Codex CLI rust-v0.136.0 compatibility, installed version, 0.136 capabilities, inherited 0.135/0.134/0.133 behavior, and vendored hook schema snapshot freshness.' },
|
|
612
629
|
{ name: 'codex-app', usage: 'sks codex-app [check|chrome-extension|pat status|remote-control]', description: 'Check Codex App install, Codex Chrome Extension web verification readiness, PAT-safe status, first-party MCP/plugin readiness, and Codex CLI 0.130.0+ remote-control availability.' },
|
|
@@ -621,6 +638,7 @@ export const COMMAND_CATALOG = [
|
|
|
621
638
|
{ name: 'auto-review', usage: 'sks auto-review status|enable|start [--high] | sks --Auto-review --high', description: 'Enable Codex automatic approval review and launch SKS Zellij with the auto-review profile.' },
|
|
622
639
|
{ name: 'dollar-commands', usage: 'sks dollar-commands [--json]', description: 'List Codex App $ commands such as $DFix and $Team.' },
|
|
623
640
|
{ name: 'fast-mode', usage: 'sks fast-mode on|off|status|clear [--json]', description: 'Toggle the project-local Fast mode default used by $Fast-On, $Fast-Off, and native-agent routes.' },
|
|
641
|
+
{ name: 'with-local-llm', usage: 'sks with-local-llm on|off|status|set-model [--json]', description: 'Toggle the optional local Ollama worker backend used by $with-local-llm-on/$with-local-llm-off and eligible simple worker slices.' },
|
|
624
642
|
{ name: 'commit', usage: 'sks commit [--message "msg"] [--json]', description: 'Stage current changes, summarize them, and create a simple git commit without the full SKS pipeline.' },
|
|
625
643
|
{ name: 'commit-and-push', usage: 'sks commit-and-push [--message "msg"] [--json]', description: 'Stage current changes, create a simple git commit, and push without the full SKS pipeline.' },
|
|
626
644
|
{ name: 'dfix', usage: 'sks dfix', description: 'Explain $DFix ultralight direct-fix mode.' },
|
|
@@ -1007,6 +1025,8 @@ export function routeReasoning(route, prompt = '') {
|
|
|
1007
1025
|
const base = ALLOWED_REASONING_EFFORTS.has(route?.reasoningPolicy) ? route.reasoningPolicy : 'medium';
|
|
1008
1026
|
if (hasFromChatImgSignal(text))
|
|
1009
1027
|
return reasoning('xhigh', 'from_chat_img_image_work_order_analysis');
|
|
1028
|
+
if (/(?:^|\s)sks\s+--mad\b|(?:^|\s)--mad\b|\$MAD-SKS\b|\bmad-sks\b|\bmadsks\b/i.test(text))
|
|
1029
|
+
return reasoning('xhigh', 'mad_sks_or_mad_launch_default');
|
|
1010
1030
|
if (route?.id === 'Team')
|
|
1011
1031
|
return teamRouteReasoning(text);
|
|
1012
1032
|
if (route?.id === 'Research' || route?.id === 'AutoResearch')
|
|
@@ -162,6 +162,8 @@ export async function guardedProcessKill(ctx, pid, opts = {}) {
|
|
|
162
162
|
export async function guardedPackageInstall(ctx, spec, opts) {
|
|
163
163
|
return guard(ctx, 'package_install', spec, opts, async () => {
|
|
164
164
|
const runOpts = { timeoutMs: opts.timeoutMs ?? 600000 };
|
|
165
|
+
if (opts.cwd !== undefined)
|
|
166
|
+
runOpts.cwd = opts.cwd;
|
|
165
167
|
if (opts.env !== undefined)
|
|
166
168
|
runOpts.env = opts.env;
|
|
167
169
|
if (opts.maxOutputBytes !== undefined)
|
package/dist/core/team-live.js
CHANGED
|
@@ -360,7 +360,13 @@ export function parseTeamSpecArgs(args = []) {
|
|
|
360
360
|
i++;
|
|
361
361
|
continue;
|
|
362
362
|
}
|
|
363
|
-
if (
|
|
363
|
+
if (/^--(?:ollama-model|local-model-model|ollama-base-url|local-model-base-url)$/.test(arg)) {
|
|
364
|
+
i++;
|
|
365
|
+
continue;
|
|
366
|
+
}
|
|
367
|
+
if (/^--(?:ollama-model|local-model-model|ollama-base-url|local-model-base-url)=/.test(arg))
|
|
368
|
+
continue;
|
|
369
|
+
if (arg === '--json' || arg === '--open-zellij' || arg === '--zellij-open' || arg === '--no-open-zellij' || arg === '--no-zellij' || arg === '--no-attach' || arg === '--separate-session' || arg === '--new-session' || arg === '--legacy-team-session' || arg === '--ollama' || arg === '--local-model' || arg === '--no-ollama' || arg === '--no-local-model')
|
|
364
370
|
continue;
|
|
365
371
|
const consumed = consumeTeamSpecText(arg, { roleCounts, explicitExecutor, explicitSession });
|
|
366
372
|
roleCounts = consumed.roleCounts;
|