sneakoscope 3.1.11 → 3.1.13

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 (49) hide show
  1. package/README.md +8 -7
  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/bin/sks.js +1 -1
  6. package/dist/commands/doctor.js +161 -2
  7. package/dist/core/agents/agent-role-config.js +12 -1
  8. package/dist/core/codex/agent-config-file-repair.js +157 -0
  9. package/dist/core/codex/codex-startup-config-postcheck.js +83 -0
  10. package/dist/core/codex-control/codex-0140-capability.js +136 -0
  11. package/dist/core/codex-control/codex-0140-feature-probes.js +195 -0
  12. package/dist/core/codex-control/codex-0140-probe-runner.js +5 -0
  13. package/dist/core/codex-control/codex-0140-real-probe-summary.js +12 -0
  14. package/dist/core/codex-control/codex-0140-real-probes.js +69 -0
  15. package/dist/core/codex-control/codex-0140-usage-parser.js +81 -0
  16. package/dist/core/codex-native/codex-native-feature-broker.js +15 -1
  17. package/dist/core/codex-native/native-capability-postcheck.js +5 -2
  18. package/dist/core/codex-native/native-capability-repair-matrix.js +4 -4
  19. package/dist/core/config/config-migration-journal.js +2 -0
  20. package/dist/core/config/secret-preservation.js +108 -11
  21. package/dist/core/config/supabase-secret-preservation.js +1 -0
  22. package/dist/core/doctor/codex-startup-config-repair.js +40 -0
  23. package/dist/core/doctor/context7-mcp-repair.js +77 -0
  24. package/dist/core/doctor/doctor-codex-startup-repair.js +127 -15
  25. package/dist/core/doctor/doctor-context7-repair.js +40 -1
  26. package/dist/core/doctor/doctor-repair-postcheck.js +17 -0
  27. package/dist/core/doctor/doctor-transaction.js +126 -0
  28. package/dist/core/doctor/supabase-mcp-repair.js +66 -0
  29. package/dist/core/fsx.js +1 -1
  30. package/dist/core/loops/loop-concurrency-budget.js +22 -0
  31. package/dist/core/mcp/mcp-config-preservation.js +53 -0
  32. package/dist/core/naruto/naruto-loop-mesh.js +5 -1
  33. package/dist/core/version.js +1 -1
  34. package/dist/core/zellij/zellij-fake-adapter.js +8 -2
  35. package/dist/core/zellij/zellij-launcher.js +16 -0
  36. package/dist/core/zellij/zellij-worker-pane-manager.js +19 -2
  37. package/dist/scripts/codex-0140-feature-gate-lib.js +14 -0
  38. package/dist/scripts/release-3112-required-gates.js +30 -0
  39. package/dist/scripts/release-3113-required-gates.js +25 -0
  40. package/package.json +38 -2
  41. package/dist/.sks-build-stamp.json +0 -8
  42. package/dist/scripts/loop-directive-check-lib.js +0 -388
  43. package/dist/scripts/loop-hardening-check-lib.js +0 -289
  44. package/dist/scripts/sks-1-12-real-execution-check-lib.js +0 -27
  45. package/dist/scripts/sks-3-1-4-directive-check-lib.js +0 -212
  46. package/dist/scripts/sks-3-1-5-directive-check-lib.js +0 -318
  47. package/dist/scripts/sks-3-1-6-directive-check-lib.js +0 -522
  48. package/dist/scripts/sks-3-1-7-directive-check-lib.js +0 -58
  49. package/dist/scripts/sks-3-1-8-check-lib.js +0 -30
