sneakoscope 0.6.37 → 0.6.38

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
@@ -7,7 +7,7 @@ Core value: repetition resistance. SKS records release traps, stale command surf
7
7
 
8
8
  ## AI Answer Snapshot
9
9
 
10
- Package: `sneakoscope`. CLI: `sks` or `sneakoscope`. `sks setup` prepares the project and installs Codex CLI when missing; open Codex App so first-party MCP/plugin tools reach CLI sessions.
10
+ Package: `sneakoscope`. CLI: `sks` or `sneakoscope`. Global install seeds `$HOME/.agents/skills` so Codex App can show `$sks`, `$team`, `$qa-loop`, and the other SKS dollar routes before a project is initialized. `sks setup` prepares project hooks/state and installs Codex CLI when missing; open Codex App so first-party MCP/plugin tools reach CLI sessions.
11
11
 
12
12
  ```bash
13
13
  npm i -g sneakoscope
@@ -53,7 +53,7 @@ UI/UX reads `design.md` first. If missing, `design-system-builder` creates it fr
53
53
 
54
54
  ## Codex App
55
55
 
56
- Run `sks setup` once. SKS creates hooks/skills plus `.sneakoscope/` state. Team status is mirrored to `team-live.md`, `team-transcript.jsonl`, and `sks team watch latest`.
56
+ Global install creates user-level `$` skills; run `sks setup` once inside each project to add project hooks/skills plus `.sneakoscope/` state. Team status is mirrored to `team-live.md`, `team-transcript.jsonl`, and `sks team watch latest`.
57
57
 
58
58
  Implementation/code-changing prompts default to Team orchestration: parallel analysis scouts, TriWiki refresh/validate, debate/consensus, then fresh parallel executors. Answer-only, DFix, Help, Wiki maintenance, and safety-specific routes stay lightweight.
59
59
 
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "sneakoscope",
3
3
  "displayName": "ㅅㅋㅅ",
4
- "version": "0.6.37",
4
+ "version": "0.6.38",
5
5
  "description": "Sneakoscope Codex: database-safe Codex CLI/App harness with Team, Ralph, 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
@@ -1,9 +1,10 @@
1
1
  import path from 'node:path';
2
+ import os from 'node:os';
2
3
  import fsp from 'node:fs/promises';
3
4
  import readline from 'node:readline/promises';
4
5
  import { stdin as input, stdout as output } from 'node:process';
5
6
  import { projectRoot, readJson, writeJsonAtomic, writeTextAtomic, appendJsonlBounded, nowIso, exists, ensureDir, tmpdir, packageRoot, dirSize, formatBytes, which, runProcess, PACKAGE_VERSION } from '../core/fsx.mjs';
6
- import { initProject, normalizeInstallScope, sksCommandPrefix } from '../core/init.mjs';
7
+ import { initProject, installSkills, normalizeInstallScope, sksCommandPrefix } from '../core/init.mjs';
7
8
  import { getCodexInfo, runCodexExec } from '../core/codex-adapter.mjs';
8
9
  import { createMission, loadMission, findLatestMission, missionDir, setCurrent, stateFile } from '../core/mission.mjs';
9
10
  import { buildQuestionSchema, writeQuestions } from '../core/questions.mjs';
@@ -209,6 +210,11 @@ async function postinstall() {
209
210
  else if (context7Install.status === 'codex_missing') console.log('Context7 MCP: Codex CLI missing. Install @openai/codex or set SKS_CODEX_BIN, then run `sks context7 setup --scope global` or `sks setup` in a project.');
210
211
  else if (context7Install.status === 'skipped') console.log(`Context7 MCP: skipped (${context7Install.reason}).`);
211
212
  else if (context7Install.status === 'failed') console.log(`Context7 MCP: auto setup failed. Run \`sks context7 setup --scope global\` or \`sks setup\`. ${context7Install.error || ''}`.trim());
213
+ const globalSkills = await ensureGlobalCodexSkillsDuringInstall();
214
+ if (globalSkills.status === 'installed') console.log(`Codex App global $ skills: installed in ${globalSkills.root} (${globalSkills.installed_count} skills).`);
215
+ else if (globalSkills.status === 'partial') console.log(`Codex App global $ skills: partial in ${globalSkills.root}; missing ${globalSkills.missing_skills.join(', ')}. Run \`sks doctor --fix\`.`);
216
+ else if (globalSkills.status === 'skipped') console.log(`Codex App global $ skills: skipped (${globalSkills.reason}).`);
217
+ else if (globalSkills.status === 'failed') console.log(`Codex App global $ skills: auto setup failed. Run \`sks doctor --fix\`. ${globalSkills.error || ''}`.trim());
212
218
  const appSetup = await ensureCodexAppProjectDuringInstall(installRoot, { shim });
213
219
  if (appSetup.status === 'installed') console.log(`Codex App project setup: installed in ${appSetup.root} (${appSetup.install_scope}; canonical picker skills include ${appSetup.aliases.join(', ')}).`);
214
220
  else if (appSetup.status === 'partial') console.log(`Codex App project setup: repaired with missing skill warning (${appSetup.missing_skills.join(', ')}). Run \`sks doctor --fix\`.`);
@@ -323,6 +329,20 @@ async function ensureGlobalContext7DuringInstall() {
323
329
  return { status: 'failed', error: `${add.stderr || add.stdout || 'codex mcp add failed'}`.trim() };
324
330
  }
