sneakoscope 0.7.1 → 0.7.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.
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "sneakoscope",
3
3
  "displayName": "ㅅㅋㅅ",
4
- "version": "0.7.1",
4
+ "version": "0.7.2",
5
5
  "description": "Sneakoscope Codex: database-safe Codex CLI/App harness with Team, Goal, AutoResearch, TriWiki, and Honest Mode.",
6
6
  "type": "module",
7
7
  "homepage": "https://github.com/mandarange/Sneakoscope-Codex#readme",
package/src/cli/main.mjs CHANGED
@@ -253,19 +253,16 @@ async function postinstall() {
253
253
  else if (globalSkills.status === 'partial') console.log(`Codex App global $ skills: partial in ${globalSkills.root}; missing ${globalSkills.missing_skills.join(', ')}. Run \`sks doctor --fix\`.`);
254
254
  else if (globalSkills.status === 'skipped') console.log(`Codex App global $ skills: skipped (${globalSkills.reason}).`);
255
255
  else if (globalSkills.status === 'failed') console.log(`Codex App global $ skills: auto setup failed. Run \`sks doctor --fix\`. ${globalSkills.error || ''}`.trim());
256
- if (process.env.SKS_POSTINSTALL_BOOTSTRAP === '1' || await shouldOfferPostinstallBootstrap(installRoot)) {
257
- const answer = (await askPostinstallQuestion('Run SKS bootstrap for this project now? [Y/n] ')).trim();
258
- const runNow = process.env.SKS_POSTINSTALL_BOOTSTRAP === '1'
259
- || answer === ''
260
- || /^(y|yes|예|네|응)$/i.test(answer);
261
- if (runNow) {
262
- await bootstrap(['--from-postinstall']);
263
- return;
264
- }
256
+ const bootstrapDecision = await postinstallBootstrapDecision(installRoot);
257
+ if (bootstrapDecision.run) {
258
+ console.log(`SKS bootstrap: ${bootstrapDecision.reason}.`);
259
+ await runPostinstallBootstrap(installRoot);
260
+ return;
265
261
  }
266
262
  console.log('\nNext:');
267
263
  console.log(' sks bootstrap');
268
- console.log('\nThis initializes the current project, installs SKS Codex App skills, verifies Codex App/Context7 readiness, and checks warp/runtime dependencies.');
264
+ console.log(`\nSKS bootstrap was not run automatically: ${bootstrapDecision.reason}.`);
265
+ console.log('This initializes the current project, installs SKS Codex App skills, verifies Codex App/Context7 readiness, and checks warp/runtime dependencies.');
269
266
  console.log('Dependency repair: sks deps check; sks deps install warp');
270
267
  console.log('Open runtime after readiness is green: sks\n');
271
268
  }
@@ -295,9 +292,23 @@ function shouldAskPostinstallQuestion() {
295
292
  return Boolean(input.isTTY && output.isTTY && process.env.CI !== 'true' && process.env.SKS_POSTINSTALL_NO_PROMPT !== '1');
296
293
  }
297
294
 
298
- async function shouldOfferPostinstallBootstrap(root) {
299
- if (process.env.SKS_POSTINSTALL_NO_BOOTSTRAP === '1') return false;
300
- return shouldAskPostinstallQuestion() && await isProjectSetupCandidate(path.resolve(root || process.cwd()));
295
+ async function postinstallBootstrapDecision(root) {
296
+ if (process.env.SKS_POSTINSTALL_NO_BOOTSTRAP === '1') return { run: false, reason: 'SKS_POSTINSTALL_NO_BOOTSTRAP=1' };
297
+ if (process.env.SKS_POSTINSTALL_BOOTSTRAP === '0') return { run: false, reason: 'SKS_POSTINSTALL_BOOTSTRAP=0' };
298
+ const candidate = await isProjectSetupCandidate(path.resolve(root || process.cwd()));
299
+ if (!candidate && process.env.SKS_POSTINSTALL_BOOTSTRAP !== '1') return { run: false, reason: 'no project marker found in install cwd' };
300
+ if (process.env.SKS_POSTINSTALL_BOOTSTRAP === '1') return { run: true, reason: 'forced by SKS_POSTINSTALL_BOOTSTRAP=1' };
301
+ return { run: true, reason: 'auto-running sks setup --bootstrap --install-scope global --force' };
302
+ }
303
+
304
+ async function runPostinstallBootstrap(root) {
305
+ const previousCwd = process.cwd();
306
+ process.chdir(path.resolve(root || previousCwd));
307
+ try {
308
+ await bootstrap(['--from-postinstall', '--install-scope', 'global', '--force']);
309
+ } finally {
310
+ process.chdir(previousCwd);
311
+ }
301
312
  }
302
313
 
303
314
  async function askPostinstallQuestion(question) {
@@ -2097,25 +2108,29 @@ async function selftest() {
2097
2108
  if (postinstallConflictPrompt.code !== 0 || !String(postinstallConflictPrompt.stdout || '').includes('Goal: completely remove the conflicting Codex harnesses')) throw new Error('selftest failed: interactive postinstall prompt did not print cleanup prompt');
2098
2109
  const postinstallSetupTmp = tmpdir();
2099
2110
  await writeJsonAtomic(path.join(postinstallSetupTmp, 'package.json'), { name: 'postinstall-setup-smoke', version: '0.0.0' });
2100
- const postinstallSetup = await runProcess(process.execPath, [path.join(packageRoot(), 'bin', 'sks.mjs'), 'postinstall'], { cwd: postinstallSetupTmp, env: { INIT_CWD: postinstallSetupTmp, HOME: path.join(postinstallSetupTmp, 'home'), SKS_SKIP_POSTINSTALL_SHIM: '1', SKS_SKIP_POSTINSTALL_CONTEXT7: '1' }, timeoutMs: 15000, maxOutputBytes: 128 * 1024 });
2111
+ const postinstallSetup = await runProcess(process.execPath, [path.join(packageRoot(), 'bin', 'sks.mjs'), 'postinstall'], { cwd: postinstallSetupTmp, env: { INIT_CWD: postinstallSetupTmp, HOME: path.join(postinstallSetupTmp, 'home'), SKS_SKIP_POSTINSTALL_SHIM: '1', SKS_SKIP_POSTINSTALL_CONTEXT7: '1', SKS_SKIP_CLI_TOOLS: '1' }, timeoutMs: 30000, maxOutputBytes: 256 * 1024 });
2101
2112
  if (postinstallSetup.code !== 0) throw new Error(`selftest failed: postinstall setup exited ${postinstallSetup.code}: ${postinstallSetup.stderr}`);
2102
2113
  if (await exists(path.join(postinstallSetupTmp, '.agents', 'skills', 'agent-team', 'SKILL.md'))) throw new Error('selftest failed: postinstall installed deprecated agent-team fallback skill');
2103
- if (!String(postinstallSetup.stdout || '').includes('Next:') || !String(postinstallSetup.stdout || '').includes('sks bootstrap')) throw new Error('selftest failed: postinstall did not print bootstrap next step');
2104
- if (await exists(path.join(postinstallSetupTmp, '.codex', 'hooks.json'))) throw new Error('selftest failed: postinstall mutated project before bootstrap approval');
2114
+ if (!String(postinstallSetup.stdout || '').includes('SKS bootstrap: auto-running sks setup --bootstrap --install-scope global --force') || !String(postinstallSetup.stdout || '').includes('SKS Ready')) throw new Error('selftest failed: postinstall did not auto-run global forced bootstrap');
2115
+ if (!(await exists(path.join(postinstallSetupTmp, '.codex', 'hooks.json')))) throw new Error('selftest failed: postinstall did not create project hooks during automatic bootstrap');
2105
2116
  if (!String(postinstallSetup.stdout || '').includes('Codex App global $ skills: installed')) throw new Error('selftest failed: postinstall did not report automatic global Codex App skills');
2117
+ const postinstallSetupManifest = await readJson(path.join(postinstallSetupTmp, '.sneakoscope', 'manifest.json'));
2118
+ if (postinstallSetupManifest.installation?.scope !== 'global') throw new Error('selftest failed: postinstall automatic bootstrap did not use global install scope');
2119
+ for (const rel of ['.agents/skills/team/SKILL.md', '.codex/config.toml', '.codex/hooks.json', '.sneakoscope/harness-guard.json', '.codex/SNEAKOSCOPE.md', 'AGENTS.md', '.gitignore']) {
2120
+ if (!(await exists(path.join(postinstallSetupTmp, rel)))) throw new Error(`selftest failed: automatic postinstall bootstrap did not create ${rel}`);
2121
+ }
2122
+ const postinstallSetupGitignore = await safeReadText(path.join(postinstallSetupTmp, '.gitignore'));
2123
+ if (!postinstallSetupGitignore.includes('.sneakoscope/') || !postinstallSetupGitignore.includes('.codex/') || !postinstallSetupGitignore.includes('.agents/') || !postinstallSetupGitignore.includes('AGENTS.md')) throw new Error('selftest failed: automatic postinstall bootstrap did not ignore SKS generated files');
2106
2124
  for (const { command } of DOLLAR_COMMANDS) {
2107
2125
  const skillName = command.slice(1).toLowerCase();
2108
2126
  if (!(await exists(path.join(postinstallSetupTmp, 'home', '.agents', 'skills', skillName, 'SKILL.md')))) throw new Error(`selftest failed: postinstall global ${command} skill not installed`);
2109
2127
  }
2110
- const postinstallBootstrapTmp = tmpdir();
2111
- await writeJsonAtomic(path.join(postinstallBootstrapTmp, 'package.json'), { name: 'postinstall-bootstrap-smoke', version: '0.0.0' });
2112
- const postinstallBootstrap = await runProcess(process.execPath, [path.join(packageRoot(), 'bin', 'sks.mjs'), 'postinstall'], { cwd: postinstallBootstrapTmp, input: 'y\n', env: { INIT_CWD: postinstallBootstrapTmp, HOME: path.join(postinstallBootstrapTmp, 'home'), SKS_SKIP_POSTINSTALL_SHIM: '1', SKS_SKIP_POSTINSTALL_CONTEXT7: '1', SKS_SKIP_POSTINSTALL_GLOBAL_SKILLS: '1', SKS_SKIP_CLI_TOOLS: '1', SKS_POSTINSTALL_PROMPT: '1' }, timeoutMs: 30000, maxOutputBytes: 256 * 1024 });
2113
- if (postinstallBootstrap.code !== 0 || !String(postinstallBootstrap.stdout || '').includes('SKS Ready')) throw new Error(`selftest failed: approved postinstall bootstrap did not run: ${postinstallBootstrap.stderr}`);
2114
- for (const rel of ['.agents/skills/team/SKILL.md', '.codex/config.toml', '.codex/hooks.json', '.sneakoscope/harness-guard.json', '.codex/SNEAKOSCOPE.md', 'AGENTS.md', '.gitignore']) {
2115
- if (!(await exists(path.join(postinstallBootstrapTmp, rel)))) throw new Error(`selftest failed: bootstrap did not create ${rel}`);
2116
- }
2117
- const postinstallBootstrapGitignore = await safeReadText(path.join(postinstallBootstrapTmp, '.gitignore'));
2118
- if (!postinstallBootstrapGitignore.includes('.sneakoscope/') || !postinstallBootstrapGitignore.includes('.codex/') || !postinstallBootstrapGitignore.includes('.agents/') || !postinstallBootstrapGitignore.includes('AGENTS.md')) throw new Error('selftest failed: bootstrap did not ignore SKS generated files');
2128
+ const oldNoBootstrap = process.env.SKS_POSTINSTALL_NO_BOOTSTRAP;
2129
+ process.env.SKS_POSTINSTALL_NO_BOOTSTRAP = '1';
2130
+ const noBootstrapDecision = await postinstallBootstrapDecision(postinstallSetupTmp);
2131
+ if (oldNoBootstrap === undefined) delete process.env.SKS_POSTINSTALL_NO_BOOTSTRAP;
2132
+ else process.env.SKS_POSTINSTALL_NO_BOOTSTRAP = oldNoBootstrap;
2133
+ if (noBootstrapDecision.run || noBootstrapDecision.reason !== 'SKS_POSTINSTALL_NO_BOOTSTRAP=1') throw new Error('selftest failed: postinstall bootstrap opt-out decision');
2119
2134
  const bootstrapJsonTmp = tmpdir();
2120
2135
  await writeJsonAtomic(path.join(bootstrapJsonTmp, 'package.json'), { name: 'bootstrap-json-smoke', version: '0.0.0' });
2121
2136
  const bootstrapJson = await runProcess(process.execPath, [path.join(packageRoot(), 'bin', 'sks.mjs'), 'bootstrap', '--json'], { cwd: bootstrapJsonTmp, env: { HOME: path.join(bootstrapJsonTmp, 'home'), SKS_SKIP_POSTINSTALL_GLOBAL_SKILLS: '1', SKS_SKIP_CLI_TOOLS: '1' }, timeoutMs: 30000, maxOutputBytes: 256 * 1024 });
package/src/core/fsx.mjs 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
 
8
- export const PACKAGE_VERSION = '0.7.1';
8
+ export const PACKAGE_VERSION = '0.7.2';
9
9
  export const DEFAULT_PROCESS_TAIL_BYTES = 256 * 1024;
10
10
  export const DEFAULT_PROCESS_TIMEOUT_MS = 30 * 60 * 1000;
11
11