sneakoscope 2.0.2 → 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.
Files changed (38) hide show
  1. package/README.md +1 -1
  2. package/crates/sks-core/Cargo.lock +1 -1
  3. package/crates/sks-core/Cargo.toml +1 -1
  4. package/crates/sks-core/src/main.rs +1 -1
  5. package/dist/.sks-build-stamp.json +4 -4
  6. package/dist/bin/sks.js +1 -1
  7. package/dist/build-manifest.json +21 -8
  8. package/dist/core/agents/agent-orchestrator.js +70 -4
  9. package/dist/core/agents/agent-patch-proof.js +5 -0
  10. package/dist/core/agents/agent-proof-evidence.js +26 -0
  11. package/dist/core/codex-control/codex-fake-sdk-adapter.js +20 -0
  12. package/dist/core/codex-control/codex-output-schemas.js +5 -1
  13. package/dist/core/codex-control/gpt-final-arbiter.js +160 -0
  14. package/dist/core/codex-control/gpt-final-context-compressor.js +17 -0
  15. package/dist/core/codex-control/gpt-final-proof-pack.js +120 -0
  16. package/dist/core/codex-control/gpt-final-review-schema.js +71 -0
  17. package/dist/core/commands/local-model-command.js +16 -1
  18. package/dist/core/commands/naruto-command.js +77 -5
  19. package/dist/core/commands/run-command.js +5 -1
  20. package/dist/core/doctor/doctor-readiness-matrix.js +15 -0
  21. package/dist/core/feature-fixtures.js +4 -0
  22. package/dist/core/fsx.js +1 -1
  23. package/dist/core/git-simple.js +143 -4
  24. package/dist/core/local-llm/local-collaboration-policy.js +93 -0
  25. package/dist/core/local-llm/local-llm-config.js +15 -0
  26. package/dist/core/pipeline/final-gpt-patch-stage.js +31 -0
  27. package/dist/core/pipeline/final-gpt-review-stage.js +5 -0
  28. package/dist/core/safety/mutation-guard.js +2 -0
  29. package/dist/core/update-check.js +60 -25
  30. package/dist/core/version.js +1 -1
  31. package/dist/scripts/codex-sdk-team-naruto-agent-pipeline-check.js +2 -1
  32. package/dist/scripts/gpt-final-arbiter-check.js +63 -0
  33. package/dist/scripts/gpt-final-arbiter-performance-check.js +36 -0
  34. package/dist/scripts/local-collab-gpt-final-availability-check.js +58 -0
  35. package/dist/scripts/local-collab-no-local-only-final-check.js +27 -0
  36. package/dist/scripts/local-collab-policy-check.js +17 -0
  37. package/package.json +8 -3
  38. 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
@@ -0,0 +1,5 @@
1
+ import { runGptFinalArbiter } from '../codex-control/gpt-final-arbiter.js';
2
+ export async function runFinalGptReviewStage(input, opts = {}) {
3
+ return runGptFinalArbiter(input, opts);
4
+ }
5
+ //# sourceMappingURL=final-gpt-review-stage.js.map
@@ -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)
@@ -1,6 +1,8 @@
1
1
  import os from 'node:os';
2
2
  import path from 'node:path';
3
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';
4
6
  const DEFAULT_REGISTRY = 'https://registry.npmjs.org/';