325
331
 
332
+ async function ensureGlobalCodexSkillsDuringInstall(opts = {}) {
333
+ if (process.env.SKS_SKIP_POSTINSTALL_GLOBAL_SKILLS === '1' && !opts.force) return { status: 'skipped', reason: 'SKS_SKIP_POSTINSTALL_GLOBAL_SKILLS=1' };
334
+ const home = opts.home || process.env.HOME || os.homedir();
335
+ if (!home) return { status: 'skipped', reason: 'home directory unavailable' };
336
+ const root = globalCodexSkillsRoot(home);
337
+ try {
338
+ const install = await installSkills(home);
339
+ const skills = await checkRequiredSkills(home, root);
340
+ return { status: skills.ok ? 'installed' : 'partial', root, installed_count: install.installed_skills.length, removed_aliases: install.removed_agent_skill_aliases, missing_skills: skills.missing };
341
+ } catch (err) {
342
+ return { status: 'failed', root, error: err.message };
343
+ }
344
+ }
345
+
326
346
  async function ensureRelatedCliTools(args = []) {
327
347
  const skip = flag(args, '--skip-cli-tools') || process.env.SKS_SKIP_CLI_TOOLS === '1';
328
348
  const codex = await ensureCodexCliTool({ skip });
@@ -1046,9 +1066,15 @@ async function codexAppHelp(args = []) {
1046
1066
  const action = args[0] || 'help';
1047
1067
  if (action === 'check' || action === 'status') {
1048
1068
  const status = await codexAppIntegrationStatus();
1049
- if (flag(args, '--json')) return console.log(JSON.stringify(status, null, 2));
1069
+ const skills = await codexAppSkillReadiness();
1070
+ const readiness = { ...status, ok: status.ok && skills.ok, runtime_ok: status.ok, skills };
1071
+ if (flag(args, '--json')) return console.log(JSON.stringify(readiness, null, 2));
1050
1072
  console.log(formatCodexAppStatus(status, { includeRaw: flag(args, '--verbose') }));
1051
- if (!status.ok) process.exitCode = 1;
1073
+ console.log('');
1074
+ console.log(`Project $ skills: ${skills.project.ok ? 'ok' : `missing ${skills.project.missing.length}`} ${skills.project.root}`);
1075
+ console.log(`Global $ skills: ${skills.global.ok ? 'ok' : `missing ${skills.global.missing.length}`} ${skills.global.root}`);
1076
+ if (!skills.ok) console.log('Run: sks setup, or reinstall/repair with npm i -g sneakoscope && sks doctor --fix');
1077
+ if (!readiness.ok) process.exitCode = 1;
1052
1078
  return;
1053
1079
  }
1054
1080
  if (action === 'open') {
@@ -1059,10 +1085,15 @@ async function codexAppHelp(args = []) {
1059
1085
  return;
1060
1086
  }
1061
1087
  const status = await codexAppIntegrationStatus();
1088
+ const skills = await codexAppSkillReadiness();
1062
1089
  console.log(`ㅅㅋㅅ App Usage
1063
1090
 
1064
1091
  ${formatCodexAppStatus(status)}
1065
1092
 
1093
+ Dollar-command skills:
1094
+ Project: ${skills.project.ok ? 'ok' : `missing ${skills.project.missing.length}`} ${skills.project.root}
1095
+ Global: ${skills.global.ok ? 'ok' : `missing ${skills.global.missing.length}`} ${skills.global.root}
1096
+
1066
1097
  Run once in the project:
1067
1098
  sks setup
1068
1099
 
@@ -1619,6 +1650,9 @@ async function setup(args) {
1619
1650
  const cliTools = await ensureRelatedCliTools(args);
1620
1651
  const globalCommand = await globalSksCommand();
1621
1652
  const res = await initProject(root, { force: flag(args, '--force'), installScope, globalCommand, localOnly });
1653
+ const globalSkills = localOnly
1654
+ ? { status: 'skipped', reason: '--local-only', root: globalCodexSkillsRoot() }
1655
+ : await ensureGlobalCodexSkillsDuringInstall({ force: flag(args, '--force') });
1622
1656
  const install = await installStatus(root, installScope, { globalCommand });
1623
1657
  const versioningInfo = await versioningStatus(root);
1624
1658
  const appRuntime = await codexAppIntegrationStatus();
@@ -1632,11 +1666,13 @@ async function setup(args) {
1632
1666
  config: path.join(root, '.codex', 'config.toml'),
1633
1667
  hooks: hooksPath,
1634
1668
  skills: path.join(root, '.agents', 'skills'),
1669
+ global_skills: globalSkills.root,
1635
1670
  agents: path.join(root, '.codex', 'agents'),
1636
1671
  quick_reference: path.join(root, '.codex', 'SNEAKOSCOPE.md'),
1637
1672
  agents_rules: path.join(root, 'AGENTS.md')
1638
1673
  },
1639
1674
  codex_app_runtime: appRuntime,
1675
+ global_skills: globalSkills,
1640
1676
  created: res.created,
1641
1677
  versioning: versioningInfo,
1642
1678
  local_only: localOnly,
@@ -1651,6 +1687,7 @@ async function setup(args) {
1651
1687
  console.log(`Version: ${versioningInfo.enabled ? (versioningInfo.hook_installed ? 'auto-bump enabled' : 'auto-bump hook missing') : 'not enabled'}${versioningInfo.package_version ? ` (${versioningInfo.package_version})` : ''}`);
1652
1688
  if (localOnly) console.log('Git: local-only (.git/info/exclude; user AGENTS preserved, SKS managed block refreshed)');
1653
1689
  console.log(`Codex App: .codex/config.toml, .codex/hooks.json, .agents/skills, .codex/agents, .codex/SNEAKOSCOPE.md`);
1690
+ console.log(`Global $: ${globalSkills.status === 'installed' ? 'ok' : globalSkills.status} ${globalSkills.root || ''}`.trimEnd());
1654
1691
  console.log(`App tools: ${appRuntime.ok ? 'ok' : 'needs setup'} Codex App=${appRuntime.app.installed ? 'ok' : 'missing'} Browser Use=${appRuntime.mcp.has_browser_use ? 'ok' : 'missing'} Computer Use=${appRuntime.mcp.has_computer_use ? 'ok' : 'missing'}`);
1655
1692
  console.log(`Prompt: intent-first routing, $Answer fact-check route, $DFix ultralight design/content route, Context7 gate`);
1656
1693
  console.log(`Skills: .agents/skills`);
@@ -1706,10 +1743,12 @@ async function doctor(args) {
1706
1743
  : null;
1707
1744
  let conflictScan = await scanHarnessConflicts(root);
1708
1745
  let repairApplied = false;
1746
+ let globalSkillsRepair = null;
1709
1747
  if (flag(args, '--fix') && !conflictScan.hard_block) {
1710
1748
  const fixScope = requestedScope || 'global';
1711
1749
  const existingManifest = await readJson(path.join(root, '.sneakoscope', 'manifest.json'), null);
1712
1750
  await initProject(root, { installScope: fixScope, globalCommand: await globalSksCommand(), localOnly: flag(args, '--local-only') || Boolean(existingManifest?.git?.local_only), force: true, repair: true });
1751
+ if (!flag(args, '--local-only')) globalSkillsRepair = await ensureGlobalCodexSkillsDuringInstall({ force: true });
1713
1752
  repairApplied = true;
1714
1753
  conflictScan = await scanHarnessConflicts(root);
1715
1754
  }
@@ -1726,6 +1765,7 @@ async function doctor(args) {
1726
1765
  const context7Status = await checkContext7(root);
1727
1766
  const appRuntime = await codexAppIntegrationStatus({ codex });
1728
1767
  const skillStatus = await checkRequiredSkills(root);
1768
+ const globalSkillStatus = await checkRequiredSkills(null, globalCodexSkillsRoot());
1729
1769
  const guardStatus = await harnessGuardStatus(root);
1730
1770
  const versioningInfo = await versioningStatus(root);
1731
1771
  const codexApp = {
@@ -1733,6 +1773,7 @@ async function doctor(args) {
1733
1773
  hooks: { ok: await exists(path.join(root, '.codex', 'hooks.json')) },
1734
1774
  versioning: versioningInfo,
1735
1775
  skills: skillStatus,
1776
+ global_skills: globalSkillStatus,
1736
1777
  agents: { ok: await exists(path.join(root, '.codex', 'agents')) },
1737
1778
  quick_reference: { ok: await exists(path.join(root, '.codex', 'SNEAKOSCOPE.md')) },
1738
1779
  agents_rules: { ok: await exists(path.join(root, 'AGENTS.md')) }
@@ -1740,7 +1781,7 @@ async function doctor(args) {
1740
1781
  const result = {
1741
1782
  node: { ok: nodeOk, version: process.version }, root, codex, rust,
1742
1783
  install,
1743
- repair: { applied: repairApplied, blocked_by_other_harness: flag(args, '--fix') && conflictScan.hard_block },
1784
+ repair: { applied: repairApplied, global_skills: globalSkillsRepair, blocked_by_other_harness: flag(args, '--fix') && conflictScan.hard_block },
1744
1785
  harness_conflicts: {
1745
1786
  ok: conflictScan.ok,
1746
1787
  hard_block: conflictScan.hard_block,
@@ -1755,14 +1796,15 @@ async function doctor(args) {
1755
1796
  versioning: versioningInfo,
1756
1797
  db_guard: { ok: dbPolicyExists && dbScan.ok, policy: dbPolicyExists ? await loadDbSafetyPolicy(root) : null, scan: dbScan },
1757
1798
  hooks: { ok: await exists(path.join(root, '.codex', 'hooks.json')) },
1758
- skills: { ok: await exists(path.join(root, '.agents', 'skills')) },
1799
+ skills: skillStatus,
1800
+ global_skills: globalSkillStatus,
1759
1801
  codex_app: {
1760
1802
  ...codexApp,
1761
1803
  ok: codexApp.config.ok && codexApp.hooks.ok && codexApp.skills.ok && codexApp.agents.ok && codexApp.quick_reference.ok && codexApp.agents_rules.ok
1762
1804
  },
1763
1805
  package: { bytes: pkgBytes, human: formatBytes(pkgBytes) }, storage
1764
1806
  };
1765
- result.ready = !result.harness_conflicts.hard_block && nodeOk && Boolean(codex.bin) && install.ok && result.sneakoscope.ok && result.context7.ok && appRuntime.ok && result.harness_guard.ok && result.versioning.ok && result.db_guard.ok && result.codex_app.ok && result.skills.ok;
1807
+ result.ready = !result.harness_conflicts.hard_block && nodeOk && Boolean(codex.bin) && install.ok && result.sneakoscope.ok && result.context7.ok && appRuntime.ok && result.harness_guard.ok && result.versioning.ok && result.db_guard.ok && result.codex_app.ok && result.skills.ok && result.global_skills.ok;
1766
1808
  if (result.harness_conflicts.hard_block) process.exitCode = 1;
1767
1809
  if (flag(args, '--json')) return console.log(JSON.stringify(result, null, 2));
1768
1810
  console.log('ㅅㅋㅅ Doctor\n');
@@ -1772,6 +1814,7 @@ async function doctor(args) {
1772
1814
  console.log(`Install: ${install.ok ? 'ok' : 'missing'} ${install.scope} (${install.command_prefix})`);
1773
1815
  console.log(`Conflicts: ${result.harness_conflicts.hard_block ? 'blocked' : 'ok'} ${result.harness_conflicts.conflicts.length} finding(s)`);
1774
1816
  if (repairApplied) console.log('Repair: regenerated SKS managed files from the installed package template');
1817
+ if (globalSkillsRepair) console.log(`Global $ repair: ${globalSkillsRepair.status} ${globalSkillsRepair.root || ''}`.trimEnd());
1775
1818
  if (flag(args, '--fix') && result.harness_conflicts.hard_block) console.log('Repair: skipped because another Codex harness needs human-approved removal first');
1776
1819
  console.log(`Rust acc.: ${rust.available ? rust.version : 'optional-missing'}`);
1777
1820
  console.log(`State: ${result.sneakoscope.ok ? 'ok' : 'missing .sneakoscope'}`);
@@ -1783,6 +1826,7 @@ async function doctor(args) {
1783
1826
  console.log(`Hooks: ${result.hooks.ok ? 'ok' : 'missing .codex/hooks.json'}`);
1784
1827
  console.log(`Codex App: ${result.codex_app.ok ? 'ok' : 'missing app files'} .codex/config.toml .codex/hooks.json .agents/skills .codex/agents .codex/SNEAKOSCOPE.md`);
1785
1828
  console.log(`Skills: ${result.skills.ok ? 'ok' : `missing ${result.skills.missing.length} skill(s)`}`);
1829
+ console.log(`Global $: ${result.global_skills.ok ? 'ok' : `missing ${result.global_skills.missing.length} skill(s)`} ${result.global_skills.root}`);
1786
1830
  console.log(`Package: ${result.package.human}`);
1787
1831
  console.log(`Storage: ${storage.total_human || '0 B'}`);
1788
1832
  console.log(`Ready: ${result.ready ? 'yes' : 'no'}`);
@@ -1795,19 +1839,31 @@ async function doctor(args) {
1795
1839
  if (!result.harness_guard.ok) console.log('Harness guard failed. Run: sks setup from a real terminal, then sks guard check.');
1796
1840
  if (!result.versioning.ok) console.log('Versioning hook missing. Run: sks versioning hook, or sks doctor --fix.');
1797
1841
  if (!result.skills.ok) console.log(`Missing skills: ${result.skills.missing.join(', ')}. Run: sks setup`);
1842
+ if (!result.global_skills.ok) console.log(`Missing global $ skills: ${result.global_skills.missing.join(', ')}. Run: npm i -g sneakoscope, or sks setup from a non-local-only run.`);
1798
1843
  if (!result.ready && !flag(args, '--fix')) console.log('Run: sks doctor --fix');
1799
1844
  }
1800
1845
 
1801
- async function checkRequiredSkills(root) {
1846
+ async function checkRequiredSkills(root, skillRoot = path.join(root, '.agents', 'skills')) {
1802
1847
  const expected = Array.from(new Set([
1803
1848
  ...DOLLAR_SKILL_NAMES,
1804
1849
  ...RECOMMENDED_SKILLS
1805
1850
  ])).sort();
1806
1851
  const missing = [];
1807
1852
  for (const name of expected) {
1808
- if (!(await exists(path.join(root, '.agents', 'skills', name, 'SKILL.md')))) missing.push(name);
1853
+ if (!(await exists(path.join(skillRoot, name, 'SKILL.md')))) missing.push(name);
1809
1854
  }
1810
- return { ok: missing.length === 0, expected, missing };
1855
+ return { ok: missing.length === 0, root: skillRoot, expected, missing };
1856
+ }
1857
+
1858
+ async function codexAppSkillReadiness(root = null) {
1859
+ root ||= await projectRoot();
1860
+ const project = await checkRequiredSkills(root);
1861
+ const global = await checkRequiredSkills(null, globalCodexSkillsRoot());
1862
+ return { ok: project.ok || global.ok, project, global };
1863
+ }
1864
+
1865
+ function globalCodexSkillsRoot(home = process.env.HOME || os.homedir()) {
1866
+ return path.join(home, '.agents', 'skills');
1811
1867
  }
1812
1868
 
1813
1869
  async function init(args) {
@@ -2339,6 +2395,11 @@ async function selftest() {
2339
2395
  if (postinstallSetup.code !== 0) throw new Error(`selftest failed: postinstall setup exited ${postinstallSetup.code}: ${postinstallSetup.stderr}`);
2340
2396
  if (await exists(path.join(postinstallSetupTmp, '.agents', 'skills', 'agent-team', 'SKILL.md'))) throw new Error('selftest failed: postinstall installed deprecated agent-team fallback skill');
2341
2397
  if (!String(postinstallSetup.stdout || '').includes('Codex App project setup: installed')) throw new Error('selftest failed: postinstall did not report automatic Codex App setup');
2398
+ if (!String(postinstallSetup.stdout || '').includes('Codex App global $ skills: installed')) throw new Error('selftest failed: postinstall did not report automatic global Codex App skills');
2399
+ for (const { command } of DOLLAR_COMMANDS) {
2400
+ const skillName = command.slice(1).toLowerCase();
2401
+ if (!(await exists(path.join(postinstallSetupTmp, 'home', '.agents', 'skills', skillName, 'SKILL.md')))) throw new Error(`selftest failed: postinstall global ${command} skill not installed`);
2402
+ }
2342
2403
  const guardBlocked = await checkHarnessModification(tmp, { tool_name: 'apply_patch', command: '*** Update File: .agents/skills/team/SKILL.md\n+tamper\n' });
2343
2404
  if (guardBlocked.action !== 'block') throw new Error('selftest failed: harness guard allowed skill tampering');
2344
2405
  const setupBlocked = await checkHarnessModification(tmp, { command: 'sks setup --force' });
@@ -2454,6 +2515,11 @@ async function selftest() {
2454
2515
  const shimDir = path.join(shimTmp, 'bin');
2455
2516
  const shimResult = await ensureSksCommandDuringInstall({ force: true, pathEnv: shimDir, home: shimTmp, target: path.join(packageRoot(), 'bin', 'sks.mjs'), nodeBin: process.execPath });
2456
2517
  if (shimResult.status !== 'created' || !(await exists(path.join(shimDir, process.platform === 'win32' ? 'sks.cmd' : 'sks')))) throw new Error('selftest failed: sks command shim not created');
2518
+ const globalSkillsTmp = tmpdir();
2519
+ const globalSkillsResult = await ensureGlobalCodexSkillsDuringInstall({ force: true, home: globalSkillsTmp });
2520
+ if (globalSkillsResult.status !== 'installed') throw new Error(`selftest failed: global Codex App skills not installed: ${globalSkillsResult.status}`);
2521
+ const globalSkillStatus = await checkRequiredSkills(globalSkillsTmp, path.join(globalSkillsTmp, '.agents', 'skills'));
2522
+ if (!globalSkillStatus.ok) throw new Error(`selftest failed: global Codex App skills missing: ${globalSkillStatus.missing.join(', ')}`);
2457
2523
  const codexSkillMirrorExists = await exists(path.join(tmp, '.codex', 'skills', 'research-discovery', 'SKILL.md'));
2458
2524
  if (codexSkillMirrorExists) throw new Error('selftest failed: generated .codex/skills mirror still installed');
2459
2525
  const codexAppSkillExists = await exists(path.join(tmp, '.agents', 'skills', 'research-discovery', 'SKILL.md'));
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.6.37';
8
+ export const PACKAGE_VERSION = '0.6.38';
9
9
  export const DEFAULT_PROCESS_TAIL_BYTES = 256 * 1024;
10
10
  export const DEFAULT_PROCESS_TIMEOUT_MS = 30 * 60 * 1000;
11
11
 
package/src/core/init.mjs CHANGED
@@ -83,109 +83,7 @@ function isSksManagedHook(hook) {
83
83
  return hook.type === 'command' && /\bhook\s+(?:user-prompt-submit|pre-tool|post-tool|permission-request|stop)\b/.test(command) && /\b(?:sks|sneakoscope|sks\.mjs)\b/.test(command);
84
84
  }
85
85
 
86
- const AGENTS_BLOCK = `
87
- # Sneakoscope Codex Managed Rules
88
-
89
- This repository uses Sneakoscope Codex.
90
-
91
- ## Ralph No-Question Rule
92
-
93
- Ralph may ask questions only during prepare. After decision-contract.json is sealed and Ralph run starts, the assistant must not ask the user questions, request confirmation, or present choices. Resolve using the decision ladder.
94
-
95
- ## Performance and Retention
96
-
97
- Sneakoscope Codex keeps runtime state bounded. Do not write large raw logs into prompts. Store raw outputs in files, keep only tails/summaries in JSON, and allow sks gc to remove old arenas, temp files, and stale mission logs.
98
-
99
- ## Update Check Before Work
100
-
101
- Before any substantive work, SKS hooks check whether the installed SKS package is behind the latest published package. If an update is available, ask the user to choose between updating now and skipping the update for this conversation only. If the user skips, continue the current conversation without asking again, but check again in the next conversation. If the user accepts, update SKS, rerun setup/doctor, then continue the original task.
102
-
103
- ## Project Versioning
104
-
105
- SKS manages the worker project's package version through a managed Git pre-commit hook. Every commit in a project with \`package.json\` gets a patch version bump in the same commit, with \`package-lock.json\` and \`npm-shrinkwrap.json\` kept in sync when present. The version guard uses a lock in the Git common directory so parallel workers or multiple worktrees do not reuse the same version. Check with \`sks versioning status\`; bypass only for exceptional maintenance with \`SKS_DISABLE_VERSIONING=1\`.
106
-
107
- ## Harness Self-Protection
108
-
109
- After setup, installed Sneakoscope harness control files are immutable to LLM tool edits. Do not edit \`.codex/hooks.json\`, \`.codex/config.toml\`, \`.codex/SNEAKOSCOPE.md\`, \`.agents/skills/\`, \`.codex/agents/\`, \`.sneakoscope/manifest.json\`, \`.sneakoscope/policy.json\`, \`.sneakoscope/db-safety.json\`, \`.sneakoscope/harness-guard.json\`, \`AGENTS.md\`, or \`node_modules/sneakoscope\` from the agent. SKS hooks block direct writes and SKS maintenance commands from LLM tool calls. The only automatic exception is the Sneakoscope engine source repository itself, detected by \`package.json\` name \`sneakoscope\` plus \`bin/sks.mjs\` and \`src/core/*\`.
110
-
111
- ## Other Harness Conflict Gate
112
-
113
- Before installing, setting up, or repairing SKS, check for incompatible Codex harnesses such as OMX or DCodex. OMX is a hard blocker. If another harness is found, SKS setup/doctor must stop and show \`sks conflicts prompt\`. Cleanup requires explicit human approval and should be performed by an LLM operator in Codex App using GPT-5.5 high mode. If the human does not approve cleanup, SKS cannot be installed in that environment.
114
-
115
- ## Honest Mode Completion
116
-
117
- Do not stop at a plan when implementation was requested. Continue until the stated goal is actually handled or a hard blocker is explicitly reported. Before the final answer, run SKS Honest Mode: re-check the goal, evidence, tests, risk boundaries, and remaining gaps. The final answer must be honest about what passed, what was not verified, and whether the goal is genuinely complete.
118
-
119
- ## Evaluation
120
-
121
- When a task claims performance, token, accuracy, context-compression, or workflow improvement, produce evidence with sks eval run or sks eval compare. Do not claim live model accuracy unless the run used an explicitly scored task dataset; otherwise call it an evidence-weighted accuracy proxy.
122
-
123
- ## Research Mode
124
-
125
- When the user asks for research, new discoveries, hypothesis generation, frontier exploration, or deep investigation, use SKS Research Mode. Research must produce candidate insights, falsification attempts, a novelty ledger, and testable next experiments. Do not present a breakthrough claim unless it is explicitly marked with evidence, confidence, falsifiers, and uncertainty.
126
-
127
- ## AutoResearch Loop
128
-
129
- For open-ended improvement, discovery, prompt, evaluation, ranking, SEO/GEO, or workflow-quality tasks, use the SKS AutoResearch loop inspired by iterative hypothesis search: define a program, choose a metric, run the smallest useful experiment, keep or discard the result, record the ledger, falsify the best candidate, and repeat within budget. Do not claim an improvement without evidence.
130
-
131
- ## Team Orchestration
132
-
133
- When the user invokes Team mode, \`$Team\`, or a general implementation/code-changing prompt, default to Codex multi-agent orchestration: parallel analysis scouts, TriWiki refresh, read-only debate, then a fresh parallel executor team. Answer, DFix, Help, Wiki maintenance, and safety-specific routes are lightweight exceptions. TriWiki is not one-time setup: before each stage read \`.sneakoscope/wiki/context-pack.json\`; hydrate low-trust claims from source/hash/RGBA anchors; refresh or pack after scout, debate, consensus, implementation, review, or blockers; validate before handoff/final claims. Role counts like \`executor:5 reviewer:2 user:1\` create exactly N \`analysis_scout_N\`, N debate participants, and a separate N-person \`executor_N\` team. Scouts split repo, docs, tests, API, DB-risk, UX-friction, and implementation surfaces. Debate is read-only and includes stubborn users, capable executors, strict reviewers, and planners. Close debate agents once the objective is sealed, refresh/validate TriWiki, then launch disjoint executor slices in parallel. The parent orchestrates, integrates, verifies, and records useful scout/debate/handoff/review lines with \`sks team event <mission-id|latest> --agent <name> --phase <phase> --message "..."\`. Do not let subagents bypass SKS hooks or destructive DB safety.
134
-
135
- ## Code-Changing Execution
136
-
137
- For code-changing work, first surface SKS route, guard, write scopes, and verification. General implementation prompts route to Team by default, then split independent write scopes across worker subagents. The parent assigns ownership, keeps urgent blockers local, integrates, and verifies. Subagents must not bypass DB safety, harness guard, Ralph, Context7, H-Proof, or Honest Mode.
138
-
139
- ## Design Execution
140
-
141
- When creating or editing UI/UX, always look for \`design.md\` first. If it does not exist, use the local design-system-builder skill to create it from \`docs/Design-Sys-Prompt.md\`; that flow must use the Codex plan tool to remove ambiguity and recommend a default font choice before implementation. When \`design.md\` exists, use the design-ui-editor skill plus the local design artifact skill, follow the design guidelines exactly, and verify the rendered result. Any image, logo, raster, or bitmap asset generation must use the Codex \`imagegen\` skill.
142
-
143
- ## Prompt Optimization Pipeline
144
-
145
- Every prompt starts with intent classification. Answer-only uses TriWiki/web/Context7 when useful plus Honest Mode, then direct reply. DFix uses its ultralight task list. General execution/code-changing prompts default to Team unless a more specific safety/research/DB/GX route applies. Extract intent, target surface, constraints, acceptance criteria, risks, and the smallest safe path before acting.
146
-
147
- ## Intent Inference And Clarification
148
-
149
- The default stance is strong intent inference: when the user speaks roughly, infer the likely goal from local context, repo conventions, current route state, and prior artifacts. Do not ask lazy discovery questions. However, ambiguity removal is mandatory when a missing answer can change the target, scope, safety boundary, data risk, irreversible operation, user-facing behavior, or acceptance criteria. Ask the smallest set of concrete questions, then seal the inferred contract before implementation.
150
-
151
- ## Reasoning Effort Routing
152
-
153
- Use temporary route-specific reasoning only. Simple fulfillment uses medium, any logical/safety/orchestration work uses high, and research or experiment loops use xhigh. Do not persist profile changes; return to the default or user-selected profile when the route gate passes.
154
-
155
- ## Context7 MCP Requirement
156
-
157
- When work depends on external libraries, frameworks, APIs, MCPs, package managers, DB SDKs, or generated documentation, use Context7 MCP before completion. The required evidence flow is resolve-library-id followed by query-docs (or legacy get-library-docs). SKS PostToolUse records these calls in context7-evidence.jsonl, and Stop hooks block required routes until evidence exists. Pure command discovery and simple $DFix copy/color/spacing edits do not require Context7.
158
-
159
- ## LLM Wiki Continuity
160
-
161
- TriWiki is the context-tracking SSOT for long-running missions, Team handoffs, and context-pressure recovery. It is anchor-first, not lossy-summary-first. Use relevant TriWiki context at every work stage, not only at the beginning: read the pack before a stage, hydrate low-trust claims during the stage, refresh after new findings or artifact changes, and validate before handoffs/final claims. Important claims, visual nodes, policy facts, and evidence pointers should receive deterministic RGBA wiki coordinates: R maps to domain angle, G maps to layer radius through sine, B maps to phase angle, and A maps to concentration/confidence. Use those trigonometric coordinates to preserve stable retrieval anchors across turns. Selected claims may be pasted as text, but non-selected claims must remain hydratable through id, hash, source path, and RGBA coordinate anchors instead of disappearing from the workflow. Refresh with \`sks wiki refresh\` or \`sks wiki pack\` and validate with \`sks wiki validate .sneakoscope/wiki/context-pack.json\` whenever route continuity, stage context, source evidence, or handoff context changes.
162
-
163
- ## Dollar Commands
164
-
165
- Codex App users may invoke local SKS modes with skill-style dollar commands. \`$DFix\` is the fast design/content fix route for small changes such as text color, copy edits, label changes, spacing tweaks, or translating visible text. \`$DFix\` bypasses the general SKS prompt pipeline and runs an ultralight task-list path: list the exact micro-edits, inspect only needed files, apply only those edits, and run only cheap verification when useful.
166
-
167
- ## Codex App Usage
168
-
169
- When this repository is opened in Codex App, use the local Sneakoscope files as the app control surface. Read \`.codex/SNEAKOSCOPE.md\` for the quick reference, load project skills from \`.agents/skills\` when applicable, and use the generated \`.codex/hooks.json\` hooks for DB safety, no-question Ralph runs, retention, and done-gate enforcement.
170
-
171
- ## Source Priority
172
-
173
- 1. Current code, tests, config
174
- 2. decision-contract.json
175
- 3. vgraph.json
176
- 4. beta.json
177
- 5. GX render/snapshot metadata
178
- 6. LLM Wiki coordinate index
179
- 7. model knowledge only if explicitly allowed
180
-
181
- ## Database Safety
182
-
183
- Sneakoscope Codex treats database access as high risk. Destructive database operations are never allowed: DROP, TRUNCATE, mass DELETE/UPDATE, reset, push, repair, project deletion, branch reset/merge/delete, RLS disabling, broad grants/revokes, and any operation that could erase or overwrite data. Supabase/Postgres MCP should be read-only and project-scoped by default. Live database writes must not be performed through direct execute_sql; schema changes must be migration-file based and allowed only for local or preview/branch environments by the sealed contract.
184
-
185
- ## Done Means
186
-
187
- A task is not done until relevant tests are run or justified, unsupported critical claims are zero, database safety violations are zero, visual/wiki drift is low or explicitly accepted, and final output includes evidence.
188
- `;
86
+ const AGENTS_BLOCK = "\n# Sneakoscope Codex Managed Rules\n\nThis repository uses Sneakoscope Codex.\n\n## Core Rules\n\n- Ralph asks only during prepare. After `decision-contract.json` is sealed, do not ask the user; resolve with the decision ladder.\n- Keep runtime state bounded: raw logs go to files, prompts get tails/summaries, and `sks gc` may prune stale artifacts.\n- Before substantive work, SKS checks npm for a newer package. If newer, ask update-now vs skip-for-this-conversation.\n- Versioning is managed by the SKS pre-commit hook; check `sks versioning status`. Bypass only with `SKS_DISABLE_VERSIONING=1`.\n- Installed harness files are immutable to LLM edits: `.codex/*`, `.agents/skills/`, `.codex/agents/`, `.sneakoscope/*policy*.json`, `AGENTS.md`, and `node_modules/sneakoscope`. The Sneakoscope engine source repo is the only automatic exception.\n- OMX/DCodex conflicts block setup/doctor. Show `sks conflicts prompt`; cleanup requires explicit human approval.\n- Do not stop at a plan when implementation was requested. Finish, verify, or report the hard blocker.\n\n## Routes\n\n- General execution/code-changing prompts default to `$Team`: analysis scouts, TriWiki refresh/validate, read-only debate, consensus, fresh executor team, review, integration, Honest Mode.\n- `$DFix` is only for tiny design/content edits and bypasses the main pipeline. `$Answer`, `$Help`, and `$Wiki` stay lightweight.\n- For code work, surface route/guard/write scopes first, split independent worker scopes when available, and keep parent-owned integration and verification.\n- Design work reads `design.md`; if missing, use `design-system-builder`. Image/logo/raster assets use `imagegen`.\n- Research, AutoResearch, performance, token, accuracy, SEO/GEO, or workflow-improvement claims need experiment/eval evidence. Do not claim live model accuracy without a scored dataset.\n\n## Evidence And Context\n\n- Context7 is required for external libraries, APIs, MCPs, package managers, DB SDKs, and generated docs: resolve-library-id then query-docs.\n- TriWiki is the context-tracking SSOT for long-running missions, Team handoffs, and context-pressure recovery. Read `.sneakoscope/wiki/context-pack.json` before each stage, hydrate low-trust claims from source/hash/RGBA anchors, refresh after findings or artifact changes, and validate before handoffs/final claims.\n- Source priority: current code/tests/config, decision contract, vgraph, beta, GX render/snapshot metadata, LLM Wiki coordinate index, then model knowledge only if allowed.\n- Honest Mode before final: re-check goal, evidence, tests, risk boundaries, and remaining gaps. Say what passed and what was not verified.\n\n## Safety\n\n- Database access is high risk. Use read-only inspection by default; live data mutation is out of scope unless a sealed contract allows local or branch-only migration files.\n- Task completion requires relevant tests or justification, zero unsupported critical claims, accepted visual/wiki drift, and final evidence.\n\n## Codex App\n\nUse `.codex/SNEAKOSCOPE.md`, generated `.agents/skills`, `.codex/hooks.json`, and SKS dollar commands (`$sks`, `$team`, `$dfix`, `$qa-loop`, etc.) as the app control surface.\n";
189
87
 
190
88
  export async function initProject(root, opts = {}) {
191
89
  const created = [];
@@ -666,7 +564,7 @@ Hooks route Codex App events through SKS guards; status messages show checks, wh
666
564
  `;
667
565
  }
668
566
 
669
- async function installSkills(root) {
567
+ export async function installSkills(root) {
670
568
  const skills = {
671
569
  'dfix': `---\nname: dfix\ndescription: Ultralight fast design/content fix mode for $DFix or $dfix requests and inferred simple edits such as text color, copy, labels, spacing, or translation.\n---\n\nYou are running SKS DFix mode.\n\nPurpose:\n- Bypass the general SKS prompt pipeline for small design/content requests.\n- Convert the request into a tiny task list, then execute only those tasks.\n- Use for requests like 글자 색 바꿔줘, 내용을 영어로 바꿔줘, button label 수정, spacing 조정, copy replacement, simple style tweaks.\n\nUltralight loop:\n1. List the exact micro-edits implied by the request.\n2. Inspect only the files needed to locate those targets.\n3. Apply only the listed edits.\n4. Run only cheap verification when useful.\n5. Final response should be short: what changed and any verification.\n\nRules:\n- Do not enter the general prompt pipeline, mission workflow, ambiguity gate, TriWiki refresh, Context7 routing, subagent orchestration, Ralph, Research, eval, or broad redesign.\n- Do not ask for more requirements when the target can be inferred from local context.\n- For UI/UX micro-edits, read \`design.md\` when present and preserve the existing design system and component patterns.\n- If \`design.md\` is missing and the change requires design judgment instead of a tiny mechanical edit, reroute to design-system-builder before editing.\n- Use imagegen for any image/logo/raster asset.\n`,
672
570
  'answer': `---\nname: answer\ndescription: Answer-only research route for ordinary questions that should not start implementation.\n---\n\nUse when the user is asking for an explanation, comparison, status, facts, source-backed research, or documentation guidance rather than asking you to change files or run work.\n\nEvidence flow:\n1. Use current repo files and TriWiki first when the answer is project-local.\n2. Hydrate low-trust wiki claims from source paths before relying on them.\n3. Use web search for current, external, or uncertain facts when browsing is available or the user asks for latest/source-backed information.\n4. Use Context7 resolve-library-id plus query-docs when the answer depends on package, API, framework, SDK, MCP, or generated documentation behavior.\n5. End with Honest Mode fact-checking: separate verified facts, source-backed inferences, and uncertainty.\n\nRules:\n- Do not create route mission state, ambiguity-gate questions, subagents, Team handoffs, Ralph, Research loops, eval loops, or file edits.\n- If the prompt turns out to request implementation, state the reroute and use the proper execution pipeline.\n`,
@@ -710,9 +608,11 @@ async function installSkills(root) {
710
608
  await writeTextAtomic(path.join(dir, 'SKILL.md'), `${skillContent.trim()}\n`);
711
609
  await writeSkillMetadata(dir, name);
712
610
  }
611
+ const skillNames = Object.keys(skills);
713
612
  return {
714
- removed_agent_skill_aliases: await removeGeneratedAgentSkillAliases(root, Object.keys(skills)),
715
- removed_codex_skill_mirrors: await removeGeneratedCodexSkillMirrors(root, Object.keys(skills))
613
+ installed_skills: skillNames,
614
+ removed_agent_skill_aliases: await removeGeneratedAgentSkillAliases(root, skillNames),
615
+ removed_codex_skill_mirrors: await removeGeneratedCodexSkillMirrors(root, skillNames)
716
616
  };
717
617
  }
718
618