sneakoscope 6.0.0 → 6.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (89) hide show
  1. package/README.md +2 -1
  2. package/crates/sks-core/Cargo.lock +1 -1
  3. package/crates/sks-core/Cargo.toml +1 -1
  4. package/dist/bin/fast-inline.js +0 -40
  5. package/dist/bin/sks-dispatch.js +0 -16
  6. package/dist/cli/codex-app-command.js +1 -2
  7. package/dist/cli/help-fast.js +2 -2
  8. package/dist/cli/install-helpers.js +26 -21
  9. package/dist/config/skills-manifest.json +57 -57
  10. package/dist/core/agents/agent-effort-policy.js +19 -38
  11. package/dist/core/agents/agent-orchestrator.js +2 -2
  12. package/dist/core/agents/agent-role-config.js +17 -10
  13. package/dist/core/agents/agent-roster.js +19 -39
  14. package/dist/core/agents/agent-scheduler.js +6 -5
  15. package/dist/core/agents/agent-schema.js +4 -5
  16. package/dist/core/agents/agent-task-graph.js +1 -1
  17. package/dist/core/agents/agent-work-partition.js +2 -1
  18. package/dist/core/agents/native-worker-backend-router.js +1 -1
  19. package/dist/core/agents/route-collaboration-ledger.js +2 -2
  20. package/dist/core/auto-review.js +1 -4
  21. package/dist/core/codex/codex-config-guard.js +11 -9
  22. package/dist/core/codex-adapter.js +2 -2
  23. package/dist/core/codex-app/codex-agent-role-sync.js +0 -1
  24. package/dist/core/codex-app/codex-app-fast-ui-repair.js +7 -4
  25. package/dist/core/codex-app/codex-app-ui-state-snapshot.js +1 -7
  26. package/dist/core/codex-app.js +0 -2
  27. package/dist/core/codex-control/codex-model-capabilities.js +1 -2
  28. package/dist/core/codex-control/codex-model-metadata.js +13 -6
  29. package/dist/core/codex-control/codex-sdk-config-policy.js +3 -3
  30. package/dist/core/codex-control/codex-task-runner.js +2 -3
  31. package/dist/core/codex-model-guard.js +24 -89
  32. package/dist/core/commands/basic-cli.js +6 -0
  33. package/dist/core/commands/loop-command.js +2 -2
  34. package/dist/core/commands/mad-db-command.js +1 -1
  35. package/dist/core/commands/naruto-command.js +11 -11
  36. package/dist/core/commands/profile-command.js +14 -5
  37. package/dist/core/commands/qa-loop-command.js +2 -2
  38. package/dist/core/commands/research-command.js +2 -2
  39. package/dist/core/doctor/doctor-codex-startup-repair.js +0 -3
  40. package/dist/core/evaluation.js +1 -1
  41. package/dist/core/feature-fixtures.js +2 -2
  42. package/dist/core/feature-registry.js +1 -1
  43. package/dist/core/hooks-runtime.js +7 -45
  44. package/dist/core/image-ux-review/imagegen-adapter.js +17 -2
  45. package/dist/core/init/skills.js +6 -7
  46. package/dist/core/init.js +7 -20
  47. package/dist/core/loops/loop-concurrency-budget.js +6 -4
  48. package/dist/core/loops/loop-planner.js +1 -1
  49. package/dist/core/loops/loop-runtime.js +2 -2
  50. package/dist/core/loops/loop-scheduler.js +7 -7
  51. package/dist/core/managed-assets/managed-assets-manifest.js +1 -4
  52. package/dist/core/naruto/naruto-concurrency-governor.js +20 -17
  53. package/dist/core/naruto/naruto-loop-mesh.js +3 -3
  54. package/dist/core/naruto/resource-pressure-monitor.js +5 -2
  55. package/dist/core/provider/model-router.js +15 -35
  56. package/dist/core/release/release-gate-batch-runner.js +2 -1
  57. package/dist/core/release/release-gate-resource-governor.js +12 -12
  58. package/dist/core/release/resource-class-budget.js +5 -5
  59. package/dist/core/routes/constants.js +3 -4
  60. package/dist/core/routes.js +1 -1
  61. package/dist/core/structured-output-adapter.js +15 -1
  62. package/dist/core/update/update-migration-state.js +3 -16
  63. package/dist/core/version.js +1 -1
  64. package/dist/scripts/agent-backfill-replenishment-check.js +1 -1
  65. package/dist/scripts/agent-dynamic-pool-check.js +3 -3
  66. package/dist/scripts/agent-dynamic-pool-fixture.js +1 -1
  67. package/dist/scripts/agent-goal-mode-propagation-check.js +1 -1
  68. package/dist/scripts/agent-patch-swarm-gate-lib.js +2 -2
  69. package/dist/scripts/agent-role-config-repair-check.js +9 -5
  70. package/dist/scripts/agent-scheduler-proof-check.js +1 -1
  71. package/dist/scripts/agent-scheduler-proof-hardening-check.js +1 -1
  72. package/dist/scripts/agent-source-intelligence-propagation-check.js +1 -1
  73. package/dist/scripts/agent-strategy-to-lease-wiring-check.js +2 -2
  74. package/dist/scripts/agent-zellij-dynamic-backfill-panes-check.js +1 -1
  75. package/dist/scripts/codex-app-fast-ui-preservation-check.js +2 -2
  76. package/dist/scripts/codex-app-ui-preservation-check.js +6 -5
  77. package/dist/scripts/codex-lb-fast-ui-preservation-check.js +4 -4
  78. package/dist/scripts/codex-lb-gpt55-fast-profile-check.js +3 -2
  79. package/dist/scripts/doctor-fixes-codex-app-fast-ui-check.js +6 -6
  80. package/dist/scripts/install-update-preserves-config-check.js +3 -3
  81. package/dist/scripts/loop-hardening-check-lib.js +1 -1
  82. package/dist/scripts/naruto-parallelism-mode-check.js +2 -1
  83. package/dist/scripts/naruto-shadow-clone-swarm-check.js +25 -32
  84. package/dist/scripts/npm-publish-performance-check.js +1 -1
  85. package/dist/scripts/release-aggressive-resource-governor-check.js +2 -2
  86. package/dist/scripts/release-parallel-check.js +1 -2
  87. package/dist/scripts/release-real-check.js +1 -1
  88. package/dist/scripts/sizecheck.js +3 -3
  89. package/package.json +3 -2