5
7
  export async function runSksUpdateCheck(options = {}) {
6
8
  const packageName = options.packageName || 'sneakoscope';
@@ -17,9 +19,21 @@ export async function runSksUpdateCheck(options = {}) {
17
19
  effectiveOptions.timeoutMs = options.timeoutMs;
18
20
  if (options.maxOutputBytes !== undefined)
19
21
  effectiveOptions.maxOutputBytes = options.maxOutputBytes;
20
- const effective = await detectEffectiveSksVersion(effectiveOptions);
21
- const current = effective.current;
22
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;
23
37
  if (override)
24
38
  return buildResult({ packageName, current, effective, latest: override, registry, npmBin });
25
39
  if (!npmBin) {
@@ -33,16 +47,18 @@ export async function runSksUpdateCheck(options = {}) {
33
47
  error: 'npm not found on PATH'
34
48
  });
35
49
  }
36
- const args = ['view', packageName, 'version', '--silent', '--registry', registry];
37
- const result = await runProcess(npmBin, args, {
38
- env,
39
- timeoutMs: options.timeoutMs ?? 5000,
40
- maxOutputBytes: options.maxOutputBytes ?? 4096
41
- }).catch((err) => ({
42
- code: 1,
43
- stdout: '',
44
- stderr: err instanceof Error ? err.message : String(err)
45
- }));
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
+ }
46
62
  if (result.code !== 0) {
47
63
  return buildResult({
48
64
  packageName,
@@ -157,7 +173,17 @@ export async function runSksUpdateNow(options = {}) {
157
173
  error: null
158
174
  });
159
175
  }
160
- const install = await runProcess(npmBin, npmArgs, {
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,
161
187
  cwd,
162
188
  env,
163
189
  timeoutMs: options.timeoutMs ?? 10 * 60 * 1000,
@@ -202,25 +228,34 @@ export async function detectEffectiveSksVersion(options = {}) {
202
228
  };
203
229
  add(options.currentVersion || PACKAGE_VERSION, 'runtime');
204
230
  add(env.SKS_INSTALLED_SKS_VERSION, 'env:SKS_INSTALLED_SKS_VERSION');
205
- const pkg = await readJson(path.join(packageRoot(), 'package.json'), {}).catch(() => ({}));
206
- add(pkg?.version, 'packageRoot:package.json');
207
- const sks = await which('sks').catch(() => null);
208
- if (sks) {
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;
209
236
  const result = await runProcess(sks, ['--version'], {
210
237
  timeoutMs: 2000,
211
238
  maxOutputBytes: 4096,
212
239
  env: { ...env, SKS_DISABLE_UPDATE_CHECK: '1' }
213
240
  }).catch((err) => ({ code: 1, stdout: '', stderr: err?.message || String(err) }));
214
- if (result.code === 0)
215
- add(result.stdout, `PATH:${sks}`);
216
- else
217
- errors.push(`path_sks_version:${String(result.stderr || result.stdout || 'failed').trim()}`);
218
- }
219
- if (npmBin) {
220
- const npmGlobal = await detectNpmGlobalPackageVersion(npmBin, packageName, env, {
241
+ return { sks, result };
242
+ })
243
+ .catch(() => null);
244
+ const npmGlobalPromise = npmBin
245
+ ? detectNpmGlobalPackageVersion(npmBin, packageName, env, {
221
246
  timeoutMs: options.timeoutMs ?? 2500,
222
247
  maxOutputBytes: options.maxOutputBytes ?? 8192
223
- }).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) {
224
259
  add(npmGlobal.version, `npm-global:${packageName}`);
225
260
  if (npmGlobal.error)
226
261
  errors.push(`npm_global_version:${npmGlobal.error}`);
@@ -1,2 +1,2 @@
1
- export const PACKAGE_VERSION = '2.0.2';
1
+ export const PACKAGE_VERSION = '2.0.4';
2
2
  //# sourceMappingURL=version.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("hasFlag(args, '--mock') ? 'fake' : 'codex-sdk'"), 'Agent command surface must default to codex-sdk');
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
@@ -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
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "sneakoscope",
3
3
  "displayName": "ㅅㅋㅅ",
4
- "version": "2.0.2",
4
+ "version": "2.0.4",
5
5
  "description": "Sneakoscope Codex: fast proof-first Codex trust layer with image-based Voxel TriWiki.",
6
6
  "type": "module",
7
7
  "homepage": "https://github.com/mandarange/Sneakoscope-Codex#readme",
@@ -283,11 +283,16 @@
283
283
  "codex-control:tool-call-sequence-repair": "node ./dist/scripts/codex-control-tool-call-sequence-repair-check.js",
284
284
  "codex-control:keepalive-no-cot-leak": "node ./dist/scripts/codex-control-keepalive-no-cot-leak-check.js",
285
285
  "codex-control:real-smoke": "node ./dist/scripts/codex-sdk-real-smoke-check.js",
286
+ "local-collab:policy": "node ./dist/scripts/local-collab-policy-check.js",
287
+ "local-collab:gpt-final-arbiter": "node ./dist/scripts/gpt-final-arbiter-check.js",
288
+ "local-collab:no-local-only-final": "node ./dist/scripts/local-collab-no-local-only-final-check.js",
289
+ "local-collab:gpt-final-availability": "node ./dist/scripts/local-collab-gpt-final-availability-check.js",
290
+ "local-collab:gpt-final-performance": "node ./dist/scripts/gpt-final-arbiter-performance-check.js",
286
291
  "ultra-router:classification": "node ./dist/scripts/ultra-router-classification-check.js",
287
292
  "ultra-router:auto-router": "node ./dist/scripts/ultra-router-auto-router-check.js",
288
293
  "coverage": "node --experimental-test-coverage --test \"test/**/*.test.mjs\"",
289
- "release:check": "npm run release:check:parallel && npm run mad-sks:app-ui-no-mutation && npm run codex-app:fast-ui-preservation && npm run codex-app:ui-clobber-guard && npm run doctor:fixes-codex-app-fast-ui && npm run provider:badge-context && npm run provider:context-config-toml && npm run codex-app:provider-badge && npm run zellij:spawn-on-demand-layout && npm run zellij:worker-pane-manager && npm run zellij:worker-pane-manager-single-owner && npm run agent:worker-pane-communication-contract && npm run runtime:no-mjs-scripts && npm run runtime:ts-python-boundary && npm run codex-sdk:capability && npm run codex-sdk:no-legacy-fallback && npm run codex-sdk:backend-router && npm run codex-sdk:structured-output && npm run codex-sdk:event-stream-ledger && npm run codex-sdk:thread-registry && npm run codex-sdk:sandbox-policy && npm run codex-sdk:zellij-pane-binding && npm run codex-sdk:all-pipelines && npm run codex-sdk:dfix-pipeline && npm run codex-sdk:qa-pipeline && npm run codex-sdk:research-pipeline && npm run codex-sdk:team-naruto-agent-pipeline && npm run codex-sdk:release-review-pipeline && npm run codex-sdk:ux-ppt-review-pipeline && npm run codex-sdk:core-skill-pipeline && npm run codex-control:capability && npm run codex-control:no-legacy-fallback && npm run codex-control:structured-output && npm run codex-control:event-stream-ledger && npm run codex-control:thread-registry && npm run codex-control:side-effect-scope && npm run codex-control:all-pipelines && npm run codex-control:empty-result-retry && npm run codex-control:stream-idle-watchdog && npm run codex-control:tool-call-sequence-repair && npm run codex-control:keepalive-no-cot-leak && npm run ultra-router:classification && npm run ultra-router:auto-router && npm run release:version-truth && npm run codex:0.136-compat && npm run codex:0.135-compat && npm run doctor:codex-doctor-parity && npm run codex:permission-profiles && npm run codex:legacy-profile-consumers-removed && npm run terminal:keyboard-enhancement-safety && npm run terminal:tui-output-stability && npm run codex:resume-cwd-truth && npm run mcp:tool-naming-parity && npm run responses:retry-policy-centralized && npm run runtime:no-tmux && npm run zellij:layout-valid && npm run agent:zellij-dynamic-backfill-panes && npm run agent:worker-pane-communication-contract && npm run agent:slot-pane-binding-proof && npm run zellij:worker-pane-manager && npm run zellij:spawn-on-demand-layout && npm run zellij:lane-renderer && npm run mad-sks:zellij-launch && npm run mad-sks:zellij-default-pane-worker && npm run agent:zellij-runtime && npm run codex:config-eperm-fixture && npm run doctor:fix-proves-codex-read && npm run mad:preflight-blocks-unreadable-config && npm run fast:codex-service-tier-proof && npm run codex:project-config-policy-splitter && npm run test:no-orphan-dist-imports && npm run agent:patch-envelope-extraction && npm run agent:patch-queue-runtime && npm run agent:strategy-to-lease-wiring && npm run agent:patch-swarm-runtime && npm run agent:patch-transaction-journal && npm run agent:patch-conflict-rebase && npm run agent:strategy-to-patch-strict && npm run agent:patch-swarm-runtime-truth && npm run agent:rollback-command && npm run agent:patch-verification-dag && npm run agent:patch-rollback-dag && npm run agent:patch-proof-runtime && npm run agent:patch-swarm-route-blackbox && npm run team:patch-swarm-route-blackbox && npm run dfix:patch-swarm-route-blackbox && npm run appshots:thread-attachment-discovery && npm run mcp:readonly-runtime-scheduler && npm run codex:0.134-runner-truth && npm run agent:native-cli-session-swarm && npm run agent:native-cli-session-swarm-10 && npm run agent:native-cli-session-swarm-20 && npm run agent:no-subagent-scaling && npm run agent:native-cli-session-proof && npm run agent:worker-backend-router && npm run agent:codex-child-overlap && npm run agent:model-authored-patch-envelope && npm run agent:fast-mode-default && npm run agent:fast-mode-worker-propagation && npm run codex:fast-mode-profile-propagation && npm run mad-sks:fast-mode-propagation && npm run zellij:launch-command-truth && npm run zellij:real-session-heartbeat && npm run zellij:ui-design && npm run zellij:doctor-readiness && npm run legacy:upgrade-zero-break && npm run publish:packlist-performance && npm run postinstall:safe-side-effects && npm run runtime:ts-rust-boundary && npm run core-skill:card-schema && npm run core-skill:rollout-scoring && npm run core-skill:patch && npm run core-skill:heldout-validation && npm run core-skill:deployment-snapshot && npm run core-skill:no-inference-optimizer && npm run core-skill:route-runtime-integration && npm run core-skill:promotion-side-effect-ledger && npm run core-skill:legacy-promotion-api-audit && npm run safety:side-effect-zero && npm run safety:mutation-callsite-coverage && npm run safety:mutation-callsite-coverage:repo-wide && npm run side-effect:runtime-report && npm run release:gate-planner && npm run release:dynamic-performance && npm run release:provenance && npm run release:gate-budget && npm run agent:wiki-context-proof && npm run shared-memory:check && npm run wrongness:check && npm run wrongness:fixtures && npm run trust:check && npm run git-collaboration:e2e && node ./dist/scripts/release-check-stamp.js write && npm run release:readiness --silent && node ./dist/scripts/release-check-stamp.js write",
290
- "release:real-check": "node ./dist/scripts/release-real-check.js && npm run codex-control:real-smoke -- --require-real && npm run codex-sdk:real-smoke -- --require-real && npm run zellij:real-session-launch -- --require-real --main-only --mission M-release-real-zellij-extra --session sks-rrz-extra && npm run zellij:pane-proof -- --require-real --mission M-release-real-zellij-extra --session sks-rrz-extra --expected-lanes 0 && npm run zellij:screen-proof -- --require-real --main-only --mission M-release-real-zellij-extra && npm run zellij:real-session-cleanup -- --mission M-release-real-zellij-extra --session sks-rrz-extra && npm run agent:real-codex-in-zellij-worker-pane -- --require-real",
294
+ "release:check": "npm run release:check:parallel && npm run mad-sks:app-ui-no-mutation && npm run codex-app:fast-ui-preservation && npm run codex-app:ui-clobber-guard && npm run doctor:fixes-codex-app-fast-ui && npm run provider:badge-context && npm run provider:context-config-toml && npm run codex-app:provider-badge && npm run zellij:spawn-on-demand-layout && npm run zellij:worker-pane-manager && npm run zellij:worker-pane-manager-single-owner && npm run agent:worker-pane-communication-contract && npm run runtime:no-mjs-scripts && npm run runtime:ts-python-boundary && npm run codex-sdk:capability && npm run codex-sdk:no-legacy-fallback && npm run codex-sdk:backend-router && npm run codex-sdk:structured-output && npm run codex-sdk:event-stream-ledger && npm run codex-sdk:thread-registry && npm run codex-sdk:sandbox-policy && npm run codex-sdk:zellij-pane-binding && npm run codex-sdk:all-pipelines && npm run codex-sdk:dfix-pipeline && npm run codex-sdk:qa-pipeline && npm run codex-sdk:research-pipeline && npm run codex-sdk:team-naruto-agent-pipeline && npm run codex-sdk:release-review-pipeline && npm run codex-sdk:ux-ppt-review-pipeline && npm run codex-sdk:core-skill-pipeline && npm run codex-control:capability && npm run codex-control:no-legacy-fallback && npm run codex-control:structured-output && npm run codex-control:event-stream-ledger && npm run codex-control:thread-registry && npm run codex-control:side-effect-scope && npm run codex-control:all-pipelines && npm run codex-control:empty-result-retry && npm run codex-control:stream-idle-watchdog && npm run codex-control:tool-call-sequence-repair && npm run codex-control:keepalive-no-cot-leak && npm run local-collab:policy && npm run local-collab:gpt-final-arbiter && npm run local-collab:no-local-only-final && npm run local-collab:gpt-final-availability && npm run ultra-router:classification && npm run ultra-router:auto-router && npm run release:version-truth && npm run codex:0.136-compat && npm run codex:0.135-compat && npm run doctor:codex-doctor-parity && npm run codex:permission-profiles && npm run codex:legacy-profile-consumers-removed && npm run terminal:keyboard-enhancement-safety && npm run terminal:tui-output-stability && npm run codex:resume-cwd-truth && npm run mcp:tool-naming-parity && npm run responses:retry-policy-centralized && npm run runtime:no-tmux && npm run zellij:layout-valid && npm run agent:zellij-dynamic-backfill-panes && npm run agent:worker-pane-communication-contract && npm run agent:slot-pane-binding-proof && npm run zellij:worker-pane-manager && npm run zellij:spawn-on-demand-layout && npm run zellij:lane-renderer && npm run mad-sks:zellij-launch && npm run mad-sks:zellij-default-pane-worker && npm run agent:zellij-runtime && npm run codex:config-eperm-fixture && npm run doctor:fix-proves-codex-read && npm run mad:preflight-blocks-unreadable-config && npm run fast:codex-service-tier-proof && npm run codex:project-config-policy-splitter && npm run test:no-orphan-dist-imports && npm run agent:patch-envelope-extraction && npm run agent:patch-queue-runtime && npm run agent:strategy-to-lease-wiring && npm run agent:patch-swarm-runtime && npm run agent:patch-transaction-journal && npm run agent:patch-conflict-rebase && npm run agent:strategy-to-patch-strict && npm run agent:patch-swarm-runtime-truth && npm run agent:rollback-command && npm run agent:patch-verification-dag && npm run agent:patch-rollback-dag && npm run agent:patch-proof-runtime && npm run agent:patch-swarm-route-blackbox && npm run team:patch-swarm-route-blackbox && npm run dfix:patch-swarm-route-blackbox && npm run appshots:thread-attachment-discovery && npm run mcp:readonly-runtime-scheduler && npm run codex:0.134-runner-truth && npm run agent:native-cli-session-swarm && npm run agent:native-cli-session-swarm-10 && npm run agent:native-cli-session-swarm-20 && npm run agent:no-subagent-scaling && npm run agent:native-cli-session-proof && npm run agent:worker-backend-router && npm run agent:codex-child-overlap && npm run agent:model-authored-patch-envelope && npm run agent:fast-mode-default && npm run agent:fast-mode-worker-propagation && npm run codex:fast-mode-profile-propagation && npm run mad-sks:fast-mode-propagation && npm run zellij:launch-command-truth && npm run zellij:real-session-heartbeat && npm run zellij:ui-design && npm run zellij:doctor-readiness && npm run legacy:upgrade-zero-break && npm run publish:packlist-performance && npm run postinstall:safe-side-effects && npm run runtime:ts-rust-boundary && npm run core-skill:card-schema && npm run core-skill:rollout-scoring && npm run core-skill:patch && npm run core-skill:heldout-validation && npm run core-skill:deployment-snapshot && npm run core-skill:no-inference-optimizer && npm run core-skill:route-runtime-integration && npm run core-skill:promotion-side-effect-ledger && npm run core-skill:legacy-promotion-api-audit && npm run safety:side-effect-zero && npm run safety:mutation-callsite-coverage && npm run safety:mutation-callsite-coverage:repo-wide && npm run side-effect:runtime-report && npm run release:gate-planner && npm run release:dynamic-performance && npm run release:provenance && npm run release:gate-budget && npm run agent:wiki-context-proof && npm run shared-memory:check && npm run wrongness:check && npm run wrongness:fixtures && npm run trust:check && npm run git-collaboration:e2e && node ./dist/scripts/release-check-stamp.js write && npm run release:readiness --silent && node ./dist/scripts/release-check-stamp.js write",
295
+ "release:real-check": "node ./dist/scripts/release-real-check.js && npm run codex-control:real-smoke -- --require-real && npm run codex-sdk:real-smoke -- --require-real && npm run zellij:real-session-launch -- --require-real --main-only --mission M-release-real-zellij-extra --session sks-rrz-extra && npm run zellij:pane-proof -- --require-real --mission M-release-real-zellij-extra --session sks-rrz-extra --expected-lanes 0 && npm run zellij:screen-proof -- --require-real --main-only --mission M-release-real-zellij-extra && npm run zellij:real-session-cleanup -- --mission M-release-real-zellij-extra --session sks-rrz-extra && npm run agent:real-codex-in-zellij-worker-pane -- --require-real && SKS_REQUIRE_LOCAL_LLM=1 SKS_REQUIRE_GPT_FINAL=1 npm run local-collab:gpt-final-performance",
291
296
  "release:publish": "npm run publish:npm",
292
297
  "publish:dry": "npm run release:metadata && npm run release:version-truth && npm run publish:packlist-performance && npm run prepublish:release-check-or-fast && node ./dist/scripts/release-check-stamp.js verify && npm run release:provenance -- --publish && npm run release:dist-freshness && npm --cache /tmp/sks-npm-cache publish --dry-run --registry https://registry.npmjs.org/ --access public",
293
298
  "publish:npm": "npm --cache /tmp/sks-npm-cache publish --registry https://registry.npmjs.org/ --access public",
@@ -0,0 +1,57 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "sks.local-collaboration-policy.v1",
4
+ "type": "object",
5
+ "required": [
6
+ "schema",
7
+ "mode",
8
+ "gpt_final_required",
9
+ "gpt_final_backend_must_be_remote",
10
+ "local_only_draft",
11
+ "final_accepted_statuses",
12
+ "final_patch_source_when_enabled",
13
+ "blockers"
14
+ ],
15
+ "properties": {
16
+ "schema": {
17
+ "const": "sks.local-collaboration-policy.v1"
18
+ },
19
+ "mode": {
20
+ "enum": [
21
+ "disabled",
22
+ "local-draft-gpt-final",
23
+ "local-worker-gpt-orchestrator",
24
+ "local-parallel-gpt-final",
25
+ "local-only-draft"
26
+ ]
27
+ },
28
+ "gpt_final_required": {
29
+ "type": "boolean"
30
+ },
31
+ "gpt_final_backend_must_be_remote": {
32
+ "type": "boolean"
33
+ },
34
+ "local_only_draft": {
35
+ "type": "boolean"
36
+ },
37
+ "final_accepted_statuses": {
38
+ "type": "array",
39
+ "items": {
40
+ "enum": [
41
+ "approved",
42
+ "modified"
43
+ ]
44
+ }
45
+ },
46
+ "final_patch_source_when_enabled": {
47
+ "const": "gpt_final_arbiter"
48
+ },
49
+ "blockers": {
50
+ "type": "array",
51
+ "items": {
52
+ "type": "string"
53
+ }
54
+ }
55
+ },
56
+ "additionalProperties": true
57
+ }