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
|
@@ -1,5 +1,8 @@
|
|
|
1
|
+
import os from 'node:os';
|
|
1
2
|
import path from 'node:path';
|
|
2
3
|
import { PACKAGE_VERSION, packageRoot, readJson, runProcess, which } from './fsx.js';
|
|
4
|
+
import { createRequestedScopeContract } from './safety/requested-scope-contract.js';
|
|
5
|
+
import { guardedPackageInstall, guardContextForRoute } from './safety/mutation-guard.js';
|
|
3
6
|
const DEFAULT_REGISTRY = 'https://registry.npmjs.org/';
|
|
4
7
|
export async function runSksUpdateCheck(options = {}) {
|
|
5
8
|
const packageName = options.packageName || 'sneakoscope';
|
|
@@ -16,9 +19,21 @@ export async function runSksUpdateCheck(options = {}) {
|
|
|
16
19
|
effectiveOptions.timeoutMs = options.timeoutMs;
|
|
17
20
|
if (options.maxOutputBytes !== undefined)
|
|
18
21
|
effectiveOptions.maxOutputBytes = options.maxOutputBytes;
|
|
19
|
-
const effective = await detectEffectiveSksVersion(effectiveOptions);
|
|
20
|
-
const current = effective.current;
|
|
21
22
|
const override = env[versionOverrideEnvName(packageName)];
|
|
23
|
+
const effectivePromise = detectEffectiveSksVersion(effectiveOptions);
|
|
24
|
+
const latestPromise = !override && npmBin
|
|
25
|
+
? runProcess(npmBin, ['view', packageName, 'version', '--silent', '--registry', registry], {
|
|
26
|
+
env,
|
|
27
|
+
timeoutMs: options.timeoutMs ?? 5000,
|
|
28
|
+
maxOutputBytes: options.maxOutputBytes ?? 4096
|
|
29
|
+
}).catch((err) => ({
|
|
30
|
+
code: 1,
|
|
31
|
+
stdout: '',
|
|
32
|
+
stderr: err instanceof Error ? err.message : String(err)
|
|
33
|
+
}))
|
|
34
|
+
: Promise.resolve(null);
|
|
35
|
+
const effective = await effectivePromise;
|
|
36
|
+
const current = effective.current;
|
|
22
37
|
if (override)
|
|
23
38
|
return buildResult({ packageName, current, effective, latest: override, registry, npmBin });
|
|
24
39
|
if (!npmBin) {
|
|
@@ -32,16 +47,18 @@ export async function runSksUpdateCheck(options = {}) {
|
|
|
32
47
|
error: 'npm not found on PATH'
|
|
33
48
|
});
|
|
34
49
|
}
|
|
35
|
-
const
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
50
|
+
const result = await latestPromise;
|
|
51
|
+
if (!result) {
|
|
52
|
+
return buildResult({
|
|
53
|
+
packageName,
|
|
54
|
+
current,
|
|
55
|
+
effective,
|
|
56
|
+
latest: null,
|
|
57
|
+
registry,
|
|
58
|
+
npmBin,
|
|
59
|
+
error: 'npm view failed'
|
|
60
|
+
});
|
|
61
|
+
}
|
|
45
62
|
if (result.code !== 0) {
|
|
46
63
|
return buildResult({
|
|
47
64
|
packageName,
|
|
@@ -62,6 +79,142 @@ export async function runSksUpdateCheck(options = {}) {
|
|
|
62
79
|
npmBin
|
|
63
80
|
});
|
|
64
81
|
}
|
|
82
|
+
export async function runSksUpdateNow(options = {}) {
|
|
83
|
+
const packageName = options.packageName || 'sneakoscope';
|
|
84
|
+
const registry = options.registry || DEFAULT_REGISTRY;
|
|
85
|
+
const env = options.env || process.env;
|
|
86
|
+
const npmBin = options.npmBin === undefined ? await which('npm') : options.npmBin;
|
|
87
|
+
const cwd = os.homedir();
|
|
88
|
+
const check = await runSksUpdateCheck({
|
|
89
|
+
...options,
|
|
90
|
+
packageName,
|
|
91
|
+
registry,
|
|
92
|
+
npmBin,
|
|
93
|
+
env
|
|
94
|
+
});
|
|
95
|
+
const requestedVersion = parseVersionText(options.version || '') || null;
|
|
96
|
+
const installVersion = requestedVersion || check.latest;
|
|
97
|
+
const npmArgs = installVersion ? sksGlobalInstallArgs(packageName, installVersion, registry) : [];
|
|
98
|
+
const command = npmBin && npmArgs.length ? [npmBin, ...npmArgs].join(' ') : null;
|
|
99
|
+
const globalRoot = npmBin ? await detectNpmGlobalRoot(npmBin, env, options).catch(() => null) : null;
|
|
100
|
+
if (!npmBin) {
|
|
101
|
+
return buildUpdateNowResult({
|
|
102
|
+
packageName,
|
|
103
|
+
from: check.current,
|
|
104
|
+
latest: check.latest,
|
|
105
|
+
requestedVersion,
|
|
106
|
+
installVersion,
|
|
107
|
+
npmBin: null,
|
|
108
|
+
npmArgs,
|
|
109
|
+
command,
|
|
110
|
+
cwd,
|
|
111
|
+
registry,
|
|
112
|
+
globalRoot,
|
|
113
|
+
status: 'unavailable',
|
|
114
|
+
ok: false,
|
|
115
|
+
installCode: null,
|
|
116
|
+
error: 'npm not found on PATH'
|
|
117
|
+
});
|
|
118
|
+
}
|
|
119
|
+
if (!installVersion) {
|
|
120
|
+
return buildUpdateNowResult({
|
|
121
|
+
packageName,
|
|
122
|
+
from: check.current,
|
|
123
|
+
latest: check.latest,
|
|
124
|
+
requestedVersion,
|
|
125
|
+
installVersion,
|
|
126
|
+
npmBin,
|
|
127
|
+
npmArgs,
|
|
128
|
+
command,
|
|
129
|
+
cwd,
|
|
130
|
+
registry,
|
|
131
|
+
globalRoot,
|
|
132
|
+
status: 'unavailable',
|
|
133
|
+
ok: false,
|
|
134
|
+
installCode: null,
|
|
135
|
+
error: check.error || 'latest version unavailable'
|
|
136
|
+
});
|
|
137
|
+
}
|
|
138
|
+
if (!requestedVersion && check.latest && !check.update_available) {
|
|
139
|
+
return buildUpdateNowResult({
|
|
140
|
+
packageName,
|
|
141
|
+
from: check.current,
|
|
142
|
+
latest: check.latest,
|
|
143
|
+
requestedVersion,
|
|
144
|
+
installVersion,
|
|
145
|
+
npmBin,
|
|
146
|
+
npmArgs,
|
|
147
|
+
command,
|
|
148
|
+
cwd,
|
|
149
|
+
registry,
|
|
150
|
+
globalRoot,
|
|
151
|
+
status: 'current',
|
|
152
|
+
ok: true,
|
|
153
|
+
installCode: null,
|
|
154
|
+
error: null
|
|
155
|
+
});
|
|
156
|
+
}
|
|
157
|
+
if (options.dryRun) {
|
|
158
|
+
return buildUpdateNowResult({
|
|
159
|
+
packageName,
|
|
160
|
+
from: check.current,
|
|
161
|
+
latest: check.latest,
|
|
162
|
+
requestedVersion,
|
|
163
|
+
installVersion,
|
|
164
|
+
npmBin,
|
|
165
|
+
npmArgs,
|
|
166
|
+
command,
|
|
167
|
+
cwd,
|
|
168
|
+
registry,
|
|
169
|
+
globalRoot,
|
|
170
|
+
status: 'dry_run',
|
|
171
|
+
ok: true,
|
|
172
|
+
installCode: null,
|
|
173
|
+
error: null
|
|
174
|
+
});
|
|
175
|
+
}
|
|
176
|
+
const mutationLedgerRoot = env.SKS_MUTATION_LEDGER_ROOT || packageRoot();
|
|
177
|
+
const installContract = createRequestedScopeContract({
|
|
178
|
+
route: 'update',
|
|
179
|
+
userRequest: command || `npm global install ${packageName}`,
|
|
180
|
+
projectRoot: mutationLedgerRoot,
|
|
181
|
+
overrides: { package_install: true }
|
|
182
|
+
});
|
|
183
|
+
const install = await guardedPackageInstall(guardContextForRoute(mutationLedgerRoot, installContract, command || `npm global install ${packageName}`), `${packageName}@${installVersion}`, {
|
|
184
|
+
confirmed: true,
|
|
185
|
+
command: npmBin,
|
|
186
|
+
args: npmArgs,
|
|
187
|
+
cwd,
|
|
188
|
+
env,
|
|
189
|
+
timeoutMs: options.timeoutMs ?? 10 * 60 * 1000,
|
|
190
|
+
maxOutputBytes: options.maxOutputBytes ?? 128 * 1024
|
|
191
|
+
}).catch((err) => ({
|
|
192
|
+
code: 1,
|
|
193
|
+
stdout: '',
|
|
194
|
+
stderr: err instanceof Error ? err.message : String(err)
|
|
195
|
+
}));
|
|
196
|
+
const ok = install.code === 0;
|
|
197
|
+
return buildUpdateNowResult({
|
|
198
|
+
packageName,
|
|
199
|
+
from: check.current,
|
|
200
|
+
latest: check.latest,
|
|
201
|
+
requestedVersion,
|
|
202
|
+
installVersion,
|
|
203
|
+
npmBin,
|
|
204
|
+
npmArgs,
|
|
205
|
+
command,
|
|
206
|
+
cwd,
|
|
207
|
+
registry,
|
|
208
|
+
globalRoot,
|
|
209
|
+
status: ok ? 'updated' : 'failed',
|
|
210
|
+
ok,
|
|
211
|
+
installCode: install.code,
|
|
212
|
+
error: ok ? null : `${install.stderr || install.stdout || 'npm global install failed'}`.trim()
|
|
213
|
+
});
|
|
214
|
+
}
|
|
215
|
+
export function sksGlobalInstallArgs(packageName, version, registry = DEFAULT_REGISTRY) {
|
|
216
|
+
return ['install', '--global', `${packageName}@${version}`, '--registry', registry];
|
|
217
|
+
}
|
|
65
218
|
export async function detectEffectiveSksVersion(options = {}) {
|
|
66
219
|
const packageName = options.packageName || 'sneakoscope';
|
|
67
220
|
const env = options.env || process.env;
|
|
@@ -75,25 +228,34 @@ export async function detectEffectiveSksVersion(options = {}) {
|
|
|
75
228
|
};
|
|
76
229
|
add(options.currentVersion || PACKAGE_VERSION, 'runtime');
|
|
77
230
|
add(env.SKS_INSTALLED_SKS_VERSION, 'env:SKS_INSTALLED_SKS_VERSION');
|
|
78
|
-
const
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
231
|
+
const packageRootPromise = readJson(path.join(packageRoot(), 'package.json'), {}).catch(() => ({}));
|
|
232
|
+
const pathSksPromise = which('sks')
|
|
233
|
+
.then(async (sks) => {
|
|
234
|
+
if (!sks)
|
|
235
|
+
return null;
|
|
82
236
|
const result = await runProcess(sks, ['--version'], {
|
|
83
237
|
timeoutMs: 2000,
|
|
84
238
|
maxOutputBytes: 4096,
|
|
85
239
|
env: { ...env, SKS_DISABLE_UPDATE_CHECK: '1' }
|
|
86
240
|
}).catch((err) => ({ code: 1, stdout: '', stderr: err?.message || String(err) }));
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
if (npmBin) {
|
|
93
|
-
const npmGlobal = await detectNpmGlobalPackageVersion(npmBin, packageName, env, {
|
|
241
|
+
return { sks, result };
|
|
242
|
+
})
|
|
243
|
+
.catch(() => null);
|
|
244
|
+
const npmGlobalPromise = npmBin
|
|
245
|
+
? detectNpmGlobalPackageVersion(npmBin, packageName, env, {
|
|
94
246
|
timeoutMs: options.timeoutMs ?? 2500,
|
|
95
247
|
maxOutputBytes: options.maxOutputBytes ?? 8192
|
|
96
|
-
}).catch((err) => ({ version: null, error: err?.message || String(err) }))
|
|
248
|
+
}).catch((err) => ({ version: null, error: err?.message || String(err) }))
|
|
249
|
+
: Promise.resolve(null);
|
|
250
|
+
const [pkg, pathSks, npmGlobal] = await Promise.all([packageRootPromise, pathSksPromise, npmGlobalPromise]);
|
|
251
|
+
add(pkg?.version, 'packageRoot:package.json');
|
|
252
|
+
if (pathSks?.sks) {
|
|
253
|
+
if (pathSks.result.code === 0)
|
|
254
|
+
add(pathSks.result.stdout, `PATH:${pathSks.sks}`);
|
|
255
|
+
else
|
|
256
|
+
errors.push(`path_sks_version:${String(pathSks.result.stderr || pathSks.result.stdout || 'failed').trim()}`);
|
|
257
|
+
}
|
|
258
|
+
if (npmGlobal) {
|
|
97
259
|
add(npmGlobal.version, `npm-global:${packageName}`);
|
|
98
260
|
if (npmGlobal.error)
|
|
99
261
|
errors.push(`npm_global_version:${npmGlobal.error}`);
|
|
@@ -183,12 +345,40 @@ function buildResult(input) {
|
|
|
183
345
|
mode: 'function',
|
|
184
346
|
route_required: false,
|
|
185
347
|
pipeline_required: false,
|
|
186
|
-
command: updateAvailable ? `
|
|
348
|
+
command: updateAvailable ? `sks update now --version ${input.latest}` : null,
|
|
187
349
|
npm_bin: input.npmBin,
|
|
188
350
|
registry: input.registry,
|
|
189
351
|
error: input.error || null
|
|
190
352
|
};
|
|
191
353
|
}
|
|
354
|
+
function buildUpdateNowResult(input) {
|
|
355
|
+
return {
|
|
356
|
+
schema: 'sks.update-now.v1',
|
|
357
|
+
ok: input.ok,
|
|
358
|
+
status: input.status,
|
|
359
|
+
package: input.packageName,
|
|
360
|
+
from: input.from,
|
|
361
|
+
latest: input.latest,
|
|
362
|
+
requested_version: input.requestedVersion,
|
|
363
|
+
install_version: input.installVersion,
|
|
364
|
+
npm_bin: input.npmBin,
|
|
365
|
+
npm_args: input.npmArgs,
|
|
366
|
+
command: input.command,
|
|
367
|
+
cwd: input.cwd,
|
|
368
|
+
registry: input.registry,
|
|
369
|
+
global_root: input.globalRoot,
|
|
370
|
+
install_code: input.installCode,
|
|
371
|
+
error: input.error
|
|
372
|
+
};
|
|
373
|
+
}
|
|
374
|
+
async function detectNpmGlobalRoot(npmBin, env, opts = {}) {
|
|
375
|
+
const result = await runProcess(npmBin, ['root', '--global', '--silent'], {
|
|
376
|
+
env,
|
|
377
|
+
timeoutMs: opts.timeoutMs ?? 2500,
|
|
378
|
+
maxOutputBytes: opts.maxOutputBytes ?? 4096
|
|
379
|
+
}).catch(() => ({ code: 1, stdout: '', stderr: '' }));
|
|
380
|
+
return result.code === 0 ? String(result.stdout || '').trim().split(/\r?\n/).pop() || null : null;
|
|
381
|
+
}
|
|
192
382
|
function versionOverrideEnvName(packageName) {
|
|
193
383
|
return `SKS_NPM_VIEW_${packageName.replace(/[^A-Za-z0-9]+/g, '_').toUpperCase()}_VERSION`;
|
|
194
384
|
}
|
|
@@ -87,6 +87,7 @@ export async function runVerificationTask(task, opts = {}) {
|
|
|
87
87
|
let timedOut = false;
|
|
88
88
|
const timeoutMs = task.timeout_ms || 10 * 60 * 1000;
|
|
89
89
|
let killTimeout = null;
|
|
90
|
+
let exitFallback = null;
|
|
90
91
|
const finish = (payload) => {
|
|
91
92
|
if (settled)
|
|
92
93
|
return;
|
|
@@ -94,6 +95,8 @@ export async function runVerificationTask(task, opts = {}) {
|
|
|
94
95
|
clearTimeout(timeout);
|
|
95
96
|
if (killTimeout)
|
|
96
97
|
clearTimeout(killTimeout);
|
|
98
|
+
if (exitFallback)
|
|
99
|
+
clearTimeout(exitFallback);
|
|
97
100
|
resolve(payload);
|
|
98
101
|
};
|
|
99
102
|
const timeout = setTimeout(() => {
|
|
@@ -113,6 +116,15 @@ export async function runVerificationTask(task, opts = {}) {
|
|
|
113
116
|
child.on('error', (err) => {
|
|
114
117
|
finish({ code: null, error: err.message });
|
|
115
118
|
});
|
|
119
|
+
child.on('exit', (code) => {
|
|
120
|
+
if (settled)
|
|
121
|
+
return;
|
|
122
|
+
exitFallback = setTimeout(async () => {
|
|
123
|
+
if (timedOut)
|
|
124
|
+
await waitForProcessTreeExit(child.pid, 2_000);
|
|
125
|
+
finish({ code, ...(timedOut ? { error: `timeout:${timeoutMs}` } : {}) });
|
|
126
|
+
}, 1_000);
|
|
127
|
+
});
|
|
116
128
|
child.on('close', async (code) => {
|
|
117
129
|
if (timedOut)
|
|
118
130
|
await waitForProcessTreeExit(child.pid, 2_000);
|
package/dist/core/version.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export const PACKAGE_VERSION = '2.0.
|
|
1
|
+
export const PACKAGE_VERSION = '2.0.4';
|
|
2
2
|
//# sourceMappingURL=version.js.map
|
|
@@ -57,6 +57,8 @@ export function buildWorkerPaneArtifact(input) {
|
|
|
57
57
|
opened_at: now,
|
|
58
58
|
closed_at: null,
|
|
59
59
|
close: null,
|
|
60
|
+
direction_requested: 'right',
|
|
61
|
+
direction_applied: input.directionApplied || 'not_applied',
|
|
60
62
|
sdk_thread_id: input.sdkThreadId || null,
|
|
61
63
|
sdk_run_id: input.sdkRunId || null,
|
|
62
64
|
stream_event_count: Number(input.streamEventCount || 0),
|
|
@@ -81,13 +83,25 @@ export async function openWorkerPane(input) {
|
|
|
81
83
|
optional: false
|
|
82
84
|
});
|
|
83
85
|
const paneName = buildWorkerPaneTitle(input.slotId, input.generationIndex, providerContext, input.serviceTier);
|
|
84
|
-
|
|
85
|
-
? await runZellij(['--session', input.sessionName, 'action', 'new-pane', '--name', paneName, '--', 'sh', '-lc', input.workerCommand], {
|
|
86
|
+
let launch = createSession.ok
|
|
87
|
+
? await runZellij(['--session', input.sessionName, 'action', 'new-pane', '--direction', 'right', '--name', paneName, '--', 'sh', '-lc', input.workerCommand], {
|
|
86
88
|
cwd,
|
|
87
89
|
timeoutMs: 5000,
|
|
88
90
|
optional: false
|
|
89
91
|
})
|
|
90
92
|
: null;
|
|
93
|
+
let directionApplied = launch?.ok ? 'right' : 'not_applied';
|
|
94
|
+
if (createSession.ok && launch && !launch.ok) {
|
|
95
|
+
const fallback = await runZellij(['--session', input.sessionName, 'action', 'new-pane', '--name', paneName, '--', 'sh', '-lc', input.workerCommand], {
|
|
96
|
+
cwd,
|
|
97
|
+
timeoutMs: 5000,
|
|
98
|
+
optional: false
|
|
99
|
+
});
|
|
100
|
+
if (fallback.ok) {
|
|
101
|
+
launch = fallback;
|
|
102
|
+
directionApplied = 'unknown';
|
|
103
|
+
}
|
|
104
|
+
}
|
|
91
105
|
const stdoutPaneId = launch?.ok ? extractZellijPaneIdFromOutput(launch.stdout_tail) : null;
|
|
92
106
|
const reconciledPane = stdoutPaneId ? null : launch?.ok ? await reconcileZellijWorkerPaneId(input.sessionName, paneName, path.join(root, input.resultPath), cwd) : null;
|
|
93
107
|
const paneId = stdoutPaneId || reconciledPane?.pane_id || null;
|
|
@@ -110,6 +124,7 @@ export async function openWorkerPane(input) {
|
|
|
110
124
|
createSession,
|
|
111
125
|
launch,
|
|
112
126
|
paneReconciliation: reconciledPane,
|
|
127
|
+
directionApplied,
|
|
113
128
|
status: blockers.length ? 'failed' : 'running',
|
|
114
129
|
providerContext,
|
|
115
130
|
serviceTier: input.serviceTier || providerContext.service_tier,
|
|
@@ -139,6 +154,8 @@ export async function openWorkerPane(input) {
|
|
|
139
154
|
provider: record.provider,
|
|
140
155
|
service_tier: record.service_tier,
|
|
141
156
|
provider_context: record.provider_context,
|
|
157
|
+
direction_requested: record.direction_requested,
|
|
158
|
+
direction_applied: record.direction_applied,
|
|
142
159
|
command: '<native-cli-worker-command>',
|
|
143
160
|
worker_artifact_dir: input.workerArtifactDir,
|
|
144
161
|
worker_result_path: input.resultPath,
|
|
@@ -20,6 +20,6 @@ assertGate(Object.keys(graph.command_to_module_ownership).length > 0, 'AST-aware
|
|
|
20
20
|
assertGate(graph.test_ownership_confidence >= 0, 'AST-aware work graph must record test ownership confidence', graph);
|
|
21
21
|
assertGate(['proven', 'partial', 'blocked'].includes(graph.proof_level), 'AST-aware work graph must report an honest proof level', graph);
|
|
22
22
|
fs.mkdirSync(path.join(root, '.sneakoscope', 'reports'), { recursive: true });
|
|
23
|
-
fs.writeFileSync(path.join(root, '.sneakoscope', 'reports', `agent-intelligent-work-graph-v2-${releaseVersion}.json`), `${JSON.stringify(graph, null, 2)}\n`);
|
|
23
|
+
fs.writeFileSync(path.join(root, '.sneakoscope', 'reports', `agent-intelligent-work-graph-v2-${releaseVersion}.json`), `${JSON.stringify(graphMod.compactIntelligentWorkGraph(graph), null, 2)}\n`);
|
|
24
24
|
emitGate('agent:ast-aware-work-graph', { score: graph.work_graph_quality_score, ast_coverage: graph.ast_coverage, proof_level: graph.proof_level });
|
|
25
25
|
//# sourceMappingURL=agent-ast-aware-work-graph-check.js.map
|
|
@@ -6,6 +6,7 @@ const naruto = readText('src/core/commands/naruto-command.ts');
|
|
|
6
6
|
const agent = readText('src/core/agents/agent-command-surface.ts');
|
|
7
7
|
assertGate(team.includes("backend: mock ? 'fake' : 'codex-sdk'"), 'Team must default to codex-sdk');
|
|
8
8
|
assertGate(naruto.includes("backend: 'codex-sdk'"), 'Naruto help/defaults must expose codex-sdk');
|
|
9
|
-
assertGate(agent.includes("
|
|
9
|
+
assertGate(agent.includes("useOllama && !noOllama ? 'ollama' : 'codex-sdk'"), 'Agent command surface must default to codex-sdk unless local model is explicit');
|
|
10
|
+
assertGate(agent.includes('backendExplicit'), 'Agent command surface must preserve explicit backend/local-model intent');
|
|
10
11
|
emitGate('codex-sdk:team-naruto-agent-pipeline', { routes: ['$Team', '$Naruto', '$Agent'] });
|
|
11
12
|
//# sourceMappingURL=codex-sdk-team-naruto-agent-pipeline-check.js.map
|
|
@@ -14,13 +14,23 @@ const repaired = await repairCodexAppFastUi(root, { codexHome, apply: true });
|
|
|
14
14
|
const projectAfter = await fs.readFile(path.join(root, '.codex', 'config.toml'), 'utf8');
|
|
15
15
|
const homeAfter = await fs.readFile(path.join(codexHome, 'config.toml'), 'utf8');
|
|
16
16
|
const backups = repaired.actions.filter((action) => action.changed).map((action) => action.backup_path).filter(Boolean);
|
|
17
|
+
const unsafeRoot = await fs.mkdtemp(path.join(os.tmpdir(), 'sks-doctor-fast-ui-unsafe-'));
|
|
18
|
+
const unsafeCodexHome = path.join(unsafeRoot, 'home', '.codex');
|
|
19
|
+
await fs.mkdir(path.join(unsafeRoot, '.codex'), { recursive: true });
|
|
20
|
+
await fs.mkdir(unsafeCodexHome, { recursive: true });
|
|
21
|
+
await fs.writeFile(path.join(unsafeCodexHome, 'config.toml'), 'service_tier = "standard"\n');
|
|
22
|
+
const unsafePlan = await repairCodexAppFastUi(unsafeRoot, { codexHome: unsafeCodexHome, apply: false });
|
|
17
23
|
const ok = plan.fast_selector === 'manual_action_required'
|
|
24
|
+
&& plan.safe_auto_apply === true
|
|
18
25
|
&& repaired.fast_selector === 'repaired'
|
|
26
|
+
&& repaired.safe_auto_apply === true
|
|
19
27
|
&& backups.length >= 2
|
|
20
28
|
&& !/model_provider\s*=/.test(projectAfter)
|
|
21
29
|
&& !/service_tier\s*=/.test(homeAfter)
|
|
22
|
-
&& /fast_mode = false/.test(homeAfter)
|
|
23
|
-
|
|
30
|
+
&& /fast_mode = false/.test(homeAfter)
|
|
31
|
+
&& unsafePlan.requires_confirmation === true
|
|
32
|
+
&& unsafePlan.safe_auto_apply === false;
|
|
33
|
+
emit({ schema: 'sks.doctor-fixes-codex-app-fast-ui-check.v1', ok, plan, repaired, unsafe_plan: unsafePlan, project_after: projectAfter, home_after: homeAfter, blockers: ok ? [] : ['doctor_fixes_codex_app_fast_ui_check_failed'] });
|
|
24
34
|
function emit(report) {
|
|
25
35
|
console.log(JSON.stringify(report, null, 2));
|
|
26
36
|
if (!report.ok)
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// @ts-nocheck
|
|
3
|
+
import fs from 'node:fs/promises';
|
|
4
|
+
import os from 'node:os';
|
|
5
|
+
import path from 'node:path';
|
|
6
|
+
import { assertGate, emitGate, importDist, readJsonFile, root } from './lib/codex-sdk-gate-lib.js';
|
|
7
|
+
const mod = await importDist('core/codex-control/gpt-final-arbiter.js');
|
|
8
|
+
const old = snapshotEnv();
|
|
9
|
+
process.env.NODE_ENV = 'test';
|
|
10
|
+
process.env.SKS_CODEX_SDK_FAKE = '1';
|
|
11
|
+
delete process.env.SKS_GPT_FINAL_ARBITER_UNAVAILABLE;
|
|
12
|
+
try {
|
|
13
|
+
const tmp = await fs.mkdtemp(path.join(os.tmpdir(), 'sks-gpt-final-arbiter-'));
|
|
14
|
+
const approved = await mod.runGptFinalArbiter(fixtureInput('approved'), { cwd: root, mutationLedgerRoot: tmp });
|
|
15
|
+
assertGate(approved.ok === true, 'GPT final arbiter fixture must approve safe candidate', approved);
|
|
16
|
+
assertGate(approved.backend === 'codex-sdk', 'GPT final arbiter backend must be codex-sdk');
|
|
17
|
+
assertGate(approved.result.status === 'approved', 'safe candidate must return approved');
|
|
18
|
+
assertGate(approved.final_gate.ok === true, 'approved arbiter result must pass final gate');
|
|
19
|
+
const artifact = await readJsonFile(path.join(tmp, 'gpt-final-arbiter.json'));
|
|
20
|
+
assertGate(artifact.result.schema === 'sks.gpt-final-arbiter-result.v1', 'arbiter artifact must contain schema-valid result');
|
|
21
|
+
const unsafeTmp = await fs.mkdtemp(path.join(os.tmpdir(), 'sks-gpt-final-arbiter-unsafe-'));
|
|
22
|
+
const rejected = await mod.runGptFinalArbiter({ ...fixtureInput('unsafe'), candidate_diff: 'unsafe delete all credential patch' }, { cwd: root, mutationLedgerRoot: unsafeTmp });
|
|
23
|
+
assertGate(rejected.ok === false, 'unsafe candidate must not pass final arbiter');
|
|
24
|
+
assertGate(rejected.result.status === 'rejected', 'unsafe candidate must be rejected');
|
|
25
|
+
assertGate(rejected.blockers.includes('unsafe_candidate_patch'), 'unsafe rejection blocker must be preserved');
|
|
26
|
+
emitGate('local-collab:gpt-final-arbiter', { approved: approved.result.status, rejected: rejected.result.status });
|
|
27
|
+
}
|
|
28
|
+
finally {
|
|
29
|
+
restoreEnv(old);
|
|
30
|
+
}
|
|
31
|
+
function fixtureInput(label) {
|
|
32
|
+
return {
|
|
33
|
+
schema: 'sks.gpt-final-arbiter-input.v1',
|
|
34
|
+
route: '$Naruto',
|
|
35
|
+
mission_id: `M-${label}`,
|
|
36
|
+
local_mode: 'local-parallel-gpt-final',
|
|
37
|
+
local_outputs: [
|
|
38
|
+
{ worker_id: 'slot-001/gen-1', backend: 'local-llm', summary: 'candidate patch drafted', patch_envelopes: [], proof: 'local draft' }
|
|
39
|
+
],
|
|
40
|
+
candidate_diff: 'diff --git a/example.ts b/example.ts',
|
|
41
|
+
candidate_patch_envelopes: [],
|
|
42
|
+
verification_results: [{ ok: true, status: 'passed' }],
|
|
43
|
+
side_effect_report: { ok: true },
|
|
44
|
+
mutation_ledger: { ok: true },
|
|
45
|
+
rollback_plan: { ok: true }
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
function snapshotEnv() {
|
|
49
|
+
return {
|
|
50
|
+
NODE_ENV: process.env.NODE_ENV,
|
|
51
|
+
SKS_CODEX_SDK_FAKE: process.env.SKS_CODEX_SDK_FAKE,
|
|
52
|
+
SKS_GPT_FINAL_ARBITER_UNAVAILABLE: process.env.SKS_GPT_FINAL_ARBITER_UNAVAILABLE
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
function restoreEnv(old) {
|
|
56
|
+
for (const [key, value] of Object.entries(old)) {
|
|
57
|
+
if (value === undefined)
|
|
58
|
+
delete process.env[key];
|
|
59
|
+
else
|
|
60
|
+
process.env[key] = value;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
//# sourceMappingURL=gpt-final-arbiter-check.js.map
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// @ts-nocheck
|
|
3
|
+
import { assertGate, emitGate, importDist } from './lib/codex-sdk-gate-lib.js';
|
|
4
|
+
const compressor = await importDist('core/codex-control/gpt-final-context-compressor.js');
|
|
5
|
+
const local_outputs = Array.from({ length: 20 }, (_, index) => ({
|
|
6
|
+
worker_id: `slot-${String(index + 1).padStart(3, '0')}/gen-1`,
|
|
7
|
+
backend: 'local-llm',
|
|
8
|
+
status: 'done',
|
|
9
|
+
summary: `worker ${index + 1} summarized a bounded shard`,
|
|
10
|
+
changed_files: [`src/example-${index + 1}.ts`],
|
|
11
|
+
blockers: []
|
|
12
|
+
}));
|
|
13
|
+
const candidate_patch_envelopes = local_outputs.map((output, index) => ({
|
|
14
|
+
id: `patch-${index + 1}`,
|
|
15
|
+
agent_id: output.worker_id,
|
|
16
|
+
source: 'model_authored',
|
|
17
|
+
lease_id: `lease-${index + 1}`,
|
|
18
|
+
rollback_hint: { ok: true },
|
|
19
|
+
operations: [{ op: 'replace', path: output.changed_files[0], search: 'before', replace: 'after' }]
|
|
20
|
+
}));
|
|
21
|
+
const report = compressor.compressGptFinalContext({
|
|
22
|
+
route: '$Naruto',
|
|
23
|
+
mission_id: 'M-20-local-workers',
|
|
24
|
+
local_mode: 'local-parallel-gpt-final',
|
|
25
|
+
local_outputs,
|
|
26
|
+
candidate_patch_envelopes,
|
|
27
|
+
verification_results: [{ ok: true, status: 'passed' }],
|
|
28
|
+
side_effect_report: { ok: true },
|
|
29
|
+
mutation_ledger: { ok: true },
|
|
30
|
+
rollback_plan: { ok: true }
|
|
31
|
+
});
|
|
32
|
+
assertGate(report.proof_pack.worker_count === 20, 'proof pack must include 20 worker summaries');
|
|
33
|
+
assertGate(report.proof_pack.token_budget_estimate < 8000, '20-worker proof pack must stay under token budget', report.proof_pack);
|
|
34
|
+
assertGate(report.latency_budget.ok === true, 'GPT final latency budget report must pass');
|
|
35
|
+
emitGate('local-collab:gpt-final-performance', { workers: report.proof_pack.worker_count, token_budget_estimate: report.proof_pack.token_budget_estimate });
|
|
36
|
+
//# sourceMappingURL=gpt-final-arbiter-performance-check.js.map
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// @ts-nocheck
|
|
3
|
+
import fs from 'node:fs/promises';
|
|
4
|
+
import os from 'node:os';
|
|
5
|
+
import path from 'node:path';
|
|
6
|
+
import { assertGate, emitGate, importDist, root } from './lib/codex-sdk-gate-lib.js';
|
|
7
|
+
const arbiterMod = await importDist('core/codex-control/gpt-final-arbiter.js');
|
|
8
|
+
const doctorMod = await importDist('core/doctor/doctor-readiness-matrix.js');
|
|
9
|
+
const old = snapshotEnv();
|
|
10
|
+
try {
|
|
11
|
+
process.env.SKS_GPT_FINAL_ARBITER_UNAVAILABLE = '1';
|
|
12
|
+
const unavailable = await arbiterMod.runGptFinalArbiter(input('unavailable'), { writeArtifact: false, forceUnavailable: true });
|
|
13
|
+
assertGate(unavailable.ok === false, 'GPT unavailable fixture must block final apply');
|
|
14
|
+
assertGate(unavailable.blockers.includes('gpt_final_arbiter_unavailable'), 'GPT unavailable blocker must be present');
|
|
15
|
+
const doctor = doctorMod.buildDoctorReadinessMatrix({
|
|
16
|
+
codex: { available: false },
|
|
17
|
+
codex_config: { ok: true, checks: [] },
|
|
18
|
+
local_collaboration: { mode: 'local-parallel-gpt-final', gpt_final_arbiter_available: false }
|
|
19
|
+
});
|
|
20
|
+
assertGate(doctor.blockers.includes('gpt_final_arbiter_unavailable'), 'doctor must report gpt_final_arbiter_unavailable');
|
|
21
|
+
delete process.env.SKS_GPT_FINAL_ARBITER_UNAVAILABLE;
|
|
22
|
+
process.env.NODE_ENV = 'test';
|
|
23
|
+
process.env.SKS_CODEX_SDK_FAKE = '1';
|
|
24
|
+
const tmp = await fs.mkdtemp(path.join(os.tmpdir(), 'sks-gpt-final-available-'));
|
|
25
|
+
const available = await arbiterMod.runGptFinalArbiter(input('available'), { cwd: root, mutationLedgerRoot: tmp });
|
|
26
|
+
assertGate(available.ok === true, 'GPT available fixture must pass final arbiter');
|
|
27
|
+
emitGate('local-collab:gpt-final-availability', { unavailable: unavailable.result.status, available: available.result.status });
|
|
28
|
+
}
|
|
29
|
+
finally {
|
|
30
|
+
restoreEnv(old);
|
|
31
|
+
}
|
|
32
|
+
function input(label) {
|
|
33
|
+
return {
|
|
34
|
+
schema: 'sks.gpt-final-arbiter-input.v1',
|
|
35
|
+
route: '$Team',
|
|
36
|
+
mission_id: `M-${label}`,
|
|
37
|
+
local_mode: 'local-parallel-gpt-final',
|
|
38
|
+
local_outputs: [{ worker_id: 'local', backend: 'local-llm', summary: 'candidate' }],
|
|
39
|
+
candidate_patch_envelopes: [],
|
|
40
|
+
verification_results: []
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
function snapshotEnv() {
|
|
44
|
+
return {
|
|
45
|
+
NODE_ENV: process.env.NODE_ENV,
|
|
46
|
+
SKS_CODEX_SDK_FAKE: process.env.SKS_CODEX_SDK_FAKE,
|
|
47
|
+
SKS_GPT_FINAL_ARBITER_UNAVAILABLE: process.env.SKS_GPT_FINAL_ARBITER_UNAVAILABLE
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
function restoreEnv(old) {
|
|
51
|
+
for (const [key, value] of Object.entries(old)) {
|
|
52
|
+
if (value === undefined)
|
|
53
|
+
delete process.env[key];
|
|
54
|
+
else
|
|
55
|
+
process.env[key] = value;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
//# sourceMappingURL=local-collab-gpt-final-availability-check.js.map
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// @ts-nocheck
|
|
3
|
+
import { assertGate, emitGate, importDist } from './lib/codex-sdk-gate-lib.js';
|
|
4
|
+
const policyMod = await importDist('core/local-llm/local-collaboration-policy.js');
|
|
5
|
+
const arbiterMod = await importDist('core/codex-control/gpt-final-arbiter.js');
|
|
6
|
+
const gate = policyMod.evaluateLocalCollaborationFinalGate({
|
|
7
|
+
mode: 'local-only-draft',
|
|
8
|
+
localParticipated: true,
|
|
9
|
+
gptFinalStatus: null,
|
|
10
|
+
gptFinalAvailable: false,
|
|
11
|
+
applyPatches: true
|
|
12
|
+
});
|
|
13
|
+
assertGate(gate.ok === false, 'local-only-draft must not be final accepted');
|
|
14
|
+
assertGate(gate.final_status === 'draft_only', 'local-only-draft must end as draft_only');
|
|
15
|
+
assertGate(gate.apply_allowed === false, 'local-only-draft must block apply');
|
|
16
|
+
const result = await arbiterMod.runGptFinalArbiter({
|
|
17
|
+
schema: 'sks.gpt-final-arbiter-input.v1',
|
|
18
|
+
route: '$DFix',
|
|
19
|
+
mission_id: 'M-local-only-draft',
|
|
20
|
+
local_mode: 'local-only-draft',
|
|
21
|
+
local_outputs: [{ worker_id: 'local', backend: 'local-llm', summary: 'draft only' }],
|
|
22
|
+
candidate_patch_envelopes: []
|
|
23
|
+
}, { writeArtifact: false });
|
|
24
|
+
assertGate(result.ok === false, 'local-only-draft arbiter result must not pass');
|
|
25
|
+
assertGate(result.blockers.includes('needs_gpt_final_review'), 'local-only-draft arbiter must include needs_gpt_final_review');
|
|
26
|
+
emitGate('local-collab:no-local-only-final', { final_status: gate.final_status, blockers: result.blockers.length });
|
|
27
|
+
//# sourceMappingURL=local-collab-no-local-only-final-check.js.map
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// @ts-nocheck
|
|
3
|
+
import { assertGate, emitGate, importDist, readText } from './lib/codex-sdk-gate-lib.js';
|
|
4
|
+
const policyMod = await importDist('core/local-llm/local-collaboration-policy.js');
|
|
5
|
+
const schemaText = readText('schemas/local-llm/local-collaboration-policy.schema.json');
|
|
6
|
+
const policy = policyMod.resolveLocalCollaborationPolicy({ env: {} });
|
|
7
|
+
assertGate(policy.mode === 'local-parallel-gpt-final', 'default local collaboration mode must be local-parallel-gpt-final');
|
|
8
|
+
assertGate(policy.gpt_final_required === true, 'default local collaboration mode must require GPT final');
|
|
9
|
+
assertGate(policy.final_patch_source_when_enabled === 'gpt_final_arbiter', 'final patch source must be GPT final arbiter');
|
|
10
|
+
assertGate(schemaText.includes('local-only-draft'), 'policy schema must include local-only-draft mode');
|
|
11
|
+
const draft = policyMod.resolveLocalCollaborationPolicy({ mode: 'local-only-draft' });
|
|
12
|
+
const draftGate = policyMod.evaluateLocalCollaborationFinalGate({ policy: draft, localParticipated: true, applyPatches: true });
|
|
13
|
+
assertGate(draftGate.ok === false, 'local-only-draft must not pass final gate');
|
|
14
|
+
assertGate(draftGate.blockers.includes('needs_gpt_final_review'), 'local-only-draft must carry needs_gpt_final_review');
|
|
15
|
+
assertGate(draftGate.blockers.includes('local_only_draft_apply_blocked'), 'local-only-draft must block apply');
|
|
16
|
+
emitGate('local-collab:policy', { default_mode: policy.mode, draft_blockers: draftGate.blockers.length });
|
|
17
|
+
//# sourceMappingURL=local-collab-policy-check.js.map
|