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
@@ -2,7 +2,7 @@ import { probeHardwareCapacity } from './hardware-capacity-probe.js';
2
2
  import { applyNarutoBackpressure } from './naruto-backpressure.js';
3
3
  import { monitorNarutoResourcePressure } from './resource-pressure-monitor.js';
4
4
  export function decideNarutoConcurrency(input = {}) {
5
- const requestedClones = normalizePositiveInt(input.requestedClones, 12);
5
+ const requestedClones = normalizePositiveInt(input.requestedClones, 8);
6
6
  const totalWorkItems = normalizePositiveInt(input.totalWorkItems, requestedClones);
7
7
  const pending = normalizeNonNegativeInt(input.pendingWorkQueueSize, totalWorkItems);
8
8
  const leaseConflicts = normalizeNonNegativeInt(input.activeLeaseConflicts, 0);
@@ -12,34 +12,37 @@ export function decideNarutoConcurrency(input = {}) {
12
12
  const parallelismMode = normalizeParallelismMode(input.parallelismMode);
13
13
  const freeGb = hardware.free_memory_bytes / (1024 * 1024 * 1024);
14
14
  const totalGb = hardware.total_memory_bytes / (1024 * 1024 * 1024);
15
- const reclaimableFloorGb = totalGb >= 32 ? 16 : totalGb >= 16 ? 8 : totalGb >= 8 ? 4 : Math.max(1, freeGb);
16
- const memoryBudgetGb = Math.max(freeGb, reclaimableFloorGb);
15
+ const reservedInteractiveGb = Math.max(2, totalGb * 0.2);
16
+ const memoryBudgetGb = Math.max(0.5, freeGb - reservedInteractiveGb);
17
17
  const heavy = backend === 'codex-sdk' || backend === 'zellij' || backend === 'process' || backend === 'ollama';
18
- const gbPerWorker = heavy ? Number(process.env.SKS_NARUTO_GB_PER_WORKER || 0.25) : Number(process.env.SKS_NARUTO_LIGHT_GB_PER_WORKER || 0.1);
19
- const memoryCap = Math.max(1, Math.floor(memoryBudgetGb / Math.max(0.05, gbPerWorker)));
18
+ const gbPerWorker = heavy ? Number(process.env.SKS_NARUTO_GB_PER_WORKER || 1.5) : Number(process.env.SKS_NARUTO_LIGHT_GB_PER_WORKER || 0.5);
19
+ const memoryCap = Math.max(1, Math.floor(memoryBudgetGb / Math.max(0.25, gbPerWorker)));
20
20
  const fdCap = Math.max(1, Math.floor((hardware.file_descriptor_limit - hardware.process_count) / 6));
21
- const cpuCap = Math.max(1, hardware.cpu_core_count * (heavy ? 2 : 4));
22
- const ioCap = Math.max(2, Math.floor(hardware.cpu_core_count / 2));
23
- const processCap = Math.max(1, Number(process.env.SKS_NARUTO_HEADLESS_PROCESS_CAP || cpuCap + ioCap));
21
+ const cpuCap = Math.max(1, Math.min(4, Math.floor(hardware.cpu_core_count * (heavy ? 0.4 : 0.5))));
22
+ const ioCap = Math.max(1, Math.min(2, Math.floor(hardware.cpu_core_count / 4)));
23
+ const configuredProcessCap = Math.max(1, Number(process.env.SKS_NARUTO_HEADLESS_PROCESS_CAP || 4));
24
+ const processCap = Math.min(configuredProcessCap, cpuCap, 4);
24
25
  const gitWorktreeCap = Math.max(1, Number(process.env.SKS_NARUTO_GIT_WORKTREE_CAP || Math.min(requestedClones, processCap)));
25
26
  const localLlmParallel = Math.max(1, Math.min(4, hardware.local_llm_max_parallel_requests));
26
27
  const remoteCodexParallel = Math.max(1, Math.min(hardware.remote_api_rate_limit_budget, requestedClones));
27
28
  const backendBudget = backend === 'ollama' || backend === 'local-llm'
28
29
  ? localLlmParallel
29
30
  : backend === 'codex-sdk' || backend === 'zellij'
30
- ? Math.max(remoteCodexParallel, Math.min(requestedClones, processCap))
31
+ ? Math.min(remoteCodexParallel, processCap)
31
32
  : processCap;
32
33
  const queueCap = Math.max(1, Math.min(requestedClones, pending || totalWorkItems));
33
34
  const leaseCap = Math.max(1, requestedClones - leaseConflicts);
34
- const rawSafe = Math.max(1, Math.min(requestedClones, totalWorkItems, memoryCap, fdCap, cpuCap + ioCap, gitWorktreeCap + processCap, backendBudget, queueCap, leaseCap, 100));
35
+ const rawSafe = Math.max(1, Math.min(requestedClones, totalWorkItems, memoryCap, fdCap, cpuCap, ioCap + 1, gitWorktreeCap, processCap, backendBudget, queueCap, leaseCap, 4));
35
36
  const pressure = monitorNarutoResourcePressure(hardware, { activeWorkers: rawSafe, zellijVisiblePaneCap });
36
37
  const backpressure = applyNarutoBackpressure(rawSafe, pressure);
37
38
  const currentSafeActiveWorkers = Math.max(1, Math.min(rawSafe, backpressure.adjusted_active_workers));
38
- const safeActiveWorkers = parallelismMode === 'extreme'
39
- ? rawSafe
39
+ // Every mode respects live backpressure. Modes only lower the bounded cap.
40
+ const modeCap = parallelismMode === 'safe'
41
+ ? Math.max(1, Math.ceil(rawSafe * 0.5))
40
42
  : parallelismMode === 'balanced'
41
- ? Math.max(1, Math.min(rawSafe, Math.max(16, Math.floor(rawSafe * 0.75))))
42
- : currentSafeActiveWorkers;
43
+ ? Math.max(1, Math.ceil(rawSafe * 0.75))
44
+ : rawSafe;
45
+ const safeActiveWorkers = Math.max(1, Math.min(modeCap, currentSafeActiveWorkers));
43
46
  const safeVisible = Math.min(safeActiveWorkers, zellijVisiblePaneCap);
44
47
  const reasons = [
45
48
  ...(memoryCap < requestedClones ? ['memory_cap'] : []),
@@ -65,7 +68,7 @@ export function decideNarutoConcurrency(input = {}) {
65
68
  process_parallel: processCap,
66
69
  git_worktree_parallel: gitWorktreeCap,
67
70
  cpu_io_parallel: cpuCap + ioCap,
68
- verification_parallel: Math.max(1, Math.min(hardware.cpu_core_count * 2, safeActiveWorkers, 16)),
71
+ verification_parallel: Math.max(1, Math.min(2, safeActiveWorkers)),
69
72
  parallelism_mode: parallelismMode,
70
73
  reasons: [...new Set(reasons)],
71
74
  backpressure: backpressure.backpressure,
@@ -73,10 +76,10 @@ export function decideNarutoConcurrency(input = {}) {
73
76
  };
74
77
  }
75
78
  function normalizeParallelismMode(value) {
76
- const text = String(value || process.env.SKS_NARUTO_PARALLELISM || 'extreme').toLowerCase();
79
+ const text = String(value || process.env.SKS_NARUTO_PARALLELISM || 'safe').toLowerCase();
77
80
  if (text === 'safe' || text === 'balanced' || text === 'extreme')
78
81
  return text;
79
- return 'extreme';
82
+ return 'safe';
80
83
  }
81
84
  function normalizePositiveInt(value, fallback) {
82
85
  const parsed = Number(value);
@@ -27,10 +27,10 @@ export async function runNarutoLoopMesh(input) {
27
27
  });
28
28
  }
29
29
  export function splitActiveWorkerBudget(plan, parallelism) {
30
- const cap = parallelism === 'safe' ? 8 : parallelism === 'extreme' ? 32 : 16;
31
- const integrationReserved = 2;
30
+ const cap = parallelism === 'safe' ? 2 : parallelism === 'extreme' ? 4 : 3;
31
+ const integrationReserved = 1;
32
32
  const nonIntegration = plan.graph.nodes.filter((node) => node.route !== '$Integration');
33
- const perLoopCap = Math.max(2, Math.floor((cap - integrationReserved) / Math.max(1, nonIntegration.length)));
33
+ const perLoopCap = Math.max(1, Math.floor((cap - integrationReserved) / Math.max(1, nonIntegration.length)));
34
34
  const perLoop = nonIntegration.map((node) => ({
35
35
  loop_id: node.loop_id,
36
36
  maker_checker_workers: Math.min(perLoopCap, node.maker.worker_count + node.checker.worker_count)
@@ -8,13 +8,16 @@ export function monitorNarutoResourcePressure(probe, input = {}) {
8
8
  const fdPressure = Math.min(1, (activeWorkers * 6 + probe.process_count) / Math.max(1, probe.file_descriptor_limit));
9
9
  const zellijPressure = Math.min(1, probe.zellij_pane_count / zellijCap);
10
10
  const diskIoPressure = Number(probe.disk_io_pressure || 0);
11
- const sample = movingAveragePressure({
11
+ const current = {
12
12
  memory: memoryPressure,
13
13
  cpu: cpuPressure,
14
14
  fd: fdPressure,
15
15
  zellij: zellijPressure,
16
16
  disk: diskIoPressure
17
- });
17
+ };
18
+ const average = movingAveragePressure(current);
19
+ const pressureKeys = Object.keys(current);
20
+ const sample = Object.fromEntries(pressureKeys.map((key) => [key, Math.max(current[key] || 0, average[key] || 0)]));
18
21
  const entries = Object.entries(sample).sort((a, b) => b[1] - a[1]);
19
22
  const [dominantMetric = 'unknown', dominantPressure = 0] = entries[0] || [];
20
23
  const reasons = entries
@@ -1,37 +1,16 @@
1
- import { REQUIRED_CODEX_MODEL } from '../codex-model-guard.js';
2
- const CHAINS = {
3
- quick: [
4
- { model: 'gpt-5.4-mini', reasoning: 'low', serviceTier: 'fast' },
5
- { model: REQUIRED_CODEX_MODEL, reasoning: 'low', serviceTier: 'fast' }
6
- ],
7
- standard: [
8
- { model: REQUIRED_CODEX_MODEL, reasoning: 'medium', serviceTier: 'fast' }
9
- ],
10
- agentic: [
11
- { model: 'gpt-5.3-codex', reasoning: 'high', serviceTier: 'fast' },
12
- { model: REQUIRED_CODEX_MODEL, reasoning: 'high', serviceTier: 'fast' }
13
- ],
14
- ultrabrain: [
15
- { model: REQUIRED_CODEX_MODEL, reasoning: 'xhigh', serviceTier: 'standard' }
16
- ],
17
- verify: [
18
- { model: 'gpt-5.4-mini', reasoning: 'medium', serviceTier: 'fast' }
19
- ],
20
- review: [
21
- { model: REQUIRED_CODEX_MODEL, reasoning: 'high', serviceTier: 'fast' }
22
- ]
1
+ const CATEGORY_POLICY = {
2
+ quick: { reasoning: 'low', serviceTier: 'fast' },
3
+ standard: { reasoning: 'medium', serviceTier: 'fast' },
4
+ agentic: { reasoning: 'high', serviceTier: 'fast' },
5
+ ultrabrain: { reasoning: 'xhigh', serviceTier: 'standard' },
6
+ verify: { reasoning: 'medium', serviceTier: 'fast' },
7
+ review: { reasoning: 'high', serviceTier: 'fast' }
23
8
  };
24
9
  export async function routeModel(category, opts = {}) {
25
- const chain = CHAINS[category] || CHAINS.standard;
26
- const degraded = new Set((opts.lbHealth?.degraded_models || []).map((model) => String(model)));
27
- for (const choice of chain) {
28
- if (degraded.has(choice.model))
29
- continue;
30
- if (opts.lbHealth?.quota_low && choice.reasoning === 'xhigh')
31
- return { ...choice, reasoning: 'high' };
32
- return choice;
33
- }
34
- return chain[chain.length - 1] ?? CHAINS.standard[0];
10
+ const policy = CATEGORY_POLICY[category] || CATEGORY_POLICY.standard;
11
+ const model = String(opts.model || process.env.SKS_CODEX_MODEL || process.env.CODEX_MODEL || '').trim();
12
+ const reasoning = opts.lbHealth?.quota_low && policy.reasoning === 'xhigh' ? 'high' : policy.reasoning;
13
+ return { model, reasoning, serviceTier: policy.serviceTier };
35
14
  }
36
15
  export function categoryForWorkerRole(role) {
37
16
  const text = String(role || '').toLowerCase();
@@ -46,9 +25,10 @@ export function categoryForWorkerRole(role) {
46
25
  return 'agentic';
47
26
  }
48
27
  export function modelRouteReason(category, choice, opts = {}) {
28
+ const model = choice.model || 'codex-selected';
49
29
  if (opts.explicit)
50
- return `${category}->${choice.model} (explicit env override)`;
51
- const suffix = opts.quotaLow ? 'quota discipline' : opts.degraded?.length ? 'lb degraded fallback' : 'quota discipline';
52
- return `${category}->${choice.model} (${suffix})`;
30
+ return `${category}->${model} (explicit model preserved)`;
31
+ const suffix = opts.quotaLow ? 'quota discipline' : 'Codex catalog passthrough';
32
+ return `${category}->${model} (${suffix})`;
53
33
  }
54
34
  //# sourceMappingURL=model-router.js.map
@@ -13,7 +13,8 @@ export function isReleaseGateBatchable(gate) {
13
13
  return gate.resource.every((resource) => resource === 'cpu-light' || resource === 'fs-read') && !gate.resource.some((resource) => DISALLOWED_BATCH_RESOURCES.has(resource));
14
14
  }
15
15
  export async function runReleaseGateBatch(root, gates, input = {}) {
16
- const concurrency = Math.max(1, Math.floor(Number(input.concurrency || process.env.SKS_RELEASE_BATCH_CONCURRENCY || 4)));
16
+ const requestedConcurrency = Math.max(1, Math.floor(Number(input.concurrency || process.env.SKS_RELEASE_BATCH_CONCURRENCY || 2)));
17
+ const concurrency = Math.min(requestedConcurrency, 4);
17
18
  const runId = `rgb-${new Date().toISOString().replace(/[:.]/g, '-')}-${process.pid}`;
18
19
  const reportRoot = input.reportRoot || path.join(root, '.sneakoscope', 'reports', 'release-gate-batches', runId);
19
20
  const nonBatchable = gates.filter((gate) => !isReleaseGateBatchable(gate));
@@ -3,23 +3,23 @@ const EXCLUSIVE_RESOURCES = new Set(['timing-sensitive']);
3
3
  export function defaultReleaseGateBudget() {
4
4
  const cores = Math.max(1, os.cpus().length || 1);
5
5
  const base = {
6
- 'cpu-light': Math.min(24, cores * 3),
7
- 'cpu-heavy': Math.max(1, cores),
8
- 'io-light': Math.min(96, cores * 10),
9
- 'io-heavy': Math.min(12, Math.max(1, cores)),
10
- git: Math.min(12, Math.max(1, cores)),
11
- 'git-worktree': Math.min(8, Math.max(1, cores)),
12
- python: Math.min(12, Math.max(1, cores)),
13
- network: 12,
6
+ 'cpu-light': Math.max(1, Math.min(4, Math.floor(cores / 2))),
7
+ 'cpu-heavy': Math.max(1, Math.min(2, Math.floor(cores / 4))),
8
+ 'io-light': 4,
9
+ 'io-heavy': 2,
10
+ git: 2,
11
+ 'git-worktree': 1,
12
+ python: 2,
13
+ network: 2,
14
14
  'zellij-real': 1,
15
15
  'browser-real': 1,
16
16
  'secret-sensitive': 1,
17
17
  'local-llm-real': Math.max(1, Number(process.env.SKS_LOCAL_LLM_MAX_PARALLEL || 1)),
18
- 'remote-model-real': 6,
18
+ 'remote-model-real': 2,
19
19
  'global-config': 1,
20
20
  publish: 1,
21
- 'fs-read': Math.min(96, cores * 10),
22
- 'fs-write': Math.min(12, Math.max(1, cores)),
21
+ 'fs-read': 4,
22
+ 'fs-write': 2,
23
23
  'timing-sensitive': 1
24
24
  };
25
25
  for (const key of Object.keys(base)) {
@@ -64,7 +64,7 @@ export function pickLaunchableReleaseGates(input) {
64
64
  }
65
65
  export function defaultReleaseGateMaxTotal() {
66
66
  const cores = Math.max(1, os.cpus().length || 1);
67
- return Math.max(8, Math.min(32, cores * 3));
67
+ return Math.max(1, Math.min(4, Math.floor(cores / 2)));
68
68
  }
69
69
  function envInt(name, fallback, opts = {}) {
70
70
  const parsed = Number(process.env[name]);
@@ -4,11 +4,11 @@ export function computeResourceClassBudget(env = process.env) {
4
4
  const cpus = Math.max(2, os.cpus().length || 2);
5
5
  return {
6
6
  schema: RESOURCE_CLASS_BUDGET_SCHEMA,
7
- cpu_light: readEnvInt(env, 'SKS_RESOURCE_CPU_LIGHT', Math.max(2, cpus - 1)),
8
- cpu_heavy: readEnvInt(env, 'SKS_RESOURCE_CPU_HEAVY', Math.max(1, Math.floor(cpus / 2))),
9
- io_light: readEnvInt(env, 'SKS_RESOURCE_IO_LIGHT', 8),
7
+ cpu_light: readEnvInt(env, 'SKS_RESOURCE_CPU_LIGHT', Math.max(1, Math.min(4, Math.floor(cpus / 2)))),
8
+ cpu_heavy: readEnvInt(env, 'SKS_RESOURCE_CPU_HEAVY', Math.max(1, Math.min(2, Math.floor(cpus / 4)))),
9
+ io_light: readEnvInt(env, 'SKS_RESOURCE_IO_LIGHT', 4),
10
10
  io_heavy: readEnvInt(env, 'SKS_RESOURCE_IO_HEAVY', 2),
11
- fs_read: readEnvInt(env, 'SKS_RESOURCE_FS_READ', 8),
11
+ fs_read: readEnvInt(env, 'SKS_RESOURCE_FS_READ', 4),
12
12
  network: readEnvInt(env, 'SKS_RESOURCE_NETWORK', 2),
13
13
  remote_model_real: readEnvInt(env, 'SKS_RESOURCE_REMOTE_MODEL_REAL', 1),
14
14
  zellij_real: readEnvInt(env, 'SKS_RESOURCE_ZELLIJ_REAL', 1),
@@ -18,6 +18,6 @@ export function computeResourceClassBudget(env = process.env) {
18
18
  }
19
19
  function readEnvInt(env, key, fallback) {
20
20
  const value = Number(env[key]);
21
- return Number.isFinite(value) && value > 0 ? Math.floor(value) : fallback;
21
+ return Number.isFinite(value) && value > 0 ? Math.min(Math.floor(value), fallback) : fallback;
22
22
  }
23
23
  //# sourceMappingURL=resource-class-budget.js.map
@@ -44,9 +44,8 @@ export const RECOMMENDED_SKILLS = [
44
44
  REFLECTION_SKILL_NAME,
45
45
  'honest-mode'
46
46
  ];
47
- // 'ultra' is gpt-5.6's top reasoning level (codex-lb v1.20.1-r3 exposes the
48
- // 5.6 trio with a 6-level low~ultra range). Whether a given model actually
49
- // advertises it still comes from runtime metadata (codex-model-metadata.ts);
50
- // this set only gates what values SKS accepts as user/route input.
47
+ // Route-level effort names are scheduling intents, not model compatibility
48
+ // claims. Actual per-model options come from Codex runtime metadata; SKS never
49
+ // derives them from a model slug.
51
50
  export const ALLOWED_REASONING_EFFORTS = new Set(['low', 'medium', 'high', 'xhigh', 'ultra']);
52
51
  //# sourceMappingURL=constants.js.map
@@ -296,7 +296,7 @@ export const ROUTES = [
296
296
  reasoningPolicy: 'high',
297
297
  stopGate: 'release-readiness-report.json',
298
298
  cliEntrypoint: 'sks agent run "release audit" --route "$Release-Review" --agents <n> --concurrency <n> --mock --json',
299
- examples: ['$Release-Review agents:10 concurrency:5 release audit', 'sks agent run "wide release audit" --route "$Release-Review" --agents 10 --concurrency 5 --mock --json']
299
+ examples: ['$Release-Review agents:10 concurrency:4 release audit', 'sks agent run "wide release audit" --route "$Release-Review" --agents 10 --concurrency 4 --mock --json']
300
300
  },
301
301
  {
302
302
  id: 'QALoop',
@@ -29,9 +29,23 @@ export function ensureStrictObjectSchema(schema) {
29
29
  return next;
30
30
  }
31
31
  export async function runOpenAIStructuredOutput(request) {
32
- const model = request.model || process.env.OPENAI_STRUCTURED_OUTPUT_MODEL || 'gpt-5.4-mini';
32
+ const model = String(request.model || process.env.OPENAI_STRUCTURED_OUTPUT_MODEL || '').trim();
33
33
  const apiKey = request.apiKey || process.env.OPENAI_API_KEY || null;
34
34
  const sourceSha = request.imagePath ? sha256(await fsp.readFile(path.resolve(request.imagePath))) : null;
35
+ if (!model) {
36
+ return {
37
+ schema: 'sks.structured-output-adapter-result.v1',
38
+ ok: false,
39
+ status: 'integration_optional',
40
+ provider: 'openai_responses_text_format',
41
+ model: '',
42
+ parsed_json: null,
43
+ validation: { ok: false, issues: ['openai_structured_output_model_missing'] },
44
+ blocker: structuredOutputBlocker('openai_structured_output_model_missing', 'Pass request.model or set OPENAI_STRUCTURED_OUTPUT_MODEL; SKS does not invent a model identifier.'),
45
+ setup_guidance: 'Choose any model available to your OpenAI account and pass it explicitly, or use Codex structured output so the current Codex selection is inherited.',
46
+ source_sha256: sourceSha
47
+ };
48
+ }
35
49
  if (!apiKey) {
36
50
  return {
37
51
  schema: 'sks.structured-output-adapter-result.v1',
@@ -8,7 +8,6 @@ import { COMMANDS } from '../../cli/command-registry.js';
8
8
  import { reconcileSkills } from '../init/skills.js';
9
9
  import { codexHookTrustDoctor } from '../codex-hooks/codex-hook-trust-doctor.js';
10
10
  import { writeCodexConfigGuarded } from '../codex/codex-config-guard.js';
11
- import { REQUIRED_CODEX_MODEL } from '../codex-model-guard.js';
12
11
  export const UPDATE_MIGRATION_SCHEMA = 'sks.project-migration-receipt.v2';
13
12
  export const INSTALLATION_EPOCH_SCHEMA = 'sks.installation-epoch.v1';
14
13
  export function installationEpochPath() {
@@ -528,7 +527,9 @@ function tomlTableString(text, table, key) {
528
527
  return match?.[1] || null;
529
528
  }
530
529
  function topLevelTomlString(text, key) {
531
- const top = String(text || '').slice(0, Math.max(0, String(text || '').search(/^\s*\[/m)));
530
+ const source = String(text || '');
531
+ const firstTable = source.search(/^\s*\[/m);
532
+ const top = firstTable < 0 ? source : source.slice(0, firstTable);
532
533
  const match = top.match(new RegExp(`^\\s*${escapeRegExp(key)}\\s*=\\s*"([^"]*)"\\s*$`, 'm'));
533
534
  return match?.[1] || null;
534
535
  }
@@ -589,20 +590,6 @@ function upsertTomlTableKeyLocal(text, table, line) {
589
590
  lines.splice(end, 0, line);
590
591
  return `${lines.join('\n')}\n`;
591
592
  }
592
- function upsertTopLevelTomlStringLocal(text, key, value) {
593
- const raw = String(text || '').trimEnd();
594
- const line = `${key} = ${JSON.stringify(value)}`;
595
- const lines = raw ? raw.split(/\r?\n/) : [];
596
- const firstTable = lines.findIndex((candidate) => /^\s*\[[^\]]+\]\s*$/.test(candidate || ''));
597
- const end = firstTable < 0 ? lines.length : firstTable;
598
- for (let index = 0; index < end; index += 1) {
599
- if (new RegExp(`^\\s*${escapeRegExp(key)}\\s*=`).test(lines[index] || '')) {
600
- lines[index] = line;
601
- return `${lines.join('\n')}\n`;
602
- }
603
- }
604
- return insertTopLevelTomlKey(raw, line);
605
- }
606
593
  function tomlTableHasKey(text, table, key) {
607
594
  const block = tomlTableBlock(text, table);
608
595
  return Boolean(block && new RegExp(`^\\s*${escapeRegExp(key)}\\s*=`, 'm').test(block));
@@ -1,2 +1,2 @@
1
- export const PACKAGE_VERSION = '6.0.0';
1
+ export const PACKAGE_VERSION = '6.0.2';
2
2
  //# sourceMappingURL=version.js.map
@@ -2,7 +2,7 @@
2
2
  // @ts-nocheck
3
3
  import { assertGate, emitGate } from './sks-1-18-gate-lib.js';
4
4
  import { runDynamicPoolFixture } from './agent-dynamic-pool-fixture.js';
5
- const fixture = await runDynamicPoolFixture({ target: 5, total: 8 });
5
+ const fixture = await runDynamicPoolFixture({ target: 4, total: 8 });
6
6
  const backfills = fixture.events.filter((event) => event.event_type === 'backfill_event');
7
7
  const firstSlowCompletionIndex = fixture.events.findIndex((event) => event.event_type === 'session_completed' && /work-00[3-5]/.test(String(event.work_item_id || '')));
8
8
  const secondBackfillIndex = fixture.events.findIndex((event, index) => index > fixture.events.findIndex((row) => row.event_type === 'backfill_event') && event.event_type === 'backfill_event');
@@ -2,11 +2,11 @@
2
2
  // @ts-nocheck
3
3
  import { assertGate, emitGate } from './sks-1-18-gate-lib.js';
4
4
  import { runDynamicPoolFixture } from './agent-dynamic-pool-fixture.js';
5
- const fixture = await runDynamicPoolFixture({ target: 5, total: 8 });
5
+ const fixture = await runDynamicPoolFixture({ target: 4, total: 8 });
6
6
  const state = fixture.result.state;
7
7
  assertGate(fixture.result.ok === true, 'dynamic pool fixture must drain cleanly', state);
8
- assertGate(state.target_active_slots === 5, 'target active slots must be 5', state);
9
- assertGate(state.max_observed_active_slots === 5, 'scheduler must observe 5 active slots', state);
8
+ assertGate(state.target_active_slots === 4, 'target active slots must be desktop-safe (4)', state);
9
+ assertGate(state.max_observed_active_slots === 4, 'scheduler must observe at most 4 active slots', state);
10
10
  assertGate(state.pending_queue_drained === true, 'pending queue must drain', state);
11
11
  assertGate(state.all_slots_closed_after_drain === true, 'all slots must close after drain', state);
12
12
  emitGate('agent:dynamic-pool', { target_active_slots: state.target_active_slots, max_observed_active_slots: state.max_observed_active_slots, total_work_items: state.total_work_items });
@@ -5,7 +5,7 @@ import os from 'node:os';
5
5
  import path from 'node:path';
6
6
  import { importDist } from './sks-1-18-gate-lib.js';
7
7
  export async function runDynamicPoolFixture(opts = {}) {
8
- const target = opts.target || 5;
8
+ const target = opts.target || 4;
9
9
  const total = opts.total || 8;
10
10
  const root = await fs.mkdtemp(path.join(os.tmpdir(), 'sks-dynamic-pool-'));
11
11
  const scheduler = await importDist('core/agents/agent-scheduler.js');
@@ -2,7 +2,7 @@
2
2
  // @ts-nocheck
3
3
  import { assertGate, emitGate } from './sks-1-18-gate-lib.js';
4
4
  import { runDynamicPoolFixture } from './agent-dynamic-pool-fixture.js';
5
- const fixture = await runDynamicPoolFixture({ target: 5, total: 8 });
5
+ const fixture = await runDynamicPoolFixture({ target: 4, total: 8 });
6
6
  const allResultsHaveRefs = fixture.result.results.every((result) => result.goal_mode_ref?.artifact === 'goal-mode-applied.json');
7
7
  assertGate(allResultsHaveRefs, 'all dynamic generations must propagate Goal mode refs', fixture.result.results);
8
8
  emitGate('agent:goal-mode-propagation', { result_count: fixture.result.results.length });
@@ -37,8 +37,8 @@ export async function runPatchSwarmRouteBlackbox({ gate, route, routeCommand, re
37
37
  backend: 'fake',
38
38
  mock: true,
39
39
  agents: 5,
40
- concurrency: 5,
41
- targetActiveSlots: 5,
40
+ concurrency: 4,
41
+ targetActiveSlots: 4,
42
42
  desiredWorkItemCount: 10,
43
43
  minimumWorkItems: 10,
44
44
  writeMode: 'parallel',
@@ -5,8 +5,6 @@ import os from 'node:os';
5
5
  import path from 'node:path';
6
6
  import { assertGate, emitGate, importDist } from './sks-1-18-gate-lib.js';
7
7
  const mod = await importDist('core/agents/agent-role-config.js');
8
- const modelGuard = await importDist('core/codex-model-guard.js');
9
- const requiredModel = modelGuard.REQUIRED_CODEX_MODEL;
10
8
  const root = fs.mkdtempSync(path.join(os.tmpdir(), 'sks-role-repair-'));
11
9
  fs.mkdirSync(path.join(root, '.sneakoscope', 'reports'), { recursive: true });
12
10
  const plan = await mod.repairAgentRoleConfigs({ root, apply: false, codexHome: path.join(root, 'codex-home') });
@@ -19,19 +17,25 @@ const stalePlan = await mod.repairAgentRoleConfigs({ root: staleRoot, apply: fal
19
17
  const staleRepair = await mod.repairAgentRoleConfigs({ root: staleRoot, apply: true, codexHome: path.join(staleRoot, 'codex-home') });
20
18
  const repairedText = fs.readFileSync(path.join(staleRoot, '.codex', 'agents', 'analysis-scout.toml'), 'utf8');
21
19
  const createdText = fs.readFileSync(analysisScout, 'utf8');
20
+ const globalRole = path.join(root, 'codex-home', 'agents', 'analysis-scout.toml');
21
+ fs.mkdirSync(path.dirname(globalRole), { recursive: true });
22
+ fs.writeFileSync(globalRole, 'name = "analysis_scout"\ndescription = "SKS stale global role"\nmodel = "gpt-5.5"\nmodel_reasoning_effort = "low"\nsandbox_mode = "workspace-write"\ndeveloper_instructions = """\nSKS role\n"""\n');
23
+ const globalRepair = await mod.repairAgentRoleConfigs({ root, apply: true, codexHome: path.join(root, 'codex-home') });
24
+ const globalRepairedText = fs.readFileSync(globalRole, 'utf8');
22
25
  const report = {
23
26
  schema: 'sks.agent-role-config-repair-check.v1',
24
27
  plan_ok: plan.ok === true && plan.missing.includes('analysis-scout.toml'),
25
28
  repair_ok: repair.ok === true,
26
29
  analysis_scout_created: fs.existsSync(analysisScout),
27
- created_matches_model: createdText.includes(`model = "${requiredModel}"`),
30
+ created_inherits_model: !/^(?:model|model_reasoning_effort)\s*=/m.test(createdText),
28
31
  created_write_capable: createdText.includes('sandbox_mode = "workspace-write"') && !createdText.includes('Do not edit files.'),
29
32
  stale_detected: stalePlan.stale.includes('analysis-scout.toml'),
30
- stale_repaired: staleRepair.repaired.includes('.codex/agents/analysis-scout.toml') && repairedText.includes('name = "analysis_scout"') && repairedText.includes(`model = "${requiredModel}"`) && repairedText.includes('sandbox_mode = "workspace-write"'),
33
+ stale_repaired: staleRepair.repaired.includes('.codex/agents/analysis-scout.toml') && repairedText.includes('name = "analysis_scout"') && !/^(?:model|model_reasoning_effort)\s*=/m.test(repairedText) && repairedText.includes('sandbox_mode = "workspace-write"'),
34
+ global_stale_repaired_with_valid_project_copy: globalRepair.repaired.some((file) => file.endsWith('codex-home/agents/analysis-scout.toml')) && !/^(?:model|model_reasoning_effort)\s*=/m.test(globalRepairedText),
31
35
  warnings_suppressed: repair.warnings_suppressed === true,
32
36
  artifact_written: fs.existsSync(path.join(root, '.sneakoscope', 'reports', 'agent-role-config-repair.json'))
33
37
  };
34
- const ok = report.plan_ok && report.repair_ok && report.analysis_scout_created && report.created_matches_model && report.created_write_capable && report.stale_detected && report.stale_repaired && report.warnings_suppressed && report.artifact_written;
38
+ const ok = report.plan_ok && report.repair_ok && report.analysis_scout_created && report.created_inherits_model && report.created_write_capable && report.stale_detected && report.stale_repaired && report.global_stale_repaired_with_valid_project_copy && report.warnings_suppressed && report.artifact_written;
35
39
  assertGate(ok, 'doctor --fix must repair missing SKS-owned agent role configs', report);
36
40
  emitGate('agent:role-config-repair', report);
37
41
  //# sourceMappingURL=agent-role-config-repair-check.js.map
@@ -2,7 +2,7 @@
2
2
  // @ts-nocheck
3
3
  import { assertGate, emitGate } from './sks-1-18-gate-lib.js';
4
4
  import { runDynamicPoolFixture } from './agent-dynamic-pool-fixture.js';
5
- const fixture = await runDynamicPoolFixture({ target: 5, total: 8 });
5
+ const fixture = await runDynamicPoolFixture({ target: 4, total: 8 });
6
6
  const state = fixture.result.state;
7
7
  for (const key of ['target_active_slots', 'max_observed_active_slots', 'pending_queue_drained', 'backfill_count', 'expected_backfill_count', 'slot_count', 'generation_count']) {
8
8
  assertGate(Object.prototype.hasOwnProperty.call(state, key) || key === 'slot_count' || key === 'generation_count', `scheduler state/proof missing ${key}`, state);
@@ -15,7 +15,7 @@ for (const token of [
15
15
  ]) {
16
16
  assertGate(proofSource.includes(token), `scheduler proof hardening missing ${token}`);
17
17
  }
18
- const fixture = await runDynamicPoolFixture({ target: 5, total: 8 });
18
+ const fixture = await runDynamicPoolFixture({ target: 4, total: 8 });
19
19
  assertGate(fixture.result.state.pending_queue_drained === true, 'positive scheduler fixture must drain', fixture.result.state);
20
20
  assertGate(fixture.result.state.backfill_count >= fixture.result.state.expected_backfill_count, 'positive scheduler fixture must satisfy backfill invariant', fixture.result.state);
21
21
  emitGate('agent:scheduler-proof-hardening', { checked_blockers: 8, backfill_count: fixture.result.state.backfill_count });
@@ -2,7 +2,7 @@
2
2
  // @ts-nocheck
3
3
  import { assertGate, emitGate } from './sks-1-18-gate-lib.js';
4
4
  import { runDynamicPoolFixture } from './agent-dynamic-pool-fixture.js';
5
- const fixture = await runDynamicPoolFixture({ target: 5, total: 8 });
5
+ const fixture = await runDynamicPoolFixture({ target: 4, total: 8 });
6
6
  const allResultsHaveRefs = fixture.result.results.every((result) => result.source_intelligence_refs?.artifact === 'source-intelligence-evidence.json');
7
7
  assertGate(allResultsHaveRefs, 'all dynamic generations must propagate source intelligence refs', fixture.result.results);
8
8
  emitGate('agent:source-intelligence-propagation', { result_count: fixture.result.results.length });
@@ -11,10 +11,10 @@ const tmp = makeTempPatchProject('sks-strategy-lease-');
11
11
  const files = Array.from({ length: 10 }, (_, index) => `file-${index + 1}.txt`);
12
12
  const prompt = files.map((file) => `\`${file}\``).join(' ');
13
13
  const compiled = strategy.compileStrategy({ prompt, route: '$Agent', agentCount: 5 });
14
- const roster = rosterMod.buildAgentRoster({ agents: 5, concurrency: 5, prompt });
14
+ const roster = rosterMod.buildAgentRoster({ agents: 5, concurrency: 4, prompt });
15
15
  const partition = await partitionMod.buildAgentWorkPartition(tmp, roster, prompt, {
16
16
  route: '$Agent',
17
- targetActiveSlots: 5,
17
+ targetActiveSlots: 4,
18
18
  desiredWorkItemCount: 10,
19
19
  minimumWorkItems: 10,
20
20
  strategyOwnershipPlan: compiled.file_ownership_plan,
@@ -7,7 +7,7 @@ const freshness = ensureDistFresh({ rebuild: true });
7
7
  if (!freshness.ok)
8
8
  fail('dist_not_fresh', { freshness });
9
9
  const proof = await import(pathToFileURL(path.join(root, 'dist', 'core', 'agents', 'agent-slot-pane-binding-proof.js')).href);
10
- const targetActiveSlots = 5;
10
+ const targetActiveSlots = 4;
11
11
  const workItems = 10;
12
12
  const records = Array.from({ length: workItems }, (_, index) => {
13
13
  const slotIndex = (index % targetActiveSlots) + 1;
@@ -17,12 +17,12 @@ const clean = await evaluateCodexAppFastUiPreservation(tmp, { before, after, cod
17
17
  const badRoot = await fs.mkdtemp(path.join(os.tmpdir(), 'sks-fast-ui-preservation-bad-'));
18
18
  await fs.mkdir(path.join(badRoot, '.codex'), { recursive: true });
19
19
  await fs.mkdir(path.join(badRoot, 'home', '.codex'), { recursive: true });
20
- await fs.writeFile(path.join(badRoot, '.codex', 'config.toml'), 'model_provider = "codex-lb"\n');
20
+ await fs.writeFile(path.join(badRoot, '.codex', 'config.toml'), 'openai_base_url = "https://override.invalid"\n');
21
21
  await fs.writeFile(path.join(badRoot, 'home', '.codex', 'config.toml'), '');
22
22
  const bad = await evaluateCodexAppFastUiPreservation(badRoot, { codexHome: path.join(badRoot, 'home', '.codex') });
23
23
  const serialized = JSON.stringify({ clean, bad });
24
24
  const secretSafe = !serialized.includes('secret-should-not-leak');
25
- const ok = clean.ok && !bad.ok && bad.project_local_forbidden_keys.includes('model_provider') && secretSafe;
25
+ const ok = clean.ok && !bad.ok && bad.project_local_forbidden_keys.includes('openai_base_url') && secretSafe;
26
26
  emit({ schema: 'sks.codex-app-fast-ui-preservation-check.v1', ok, clean, bad, secret_safe: secretSafe, blockers: ok ? [] : ['codex_app_fast_ui_preservation_check_failed'] });
27
27
  function emit(report) {
28
28
  console.log(JSON.stringify(report, null, 2));
@@ -44,8 +44,8 @@ delete process.env.SKS_MANAGE_CODEX_APP_PLUGINS;
44
44
  }
45
45
  // 2) Default install must NOT auto-enable any marketplace plugins.
46
46
  {
47
- const out = normalize('model = "gpt-5.5"\n');
48
- results.push({ case: 'no_plugins_by_default', ok: !hasPluginTables(out) });
47
+ const out = normalize('model = "future-codex-model"\n');
48
+ results.push({ case: 'no_plugins_by_default', ok: !hasPluginTables(out) && /model = "future-codex-model"/.test(out) });
49
49
  }
50
50
  // 3) A user's disabled plugin must be left untouched (not reverted to enabled).
51
51
  {
@@ -67,16 +67,17 @@ delete process.env.SKS_MANAGE_CODEX_APP_PLUGINS;
67
67
  && featureValue(out, 'multi_agent') === 'true'
68
68
  && featureValue(out, 'fast_mode') === 'true'
69
69
  && !/\[user\.fast_mode\]/.test(out)
70
- && !/\[profiles\.sks-fast-high\]/.test(out);
70
+ && !/\[profiles\.sks-fast-high\]/.test(out)
71
+ && !/^model\s*=/m.test(out);
71
72
  results.push({ case: 'fresh_config_seeds_defaults', ok });
72
73
  }
73
74
  // 6) Opt-in enables plugins on a fresh config, but still preserves a user-disabled one.
74
75
  {
75
76
  process.env.SKS_MANAGE_CODEX_APP_PLUGINS = '1';
76
- const fresh = normalize('model = "gpt-5.5"\n');
77
+ const fresh = normalize('model = "future-codex-model"\n');
77
78
  const userDisabled = normalize('[plugins."chrome@openai-bundled"]\nenabled = false\n');
78
79
  delete process.env.SKS_MANAGE_CODEX_APP_PLUGINS;
79
- const ok = hasPluginTables(fresh) && /\[plugins\."chrome@openai-bundled"\][\s\S]*enabled = false/.test(userDisabled);
80
+ const ok = hasPluginTables(fresh) && /model = "future-codex-model"/.test(fresh) && /\[plugins\."chrome@openai-bundled"\][\s\S]*enabled = false/.test(userDisabled);
80
81
  results.push({ case: 'optin_enables_but_preserves_user', ok });
81
82
  }
82
83
  if (prevEnv === undefined)
@@ -17,7 +17,7 @@ const oauthAuth = JSON.stringify({
17
17
  account_id: 'acct-fast-ui-fixture'
18
18
  }, null, 2);
19
19
  await fs.writeFile(configPath, [
20
- 'model = "gpt-5.5"',
20
+ 'model = "future-codex-model"',
21
21
  'model_reasoning_effort = "low"',
22
22
  'model_provider = "codex-lb"',
23
23
  'service_tier = "fast"',
@@ -79,8 +79,8 @@ function assertConfig(text, label) {
79
79
  ...(tableKey(text, 'features', 'fast_mode_ui') ? ['features_fast_mode_ui_legacy_flag_present'] : []),
80
80
  ...(hasTable(text, 'model_providers.codex-lb') ? [] : ['codex_lb_provider_table_missing']),
81
81
  ...(tableKey(text, 'model_providers.codex-lb', 'requires_openai_auth') === 'true' ? [] : ['requires_openai_auth_not_true']),
82
- ...(topLevelKey(text, 'model') ? ['top_level_model_forbidden'] : []),
83
- ...(topLevelKey(text, 'model_reasoning_effort') ? ['top_level_model_reasoning_effort_forbidden'] : [])
82
+ ...(topLevelKey(text, 'model') === 'future-codex-model' ? [] : ['user_model_not_preserved']),
83
+ ...(topLevelKey(text, 'model_reasoning_effort') === 'low' ? [] : ['user_reasoning_effort_not_preserved'])
84
84
  ];
85
85
  return { label, ok: blockers.length === 0, blockers };
86
86
  }
@@ -97,7 +97,7 @@ function tableKey(text, table, key) {
97
97
  }
98
98
  function topLevelKey(text, key) {
99
99
  const top = text.split(/\n\s*\[/)[0] || '';
100
- return new RegExp(`(^|\\n)\\s*${escapeRegExp(key)}\\s*=`).test(top);
100
+ return top.match(new RegExp(`(^|\\n)\\s*${escapeRegExp(key)}\\s*=\\s*([^\\n#]+)`))?.[2]?.trim().replace(/^"|"$/g, '') || '';
101
101
  }
102
102
  function escapeRegExp(value) {
103
103
  return value.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');