sneakoscope 4.8.1 → 4.8.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -49,7 +49,7 @@ sks seo-geo-optimizer apply latest --mode seo --apply --json
49
49
  sks seo-geo-optimizer audit --mode geo --target package --offline --json
50
50
  ```
51
51
 
52
- > 📋 **Current release: `v4.8.1`** — full release history lives in [CHANGELOG.md](CHANGELOG.md). This README documents how Sneakoscope works today, not its version-by-version changes. Release readiness is tracked in [docs/release-readiness.md](docs/release-readiness.md).
52
+ > 📋 **Current release: `v4.8.3`** — full release history lives in [CHANGELOG.md](CHANGELOG.md). This README documents how Sneakoscope works today, not its version-by-version changes. Release readiness is tracked in [docs/release-readiness.md](docs/release-readiness.md).
53
53
 
54
54
  ## 🍥 Parallelism, UX, And Integrations
55
55
 
@@ -763,7 +763,7 @@ npm run release:check
763
763
  npm run publish:dry
764
764
  ```
765
765
 
766
- `release:check` runs the change-aware affected release gate for ordinary local checks. Publish readiness uses `release:check:full`, which runs the full release DAG and writes a source digest stamp under `.sneakoscope/reports/` so publish commands can verify the same source/dist state. The DAG preserves the 1.18 baseline gates and adds Codex 0.136 compatibility, inherited Codex 0.135/0.134 runner truth, patch swarm runtime truth, transaction journaling, serial conflict rebase, strict strategy-to-patch proof, rollback command proof, Native CLI Session Swarm 5/10/20-process proof, Real Worker Backend Router proof, Codex child overlap proof, model-authored patch-envelope separation, Zellij layout/pane/screen/socket-dir proof, no-subagent-scaling proof, Fast mode default/worker/Codex/MAD propagation proof, Appshots attachment provenance, MCP runtime overlap evidence, task graph expansion, schema-bound follow-up work, actual Agent/Team/Research/QA route blackboxes, scheduler proof hardening, Source Intelligence propagation, Goal mode propagation checks, slot telemetry, update notice, MAD-DB, and Naruto SSOT gates. Broader live gates remain explicit scripts such as `release:real-check`; real Codex patch smoke, real Codex parallel worker proof, and real Zellij proof are optional unless their `SKS_REQUIRE_REAL_*` or `SKS_REQUIRE_ZELLIJ=1` environment variables are set. Generate the human-readable registry with `sks features inventory --write-docs`. Plain `npm publish` uses the `latest` dist-tag. `npm run publish:dry` runs `release:check:full`, verifies the fresh stamp, and then performs provenance/registry and npm dry-run checks. `npm run publish:npm` and `npm run release:publish` run the same prepublish gate and then `npm publish --ignore-scripts`, so the real publish path stays strict even when lifecycle scripts are skipped. npm's `prepublishOnly` uses `prepublish-release-check-or-fast` to accept that current stamp before the real publish; if the stamp is missing or stale, it runs `release:check:full` once before continuing.
766
+ `release:check` runs the change-aware affected release gate for ordinary local checks. Publish readiness uses `release:check:full`, which runs the full release DAG and writes a source digest stamp under `.sneakoscope/reports/` so publish commands can verify the same source/dist state. The DAG preserves the 1.18 baseline gates and adds Codex 0.136 compatibility, inherited Codex 0.135/0.134 runner truth, patch swarm runtime truth, transaction journaling, serial conflict rebase, strict strategy-to-patch proof, rollback command proof, Native CLI Session Swarm 5/10/20-process proof, Real Worker Backend Router proof, Codex child overlap proof, model-authored patch-envelope separation, Zellij layout/pane/screen/socket-dir proof, no-subagent-scaling proof, Fast mode default/worker/Codex/MAD propagation proof, Appshots attachment provenance, MCP runtime overlap evidence, task graph expansion, schema-bound follow-up work, actual Agent/Team/Research/QA route blackboxes, scheduler proof hardening, Source Intelligence propagation, Goal mode propagation checks, slot telemetry, update notice, MAD-DB, and Naruto SSOT gates. Broader live gates remain explicit scripts such as `release:real-check`; real Codex patch smoke, real Codex parallel worker proof, and real Zellij proof are optional unless their `SKS_REQUIRE_REAL_*` or `SKS_REQUIRE_ZELLIJ=1` environment variables are set. Generate the human-readable registry with `sks features inventory --write-docs`. Plain `npm publish` uses the `latest` dist-tag. `npm run publish:dry` runs `release:check:full`, verifies the fresh stamp, and then performs provenance/registry and npm dry-run checks. `npm run publish:npm` and `npm run release:publish` run `npm run publish:prep-ignore-scripts` first, then `npm publish --ignore-scripts`, so the real publish path stays strict even when lifecycle scripts are skipped. Operators who intentionally run `npm publish --ignore-scripts` directly must run `npm run publish:prep-ignore-scripts` immediately before it. npm's `prepublishOnly` uses `prepublish-release-check-or-fast` to accept that current stamp before the real publish; if the stamp is missing or stale, it runs `release:check:full` once before continuing.
767
767
 