@@ -5,7 +5,6 @@ import path from 'node:path';
5
5
  import { codexFastModeDesktopStatus, codexLbConfigPath, configureCodexLb, ensureGlobalCodexFastModeDuringInstall, releaseCodexLbAuthHold, repairCodexLbAuth } from '../cli/install-helpers.js';
6
6
  import { repairCodexConfigStructure, splitCodexProjectConfigPolicy } from '../core/codex/codex-project-config-policy.js';
7
7
  import { parseCodexConfigToml, validateCodexConfigRoundTrip } from '../core/codex/codex-config-toml.js';
8
- import { REQUIRED_CODEX_MODEL } from '../core/codex-model-guard.js';
9
8
  const tmp = await fs.mkdtemp(path.join(os.tmpdir(), 'sks-codex-lb-gpt55-fast-'));
10
9
  const home = path.join(tmp, 'home');
11
10
  const root = path.join(tmp, 'project');
@@ -46,7 +45,7 @@ await fs.writeFile(projectConfig, [
46
45
  'enabled = true',
47
46
  '',
48
47
  '[profiles.sks-fast-high]',
49
- `model = "${REQUIRED_CODEX_MODEL}"`,
48
+ 'model = "future-codex-model"',
50
49
  'service_tier = "fast"',
51
50
  ''
52
51
  ].join('\n'));