@@ -0,0 +1,126 @@
1
+ import path from 'node:path';
2
+ import { nowIso, writeJsonAtomic } from '../fsx.js';
3
+ export async function runDoctorFixTransaction(input) {
4
+ const startedAt = nowIso();
5
+ const phases = [];
6
+ let rollbackPerformed = false;
7
+ for (const definition of input.phases) {
8
+ const phaseStarted = nowIso();
9
+ const startedMs = Date.now();
10
+ let phase = {
11
+ id: definition.id,
12
+ ok: false,
13
+ repaired: false,
14
+ manual_required: false,
15
+ required_for_ready: definition.required_for_ready !== false,
16
+ blockers: [],
17
+ warnings: [],
18
+ artifact_path: null,
19
+ started_at: phaseStarted
20
+ };
21
+ try {
22
+ const result = await definition.run();
23
+ phase = normalizePhase(definition, result, phase, startedMs);
24
+ if (definition.postcheck) {
25
+ const postcheck = await definition.postcheck(phase);
26
+ if (postcheck)
27
+ phase = mergePhase(phase, postcheck);
28
+ }
29
+ }
30
+ catch (err) {
31
+ phase = normalizePhase(definition, {
32
+ id: definition.id,
33
+ ok: false,
34
+ blockers: [messageOf(err)]
35
+ }, phase, startedMs);
36
+ }
37
+ if (!phase.ok && definition.rollback) {
38
+ try {
39
+ await definition.rollback(phase);
40
+ phase.rollback_performed = true;
41
+ rollbackPerformed = true;
42
+ }
43
+ catch (err) {
44
+ phase.rollback_performed = true;
45
+ rollbackPerformed = true;
46
+ phase.blockers = [...(phase.blockers || []), `rollback_failed:${messageOf(err)}`];
47
+ }
48
+ }
49
+ phase.completed_at = phase.completed_at || nowIso();
50
+ phase.duration_ms = phase.duration_ms ?? Math.max(0, Date.now() - startedMs);
51
+ phases.push(phase);
52
+ }
53
+ const writeInput = {
54
+ root: input.root,
55
+ startedAt,
56
+ phases,
57
+ rollbackPerformed
58
+ };
59
+ if (input.reportPath !== undefined)
60
+ writeInput.reportPath = input.reportPath;
61
+ return writeDoctorFixTransaction(writeInput);
62
+ }
63
+ export async function writeDoctorFixTransaction(input) {
64
+ const root = path.resolve(input.root);
65
+ const phases = input.phases.map((phase) => ({
66
+ id: phase.id,
67
+ ok: phase.ok === true,
68
+ repaired: phase.repaired === true,
69
+ manual_required: phase.manual_required === true,
70
+ required_for_ready: phase.required_for_ready !== false,
71
+ blockers: phase.blockers || [],
72
+ warnings: phase.warnings || [],
73
+ artifact_path: phase.artifact_path || null,
74
+ started_at: phase.started_at || null,
75
+ completed_at: phase.completed_at || null,
76
+ duration_ms: Number.isFinite(phase.duration_ms) ? Number(phase.duration_ms) : null,
77
+ rollback_performed: phase.rollback_performed === true
78
+ }));
79
+ const postcheckOk = phases.every((phase) => phase.ok || (phase.manual_required && !phase.required_for_ready));
80
+ const report = {
81
+ schema: 'sks.doctor-fix-transaction.v1',
82
+ ok: postcheckOk,
83
+ root,
84
+ started_at: input.startedAt || nowIso(),
85
+ completed_at: nowIso(),
86
+ phases,
87
+ postcheck_ok: postcheckOk,
88
+ rollback_performed: input.rollbackPerformed === true,
89
+ raw_secret_values_recorded: false
90
+ };
91
+ if (input.reportPath !== null)
92
+ await writeJsonAtomic(input.reportPath || path.join(root, '.sneakoscope', 'reports', 'doctor-fix-transaction.json'), report).catch(() => undefined);
93
+ return report;
94
+ }
95
+ function normalizePhase(definition, result, fallback, startedMs) {
96
+ const phase = result || fallback;
97
+ return {
98
+ id: phase.id || definition.id,
99
+ ok: phase.ok === true,
100
+ repaired: phase.repaired === true,
101
+ manual_required: phase.manual_required === true,
102
+ required_for_ready: phase.required_for_ready ?? definition.required_for_ready !== false,
103
+ blockers: phase.blockers || [],
104
+ warnings: phase.warnings || [],
105
+ artifact_path: phase.artifact_path || null,
106
+ started_at: phase.started_at || fallback.started_at || nowIso(),
107
+ completed_at: phase.completed_at || nowIso(),
108
+ duration_ms: phase.duration_ms ?? Math.max(0, Date.now() - startedMs),
109
+ rollback_performed: phase.rollback_performed === true
110
+ };
111
+ }
112
+ function mergePhase(phase, update) {
113
+ return {
114
+ ...phase,
115
+ ...update,
116
+ ok: phase.ok === true && update.ok !== false,
117
+ repaired: phase.repaired === true || update.repaired === true,
118
+ manual_required: phase.manual_required === true || update.manual_required === true,
119
+ blockers: [...(phase.blockers || []), ...(update.blockers || [])],
120
+ warnings: [...(phase.warnings || []), ...(update.warnings || [])]
121
+ };
122
+ }
123
+ function messageOf(err) {
124
+ return err instanceof Error ? err.message : String(err);
125
+ }
126
+ //# sourceMappingURL=doctor-transaction.js.map
@@ -0,0 +1,66 @@
1
+ import path from 'node:path';
2
+ import { nowIso, writeJsonAtomic, writeTextAtomic } from '../fsx.js';
3
+ import { mcpServerBlock, mcpServerExplicitlyDisabled, readProjectCodexConfig, replaceOrAppendMcpServerBlock } from '../mcp/mcp-config-preservation.js';
4
+ export async function repairSupabaseMcp(input) {
5
+ const root = path.resolve(input.root);
6
+ const config = await readProjectCodexConfig(root);
7
+ const disabled = mcpServerExplicitlyDisabled(config.text, 'supabase') || mcpServerExplicitlyDisabled(config.text, 'supabase_sauron');
8
+ const block = mcpServerBlock(config.text, 'supabase') || '';
9
+ const configured = Boolean(block);
10
+ const tokenEnvPresent = Boolean(process.env.SUPABASE_ACCESS_TOKEN);
11
+ const readOnlyBefore = /read[_-]?only\s*=\s*true|access_mode\s*=\s*"read-only"|--read-only/.test(block);
12
+ const unsafeWriteAccessBefore = configured && !disabled && !readOnlyBefore && /write|service_role|SUPABASE_ACCESS_TOKEN/.test(block);
13
+ let afterText = config.text;
14
+ let readOnlyMigrated = false;
15
+ if (configured && !disabled && !readOnlyBefore && input.apply) {
16
+ afterText = replaceOrAppendMcpServerBlock(config.text, 'supabase', setReadOnly(block));
17
+ readOnlyMigrated = afterText !== config.text;
18
+ if (readOnlyMigrated)
19
+ await writeTextAtomic(config.path, afterText);
20
+ }
21
+ const afterBlock = readOnlyMigrated ? mcpServerBlock(afterText, 'supabase') || '' : block;
22
+ const readOnlyAfter = /read[_-]?only\s*=\s*true|access_mode\s*=\s*"read-only"|--read-only/.test(afterBlock);
23
+ const unsafeWriteAccess = configured && !disabled && !readOnlyAfter && /write|service_role|SUPABASE_ACCESS_TOKEN/.test(afterBlock);
24
+ const writeScopeRequiresConfirmation = configured && !disabled && (unsafeWriteAccessBefore || !readOnlyAfter);
25
+ const readyBlocking = unsafeWriteAccess;
26
+ const manualRequired = configured && !disabled && (!tokenEnvPresent || writeScopeRequiresConfirmation);
27
+ const report = {
28
+ schema: 'sks.doctor-supabase-mcp-repair.v1',
29
+ generated_at: nowIso(),
30
+ ok: !configured || disabled || !unsafeWriteAccess,
31
+ apply: input.apply === true,
32
+ configured,
33
+ disabled,
34
+ disabled_preserved: disabled,
35
+ token_env_present: tokenEnvPresent,
36
+ unsafe_write_access: unsafeWriteAccess,
37
+ read_only_migrated: readOnlyMigrated,
38
+ write_scope_requires_confirmation: writeScopeRequiresConfirmation,
39
+ ready_blocking: readyBlocking,
40
+ manual_required: manualRequired,
41
+ next_action: manualRequired
42
+ ? tokenEnvPresent
43
+ ? 'Set Supabase MCP to read-only or explicitly approve write-scoped MCP use.'
44
+ : 'Set SUPABASE_ACCESS_TOKEN only if Supabase write MCP features are required; otherwise keep Supabase MCP disabled/read-only.'
45
+ : null,
46
+ blockers: readyBlocking ? ['supabase_mcp_write_access_not_safe_by_default'] : [],
47
+ warnings: [
48
+ ...(configured && !tokenEnvPresent ? ['supabase_access_token_unset_write_features_manual_required'] : []),
49
+ ...(readOnlyMigrated ? ['supabase_mcp_migrated_to_read_only'] : [])
50
+ ],
51
+ raw_secret_values_recorded: false
52
+ };
53
+ if (input.reportPath !== null)
54
+ await writeJsonAtomic(input.reportPath || path.join(root, '.sneakoscope', 'reports', 'doctor-supabase-mcp-repair.json'), report).catch(() => undefined);
55
+ return report;
56
+ }
57
+ function setReadOnly(block) {
58
+ const lines = String(block || '').replace(/\s*$/, '').split(/\r?\n/);
59
+ const index = lines.findIndex((line) => /^\s*read[_-]?only\s*=/.test(line));
60
+ if (index >= 0)
61
+ lines[index] = 'read_only = true';
62
+ else
63
+ lines.push('read_only = true');
64
+ return `${lines.join('\n')}\n`;
65
+ }
66
+ //# sourceMappingURL=supabase-mcp-repair.js.map
package/dist/core/fsx.js CHANGED
@@ -5,7 +5,7 @@ import os from 'node:os';
5
5
  import crypto from 'node:crypto';