768
768
  Version bumps are manual. Run `sks versioning bump` only when preparing release metadata; SKS will not create `.git/hooks/pre-commit` or auto-bump during ordinary commits.
769
769
 
@@ -76,7 +76,7 @@ dependencies = [
76
76
 
77
77
  [[package]]
78
78
  name = "sks-core"
79
- version = "4.8.1"
79
+ version = "4.8.3"
80
80
  dependencies = [
81
81
  "serde_json",
82
82
  ]
@@ -1,6 +1,6 @@
1
1
  [package]
2
2
  name = "sks-core"
3
- version = "4.8.1"
3
+ version = "4.8.3"
4
4
  edition = "2021"
5
5
 
6
6
  [dependencies]
@@ -4,7 +4,7 @@ use std::io::{self, Read, Seek, SeekFrom};
4
4
  fn main() {
5
5
  let mut args = std::env::args().skip(1);
6
6
  match args.next().as_deref() {
7
- Some("--version") => println!("sks-rs 4.8.1"),
7
+ Some("--version") => println!("sks-rs 4.8.3"),
8
8
  Some("compact-info") => {
9
9
  let mut input = String::new();
10
10
  let _ = io::stdin().read_to_string(&mut input);
package/dist/bin/sks.js CHANGED
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
- const FAST_PACKAGE_VERSION = '4.8.1';
2
+ const FAST_PACKAGE_VERSION = '4.8.3';
3
3
  const args = process.argv.slice(2);
4
4
  try {
5
5
  if (args[0] === '--agent' && args[1] === 'worker') {
@@ -3,6 +3,8 @@ import os from 'node:os';
3
3
  import path from 'node:path';
4
4
  import { ensureDir, exists, runProcess, which, writeJsonAtomic, writeTextAtomic } from '../fsx.js';
5
5
  const LABEL = 'com.sneakoscope.sks-menubar';
6
+ const CONTROL_CENTER_DOMAIN = 'com.apple.controlcenter';
7
+ const CONTROL_CENTER_PREFERRED_POSITION = 360;
6
8
  const MENU_ITEMS = [
7
9
  'Use codex-lb',
8
10
  'Use ChatGPT OAuth',
@@ -107,9 +109,19 @@ export async function installSksMenuBar(opts = {}) {
107
109
  actions.push(`wrote ${launchAgentPath}`);
108
110
  const launchWanted = opts.launch !== false && env.SKS_SKIP_SKS_MENUBAR_LAUNCH !== '1';
109
111
  const launchAllowedForHome = path.resolve(home) === realUserHome();
112
+ const installUnderTempDir = isMenuBarInstallPathUnderTempDir(executablePath, env);
110
113
  if (launchWanted && !launchAllowedForHome)
111
114
  warnings.push('launch_skipped_non_user_home');
112
- const launchRequested = launchWanted && launchAllowedForHome;
115
+ if (launchWanted && installUnderTempDir)
116
+ warnings.push('launch_skipped_temp_install');
117
+ const launchRequested = launchWanted && launchAllowedForHome && !installUnderTempDir;
118
+ if (launchRequested) {
119
+ const preferredPosition = await seedMenuBarPreferredPosition(env);
120
+ if (preferredPosition.ok)
121
+ actions.push('seeded SKS menu bar preferred position');
122
+ else
123
+ warnings.push(preferredPosition.warning);
124
+ }
113
125
  const launch = launchRequested && launchctl
114
126
  ? await launchWithLaunchctl({ launchctl, open, appPath, executablePath, launchAgentPath })
115
127
  : {
@@ -173,6 +185,60 @@ export async function installSksMenuBar(opts = {}) {
173
185
  async function fallbackTool(candidate) {
174
186
  return await exists(candidate).then((ok) => ok ? candidate : null).catch(() => null);
175
187
  }
188
+ async function seedMenuBarPreferredPosition(env) {
189
+ const defaults = env.SKS_MENUBAR_DEFAULTS || await which('defaults').catch(() => null) || await fallbackTool('/usr/bin/defaults');
190
+ if (!defaults)
191
+ return { ok: false, warning: 'defaults_missing_for_menubar_position_seed' };
192
+ // macOS stores status-item ordering hints in Control Center prefs keyed by
193
+ // autosaveName. Seeding this keeps SKS right of the notch-overflow zone.
194
+ const writes = [
195
+ ['write', CONTROL_CENTER_DOMAIN, `NSStatusItem Preferred Position ${LABEL}`, '-int', String(CONTROL_CENTER_PREFERRED_POSITION)],
196
+ ['write', CONTROL_CENTER_DOMAIN, `NSStatusItem Visible ${LABEL}`, '-bool', 'true'],
197
+ ['write', CONTROL_CENTER_DOMAIN, `NSStatusItem VisibleCC ${LABEL}`, '-bool', 'true']
198
+ ];
199
+ for (const args of writes) {
200
+ const result = await runProcess(defaults, args, {
201
+ timeoutMs: 10_000,
202
+ maxOutputBytes: 16 * 1024
203
+ }).catch((err) => ({ code: 1, stdout: '', stderr: err?.message || String(err) }));
204
+ if (result.code !== 0)
205
+ return { ok: false, warning: 'menubar_position_seed_failed' };
206
+ }
207
+ return { ok: true };
208
+ }
209
+ /**
210
+ * Refuse to auto-launch a menu bar app whose executable lives under a temp dir.
211
+ * Release gates run in hermetic envs rooted at os.tmpdir()/SKS_TMP_DIR; without
212
+ * this guard a gate could spawn a real GUI status item that leaks into the
213
+ * user's live menu bar (duplicate `com.sneakoscope.sks-menubar` process). This
214
+ * is defense-in-depth behind SKS_SKIP_SKS_MENUBAR_LAUNCH and the home check.
215
+ */
216
+ export function isMenuBarInstallPathUnderTempDir(target, env = process.env) {
217
+ const resolved = path.resolve(target);
218
+ const roots = new Set();
219
+ const addRoot = (value) => {
220
+ if (!value)
221
+ return;
222
+ const abs = path.resolve(value);
223
+ roots.add(abs);
224
+ // macOS resolves TMPDIR / os.tmpdir() (/var/folders/...) through a /private symlink.
225
+ if (abs.startsWith('/var/'))
226
+ roots.add(path.resolve('/private', abs.slice(1)));
227
+ else if (abs.startsWith('/private/var/'))
228
+ roots.add(abs.replace('/private', ''));
229
+ };
230
+ addRoot(os.tmpdir());
231
+ addRoot(env.TMPDIR);
232
+ addRoot(env.SKS_TMP_DIR);
233
+ for (const root of roots) {
234
+ if (resolved === root)
235
+ return true;
236
+ const prefix = root.endsWith(path.sep) ? root : root + path.sep;
237
+ if (resolved.startsWith(prefix))
238
+ return true;
239
+ }
240
+ return false;
241
+ }
176
242
  function realUserHome() {
177
243
  try {
178
244
  const userHome = os.userInfo().homedir;
@@ -238,6 +304,8 @@ final class AppDelegate: NSObject, NSApplicationDelegate {
238
304
  func applicationDidFinishLaunching(_ notification: Notification) {
239
305
  NSApp.setActivationPolicy(.accessory)
240
306
  statusItem = NSStatusBar.system.statusItem(withLength: NSStatusItem.variableLength)
307
+ statusItem.autosaveName = "com.sneakoscope.sks-menubar"
308
+ statusItem.isVisible = true
241
309
  if let button = statusItem.button {
242
310
  configureStatusButton(button)
243
311
  }
@@ -261,7 +329,13 @@ final class AppDelegate: NSObject, NSApplicationDelegate {
261
329
  func configureStatusButton(_ button: NSStatusBarButton) {
262
330
  button.image = nil
263
331
  button.title = "SKS"
264
- button.font = NSFont.systemFont(ofSize: NSFont.systemFontSize, weight: .semibold)
332
+ let titleFont = NSFont.systemFont(ofSize: NSFont.systemFontSize, weight: .semibold)
333
+ let titleAttributes: [NSAttributedString.Key: Any] = [
334
+ .font: titleFont,
335
+ .foregroundColor: NSColor.labelColor
336
+ ]
337
+ button.font = titleFont
338
+ button.attributedTitle = NSAttributedString(string: "SKS", attributes: titleAttributes)
265
339
  button.toolTip = "SKS - Sneakoscope Codex settings"
266
340
  button.setAccessibilityLabel("SKS")
267
341
  button.setAccessibilityHelp("Open SKS menu")
@@ -357,8 +431,8 @@ function launchAgentSource(executablePath, installDir) {
357
431
  </array>
358
432
  <key>RunAtLoad</key>
359
433
  <true/>
360
- <key>KeepAlive</key>
361
- <true/>
434
+ <key>ProcessType</key>
435
+ <string>Interactive</string>
362
436
  <key>StandardOutPath</key>
363
437
  <string>${escapeXml(path.join(installDir, 'menubar.out.log'))}</string>
364
438
  <key>StandardErrorPath</key>
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 = '4.8.1';
8
+ export const PACKAGE_VERSION = '4.8.3';
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() {
@@ -25,7 +25,10 @@ export function createReleaseGateHermeticEnv(input) {
25
25
  CODEX_HOME: input.gate.isolation.codex_home === 'temp' ? codexHome : process.env.CODEX_HOME,
26
26
  XDG_CACHE_HOME: cacheHome,
27
27
  SKS_DISABLE_REAL_MODEL_CALLS: input.gate.preset.includes('real-check') ? process.env.SKS_DISABLE_REAL_MODEL_CALLS || '0' : '1',
28
- SKS_DISABLE_GLOBAL_CONFIG_MUTATION: '1'
28
+ SKS_DISABLE_GLOBAL_CONFIG_MUTATION: '1',
29
+ // Gates must never spawn a real GUI menu bar status item into the user's
30
+ // live session. Belt to the temp-path launch guard in installSksMenuBar.
31
+ SKS_SKIP_SKS_MENUBAR_LAUNCH: '1'
29
32
  }
30
33
  };
31
34
  }
@@ -1,2 +1,2 @@
1
- export const PACKAGE_VERSION = '4.8.1';
1
+ export const PACKAGE_VERSION = '4.8.3';
2
2
  //# sourceMappingURL=version.js.map
@@ -329,6 +329,9 @@ for (const script of requiredRealScripts) {
329
329
  assertGate(pkg.bin?.sks === 'dist/bin/sks.js', 'package runtime must use dist/bin/sks.js');
330
330
  assertGate(pkg.bin?.sneakoscope === 'dist/bin/sks.js', 'sneakoscope runtime must use dist/bin/sks.js');
331
331
  assertGate(!pkg.files?.includes('src'), 'package files must not include src runtime shadows');
332
+ assertGate(pkg.scripts?.['publish:prep-ignore-scripts'] === 'npm run prepublishOnly', 'publish:prep-ignore-scripts must run the prepublishOnly release gate before lifecycle-disabled publish', { script: pkg.scripts?.['publish:prep-ignore-scripts'] || null });
333
+ assertGate(String(pkg.scripts?.['publish:ignore-scripts'] || '').includes('npm run publish:prep-ignore-scripts'), 'publish:ignore-scripts must run publish:prep-ignore-scripts before npm publish --ignore-scripts', { script: pkg.scripts?.['publish:ignore-scripts'] || null });
334
+ assertGate(String(pkg.scripts?.['publish:ignore-scripts'] || '').includes('--ignore-scripts'), 'publish:ignore-scripts must keep npm lifecycle scripts disabled for the final publish', { script: pkg.scripts?.['publish:ignore-scripts'] || null });
332
335
  for (const file of requiredDocs) {
333
336
  const absolute = path.join(root, file);
334
337
  assertGate(fs.existsSync(absolute), `missing release doc: ${file}`);
@@ -13,7 +13,7 @@ import { root, assertGate, emitGate, importDist, readText, readJson } from './sk
13
13
  assertGate(!/cargo|rustc/.test(readText('src/scripts/build-dist.ts')), 'build-dist must not invoke cargo/rustc');
14
14
  assertGate(!/cargo|rustc/.test(readText('src/scripts/clean-dist.ts')), 'clean-dist must not invoke cargo/rustc');
15
15
  const pkg = readJson('package.json');
16
- for (const s of ['prepack', 'prepublishOnly', 'publish:dry', 'publish:ignore-scripts', 'publish:npm']) {
16
+ for (const s of ['prepack', 'prepublishOnly', 'publish:dry', 'publish:prep-ignore-scripts', 'publish:ignore-scripts', 'publish:npm']) {
17
17
  assertGate(!String(pkg.scripts?.[s] || '').includes('cargo'), `publish_script_compiles_rust:${s}`);
18
18
  }
19
19
  // 2) The published binary is JS; no prebuilt native artifact is shipped or required.
@@ -4,28 +4,40 @@ import path from 'node:path';
4
4
  import { installSksMenuBar } from '../core/codex-app/sks-menubar.js';
5
5
  const temp = await fs.mkdtemp(path.join(os.tmpdir(), 'sks-menubar-check-'));
6
6
  const envHomeTemp = await fs.mkdtemp(path.join(os.tmpdir(), 'sks-menubar-env-home-check-'));
7
+ const launchGuardEnv = { ...process.env, SKS_SKIP_SKS_MENUBAR_LAUNCH: '0' };
7
8
  const result = await installSksMenuBar({
8
9
  apply: true,
9
10
  launch: true,
10
11
  home: temp,
11
12
  root: temp,
12
- sksEntry: path.join(process.cwd(), 'dist', 'bin', 'sks.js')
13
+ sksEntry: path.join(process.cwd(), 'dist', 'bin', 'sks.js'),
14
+ env: launchGuardEnv
13
15
  });
14
16
  const envHomeResult = await installSksMenuBar({
15
17
  apply: true,
16
18
  launch: true,
17
19
  root: envHomeTemp,
18
20
  sksEntry: path.join(process.cwd(), 'dist', 'bin', 'sks.js'),
19
- env: { ...process.env, HOME: envHomeTemp }
21
+ env: { ...launchGuardEnv, HOME: envHomeTemp }
20
22
  });
21
23
  const executableExists = result.executable_path ? await exists(result.executable_path) : false;
22
24
  const launchAgentExists = result.launch_agent_path ? await exists(result.launch_agent_path) : false;
23
25
  const actionScriptExists = result.action_script_path ? await exists(result.action_script_path) : false;
24
26
  const generatedSourcePath = result.app_path ? path.join(path.dirname(result.app_path), 'SKSMenuBar.swift') : null;
25
27
  const generatedSource = generatedSourcePath ? await fs.readFile(generatedSourcePath, 'utf8').catch(() => '') : '';
28
+ const launchAgentSource = result.launch_agent_path ? await fs.readFile(result.launch_agent_path, 'utf8').catch(() => '') : '';
26
29
  const hasVisibleLabelSource = generatedSource.includes('NSStatusItem.variableLength')
27
30
  && generatedSource.includes('button.title = "SKS"')
31
+ && generatedSource.includes('button.attributedTitle = NSAttributedString(string: "SKS"')
32
+ && generatedSource.includes('NSColor.labelColor')
28
33
  && generatedSource.includes('button.image = nil');
34
+ // The status item must persist its user-arranged position across restarts so a
35
+ // once-dragged item does not jump back behind the notch on the next doctor --fix.
36
+ const hasAutosaveNameSource = generatedSource.includes('statusItem.autosaveName = "com.sneakoscope.sks-menubar"');
37
+ const hasExplicitVisibleSource = generatedSource.includes('statusItem.isVisible = true');
38
+ const hasNoUnconditionalKeepAlive = !launchAgentSource.includes('<key>KeepAlive</key>');
39
+ const hasInteractiveProcessType = launchAgentSource.includes('<key>ProcessType</key>')
40
+ && launchAgentSource.includes('<string>Interactive</string>');
29
41
  const expectedMenuItems = [
30
42
  'Use codex-lb',
31
43
  'Use ChatGPT OAuth',
@@ -42,6 +54,15 @@ const launchSkippedForTempHome = result.launch?.requested === false
42
54
  const launchSkippedForEnvHome = envHomeResult.launch?.requested === false
43
55
  && envHomeResult.launch?.method === 'skipped'
44
56
  && envHomeResult.warnings.includes('launch_skipped_non_user_home');
57
+ // Temp-path guard: a temp-rooted install must never request a launch, even if
58
+ // some caller forgets SKS_SKIP_SKS_MENUBAR_LAUNCH. Both fixtures live under
59
+ // os.tmpdir(), so both results must carry the temp-install skip warning.
60
+ const launchSkippedForTempInstall = result.launch?.requested === false
61
+ && result.warnings.includes('launch_skipped_temp_install')
62
+ && envHomeResult.launch?.requested === false
63
+ && envHomeResult.warnings.includes('launch_skipped_temp_install');
64
+ const preferredPositionSkippedForTempInstall = !result.actions.includes('seeded SKS menu bar preferred position')
65
+ && !envHomeResult.actions.includes('seeded SKS menu bar preferred position');
45
66
  const ok = process.platform === 'darwin'
46
67
  ? result.ok === true
47
68
  && result.status === 'installed_launch_skipped'
@@ -52,8 +73,14 @@ const ok = process.platform === 'darwin'
52
73
  && actionScriptExists
53
74
  && hasExpectedItems
54
75
  && hasVisibleLabelSource
76
+ && hasAutosaveNameSource
77
+ && hasExplicitVisibleSource
78
+ && hasNoUnconditionalKeepAlive
79
+ && hasInteractiveProcessType
55
80
  && launchSkippedForTempHome
56
81
  && launchSkippedForEnvHome
82
+ && launchSkippedForTempInstall
83
+ && preferredPositionSkippedForTempInstall
57
84
  : result.ok === true && result.status === 'unsupported_platform';
58
85
  const report = {
59
86
  schema: 'sks.sks-menubar-install-check.v1',
@@ -67,8 +94,14 @@ const report = {
67
94
  action_script_exists: actionScriptExists,
68
95
  generated_source_path: generatedSourcePath,
69
96
  has_visible_label_source: hasVisibleLabelSource,
97
+ has_autosave_name_source: hasAutosaveNameSource,
98
+ has_explicit_visible_source: hasExplicitVisibleSource,
99
+ has_no_unconditional_keepalive: hasNoUnconditionalKeepAlive,
100
+ has_interactive_process_type: hasInteractiveProcessType,
70
101
  launch_skipped_for_temp_home: launchSkippedForTempHome,
71
102
  launch_skipped_for_env_home: launchSkippedForEnvHome,
103
+ launch_skipped_for_temp_install: launchSkippedForTempInstall,
104
+ preferred_position_skipped_for_temp_install: preferredPositionSkippedForTempInstall,
72
105
  expected_menu_items: expectedMenuItems,
73
106
  missing_expected_items: missingExpectedItems,
74
107
  has_expected_items: hasExpectedItems,
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "sneakoscope",
3
3
  "displayName": "ㅅㅋㅅ",
4
- "version": "4.8.1",
4
+ "version": "4.8.3",
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",
@@ -381,7 +381,8 @@
381
381
  "release:real-check": "node ./dist/scripts/release-real-check.js",
382
382
  "release:publish": "npm run publish:ignore-scripts",
383
383
  "publish:dry": "npm run release:metadata && npm run release:version-truth && npm run publish:packlist-performance && npm run release:check:full && node ./dist/scripts/check-publish-tag.js && node ./dist/scripts/release-check-stamp.js verify && npm run release:provenance -- --publish && npm run release:dist-freshness && node ./dist/scripts/release-registry-check.js --require-unpublished && npm --cache /tmp/sks-npm-cache publish --dry-run --ignore-scripts --registry https://registry.npmjs.org/ --access public",
384
- "publish:ignore-scripts": "npm run prepublishOnly && npm --cache /tmp/sks-npm-cache publish --ignore-scripts --registry https://registry.npmjs.org/ --access public",
384
+ "publish:prep-ignore-scripts": "npm run prepublishOnly",
385
+ "publish:ignore-scripts": "npm run publish:prep-ignore-scripts && npm --cache /tmp/sks-npm-cache publish --ignore-scripts --registry https://registry.npmjs.org/ --access public",
385
386
  "publish:npm": "npm run publish:ignore-scripts",
386
387
  "publish:fast": "node -e \"console.error('publish:fast is quarantined; use publish:dry and publish:npm with the release gates.'); process.exit(1)\"",
387
388
  "prepack": "npm run build",