@@ -87,6 +86,7 @@ function assertFastProfile(text, label) {
87
86
  ...(parsed.default_profile === undefined ? [] : ['default_profile_legacy_key_present']),
88
87
  ...(parsed.user?.fast_mode === undefined ? [] : ['user_fast_mode_legacy_table_present']),
89
88
  ...(parsed.profiles?.['sks-fast-high'] === undefined ? [] : ['sks_fast_high_legacy_profile_present']),
89
+ ...(parsed.model === undefined ? [] : ['codex_app_model_was_injected']),
90
90
  ...(provider.requires_openai_auth === true ? [] : ['codex_lb_requires_openai_auth_not_true']),
91
91
  ...(provider.wire_api === 'responses' ? [] : ['codex_lb_wire_api_not_responses']),
92
92
  ...(desktop.on ? [] : ['desktop_fast_status_off'])
@@ -95,6 +95,7 @@ function assertFastProfile(text, label) {
95
95
  label,
96
96
  ok: blockers.length === 0,
97
97
  default_profile: parsed.default_profile || null,
98
+ model: parsed.model || null,
98
99
  legacy_keys: validation.legacy_keys,
99
100
  service_tier: parsed.service_tier || null,
100
101
  provider_wire_api: provider.wire_api || null,
@@ -7,8 +7,8 @@ const root = await fs.mkdtemp(path.join(os.tmpdir(), 'sks-doctor-fast-ui-'));
7
7
  const codexHome = path.join(root, 'home', '.codex');
8
8
  await fs.mkdir(path.join(root, '.codex'), { recursive: true });
9
9
  await fs.mkdir(codexHome, { recursive: true });
10
- await fs.writeFile(path.join(root, '.codex', 'config.toml'), 'model = "gpt-5.5"\nmodel_reasoning_effort = "medium"\nmodel_provider = "codex-lb"\n');
11
- await fs.writeFile(path.join(codexHome, 'config.toml'), '# SKS forced fast UI during legacy install\nmodel = "z-ai/glm-5.2"\nmodel_reasoning_effort = "xhigh"\nmodel_provider = "codex-lb"\nservice_tier = "fast"\n[features]\nfast_mode = false # user disabled, must remain untouched\n\n[profiles.sks-fast-high]\nmodel = "gpt-5.5"\nservice_tier = "fast"\n\n[model_providers.codex-lb]\nname = "openai"\nbase_url = "https://lb.example.test/backend-api/codex"\nwire_api = "responses"\nenv_key = "CODEX_LB_API_KEY"\nsupports_websockets = true\nrequires_openai_auth = true\n');
10
+ await fs.writeFile(path.join(root, '.codex', 'config.toml'), 'model = "future-codex-model"\nmodel_reasoning_effort = "medium"\nmodel_provider = "codex-lb"\n');
11
+ await fs.writeFile(path.join(codexHome, 'config.toml'), '# SKS forced fast UI during legacy install\nmodel = "legacy-sks-model"\nmodel_reasoning_effort = "xhigh"\nmodel_provider = "codex-lb"\nservice_tier = "fast"\n[features]\nfast_mode = false # user disabled, must remain untouched\n\n[profiles.sks-fast-high]\nmodel = "legacy-profile-model"\nservice_tier = "fast"\n\n[model_providers.codex-lb]\nname = "openai"\nbase_url = "https://lb.example.test/backend-api/codex"\nwire_api = "responses"\nenv_key = "CODEX_LB_API_KEY"\nsupports_websockets = true\nrequires_openai_auth = true\n');
12
12
  const plan = await repairCodexAppFastUi(root, { codexHome, apply: false });
13
13
  const repaired = await repairCodexAppFastUi(root, { codexHome, apply: true });
14
14
  const projectAfter = await fs.readFile(path.join(root, '.codex', 'config.toml'), 'utf8');
@@ -29,12 +29,12 @@ const ok = plan.fast_selector === 'manual_action_required'
29
29
  && repaired.fast_selector === 'repaired'
30
30
  && repaired.provider_selector === 'manual_action_required'
31
31
  && repaired.safe_auto_apply === true
32
- && backups.length >= 2
33
- && !/^model\s*=/m.test(projectAfter.split(/\n\s*\[/)[0] || '')
34
- && !/^model_reasoning_effort\s*=/m.test(projectAfter.split(/\n\s*\[/)[0] || '')
32
+ && backups.length >= 1
33
+ && /^model\s*=\s*"future-codex-model"$/m.test(projectAfter.split(/\n\s*\[/)[0] || '')
34
+ && /^model_reasoning_effort\s*=\s*"medium"$/m.test(projectAfter.split(/\n\s*\[/)[0] || '')
35
35
  && !/^model\s*=/m.test(homeTopLevel)
36
36
  && !/^model_reasoning_effort\s*=/m.test(homeTopLevel)
37
- && !/model_provider\s*=/.test(projectAfter)
37
+ && /model_provider\s*=\s*"codex-lb"/.test(projectAfter)
38
38
  && !/service_tier\s*=/.test(homeTopLevel)
39
39
  && /fast_mode = false/.test(homeAfter)
40
40
  && /model_provider = "codex-lb"/.test(homeAfter)
@@ -23,7 +23,7 @@ const results = [];
23
23
  const cfg = path.join(codexDir, 'config.toml');
24
24
  const userConfig = [
25
25
  '# my hand-tuned Codex config',
26
- 'model = "gpt-5.1-codex"',
26
+ 'model = "future-codex-model"',
27
27
  'service_tier = "standard"',
28
28
  'model_reasoning_effort = "high"',
29
29
  '',
@@ -36,7 +36,7 @@ const results = [];
36
36
  const after = await fs.readFile(cfg, 'utf8');
37
37
  const backups = (await fs.readdir(codexDir)).filter((f) => f.startsWith('config.toml.sks-'));
38
38
  const ok = res.status === 'updated' &&
39
- /^model = "gpt-5\.1-codex"/m.test(after) && // user model preserved
39
+ /^model = "future-codex-model"/m.test(after) && // arbitrary user model preserved
40
40
  /^service_tier = "standard"/m.test(after) && // user tier preserved
41
41
  /^model_reasoning_effort = "high"/m.test(after) && // user effort NOT stripped
42
42
  /# my hand-tuned Codex config/.test(after) && // user comment preserved
@@ -45,7 +45,7 @@ const results = [];
45
45
  !/\[user\.fast_mode\]/.test(after) && // legacy fast UI table stripped
46
46
  backups.length >= 1 && // backup created
47
47
  Boolean(res.backup_path);
48
- results.push({ case: 'preserves_user_config', ok, status: res.status, backups, model_preserved: /gpt-5\.1-codex/.test(after) });
48
+ results.push({ case: 'preserves_user_config', ok, status: res.status, backups, model_preserved: /future-codex-model/.test(after) });
49
49
  }
50
50
  // --- Case 2: fresh/empty config gets SKS defaults without forcing fast service tier ---
51
51
  {
@@ -146,7 +146,7 @@ export async function runLoopHardeningCheck(id) {
146
146
  else if (id === 'loop:concurrency-budget' || id === 'loop:concurrency-budget-runtime' || id === 'loop:concurrency-oversubscription-blackbox') {
147
147
  const plan = samplePlan('M-check-budget', Array.from({ length: 10 }, (_, i) => sampleNode(`loop-${i}`, 'M-check-budget', 8, 8)));
148
148
  const budget = computeLoopConcurrencyBudget({ plan, parallelism: 'extreme', env: { SKS_LOOP_MAX_ACTIVE_WORKERS: '16', SKS_LOOP_MAX_ACTIVE_LOOPS: '4', SKS_LOOP_MAX_MODEL_CALLS: '8' } });
149
- assert(budget.max_active_workers === 16 && budget.max_active_loops === 4, 'env concurrency budget overrides apply', budget);
149
+ assert(budget.max_active_workers === 4 && budget.max_active_loops === 4, 'env concurrency requests cannot raise the desktop-safe loop budget', budget);
150
150
  assert(budget.per_loop_worker_budget.reduce((sum, row) => sum + row.maker_workers + row.checker_workers, 0) <= 16, 'per-loop worker budget does not oversubscribe');
151
151
  }
152
152
  else if (id === 'loop:mesh-production-e2e-blackbox') {
@@ -3,10 +3,11 @@
3
3
  import { decideNarutoConcurrency } from '../core/naruto/naruto-concurrency-governor.js';
4
4
  import { DEFAULT_NARUTO_CLONES } from '../core/agents/agent-schema.js';
5
5
  import { assertGate, emitGate, readText } from './sks-1-18-gate-lib.js';
6
- assertGate(DEFAULT_NARUTO_CLONES === 32, 'default Naruto clones must be 32');
6
+ assertGate(DEFAULT_NARUTO_CLONES === 8, 'default Naruto clone roster must be 8');
7
7
  const extreme = decideNarutoConcurrency({ requestedClones: 32, totalWorkItems: 64, backend: 'fake', parallelismMode: 'extreme' });
8
8
  const safe = decideNarutoConcurrency({ requestedClones: 32, totalWorkItems: 64, backend: 'fake', parallelismMode: 'safe' });
9
9
  assertGate(extreme.parallelism_mode === 'extreme' && safe.parallelism_mode === 'safe', 'governor must record parallelism mode', { extreme, safe });
10
+ assertGate(extreme.safe_active_workers <= 4 && safe.safe_active_workers <= extreme.safe_active_workers, 'all modes must honor the desktop-safe active-worker cap', { extreme, safe });
10
11
  assertGate(readText('src/core/commands/naruto-command.ts').includes('--parallelism'), 'Naruto CLI must parse --parallelism');
11
12
  emitGate('naruto:parallelism-mode', { extreme, safe });
12
13
  //# sourceMappingURL=naruto-parallelism-mode-check.js.map
@@ -1,9 +1,8 @@
1
1
  #!/usr/bin/env node
2
2
  // @ts-nocheck
3
3
  // $Naruto Shadow Clone Swarm gate.
4
- // Proves the high-scale mode lifts the standard 20-agent ceiling to 100 clones WITHOUT
5
- // changing it for any other route, and that an end-to-end `sks naruto run` actually
6
- // schedules >20 concurrent clone sessions to completion with proof.
4
+ // Proves Naruto can queue a 100-clone roster while active work stays bounded by
5
+ // the desktop-safe resource governor.
7
6
  import { spawnSync } from 'node:child_process';
8
7
  import fs from 'node:fs';
9
8
  import os from 'node:os';
@@ -16,11 +15,11 @@ const effortPolicy = await importDist('core/agents/agent-effort-policy.js');
16
15
  // 1) Naruto ceiling exists and is 100; standard ceiling untouched at 20.
17
16
  assertGate(schema.MAX_NARUTO_AGENT_COUNT === 100, 'MAX_NARUTO_AGENT_COUNT must be 100', { value: schema.MAX_NARUTO_AGENT_COUNT });
18
17
  assertGate(schema.MAX_AGENT_COUNT === 20, 'MAX_AGENT_COUNT must remain 20 (standard ceiling)', { value: schema.MAX_AGENT_COUNT });
19
- // 2) Cap is lifted ONLY when the naruto max is passed; default callers still clamp to 20.
18
+ // 2) Roster size can reach 100, but every scheduler caller stays desktop-safe.
20
19
  const narutoSlots = scheduler.normalizeTargetActiveSlots(100, schema.MAX_NARUTO_AGENT_COUNT);
21
20
  const defaultSlots = scheduler.normalizeTargetActiveSlots(100);
22
- assertGate(narutoSlots === 100, 'normalizeTargetActiveSlots(100, naruto-max) must be 100', { narutoSlots });
23
- assertGate(defaultSlots === 20, 'normalizeTargetActiveSlots(100) default must stay clamped to 20', { defaultSlots });
21
+ assertGate(narutoSlots === 4, 'normalizeTargetActiveSlots(100, naruto-max) must retain the desktop-safe cap', { narutoSlots });
22
+ assertGate(defaultSlots === 4, 'normalizeTargetActiveSlots(100) must stay desktop-safe', { defaultSlots });
24
23
  // 3) A 100-clone roster builds 100 unique clones (no unique-persona ceiling).
25
24
  const fullRoster = roster.buildNarutoCloneRoster({ clones: 100, maxAgentCount: schema.MAX_NARUTO_AGENT_COUNT });
26
25
  const uniqueIds = new Set(fullRoster.roster.map((row) => row.id)).size;
@@ -40,9 +39,9 @@ const tiers = new Set(effortRoster.roster.map((row) => row.service_tier));
40
39
  const fastFlags = new Set(effortRoster.roster.map((row) => row.fast_mode));
41
40
  assertGate([...efforts].every((e) => e === 'low' || e === 'medium'), 'naruto clone efforts must be only low/medium (never high/xhigh)', { efforts: [...efforts] });
42
41
  assertGate(efforts.has('low') && efforts.has('medium'), 'naruto effort must be dynamic: a no-tool prompt must yield both low and medium clones', { efforts: [...efforts] });
43
- assertGate([...modelTiers].every((tier) => tier === 'gpt-5.4-mini' || tier === 'gpt-5.5-low'), 'ordinary naruto clone model tiers must be mini or gpt-5.5-low', { modelTiers: [...modelTiers] });
44
- assertGate(modelTiers.has('gpt-5.4-mini') && modelTiers.has('gpt-5.5-low'), 'naruto model allocation must dynamically mix gpt-5.4-mini and gpt-5.5-low', { modelTiers: [...modelTiers] });
45
- assertGate([...modelEfforts].length === 1 && modelEfforts.has('low'), 'ordinary naruto clone model reasoning must stay at low', { modelEfforts: [...modelEfforts] });
42
+ assertGate([...modelTiers].every((tier) => tier === 'codex-selected-low' || tier === 'codex-selected-medium'), 'Naruto must inherit the Codex-selected model and vary only reasoning effort', { modelTiers: [...modelTiers] });
43
+ assertGate(modelTiers.has('codex-selected-low') && modelTiers.has('codex-selected-medium'), 'Naruto effort allocation must dynamically mix low and medium without changing model IDs', { modelTiers: [...modelTiers] });
44
+ assertGate([...modelEfforts].every((effort) => effort === 'low' || effort === 'medium'), 'ordinary Naruto clone model reasoning must stay low/medium', { modelEfforts: [...modelEfforts] });
46
45
  assertGate([...tiers].length === 1 && tiers.has('fast'), 'every naruto clone must be fast service tier', { tiers: [...tiers] });
47
46
  assertGate([...fastFlags].length === 1 && fastFlags.has(true), 'every naruto clone must have fast_mode=true', { fastFlags: [...fastFlags] });
48
47
  // 4c) Unit rule: no tool use -> low; any tool use -> medium; always fast.
@@ -51,9 +50,9 @@ const toolWrite = effortPolicy.decideNarutoCloneEffort({ readonly: false, prompt
51
50
  const toolReadCmd = effortPolicy.decideNarutoCloneEffort({ readonly: true, prompt: 'run the build and apply the migration' });
52
51
  const simpleWrite = effortPolicy.decideNarutoCloneEffort({ readonly: false, prompt: 'simple one-line typo fix' });
53
52
  assertGate(simple.reasoning_effort === 'low' && simple.service_tier === 'fast', 'no-tool read-only work must be low + fast', { simple });
54
- assertGate(simple.model === 'gpt-5.4-mini' && simple.model_reasoning_effort === 'low', 'no-tool read-only work must downshift to gpt-5.4-mini', { simple });
55
- assertGate(toolWrite.reasoning_effort === 'medium' && toolWrite.service_tier === 'fast' && toolWrite.model === 'gpt-5.5' && toolWrite.model_reasoning_effort === 'low', 'writing clone (tool use) must be medium + gpt-5.5 low', { toolWrite });
56
- assertGate(simpleWrite.model === 'gpt-5.4-mini' && simpleWrite.model_reasoning_effort === 'low', 'simple write work must downshift native workers to gpt-5.4-mini', { simpleWrite });
53
+ assertGate(simple.model === '' && simple.model_reasoning_effort === 'low', 'no-tool read-only work must inherit the Codex model at low effort', { simple });
54
+ assertGate(toolWrite.reasoning_effort === 'medium' && toolWrite.service_tier === 'fast' && toolWrite.model === '' && toolWrite.model_reasoning_effort === 'medium', 'writing clone must inherit the Codex model at medium effort', { toolWrite });
55
+ assertGate(simpleWrite.model === '' && simpleWrite.model_reasoning_effort === 'low', 'simple write work must inherit the Codex model at low effort', { simpleWrite });
57
56
  assertGate(toolReadCmd.reasoning_effort === 'medium' && toolReadCmd.service_tier === 'fast' && toolReadCmd.model_reasoning_effort === 'high', 'risky read-only command/migration work must escalate model reasoning to high', { toolReadCmd });
58
57
  // 5) System-safe concurrency: never spawn the whole count at once; throttle to host capacity.
59
58
  const fakeSafe = roster.systemSafeNarutoConcurrency({ backend: 'fake' });
@@ -64,22 +63,18 @@ const lowFreeButCapable = roster.systemSafeNarutoConcurrency({
64
63
  freeBytes: 512 * 1024 * 1024,
65
64
  totalBytes: 16 * 1024 * 1024 * 1024
66
65
  });
67
- assertGate(fakeSafe.cap >= 1 && fakeSafe.cap <= schema.MAX_NARUTO_AGENT_COUNT, 'fake-backend concurrency cap must be in [1, 100]', { fakeSafe });
68
- // codex-sdk workers are network-bound (each mostly idle awaiting the Codex API),
69
- // so concurrency is bounded by MEMORY + the 100-clone ceiling, NOT by CPU cores: a
70
- // capable host may run up to MAX_NARUTO_AGENT_COUNT in parallel.
71
- assertGate(heavySafe.cap >= 1 && heavySafe.cap <= schema.MAX_NARUTO_AGENT_COUNT, 'heavy-backend concurrency cap must be in [1, 100]', { heavySafe });
66
+ assertGate(fakeSafe.cap >= 1 && fakeSafe.cap <= 4, 'fake-backend active concurrency cap must stay in [1, 4]', { fakeSafe });
67
+ assertGate(heavySafe.cap >= 1 && heavySafe.cap <= 4, 'heavy-backend active concurrency cap must stay in [1, 4]', { heavySafe });
72
68
  assertGate(heavySafe.cap <= fakeSafe.cap, 'heavy backend must throttle no looser than the light backend', { heavySafe, fakeSafe });
73
69
  assertGate(heavySafe.cores >= 1, 'must detect at least one core', { cores: heavySafe.cores });
74
- assertGate(lowFreeButCapable.cap >= 4, 'capable hosts must not collapse Naruto codex-sdk concurrency to 1 just because free memory is low', { lowFreeButCapable });
75
- // A big-memory host is NOT throttled by core count: simulate 64 GB and assert the
76
- // heavy backend scales well past the old 16-core-derived ceiling toward 100.
70
+ assertGate(lowFreeButCapable.cap === 1, 'low free memory must collapse active Codex concurrency to one worker', { lowFreeButCapable });
77
71
  const bigMemoryHost = roster.systemSafeNarutoConcurrency({ backend: 'codex-sdk', cores: 4, freeBytes: 48 * 1024 * 1024 * 1024, totalBytes: 64 * 1024 * 1024 * 1024 });
78
- assertGate(bigMemoryHost.cap >= 64, 'a 64 GB host must allow >= 64 parallel codex-sdk workers regardless of core count (network-bound, memory-budgeted)', { bigMemoryHost });
79
- // 6) End-to-end run: 24 clones (> standard 20 -> ceiling lifted) all complete, while
80
- // release verification keeps live slots bounded so the gate stays hermetic under DAG load.
81
- const proofClones = 24;
82
- const proofConcurrency = 6;
72
+ assertGate(bigMemoryHost.cap >= 1 && bigMemoryHost.cap <= 4, 'large memory must not bypass the interactive CPU cap', { bigMemoryHost });
73
+ // 6) A small end-to-end run proves the same queue/drain path. The direct roster
74
+ // assertions above cover the 100-clone ceiling without making this release
75
+ // gate create dozens of unnecessary worker processes.
76
+ const proofClones = 6;
77
+ const proofConcurrency = 4;
83
78
  const cli = path.join(root, 'dist', 'bin', 'sks.js');
84
79
  const isolatedWorktreeRoot = fs.mkdtempSync(path.join(os.tmpdir(), 'sks-naruto-shadow-wt-'));
85
80
  const childEnv = { ...process.env, SKS_WORKTREE_ROOT: isolatedWorktreeRoot, SKS_DISABLE_GIT_WORKTREE: '1' };
@@ -101,13 +96,13 @@ const parsed = parseJson(run.stdout);
101
96
  assertGate(parsed !== null, 'sks naruto run must emit JSON', { stdout: tail(run.stdout) });
102
97
  assertGate(parsed.ok === true, 'naruto run must be ok', { ok: parsed.ok });
103
98
  assertGate(parsed.mode === 'NARUTO' && parsed.jutsu === 'kage_bunshin_no_jutsu', 'naruto run must report NARUTO mode', { mode: parsed.mode, jutsu: parsed.jutsu });
104
- assertGate(parsed.clones === proofClones, 'clone fan-out must use the requested count (> standard 20 ceiling)', { clones: parsed.clones });
99
+ assertGate(parsed.clones === proofClones, 'clone fan-out must use the requested queued count', { clones: parsed.clones });
105
100
  assertGate(parsed.max_clones === 100, 'naruto run must advertise the 100 ceiling', { max_clones: parsed.max_clones });
106
101
  assertGate(parsed.proof === 'passed', 'naruto run proof must pass', { proof: parsed.proof });
107
102
  // Throttle invariant: active concurrency never exceeds the requested count nor the host cap.
108
103
  assertGate(parsed.target_active_slots >= 1 && parsed.target_active_slots <= proofClones, 'active slots must be in [1, clones]', { target_active_slots: parsed.target_active_slots });
109
104
  assertGate(parsed.target_active_slots <= fakeSafe.cap, 'active slots must be throttled to the system-safe cap', { target_active_slots: parsed.target_active_slots, cap: fakeSafe.cap });
110
- assertGate(parsed.target_active_slots === proofConcurrency, 'release proof must keep Naruto live slots bounded while fan-out stays >20', { target_active_slots: parsed.target_active_slots, proofConcurrency });
105
+ assertGate(parsed.target_active_slots <= proofConcurrency && parsed.target_active_slots <= 4, 'release proof must keep Naruto live slots desktop-safe while queued fan-out remains larger', { target_active_slots: parsed.target_active_slots, proofConcurrency });
111
106
  // Task 9.1: fan-out (clones) and live concurrency (target_active_slots) are reported
112
107
  // distinctly, and concurrency_capped truthfully reflects "N clones, running M at a time".
113
108
  assertGate(typeof parsed.concurrency_capped === 'boolean', 'naruto run must report concurrency_capped', { concurrency_capped: parsed.concurrency_capped });
@@ -124,13 +119,11 @@ assertGate(new Set(writePaths).size > 1, 'naruto command default patch-envelope
124
119
  assertGate(commandGraph.active_waves.some((wave) => wave.write_paths.length > 1), 'naruto command graph must contain a parallel write wave when route-local patch envelopes do not overlap', { waves: commandGraph.active_waves.slice(0, 3) });
125
120
  const state = parsed.run?.scheduler?.state || parsed.run?.scheduler || {};
126
121
  assertGate(Number(state.completed_count) === Number(parsed.work_graph?.total_work_items || 0) && Number(state.completed_count) >= proofClones, 'all clone work items must complete despite throttling', { completed_count: state.completed_count, total_work_items: parsed.work_graph?.total_work_items, proofClones });
127
- const explicitConcurrency = spawnSync(process.execPath, [cli, 'naruto', 'run', 'explicit concurrency', '--clones', '6', '--backend', 'fake', '--work-items', '6', '--concurrency', '6', '--json', '--no-open-zellij'], { cwd: root, env: childEnv, encoding: 'utf8', timeout: 600000, maxBuffer: 4 * 1024 * 1024 });
128
- const explicitParsed = parseJson(explicitConcurrency.stdout);
129
- assertGate(explicitConcurrency.status === 0 && explicitParsed?.target_active_slots === 6, 'explicit --concurrency must let Naruto use the requested parallel slot count', { status: explicitConcurrency.status, target_active_slots: explicitParsed?.target_active_slots });
130
- // 7) A small request is NOT throttled below what was asked (cap only ever reduces, never inflates).
122
+ assertGate(parsed.target_active_slots <= 4, 'explicit --concurrency cannot bypass the desktop-safe cap', { target_active_slots: parsed.target_active_slots });
123
+ // 7) A small request is never inflated; live pressure may still reduce it.
131
124
  const small = spawnSync(process.execPath, [cli, 'naruto', 'run', 'tiny', '--clones', '2', '--backend', 'fake', '--work-items', '2', '--json', '--no-open-zellij'], { cwd: root, env: childEnv, encoding: 'utf8', timeout: 600000, maxBuffer: 4 * 1024 * 1024 });
132
125
  const smallParsed = parseJson(small.stdout);
133
- assertGate(small.status === 0 && smallParsed?.target_active_slots === 2, 'a 2-clone run must run 2 concurrently (no over-throttle)', { status: small.status, target_active_slots: smallParsed?.target_active_slots });
126
+ assertGate(small.status === 0 && smallParsed?.target_active_slots >= 1 && smallParsed?.target_active_slots <= 2, 'a 2-clone run must stay within [1, 2] active workers', { status: small.status, target_active_slots: smallParsed?.target_active_slots });
134
127
  // 8) Naruto clones always run fast. Per-route --no-fast / standard-tier requests
135
128
  // are intentionally not honored for shadow clones.
136
129
  const standardOptOut = spawnSync(process.execPath, [cli, 'naruto', 'run', 'fast opt-out ignored', '--clones', '2', '--backend', 'fake', '--work-items', '2', '--no-fast', '--service-tier', 'standard', '--json', '--no-open-zellij'], { cwd: root, env: childEnv, encoding: 'utf8', timeout: 600000, maxBuffer: 4 * 1024 * 1024 });
@@ -5,7 +5,7 @@ import path from 'node:path';
5
5
  import { spawnSync } from 'node:child_process';
6
6
  import { assertGate, emitGate, root } from './sks-1-18-gate-lib.js';
7
7
  const MAX_FILES = Number(process.env.SKS_MAX_PACK_FILES || 2100);
8
- const MAX_PACKED = Number(process.env.SKS_MAX_PACK_BYTES || 2300 * 1024);
8
+ const MAX_PACKED = Number(process.env.SKS_MAX_PACK_BYTES || 2410 * 1024);
9
9
  const BUDGET_MS = Number(process.env.SKS_PACK_BUDGET_MS || 30000);
10
10
  function runNpmPack() {
11
11
  const npmCli = process.env.npm_execpath; // set when invoked via `npm run`
@@ -4,8 +4,8 @@ process.env.SKS_RELEASE_MAX_CPU_LIGHT = '7';
4
4
  process.env.SKS_RELEASE_MAX_TOTAL = '2';
5
5
  const governor = await importDist('core/release/release-gate-resource-governor.js');
6
6
  const budget = governor.defaultReleaseGateBudget();
7
- assertGate(budget['cpu-light'] === 7, 'resource governor must honor SKS_RELEASE_MAX_CPU_LIGHT', budget);
8
- assertGate(governor.defaultReleaseGateMaxTotal() >= 8 && governor.defaultReleaseGateMaxTotal() <= 32, 'resource governor default total cap must be bounded by host capacity', { max_total: governor.defaultReleaseGateMaxTotal() });
7
+ assertGate(budget['cpu-light'] >= 1 && budget['cpu-light'] <= 4, 'resource governor env requests must not raise the desktop-safe cpu-light cap', budget);
8
+ assertGate(governor.defaultReleaseGateMaxTotal() >= 1 && governor.defaultReleaseGateMaxTotal() <= 4, 'resource governor default total cap must stay desktop-safe', { max_total: governor.defaultReleaseGateMaxTotal() });
9
9
  const gate = (id) => ({ id, resource: ['cpu-light'], deps: [], command: 'true', side_effect: 'hermetic', timeout_ms: 1000, cache: { enabled: false, inputs: [] }, isolation: { report_dir: 'per-gate' }, preset: ['release'] });
10
10
  const fsGate = (id) => ({ ...gate(id), resource: ['fs-read'] });
11
11
  const timingGate = (id) => ({ ...gate(id), resource: ['timing-sensitive'] });
@@ -1,6 +1,5 @@
1
1
  #!/usr/bin/env node
2
2
  import fs from 'node:fs';
3
- import os from 'node:os';
4
3
  import path from 'node:path';
5
4
  import { fileURLToPath } from 'node:url';
6
5
  import { buildVerificationDag } from '../core/verification/verification-dag.js';
@@ -298,7 +297,7 @@ tasks.push(task('release:metadata', 'npm run release:metadata --silent', { depen
298
297
  const dag = buildVerificationDag(tasks);
299
298
  const result = await runVerificationDag(dag, {
300
299
  cwd: root,
301
- concurrency: Number(process.env.SKS_VERIFY_CONCURRENCY || os.cpus().length || 2),
300
+ concurrency: Math.min(4, Number(process.env.SKS_VERIFY_CONCURRENCY || 2)),
302
301
  logDir,
303
302
  failFast: false
304
303
  });
@@ -6,7 +6,7 @@ import { writeJsonAtomic } from '../core/fsx.js';
6
6
  const args = process.argv.slice(2);
7
7
  const skipReleaseCheck = args.includes('--skip-release-check') || process.env.SKS_RELEASE_REAL_CHECK_SKIP_RELEASE_CHECK === '1';
8
8
  const root = process.cwd();
9
- const concurrency = Math.max(1, Math.floor(Number(process.env.SKS_RELEASE_REAL_CHECK_CONCURRENCY || 4)));
9
+ const concurrency = Math.max(1, Math.min(4, Math.floor(Number(process.env.SKS_RELEASE_REAL_CHECK_CONCURRENCY || 2))));
10
10
  const report = {
11
11
  schema: 'sks.release-real-check.v1',
12
12
  generated_at: new Date().toISOString(),
@@ -7,9 +7,9 @@ import path from 'node:path';
7
7
  import { fileURLToPath } from 'node:url';
8
8
  const root = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '..', '..');
9
9
  const limits = {
10
- packedBytes: Number(process.env.SKS_MAX_PACK_BYTES || 1536 * 1024),
11
- unpackedBytes: Number(process.env.SKS_MAX_UNPACKED_BYTES || 6400 * 1024),
12
- packFiles: Number(process.env.SKS_MAX_PACK_FILES || 1200),
10
+ packedBytes: Number(process.env.SKS_MAX_PACK_BYTES || 2410 * 1024),
11
+ unpackedBytes: Number(process.env.SKS_MAX_UNPACKED_BYTES || 10 * 1024 * 1024),
12
+ packFiles: Number(process.env.SKS_MAX_PACK_FILES || 2100),
13
13
  trackedFileBytes: Number(process.env.SKS_MAX_TRACKED_FILE_BYTES || 384 * 1024)
14
14
  };
15
15
  const trackedFileSizeAllowlist = new Set([
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "sneakoscope",
3
3
  "displayName": "ㅅㅋㅅ",
4
- "version": "6.0.0",
4
+ "version": "6.0.2",
5
5
  "description": "Proof-first Codex trust layer for bounded agent workflows, search visibility evidence, and release integrity gates.",
6
6
  "type": "module",
7
7
  "homepage": "https://github.com/mandarange/Sneakoscope-Codex#readme",
@@ -139,7 +139,8 @@
139
139
  "release:check:full": "npm run build:clean --silent && node ./dist/bin/sks.js doctor --fix --yes --json >/tmp/sks-release-check-full-doctor.json && node ./dist/scripts/release-gate-dag-runner.js --preset release --full && node ./dist/scripts/release-gate-dag-runner.js --preset bench --full && node ./dist/scripts/release-check-stamp.js write",
140
140
  "publish:packlist-performance": "node ./dist/scripts/packlist-performance-check.js",
141
141
  "publish:dry": "npm run publish:prep-ignore-scripts && npm publish --dry-run --ignore-scripts --json",
142
- "publish:prep-ignore-scripts": "npm run build:incremental --silent && npm run release:version-truth --silent && npm run publish:packlist-performance --silent && node ./dist/scripts/package-published-contract-check.js && node ./dist/scripts/release-registry-check.js --require-unpublished --require-publish-auth && npm run publish-tag:check --silent",
142
+ "publish:verify-ignore-scripts": "npm run build:clean --silent && npm run typecheck --silent && npm test --silent && npm run release:version-truth --silent && npm run release:dist-freshness --silent && npm run publish:packlist-performance --silent && node ./dist/scripts/package-published-contract-check.js && npm run publish-tag:check --silent && npm pack --dry-run --ignore-scripts --json",
143
+ "publish:prep-ignore-scripts": "npm run publish:verify-ignore-scripts --silent && node ./dist/scripts/release-registry-check.js --require-unpublished --require-publish-auth",
143
144
  "publish:ignore-scripts": "npm run publish:prep-ignore-scripts && npm publish --ignore-scripts",
144
145
  "gates:run": "node ./dist/scripts/release-gate-dag-runner.js",
145
146
  "policy:gate-audit": "node ./dist/scripts/gate-policy-audit-check.js",