6
6
  import { spawn } from 'node:child_process';
7
7
  import { fileURLToPath } from 'node:url';
8
- export const PACKAGE_VERSION = '3.1.11';
8
+ export const PACKAGE_VERSION = '3.1.13';
9
9
  export const DEFAULT_PROCESS_TAIL_BYTES = 256 * 1024;
10
10
  export const DEFAULT_PROCESS_TIMEOUT_MS = 30 * 60 * 1000;
11
11
  export function nowIso() {
@@ -3,6 +3,10 @@ import { writeJsonAtomic } from '../fsx.js';
3
3
  import { loopConcurrencyBudgetPath } from './loop-artifacts.js';
4
4
  export function computeLoopConcurrencyBudget(input) {
5
5
  const env = input.env || process.env;
6
+ const codexUsageSignal = input.codexUsageSignal || codexUsageSignalFromEnv(env);
7
+ const usageBudgetSource = codexUsageSignal.available && (codexUsageSignal.certainty === 'actual' || codexUsageSignal.certainty === 'discovered')
8
+ ? 'codex-0140-usage'
9
+ : 'sks-local-estimate';
6
10
  const cores = Math.max(1, os.cpus().length || 1);
7
11
  const requestedLoops = input.parallelism === 'safe' ? 2 : input.parallelism === 'extreme' ? Math.min(16, cores) : Math.min(8, cores);
8
12
  const envLoops = positiveInt(env.SKS_LOOP_MAX_ACTIVE_LOOPS);
@@ -32,6 +36,8 @@ export function computeLoopConcurrencyBudget(input) {
32
36
  return {
33
37
  schema: 'sks.loop-concurrency-budget.v1',
34
38
  mission_id: input.plan.mission_id,
39
+ usage_budget_source: usageBudgetSource,
40
+ codex_usage_signal: codexUsageSignal,
35
41
  max_active_loops: maxActiveLoops,
36
42
  max_active_workers: maxActiveWorkers,
37
43
  max_model_calls: maxModelCalls,
@@ -52,4 +58,20 @@ function positiveInt(value) {
52
58
  const number = Number(value);
53
59
  return Number.isFinite(number) && number >= 1 ? Math.floor(number) : null;
54
60
  }
61
+ function codexUsageSignalFromEnv(env) {
62
+ const certainty = normalizeUsageCertainty(env.SKS_CODEX_0140_USAGE_CERTAINTY);
63
+ const available = env.SKS_CODEX_0140_USAGE_AVAILABLE === '1' || certainty === 'actual' || certainty === 'discovered';
64
+ return {
65
+ available,
66
+ certainty,
67
+ source: available ? 'env' : 'none',
68
+ evidence: env.SKS_CODEX_0140_USAGE_EVIDENCE ? [env.SKS_CODEX_0140_USAGE_EVIDENCE] : [],
69
+ warnings: available ? [] : ['codex_0140_usage_signal_unavailable_using_local_estimate']
70
+ };
71
+ }
72
+ function normalizeUsageCertainty(value) {
73
+ if (value === 'actual' || value === 'discovered' || value === 'fixture' || value === 'assumed_by_version')
74
+ return value;
75
+ return 'unverified';
76
+ }
55
77
  //# sourceMappingURL=loop-concurrency-budget.js.map
@@ -0,0 +1,53 @@
1
+ import fs from 'node:fs/promises';
2
+ import path from 'node:path';
3
+ export const CONTEXT7_REMOTE_MCP_URL = 'https://mcp.context7.com/mcp';
4
+ export async function readProjectCodexConfig(root) {
5
+ const file = path.join(path.resolve(root), '.codex', 'config.toml');
6
+ const text = await fs.readFile(file, 'utf8').catch(() => '');
7
+ return { path: file, text };
8
+ }
9
+ export function mcpServerBlock(text, serverName) {
10
+ const range = tomlTableRange(text, `mcp_servers.${serverName}`, false);
11
+ return range ? String(text || '').slice(range.start, range.end) : null;
12
+ }
13
+ export function mcpServerBlockWithChildren(text, serverName) {
14
+ const range = tomlTableRange(text, `mcp_servers.${serverName}`, true);
15
+ return range ? String(text || '').slice(range.start, range.end) : null;
16
+ }
17
+ export function mcpServerExplicitlyDisabled(text, serverName) {
18
+ const block = mcpServerBlock(text, serverName);
19
+ return Boolean(block && /^\s*disabled\s*=\s*true\s*$/m.test(block));
20
+ }
21
+ export function replaceOrAppendMcpServerBlock(text, serverName, block) {
22
+ const normalizedBlock = block.endsWith('\n') ? block : `${block}\n`;
23
+ const range = tomlTableRange(text, `mcp_servers.${serverName}`, true);
24
+ if (range)
25
+ return `${text.slice(0, range.start)}${normalizedBlock}${text.slice(range.end).replace(/^\n+/, '')}`;
26
+ const prefix = text.trim() ? `${text.replace(/\s*$/, '\n\n')}` : '';
27
+ return `${prefix}${normalizedBlock}`;
28
+ }
29
+ export function removeMcpServerBlock(text, serverName) {
30
+ const range = tomlTableRange(text, `mcp_servers.${serverName}`, true);
31
+ if (!range)
32
+ return text;
33
+ return `${text.slice(0, range.start).trimEnd()}${range.start > 0 ? '\n\n' : ''}${text.slice(range.end).replace(/^\n+/, '')}`;
34
+ }
35
+ export function redactedMcpText(text) {
36
+ return String(text || '').replace(/(token|access_token|api_key|secret)\s*=\s*"[^"]*"/gi, '$1 = "<redacted>"');
37
+ }
38
+ export function tomlTableRange(text, table, includeChildren) {
39
+ const source = String(text || '');
40
+ const escaped = table.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
41
+ const header = new RegExp(`(^|\\n)\\s*\\[${escaped}\\]\\s*(?:#.*)?(?:\\n|$)`, 'g');
42
+ const match = header.exec(source);
43
+ if (!match)
44
+ return null;
45
+ const start = Number(match.index || 0) + (match[1] ? 1 : 0);
46
+ const rest = source.slice(header.lastIndex);
47
+ const nextHeader = includeChildren
48
+ ? rest.search(new RegExp(`\\n\\s*\\[(?!${escaped}(?:\\.|\\]))[^\\]]+\\]\\s*(?:#.*)?(?:\\n|$)`))
49
+ : rest.search(/\n\s*\[[^\]]+\]\s*(?:#.*)?(?:\n|$)/);
50
+ const end = nextHeader >= 0 ? header.lastIndex + nextHeader : source.length;
51
+ return { start, end };
52
+ }
53
+ //# sourceMappingURL=mcp-config-preservation.js.map
@@ -10,7 +10,11 @@ export async function runNarutoLoopMesh(input) {
10
10
  await writeJsonAtomic(`${loopRoot(input.root, input.plan.mission_id)}/naruto-loop-worker-routes.json`, {
11
11
  schema: 'sks.naruto-loop-worker-routes.v1',
12
12
  mission_id: input.plan.mission_id,
13
- active_worker_budget: activeWorkerBudget,
13
+ active_worker_budget: {
14
+ ...activeWorkerBudget,
15
+ usage_budget_source: loopConcurrencyBudget.usage_budget_source,
16
+ codex_usage_signal: loopConcurrencyBudget.codex_usage_signal
17
+ },
14
18
  loop_concurrency_budget: loopConcurrencyBudget,
15
19
  routes
16
20
  });
@@ -1,2 +1,2 @@
1
- export const PACKAGE_VERSION = '3.1.11';
1
+ export const PACKAGE_VERSION = '3.1.13';
2
2
  //# sourceMappingURL=version.js.map
@@ -13,8 +13,14 @@ export async function runFakeZellij(args = [], opts = {}) {
13
13
  result = ok(`zellij ${version}\n`);
14
14
  }
15
15
  else if (args[0] === 'attach' && args[1] === '--create-background') {
16
- getSession(String(args[2] || 'default'));
17
- result = ok('');
16
+ const name = String(args[2] || 'default');
17
+ if (env.SKS_ZELLIJ_FAKE_CREATE_BACKGROUND_EXISTS === '1' && sessions.has(name)) {
18
+ result = fail(`Session already exists: ${name}`);
19
+ }
20
+ else {
21
+ getSession(name);
22
+ result = ok('');
23
+ }
18
24
  }
19
25
  else if (args.includes('new-pane')) {
20
26
  if (args.includes('--stacked') && !supportsStacked(version)) {
@@ -57,6 +57,9 @@ export async function launchZellijLayout(opts = {}) {
57
57
  ok: false,
58
58
  blockers: [`zellij_pane_proof_exception:${err?.message || String(err)}`]
59
59
  }));
60
+ if (launch?.create_background) {
61
+ launch.create_background = normalizeExistingZellijSession(sessionName, launch.create_background);
62
+ }
60
63
  const launchOk = launch?.create_background?.ok === true;
61
64
  const ok = capability.ok && (opts.dryRun === true || capability.status !== 'ok' || launchOk) && (opts.requireZellij === true ? paneProof.ok === true : true);
62
65
  const blockers = [
@@ -192,4 +195,17 @@ function readOption(args, name, fallback) {
192
195
  const index = list.indexOf(name);
193
196
  return index >= 0 && list[index + 1] ? String(list[index + 1]) : fallback;
194
197
  }
198
+ function normalizeExistingZellijSession(sessionName, result) {
199
+ if (result.ok)
200
+ return result;
201
+ if (/Session already exists/i.test(result.stderr_tail || '')) {
202
+ return {
203
+ ...result,
204
+ ok: true,
205
+ blockers: [],
206
+ warnings: [...result.warnings, `zellij_session_already_exists:${sessionName}`]
207
+ };
208
+ }
209
+ return result;
210
+ }
195
211
  //# sourceMappingURL=zellij-launcher.js.map
@@ -311,6 +311,20 @@ export async function openWorkerPane(input) {
311
311
  const stdoutPaneId = launch?.ok ? extractZellijPaneIdFromOutput(launch.stdout_tail) : null;
312
312
  const reconciledPane = stdoutPaneId ? null : launch?.ok ? await reconcileZellijWorkerPaneId(input.sessionName, paneName, path.join(root, input.resultPath), cwd) : null;
313
313
  const paneId = stdoutPaneId || reconciledPane?.pane_id || null;
314
+ const stackPaneIds = [...new Set([
315
+ ...(freshState?.visible_worker_panes || [])
316
+ .filter((pane) => pane.pane_id && (pane.status === 'launching' || pane.status === 'running'))
317
+ .sort((a, b) => Number(a.y_order || 0) - Number(b.y_order || 0))
318
+ .map((pane) => String(pane.pane_id)),
319
+ paneId || ''
320
+ ].filter(Boolean))];
321
+ const stackPanes = stackRequested && paneId && stackPaneIds.length >= 2
322
+ ? await runZellij(['--session', input.sessionName, 'action', 'stack-panes', '--', ...stackPaneIds], {
323
+ cwd,
324
+ timeoutMs: 5000,
325
+ optional: true
326
+ })
327
+ : null;
314
328
  const renamePane = paneId ? await renameZellijPaneById(input.sessionName, paneId, paneName, cwd) : null;
315
329
  const paneIdSource = stdoutPaneId
316
330
  ? 'zellij_worker_new_pane_stdout'
@@ -329,7 +343,8 @@ export async function openWorkerPane(input) {
329
343
  ];
330
344
  const warnings = [
331
345
  ...(stackIntent && stackedCapability && !stackedCapability.supports_stacked_panes ? [`zellij_stacked_pane_fallback:${stackedCapability.fallback_mode}`] : []),
332
- ...(stackedRejectedFallback ? ['zellij_stacked_pane_rejected_fallback_down'] : [])
346
+ ...(stackedRejectedFallback ? ['zellij_stacked_pane_rejected_fallback_down'] : []),
347
+ ...(stackPanes && !stackPanes.ok ? stackPanes.blockers.map((blocker) => `zellij_stack_panes_reconcile_${blocker}`) : [])
333
348
  ];
334
349
  const record = buildWorkerPaneArtifact({
335
350
  ...input,
@@ -343,7 +358,9 @@ export async function openWorkerPane(input) {
343
358
  focus_degraded: focus ? focus.ok !== true : false,
344
359
  slot_column_anchor_pane_id: slotColumnAnchorPaneId,
345
360
  slot_column_anchor_launch: anchorLaunch,
346
- rename_pane: renamePane
361
+ rename_pane: renamePane,
362
+ stack_panes: stackPanes,
363
+ stack_pane_ids: stackPaneIds
347
364
  },
348
365
  directionRequested,
349
366
  directionApplied,
@@ -0,0 +1,14 @@
1
+ import { assertGate, emitGate } from './sks-1-18-gate-lib.js';
2
+ import { detectCodex0140Capability } from '../core/codex-control/codex-0140-capability.js';
3
+ export async function runCodex0140FeatureGate(gate, feature) {
4
+ process.env.SKS_CODEX_0140_FAKE = '1';
5
+ process.env.SKS_CODEX_VERSION_FAKE = 'codex-cli 0.140.0';
6
+ process.env.SKS_CODEX_0140_PROBE = '1';
7
+ const cap = await detectCodex0140Capability({ codexBin: 'codex' });
8
+ assertGate(cap.ok === true && cap.supports_0140 === true, `${gate} requires passing Codex 0.140 capability fixture`, cap);
9
+ const state = cap.feature_states[feature];
10
+ assertGate(cap.features[feature] === true && state?.supported === true, `${gate} requires feature ${feature}`, cap);
11
+ assertGate(state.certainty !== 'assumed_by_version' && state.certainty !== 'unverified' && state.certainty !== 'failed', `${gate} requires probed feature certainty for ${feature}`, state);
12
+ emitGate(gate, { feature, schema: cap.schema, certainty: state.certainty });
13
+ }
14
+ //# sourceMappingURL=codex-0140-feature-gate-lib.js.map
@@ -0,0 +1,30 @@
1
+ export const REQUIRED_3112_RELEASE_IDS = [
2
+ 'release:gate-script-parity',
3
+ 'release:wiring-3112-blackbox',
4
+ 'codex:0140-capability',
5
+ 'codex:0140-feature-probes',
6
+ 'codex:0140-usage',
7
+ 'codex:0140-goal-attachment-preservation',
8
+ 'codex:0140-session-delete',
9
+ 'codex:0140-import',
10
+ 'codex:0140-unified-mentions',
11
+ 'codex:0140-bedrock-managed-auth',
12
+ 'codex:0140-mcp-reliability',
13
+ 'codex:0140-sqlite-recovery',
14
+ 'codex:0140-non-tty-interrupt',
15
+ 'codex:0140-large-repo-performance',
16
+ 'pipeline:codex-0140-integration',
17
+ 'codex:0140-integration-blackbox',
18
+ 'doctor:fix-production-blackbox',
19
+ 'doctor:startup-config-repair',
20
+ 'doctor:startup-config-repair-blackbox',
21
+ 'doctor:context7-mcp-repair',
22
+ 'doctor:context7-mcp-repair-blackbox',
23
+ 'doctor:supabase-mcp-repair',
24
+ 'doctor:supabase-mcp-repair-blackbox',
25
+ 'sks:3112-all-feature-regression'
26
+ ];
27
+ export const REQUIRED_3112_REAL_CHECK_IDS = [
28
+ 'codex:0140-real-probes:require-real'
29
+ ];
30
+ //# sourceMappingURL=release-3112-required-gates.js.map
@@ -0,0 +1,25 @@
1
+ export const REQUIRED_3113_RELEASE_IDS = [
2
+ 'release:gate-script-parity',
3
+ 'release:wiring-3113-blackbox',
4
+ 'codex:0140-deep-probes',
5
+ 'codex:0140-goal-attachment-roundtrip',
6
+ 'codex:0140-usage-real-parser',
7
+ 'pipeline:codex-0140-integration',
8
+ 'doctor:transaction-engine',
9
+ 'doctor:transaction-engine-blackbox',
10
+ 'doctor:fix-production-blackbox',
11
+ 'doctor:startup-config-repair',
12
+ 'doctor:startup-config-repair-blackbox',
13
+ 'doctor:context7-mcp-repair',
14
+ 'doctor:context7-mcp-repair-blackbox',
15
+ 'doctor:supabase-mcp-repair',
16
+ 'doctor:supabase-mcp-repair-blackbox',
17
+ 'native-capability:postcheck',
18
+ 'secret:line-rollback',
19
+ 'secret:preservation-guard',
20
+ 'sks:3113-all-feature-regression'
21
+ ];
22
+ export const REQUIRED_3113_REAL_CHECK_IDS = [
23
+ 'codex:0140-real-probes:require-real'
24
+ ];
25
+ //# sourceMappingURL=release-3113-required-gates.js.map
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "sneakoscope",
3
3
  "displayName": "ㅅㅋㅅ",
4
- "version": "3.1.11",
4
+ "version": "3.1.13",
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",
@@ -23,6 +23,8 @@
23
23
  },
24
24
  "files": [
25
25
  "dist",
26
+ "!dist/*.json",
27
+ "!dist/.sks-build-stamp.json",
26
28
  "!dist/build-manifest.json",
27
29
  "!dist/**/*.d.ts",
28
30
  "!dist/**/*.d.ts.map",
@@ -31,6 +33,7 @@
31
33
  "!dist/vendor/openai-codex/rust-v0.131.0",
32
34
  "!dist/scripts/*-blackbox.js",
33
35
  "!dist/scripts/*-check.js",
36
+ "!dist/scripts/*-check-lib.js",
34
37
  "!dist/scripts/*-report.js",
35
38
  "!dist/scripts/release-readiness-report.js",
36
39
  "schemas",
@@ -922,7 +925,40 @@
922
925
  "doctor:codex-native-readiness-ux": "node ./dist/scripts/doctor-codex-native-readiness-ux-check.js",
923
926
  "doctor:codex-native-repair-actions": "node ./dist/scripts/doctor-codex-native-repair-actions-check.js",
924
927
  "codex-native:feature-broker-blackbox": "node ./dist/scripts/codex-native-feature-broker-blackbox.js",
925
- "pipeline:codex-native-e2e-blackbox": "node ./dist/scripts/pipeline-codex-native-e2e-blackbox.js"
928
+ "pipeline:codex-native-e2e-blackbox": "node ./dist/scripts/pipeline-codex-native-e2e-blackbox.js",
929
+ "release:wiring-3112-blackbox": "node ./dist/scripts/release-wiring-3112-blackbox.js",
930
+ "release:wiring-3113-blackbox": "node ./dist/scripts/release-wiring-3113-blackbox.js",
931
+ "codex:0140-capability": "node ./dist/scripts/codex-0140-capability-check.js",
932
+ "codex:0140-feature-probes": "node ./dist/scripts/codex-0140-feature-probes-check.js",
933
+ "codex:0140-deep-probes": "node ./dist/scripts/codex-0140-deep-probes-check.js",
934
+ "codex:0140-usage": "node ./dist/scripts/codex-0140-usage-check.js",
935
+ "codex:0140-usage-real-parser": "node ./dist/scripts/codex-0140-usage-real-parser-check.js",
936
+ "codex:0140-goal-attachment-preservation": "node ./dist/scripts/codex-0140-goal-attachment-preservation-check.js",
937
+ "codex:0140-goal-attachment-roundtrip": "node ./dist/scripts/codex-0140-goal-attachment-roundtrip-check.js",
938
+ "codex:0140-session-delete": "node ./dist/scripts/codex-0140-session-delete-check.js",
939
+ "codex:0140-import": "node ./dist/scripts/codex-0140-import-check.js",
940
+ "codex:0140-unified-mentions": "node ./dist/scripts/codex-0140-unified-mentions-check.js",
941
+ "codex:0140-bedrock-managed-auth": "node ./dist/scripts/codex-0140-bedrock-managed-auth-check.js",
942
+ "codex:0140-mcp-reliability": "node ./dist/scripts/codex-0140-mcp-reliability-check.js",
943
+ "codex:0140-sqlite-recovery": "node ./dist/scripts/codex-0140-sqlite-recovery-check.js",
944
+ "codex:0140-non-tty-interrupt": "node ./dist/scripts/codex-0140-non-tty-interrupt-check.js",
945
+ "codex:0140-large-repo-performance": "node ./dist/scripts/codex-0140-large-repo-performance-check.js",
946
+ "codex:0140-real-probes": "node ./dist/scripts/codex-0140-real-probes-check.js",
947
+ "codex:0140-real-probes:require-real": "node ./dist/scripts/codex-0140-real-probes-check.js --require-real --allow-network",
948
+ "pipeline:codex-0140-integration": "node ./dist/scripts/pipeline-codex-0140-integration-check.js",
949
+ "codex:0140-integration-blackbox": "node ./dist/scripts/codex-0140-integration-blackbox.js",
950
+ "doctor:transaction-engine": "node ./dist/scripts/doctor-transaction-engine-check.js",
951
+ "doctor:transaction-engine-blackbox": "node ./dist/scripts/doctor-transaction-engine-blackbox.js",
952
+ "doctor:fix-production-blackbox": "node ./dist/scripts/doctor-fix-production-blackbox.js",
953
+ "doctor:startup-config-repair": "node ./dist/scripts/doctor-startup-config-repair-check.js",
954
+ "doctor:startup-config-repair-blackbox": "node ./dist/scripts/doctor-startup-config-repair-blackbox.js",
955
+ "doctor:context7-mcp-repair": "node ./dist/scripts/doctor-context7-mcp-repair-check.js",
956
+ "doctor:context7-mcp-repair-blackbox": "node ./dist/scripts/doctor-context7-mcp-repair-blackbox.js",
957
+ "doctor:supabase-mcp-repair": "node ./dist/scripts/doctor-supabase-mcp-repair-check.js",
958
+ "doctor:supabase-mcp-repair-blackbox": "node ./dist/scripts/doctor-supabase-mcp-repair-blackbox.js",
959
+ "secret:line-rollback": "node ./dist/scripts/secret-line-rollback-check.js",
960
+ "sks:3112-all-feature-regression": "node ./dist/scripts/sks-3112-all-feature-regression-blackbox.js",
961
+ "sks:3113-all-feature-regression": "node ./dist/scripts/sks-3113-all-feature-regression-blackbox.js"
926
962
  },
927
963
  "keywords": [
928
964
  "sneakoscope",
@@ -1,8 +0,0 @@
1
- {
2
- "schema": "sks.dist-build-stamp.v1",
3
- "package_name": "sneakoscope",
4
- "package_version": "3.1.11",
5
- "source_digest": "932de0e70bb2a5b787aef2782fa56cbc4956c6077d099d9e1067b9406fd8412a",
6
- "source_file_count": 2613,
7
- "built_at_source_time": 1781554790419
8
- }