sneakoscope 0.6.60 → 0.6.62

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
@@ -2,7 +2,7 @@
2
2
 
3
3
  ![](https://github.com/mandarange/Sneakoscope-Codex/raw/dev/docs/assets/sneakoscope-codex-logo.png)
4
4
 
5
- Codex CLI/App harness for `$` routes, Team/Ralph/QA/Research, Context7, Honest Mode, DB safety, TriWiki, Codex App skills, and release readiness.
5
+ Codex CLI/App harness for `$` routes, cmux-native CLI workspaces, Team/Ralph/QA/Research, Context7, Honest Mode, DB safety, TriWiki, Codex App skills, and release readiness.
6
6
 
7
7
  Install: `npm i -g sneakoscope && sks bootstrap`
8
8
  Fallback: `npx -y -p sneakoscope sks bootstrap`
@@ -19,6 +19,7 @@ Sneakoscope (`sks`, displayed as `ㅅㅋㅅ`) wraps Codex with a repeatable cont
19
19
  | --- | --- |
20
20
  | Codex App commands | Installs generated skills so `$Team`, `$DFix`, `$QA-LOOP`, `$Ralph`, `$DB`, `$Wiki`, `$Help`, and related routes are discoverable in prompt workflows. |
21
21
  | CLI commands | Provides `sks commands`, `sks dollar-commands`, `sks usage <topic>`, bootstrap, setup, doctor, deps, selftest, wiki, team, QA, Ralph, DB, and GX commands. |
22
+ | cmux runtime | Opens Codex CLI through `sks`/`sks cmux`, exposes one-shot full-access high mode with `sks --mad --high`, and opens Team missions with cmux multi-line agent lanes when cmux is available. |
22
23
  | Team orchestration | Routes substantial code work through ambiguity removal, scouts, TriWiki refresh, debate, consensus, concrete runtime task graph/inboxes, implementation, review, integration, reflection, and Honest Mode. |
23
24
  | Ralph | Seals a decision contract up front, then continues without more user questions by using the agreed decision ladder. |
24
25
  | QA loop | Dogfoods UI/API behavior with safety boundaries, evidence capture, safe remediation, and focused rechecks. |
@@ -60,6 +61,8 @@ sks usage install
60
61
  sks usage team
61
62
  sks usage qa-loop
62
63
  sks usage codex-app
64
+ sks cmux check
65
+ sks --mad --high
63
66
  sks setup --install-scope project
64
67
  sks wiki refresh
65
68
  sks wiki validate .sneakoscope/wiki/context-pack.json
@@ -111,6 +114,7 @@ This runs repo audit, changelog check, syntax packcheck, mock selftest, sizechec
111
114
  - Node.js `>=20.11`
112
115
  - npm
113
116
  - Codex CLI/App for app-facing workflows
117
+ - cmux for the CLI-first runtime (`sks deps install cmux`)
114
118
  - Context7 MCP for current-docs-gated routes
115
119
 
116
120
  ## License
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "sneakoscope",
3
3
  "displayName": "ㅅㅋㅅ",
4
- "version": "0.6.60",
4
+ "version": "0.6.62",
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",
@@ -57,7 +57,7 @@
57
57
  "harness",
58
58
  "codex-cli",
59
59
  "codex-app",
60
- "tmux",
60
+ "cmux",
61
61
  "auto-review",
62
62
  "browser-use",
63
63
  "computer-use",
package/src/cli/main.mjs CHANGED
@@ -30,8 +30,8 @@ import { context7Evidence, evaluateStop, recordContext7Evidence, recordSubagentE
30
30
  import { TEAM_DECOMPOSITION_ARTIFACT, TEAM_GRAPH_ARTIFACT, TEAM_INBOX_DIR, TEAM_RUNTIME_TASKS_ARTIFACT, teamRuntimePlanMetadata, teamRuntimeRequiredArtifacts, validateTeamRuntimeArtifacts, writeTeamRuntimeArtifacts } from '../core/team-dag.mjs';
31
31
  import { appendTeamEvent, formatRoleCounts, initTeamLive, normalizeTeamSpec, parseTeamSpecArgs, parseTeamSpecText, readTeamDashboard, readTeamLive, readTeamTranscriptTail } from '../core/team-live.mjs';
32
32
  import { CODEX_APP_DOCS_URL, codexAppIntegrationStatus, formatCodexAppStatus } from '../core/codex-app.mjs';
33
- import { buildTmuxLaunchPlan, defaultTmuxSessionName, formatTmuxBanner, launchTmuxUi, platformTmuxInstallHint, runTmuxStatus, sanitizeTmuxSessionName, tmuxAvailable } from '../core/tmux-ui.mjs';
34
- import { autoReviewProfileName, autoReviewStatus, autoReviewSummary, enableAutoReview, disableAutoReview } from '../core/auto-review.mjs';
33
+ import { buildCmuxLaunchPlan, defaultCmuxWorkspaceName, formatCmuxBanner, launchCmuxTeamView, launchCmuxUi, platformCmuxInstallHint, runCmuxStatus, sanitizeCmuxWorkspaceName, cmuxAvailable } from '../core/cmux-ui.mjs';
34
+ import { autoReviewProfileName, autoReviewStatus, autoReviewSummary, enableAutoReview, disableAutoReview, enableMadHighProfile, madHighProfileName } from '../core/auto-review.mjs';
35
35
 
36
36
  const flag = (args, name) => args.includes(name);
37
37
  const promptOf = (args) => args.filter((x) => !String(x).startsWith('--')).join(' ').trim();
@@ -48,15 +48,16 @@ function installScopeFromArgs(args = [], fallback = 'global') {
48
48
  }
49
49
 
50
50
  export async function main(args) {
51
+ if (isMadHighLaunch(args)) return madHighCommand(args);
51
52
  if (isAutoReviewFlag(args[0])) return autoReviewCommand('start', args.slice(1));
52
53
  const [cmd, sub, ...rest] = args;
53
54
  const tail = sub === undefined ? [] : [sub, ...rest];
54
- if (!cmd) return shouldLaunchTmuxUi() ? tmuxCommand('start', []) : help();
55
+ if (!cmd) return shouldLaunchCmuxUi() ? cmuxCommand('start', []) : help();
55
56
  if (cmd === '--help' || cmd === '-h') return help();
56
57
  if (cmd === '--version' || cmd === '-v' || cmd === 'version') return version();
57
58
  if (cmd === 'postinstall') return postinstall();
58
59
  if (cmd === 'wizard' || cmd === 'ui') return wizard(tail);
59
- if (cmd === 'tmux') return String(sub || '').startsWith('--') ? tmuxCommand('start', tail) : tmuxCommand(sub, rest);
60
+ if (cmd === 'cmux') return String(sub || '').startsWith('--') ? cmuxCommand('start', tail) : cmuxCommand(sub, rest);
60
61
  if (cmd === 'auto-review' || cmd === 'autoreview') return autoReviewCommand(sub, rest);
61
62
  if (cmd === 'update-check') return updateCheck(tail);
62
63
  if (cmd === 'help') return help(tail);
@@ -113,12 +114,13 @@ Usage:
113
114
  sks usage [${USAGE_TOPICS}]
114
115
  sks quickstart
115
116
  sks bootstrap [--install-scope global|project] [--local-only] [--json]
116
- sks deps check|install [tmux|codex|context7|all] [--yes] [--json]
117
+ sks deps check|install [cmux|codex|context7|all] [--yes] [--json]
117
118
  sks codex-app
119
+ sks --mad --high
118
120
  sks auto-review status|enable|start [--high]
119
121
  sks --Auto-review [--high]
120
- sks tmux [--session name] [--no-attach]
121
- sks tmux status [--once]
122
+ sks cmux [--workspace name]
123
+ sks cmux status [--once]
122
124
  sks dollar-commands [--json]
123
125
  sks dfix
124
126
  sks qa-loop prepare "target"
@@ -190,14 +192,18 @@ function shouldShowWizard() {
190
192
  return Boolean(input.isTTY && output.isTTY && process.env.SKS_NO_WIZARD !== '1' && process.env.CI !== 'true');
191
193
  }
192
194
 
193
- function shouldLaunchTmuxUi() {
194
- return Boolean(input.isTTY && output.isTTY && process.env.SKS_NO_TMUX !== '1' && process.env.CI !== 'true');
195
+ function shouldLaunchCmuxUi() {
196
+ return Boolean(input.isTTY && output.isTTY && process.env.SKS_NO_CMUX !== '1' && process.env.CI !== 'true');
195
197
  }
196
198
 
197
199
  function isAutoReviewFlag(value) {
198
200
  return /^--?auto[-_]?review$/i.test(String(value || ''));
199
201
  }
200
202
 
203
+ function isMadHighLaunch(args = []) {
204
+ return /^--(?:mad|MAD|mad-sks)$/i.test(String(args[0] || ''));
205
+ }
206
+
201
207
  async function postinstall() {
202
208
  const installRoot = path.resolve(process.env.INIT_CWD || process.cwd());
203
209
  const conflictScan = await scanHarnessConflicts(installRoot);
@@ -235,8 +241,8 @@ async function postinstall() {
235
241
  }
236
242
  console.log('\nNext:');
237
243
  console.log(' sks bootstrap');
238
- console.log('\nThis initializes the current project, installs SKS Codex App skills, verifies Codex App/Context7 readiness, and checks tmux/runtime dependencies.');
239
- console.log('Dependency repair: sks deps check; sks deps install tmux');
244
+ console.log('\nThis initializes the current project, installs SKS Codex App skills, verifies Codex App/Context7 readiness, and checks cmux/runtime dependencies.');
245
+ console.log('Dependency repair: sks deps check; sks deps install cmux');
240
246
  console.log('Open runtime after readiness is green: sks\n');
241
247
  }
242
248
 
@@ -366,14 +372,14 @@ async function ensureGlobalCodexSkillsDuringInstall(opts = {}) {
366
372
  async function ensureRelatedCliTools(args = []) {
367
373
  const skip = flag(args, '--skip-cli-tools') || process.env.SKS_SKIP_CLI_TOOLS === '1';
368
374
  const codex = await ensureCodexCliTool({ skip });
369
- const tmux = await tmuxAvailable().catch((err) => ({ ok: false, version: null, error: err.message }));
375
+ const cmux = await cmuxAvailable().catch((err) => ({ ok: false, version: null, error: err.message }));
370
376
  return {
371
377
  codex,
372
- tmux: {
373
- ok: Boolean(tmux.ok),
374
- version: tmux.version || null,
375
- install_hint: tmux.ok ? null : platformTmuxInstallHint(),
376
- error: tmux.error || null
378
+ cmux: {
379
+ ok: Boolean(cmux.ok),
380
+ version: cmux.version || null,
381
+ install_hint: cmux.ok ? null : platformCmuxInstallHint(),
382
+ error: cmux.error || null
377
383
  }
378
384
  };
379
385
  }
@@ -1005,24 +1011,24 @@ function readNumberOption(args, name, fallback) {
1005
1011
  return Number.isFinite(value) && value > 0 ? value : fallback;
1006
1012
  }
1007
1013
 
1008
- async function tmuxCommand(sub = 'start', args = []) {
1014
+ async function cmuxCommand(sub = 'start', args = []) {
1009
1015
  const action = sub || 'start';
1010
1016
  if (action === 'status' || action === 'banner') {
1011
1017
  if (flag(args, '--json')) {
1012
1018
  const status = await codexAppIntegrationStatus();
1013
1019
  return console.log(JSON.stringify(status, null, 2));
1014
1020
  }
1015
- await runTmuxStatus(action === 'banner' ? ['--once', ...args] : args);
1021
+ await runCmuxStatus(action === 'banner' ? ['--once', ...args] : args);
1016
1022
  return;
1017
1023
  }
1018
1024
  if (action === 'check') {
1019
1025
  const root = await projectRoot();
1020
- const plan = await buildTmuxLaunchPlan({ root, session: readOption(args, '--session', null) });
1026
+ const plan = await buildCmuxLaunchPlan({ root, session: readOption(args, '--session', null) });
1021
1027
  if (flag(args, '--json')) return console.log(JSON.stringify(plan, null, 2));
1022
- console.log(formatTmuxBanner(plan.app));
1028
+ console.log(formatCmuxBanner(plan.app));
1023
1029
  console.log('');
1024
- console.log(`tmux: ${plan.tmux.ok ? 'ok' : 'missing'} ${plan.tmux.version || ''}`.trim());
1025
- console.log(`Session: ${plan.session}`);
1030
+ console.log(`cmux: ${plan.cmux.ok ? 'ok' : 'missing'} ${plan.cmux.version || ''}`.trim());
1031
+ console.log(`Workspace: ${plan.workspace}`);
1026
1032
  console.log(`Project: ${plan.root}`);
1027
1033
  console.log(`Ready: ${plan.ready ? 'yes' : 'no'}`);
1028
1034
  if (!plan.ready) {
@@ -1032,11 +1038,21 @@ async function tmuxCommand(sub = 'start', args = []) {
1032
1038
  }
1033
1039
  return;
1034
1040
  }
1035
- if (['start', 'attach', 'connect', 'open'].includes(action)) return launchTmuxUi(args);
1036
- console.error('Usage: sks tmux [check|status|banner] [--session name] [--no-attach]');
1041
+ if (['start', 'attach', 'connect', 'open'].includes(action)) return launchCmuxUi(args);
1042
+ console.error('Usage: sks cmux [check|status|banner] [--workspace name]');
1037
1043
  process.exitCode = 1;
1038
1044
  }
1039
1045
 
1046
+ async function madHighCommand(args = []) {
1047
+ const cleanArgs = args.filter((arg) => !['--mad', '--MAD', '--mad-sks', '--high'].includes(arg));
1048
+ const profile = await enableMadHighProfile();
1049
+ if (flag(args, '--json')) return console.log(JSON.stringify(profile, null, 2));
1050
+ console.log(`SKS MAD high profile ready: ${madHighProfileName()}`);
1051
+ console.log('Scope: explicit cmux launch only; normal SKS/DB safety returns after this command.');
1052
+ const workspace = readOption(cleanArgs, '--workspace', readOption(cleanArgs, '--session', `sks-mad-${defaultCmuxWorkspaceName(process.cwd())}`));
1053
+ return launchCmuxUi([...cleanArgs, '--workspace', workspace], { codexArgs: ['--profile', profile.profile_name] });
1054
+ }
1055
+
1040
1056
  async function deps(sub = 'check', args = []) {
1041
1057
  const action = sub || 'check';
1042
1058
  if (action === 'check' || action === 'status') {
@@ -1048,7 +1064,7 @@ async function deps(sub = 'check', args = []) {
1048
1064
  return;
1049
1065
  }
1050
1066
  if (action === 'install') return depsInstall(args);
1051
- console.error('Usage: sks deps check|install [tmux|codex|context7|all] [--yes] [--json]');
1067
+ console.error('Usage: sks deps check|install [cmux|codex|context7|all] [--yes] [--json]');
1052
1068
  process.exitCode = 1;
1053
1069
  }
1054
1070
 
@@ -1058,7 +1074,7 @@ async function depsStatus(root = null, opts = {}) {
1058
1074
  const codex = opts.codex || await getCodexInfo().catch(() => ({}));
1059
1075
  const app = opts.codexApp || await codexAppIntegrationStatus({ codex });
1060
1076
  const context7 = opts.context7 || await checkContext7(root);
1061
- const tmux = opts.tmux || await tmuxAvailable().catch((err) => ({ ok: false, version: null, error: err.message }));
1077
+ const cmux = opts.cmux || await cmuxAvailable().catch((err) => ({ ok: false, version: null, error: err.message }));
1062
1078
  const brew = process.platform === 'darwin' ? await which('brew').catch(() => null) : null;
1063
1079
  const globalBin = await discoverGlobalSksCommand();
1064
1080
  const npmPrefix = npmBin ? await runProcess(npmBin, ['prefix', '-g'], { timeoutMs: 8000, maxOutputBytes: 4096 }).catch(() => null) : null;
@@ -1066,10 +1082,10 @@ async function depsStatus(root = null, opts = {}) {
1066
1082
  const npmPrefixDir = npmPrefix?.code === 0 ? npmPrefix.stdout.trim().split(/\r?\n/).pop() : null;
1067
1083
  const npmBinDir = npmPrefixDir ? (process.platform === 'win32' ? npmPrefixDir : path.join(npmPrefixDir, 'bin')) : null;
1068
1084
  const nodeOk = Number(process.versions.node.split('.')[0]) >= 20;
1069
- const homebrewNeeded = process.platform === 'darwin' && !tmux.ok;
1085
+ const homebrewNeeded = process.platform === 'darwin' && !cmux.ok;
1070
1086
  return {
1071
1087
  root,
1072
- ready: Boolean(nodeOk && npmBin && globalBin && codex.bin && app.ok && context7.ok && tmux.ok),
1088
+ ready: Boolean(nodeOk && npmBin && globalBin && codex.bin && context7.ok && cmux.ok),
1073
1089
  node: { ok: nodeOk, version: process.version },
1074
1090
  npm: { ok: Boolean(npmBin), bin: npmBin, global_bin_dir: npmBinDir, global_bin_on_path: npmBinDir ? pathText.split(path.delimiter).includes(npmBinDir) : null },
1075
1091
  sneakoscope: { ok: Boolean(globalBin), bin: globalBin },
@@ -1078,13 +1094,13 @@ async function depsStatus(root = null, opts = {}) {
1078
1094
  context7,
1079
1095
  browser_use: { ok: app.mcp.has_browser_use, cache: app.plugins.browser_use_cache },
1080
1096
  computer_use: { ok: app.mcp.has_computer_use, cache: app.plugins.computer_use_cache },
1081
- tmux: { ok: Boolean(tmux.ok), version: tmux.version || null, install_hint: tmux.ok ? null : platformTmuxInstallHint(), error: tmux.error || null },
1082
- homebrew: process.platform === 'darwin' ? { ok: Boolean(brew), bin: brew, required_for_tmux_install: homebrewNeeded } : { ok: null, bin: null, required_for_tmux_install: false },
1083
- next_actions: depsNextActions({ npmBin, globalBin, codex, app, context7, tmux, brew, nodeOk })
1097
+ cmux: { ok: Boolean(cmux.ok), version: cmux.version || null, install_hint: cmux.ok ? null : platformCmuxInstallHint(), error: cmux.error || null },
1098
+ homebrew: process.platform === 'darwin' ? { ok: Boolean(brew), bin: brew, required_for_cmux_install: homebrewNeeded } : { ok: null, bin: null, required_for_cmux_install: false },
1099
+ next_actions: depsNextActions({ npmBin, globalBin, codex, app, context7, cmux, brew, nodeOk })
1084
1100
  };
1085
1101
  }
1086
1102
 
1087
- function depsNextActions({ npmBin, globalBin, codex, app, context7, tmux, brew, nodeOk }) {
1103
+ function depsNextActions({ npmBin, globalBin, codex, app, context7, cmux, brew, nodeOk }) {
1088
1104
  const out = [];
1089
1105
  if (!nodeOk) out.push('Install Node.js 20.11+.');
1090
1106
  if (!npmBin) out.push('Install npm or use a Node.js distribution that includes npm.');
@@ -1092,7 +1108,7 @@ function depsNextActions({ npmBin, globalBin, codex, app, context7, tmux, brew,
1092
1108
  if (!codex.bin) out.push('Run: sks deps install codex');
1093
1109
  if (!context7.ok) out.push('Run: sks deps install context7');
1094
1110
  if (!app.ok) out.push('Run: sks codex-app check');
1095
- if (!tmux.ok) out.push(process.platform === 'darwin' && !brew ? 'Install Homebrew, then run: sks deps install tmux' : 'Run: sks deps install tmux');
1111
+ if (!cmux.ok) out.push(process.platform === 'darwin' && !brew ? 'Install Homebrew, then run: sks deps install cmux' : 'Run: sks deps install cmux');
1096
1112
  return out;
1097
1113
  }
1098
1114
 
@@ -1107,7 +1123,7 @@ function printDepsStatus(status) {
1107
1123
  console.log(`Context7: ${status.context7.ok ? 'ok' : 'missing'}`);
1108
1124
  console.log(`Browser Use: ${status.browser_use.ok ? 'ok' : 'missing'}`);
1109
1125
  console.log(`Computer Use:${status.computer_use.ok ? ' ok' : ' missing'}`);
1110
- console.log(`tmux: ${status.tmux.ok ? 'ok' : 'missing'} ${status.tmux.version || ''}`.trimEnd());
1126
+ console.log(`cmux: ${status.cmux.ok ? 'ok' : 'missing'} ${status.cmux.version || ''}`.trimEnd());
1111
1127
  if (process.platform === 'darwin') console.log(`Homebrew: ${status.homebrew.ok ? 'ok' : 'missing'} ${status.homebrew.bin || ''}`.trimEnd());
1112
1128
  console.log(`Ready: ${status.ready ? 'true' : 'false'}`);
1113
1129
  if (status.next_actions.length) {
@@ -1119,11 +1135,11 @@ function printDepsStatus(status) {
1119
1135
  async function depsInstall(args = []) {
1120
1136
  const root = await projectRoot();
1121
1137
  const target = positionalArgs(args)[0] || 'all';
1122
- const wants = target === 'all' ? ['codex', 'context7', 'tmux'] : [target];
1138
+ const wants = target === 'all' ? ['codex', 'context7', 'cmux'] : [target];
1123
1139
  const actions = [];
1124
1140
  if (wants.includes('codex')) actions.push(await installCodexDependency(args));
1125
1141
  if (wants.includes('context7')) actions.push(await installContext7Dependency(root));
1126
- if (wants.includes('tmux')) actions.push(await installTmuxDependency(args));
1142
+ if (wants.includes('cmux')) actions.push(await installCmuxDependency(args));
1127
1143
  const status = await depsStatus(root);
1128
1144
  const result = { target, actions, status };
1129
1145
  if (flag(args, '--json')) return console.log(JSON.stringify(result, null, 2));
@@ -1147,18 +1163,22 @@ async function installContext7Dependency(root) {
1147
1163
  return { target: 'context7', status: changed ? 'project_configured' : 'already_configured', command: 'sks context7 check' };
1148
1164
  }
1149
1165
 
1150
- async function installTmuxDependency(args = []) {
1151
- const before = await tmuxAvailable().catch(() => ({ ok: false }));
1152
- if (before.ok) return { target: 'tmux', status: 'present', version: before.version || null };
1166
+ async function installCmuxDependency(args = []) {
1167
+ const before = await cmuxAvailable().catch(() => ({ ok: false }));
1168
+ if (before.ok) return { target: 'cmux', status: 'present', version: before.version || null };
1153
1169
  if (process.platform === 'darwin') {
1154
1170
  const brew = await which('brew').catch(() => null);
1155
- if (!brew) return { target: 'tmux', status: 'homebrew_missing', command: '/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)" && brew install tmux' };
1156
- if (flag(args, '--dry-run')) return { target: 'tmux', status: 'dry_run', command: `${brew} install tmux` };
1157
- if (!await confirmInstall(`Install tmux with Homebrew (${brew} install tmux)?`, args)) return { target: 'tmux', status: 'needs_approval', command: 'brew install tmux' };
1158
- const run = await runProcess(brew, ['install', 'tmux'], { timeoutMs: 180000, maxOutputBytes: 128 * 1024 });
1159
- return { target: 'tmux', status: run.code === 0 ? 'installed' : 'failed', command: 'brew install tmux', code: run.code, error: run.code === 0 ? null : `${run.stderr || run.stdout || 'brew install tmux failed'}`.trim() };
1171
+ const command = 'brew tap manaflow-ai/cmux && brew install --cask cmux';
1172
+ if (!brew) return { target: 'cmux', status: 'homebrew_missing', command: `/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)" && ${command}` };
1173
+ if (flag(args, '--dry-run')) return { target: 'cmux', status: 'dry_run', command };
1174
+ if (!await confirmInstall(`Install cmux with Homebrew (${command})?`, args)) return { target: 'cmux', status: 'needs_approval', command };
1175
+ const tap = await runProcess(brew, ['tap', 'manaflow-ai/cmux'], { timeoutMs: 180000, maxOutputBytes: 128 * 1024 });
1176
+ const run = tap.code === 0
1177
+ ? await runProcess(brew, ['install', '--cask', 'cmux'], { timeoutMs: 180000, maxOutputBytes: 128 * 1024 })
1178
+ : tap;
1179
+ return { target: 'cmux', status: run.code === 0 ? 'installed' : 'failed', command, code: run.code, error: run.code === 0 ? null : `${run.stderr || run.stdout || 'brew install --cask cmux failed'}`.trim() };
1160
1180
  }
1161
- return { target: 'tmux', status: 'manual_required', command: platformTmuxInstallHint() };
1181
+ return { target: 'cmux', status: 'manual_required', command: platformCmuxInstallHint() };
1162
1182
  }
1163
1183
 
1164
1184
  async function confirmInstall(question, args = []) {
@@ -1204,8 +1224,8 @@ async function autoReviewCommand(sub = 'status', args = []) {
1204
1224
  if (flag(args, '--json')) return console.log(JSON.stringify(status, null, 2));
1205
1225
  console.log(`SKS Auto-Review enabled: ${profile}`);
1206
1226
  const sessionArg = readOption(cleanArgs, '--session', null);
1207
- const session = sessionArg || sanitizeTmuxSessionName(`${profile}-${defaultTmuxSessionName(process.cwd())}`);
1208
- return launchTmuxUi([...cleanArgs, '--session', session], { codexArgs: ['--profile', profile] });
1227
+ const session = sessionArg || sanitizeCmuxWorkspaceName(`${profile}-${defaultCmuxWorkspaceName(process.cwd())}`);
1228
+ return launchCmuxUi([...cleanArgs, '--session', session], { codexArgs: ['--profile', profile] });
1209
1229
  }
1210
1230
  console.error('Usage: sks auto-review status|enable|disable|start [--high] [--json]');
1211
1231
  console.error('Alias: sks --Auto-review [--high]');
@@ -1220,8 +1240,8 @@ First install and bootstrap this project:
1220
1240
  sks bootstrap
1221
1241
  sks
1222
1242
 
1223
- If tmux is missing:
1224
- sks deps install tmux
1243
+ If cmux is missing:
1244
+ sks deps install cmux
1225
1245
 
1226
1246
  Initialize this project for CLI and Codex App:
1227
1247
  sks setup --bootstrap
@@ -1234,7 +1254,7 @@ Open from terminal:
1234
1254
  Verify:
1235
1255
  sks deps check
1236
1256
  sks codex-app check
1237
- sks tmux check
1257
+ sks cmux check
1238
1258
  sks auto-review status
1239
1259
  sks doctor --fix
1240
1260
  sks context7 check
@@ -1288,7 +1308,7 @@ async function codexAppHelp(args = []) {
1288
1308
  'ㅅㅋㅅ Codex App', '',
1289
1309
  formatCodexAppStatus(status), '',
1290
1310
  `Skills: project=${skills.project.ok ? 'ok' : `missing ${skills.project.missing.length}`} global=${skills.global.ok ? 'ok' : `missing ${skills.global.missing.length}`}`, '',
1291
- 'Setup:', ' sks bootstrap', ' sks deps check', ' sks codex-app check', ' sks tmux check', '',
1311
+ 'Setup:', ' sks bootstrap', ' sks deps check', ' sks codex-app check', ' sks cmux check', '',
1292
1312
  'Generated files:', ' .codex/config.toml', ' .codex/hooks.json', ' .agents/skills/', ' .codex/agents/', ' .codex/SNEAKOSCOPE.md', ' AGENTS.md', '',
1293
1313
  'Prompt routes:', formatDollarCommandsCompact(' ')
1294
1314
  ].join('\n'));
@@ -1320,11 +1340,11 @@ Examples:
1320
1340
  function usage(args = []) {
1321
1341
  const topic = String(args[0] || 'overview').toLowerCase();
1322
1342
  const blocks = {
1323
- overview: ['ㅅㅋㅅ Usage', '', 'Discover:', ' sks commands', ' sks quickstart', ' sks bootstrap', ' sks deps check', ' sks codex-app check', ' sks tmux check', ' sks dollar-commands', '', `Topics: ${USAGE_TOPICS}`],
1343
+ overview: ['ㅅㅋㅅ Usage', '', 'Discover:', ' sks commands', ' sks quickstart', ' sks bootstrap', ' sks deps check', ' sks codex-app check', ' sks cmux check', ' sks dollar-commands', '', `Topics: ${USAGE_TOPICS}`],
1324
1344
  install: ['Install', '', ' npm i -g sneakoscope', ' sks bootstrap', ' sks', '', 'Fallback:', ' npx -y -p sneakoscope sks bootstrap', '', 'Project:', ' npm i -D sneakoscope', ' npx sks setup --install-scope project'],
1325
- bootstrap: ['Bootstrap', '', ' sks bootstrap', ' sks setup --bootstrap', '', 'Creates project SKS files, Codex App skills/hooks/config, state/guard files, then checks Codex App, Context7, and tmux.'],
1326
- deps: ['Dependencies', '', ' sks deps check [--json]', ' sks deps install [tmux|codex|context7|all] [--yes]', '', 'tmux on macOS uses Homebrew only after approval.'],
1327
- tmux: ['tmux', '', ' sks', ' sks tmux check', ' sks tmux status --once', ' sks deps install tmux'],
1345
+ bootstrap: ['Bootstrap', '', ' sks bootstrap', ' sks setup --bootstrap', '', 'Creates project SKS files, Codex App skills/hooks/config, state/guard files, then checks Codex App, Context7, and cmux.'],
1346
+ deps: ['Dependencies', '', ' sks deps check [--json]', ' sks deps install [cmux|codex|context7|all] [--yes]', '', 'cmux on macOS uses Homebrew only after approval.'],
1347
+ cmux: ['cmux', '', ' sks', ' sks cmux check', ' sks cmux status --once', ' sks deps install cmux'],
1328
1348
  team: ['Team', '', ' sks team "task" executor:5 reviewer:2 user:1', ' sks team watch latest', '', '$Team runs questions -> contract -> scouts -> TriWiki attention -> debate -> runtime graph/inbox -> fresh executors -> review -> cleanup -> reflection -> Honest.'],
1329
1349
  'qa-loop': ['QA-LOOP', '', ' sks qa-loop prepare "QA this app"', ' sks qa-loop answer <MISSION_ID> answers.json', ' sks qa-loop run <MISSION_ID> --max-cycles 8', '', 'Report: YYYY-MM-DD-v<version>-qa-report.md'],
1330
1350
  ralph: ['Ralph', '', ' sks ralph prepare "task"', ' sks ralph answer <MISSION_ID> answers.json', ' sks ralph run <MISSION_ID> --max-cycles 8'],
@@ -1353,13 +1373,13 @@ async function bootstrap(args = []) {
1353
1373
  const cliTools = await ensureRelatedCliTools(args);
1354
1374
  const context7Status = await checkContext7(root);
1355
1375
  const appRuntime = await codexAppIntegrationStatus({ codex: await getCodexInfo().catch(() => ({})) });
1356
- const deps = await depsStatus(root, { context7: context7Status, codexApp: appRuntime, tmux: cliTools.tmux });
1376
+ const deps = await depsStatus(root, { context7: context7Status, codexApp: appRuntime, cmux: cliTools.cmux });
1357
1377
  const install = await installStatus(root, installScope, { globalCommand });
1358
1378
  const versioningInfo = await versioningStatus(root);
1359
1379
  const skills = await checkRequiredSkills(root);
1360
1380
  const guard = await harnessGuardStatus(root);
1361
1381
  const files = await codexAppFilesStatus(root, skills, versioningInfo);
1362
- const ready = Boolean(!conflicts.hard_block && install.ok && files.ok && skills.ok && guard.ok && context7Status.ok && appRuntime.ok && deps.tmux.ok);
1382
+ const ready = Boolean(!conflicts.hard_block && install.ok && files.ok && skills.ok && guard.ok && context7Status.ok && appRuntime.ok && deps.cmux.ok);
1363
1383
  const result = {
1364
1384
  root,
1365
1385
  ready,
@@ -1370,7 +1390,7 @@ async function bootstrap(args = []) {
1370
1390
  codex_app: appRuntime,
1371
1391
  global_skills: globalSkills,
1372
1392
  context7: context7Status,
1373
- tmux: deps.tmux,
1393
+ cmux: deps.cmux,
1374
1394
  harness_guard: guard,
1375
1395
  deps,
1376
1396
  next: ready ? ['sks', '$Team implement ...', '$QA-LOOP run ...'] : deps.next_actions
@@ -1383,7 +1403,7 @@ async function bootstrap(args = []) {
1383
1403
  console.log(`Hooks: ${files.hooks.ok ? 'ok' : 'missing'}`);
1384
1404
  console.log(`Harness guard: ${guard.ok ? 'ok' : 'blocked'}`);
1385
1405
  console.log(`Context7: ${context7Status.ok ? 'ok' : 'missing'}`);
1386
- console.log(`tmux: ${deps.tmux.ok ? 'ok' : 'missing'}${deps.tmux.version ? ` ${deps.tmux.version}` : ''}`);
1406
+ console.log(`cmux: ${deps.cmux.ok ? 'ok' : 'missing'}${deps.cmux.version ? ` ${deps.cmux.version}` : ''}`);
1387
1407
  console.log(`ready: ${ready ? 'true' : 'false'}`);
1388
1408
  if (!ready) {
1389
1409
  console.log('\nNext:');
@@ -1462,7 +1482,7 @@ async function setup(args) {
1462
1482
  console.log('ㅅㅋㅅ Setup\n');
1463
1483
  console.log(`Project: ${root}`);
1464
1484
  console.log(`Install: ${install.ok ? 'ok' : 'missing'} ${install.scope} (${install.command_prefix})`);
1465
- console.log(`CLI tools: Codex ${formatCodexCliToolStatus(cliTools.codex)}; tmux ${cliTools.tmux.ok ? `ok ${cliTools.tmux.version || ''}`.trim() : 'missing'}`);
1485
+ console.log(`CLI tools: Codex ${formatCodexCliToolStatus(cliTools.codex)}; cmux ${cliTools.cmux.ok ? `ok ${cliTools.cmux.version || ''}`.trim() : 'missing'}`);
1466
1486
  console.log(`Hooks: ${path.relative(root, hooksPath)}`);
1467
1487
  console.log(`Version: ${versioningInfo.enabled ? (versioningInfo.hook_installed ? 'auto-bump enabled' : 'auto-bump hook missing') : 'not enabled'}${versioningInfo.package_version ? ` (${versioningInfo.package_version})` : ''}`);
1468
1488
  if (localOnly) console.log('Git: local-only (.git/info/exclude; user AGENTS preserved, SKS managed block refreshed)');
@@ -1474,10 +1494,10 @@ async function setup(args) {
1474
1494
  console.log(`Next: sks context7 check; sks selftest --mock; sks commands; sks dollar-commands`);
1475
1495
  if (cliTools.codex.status === 'failed') console.log(`\nCodex CLI install failed. Run manually: npm i -g @openai/codex. ${cliTools.codex.error || ''}`.trim());
1476
1496
  if (cliTools.codex.status === 'installed_not_on_path') console.log(`\nCodex CLI installed but not on PATH. ${cliTools.codex.hint}`);
1477
- if (!cliTools.tmux.ok) console.log(`\ntmux missing. Install: ${cliTools.tmux.install_hint}`);
1497
+ if (!cliTools.cmux.ok) console.log(`\ncmux missing. Install: ${cliTools.cmux.install_hint}`);
1478
1498
  if (!install.ok && install.scope === 'global') console.log('\nGlobal command missing. Run: npm i -g sneakoscope');
1479
1499
  if (!install.ok && install.scope === 'project') console.log('\nProject package missing. Run: npm i -D sneakoscope');
1480
- if (!appRuntime.ok) console.log('\nCodex App and first-party Browser Use/Computer Use tools are required for SKS tmux/QA parity. Run: sks codex-app check');
1500
+ if (!appRuntime.ok) console.log('\nCodex App and first-party Browser Use/Computer Use tools are required for SKS cmux/QA parity. Run: sks codex-app check');
1481
1501
  }
1482
1502
 
1483
1503
  function formatCodexCliToolStatus(status = {}) {
@@ -1544,7 +1564,7 @@ async function doctor(args) {
1544
1564
  const dbScan = await scanDbSafety(root).catch((err) => ({ ok: false, findings: [{ id: 'db_safety_scan_failed', severity: 'high', reason: err.message }] }));
1545
1565
  const context7Status = await checkContext7(root);
1546
1566
  const appRuntime = await codexAppIntegrationStatus({ codex });
1547
- const tmuxStatus = await tmuxAvailable().catch((err) => ({ ok: false, version: null, error: err.message }));
1567
+ const cmuxStatus = await cmuxAvailable().catch((err) => ({ ok: false, version: null, error: err.message }));
1548
1568
  const skillStatus = await checkRequiredSkills(root);
1549
1569
  const globalSkillStatus = await checkRequiredSkills(null, globalCodexSkillsRoot());
1550
1570
  const guardStatus = await harnessGuardStatus(root);
@@ -1565,7 +1585,7 @@ async function doctor(args) {
1565
1585
  sneakoscope: { ok: await exists(path.join(root, '.sneakoscope')) },
1566
1586
  context7: context7Status,
1567
1587
  codex_app_runtime: appRuntime,
1568
- runtime: { tmux: { ok: Boolean(tmuxStatus.ok), version: tmuxStatus.version || null, install_hint: tmuxStatus.ok ? null : platformTmuxInstallHint(), error: tmuxStatus.error || null } },
1588
+ runtime: { cmux: { ok: Boolean(cmuxStatus.ok), version: cmuxStatus.version || null, install_hint: cmuxStatus.ok ? null : platformCmuxInstallHint(), error: cmuxStatus.error || null } },
1569
1589
  harness_guard: guardStatus,
1570
1590
  versioning: versioningInfo,
1571
1591
  db_guard: { ok: dbPolicyExists && dbScan.ok, policy: dbPolicyExists ? await loadDbSafetyPolicy(root) : null, scan: dbScan },
@@ -1577,7 +1597,7 @@ async function doctor(args) {
1577
1597
  },
1578
1598
  package: { bytes: pkgBytes, human: formatBytes(pkgBytes) }, storage
1579
1599
  };
1580
- result.ready = !result.harness_conflicts.hard_block && nodeOk && Boolean(codex.bin) && install.ok && result.sneakoscope.ok && result.context7.ok && appRuntime.ok && result.runtime.tmux.ok && result.harness_guard.ok && result.versioning.ok && result.db_guard.ok && result.codex_app.ok && result.skills.ok && result.global_skills.ok;
1600
+ result.ready = !result.harness_conflicts.hard_block && nodeOk && Boolean(codex.bin) && install.ok && result.sneakoscope.ok && result.context7.ok && appRuntime.ok && result.runtime.cmux.ok && result.harness_guard.ok && result.versioning.ok && result.db_guard.ok && result.codex_app.ok && result.skills.ok && result.global_skills.ok;
1581
1601
  if (result.harness_conflicts.hard_block) process.exitCode = 1;
1582
1602
  if (flag(args, '--json')) return console.log(JSON.stringify(result, null, 2));
1583
1603
  console.log('ㅅㅋㅅ Doctor\n');
@@ -1593,7 +1613,7 @@ async function doctor(args) {
1593
1613
  console.log(`State: ${result.sneakoscope.ok ? 'ok' : 'missing .sneakoscope'}`);
1594
1614
  console.log(`Context7: ${result.context7.ok ? 'ok' : 'missing MCP config'} project=${result.context7.project.ok ? 'ok' : 'missing'} global=${result.context7.global.ok ? 'ok' : 'missing'}`);
1595
1615
  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'}`);
1596
- console.log(`tmux: ${result.runtime.tmux.ok ? 'ok' : 'missing'} ${result.runtime.tmux.version || ''}`.trimEnd());
1616
+ console.log(`cmux: ${result.runtime.cmux.ok ? 'ok' : 'missing'} ${result.runtime.cmux.version || ''}`.trimEnd());
1597
1617
  console.log(`Guard: ${result.harness_guard.ok ? 'ok' : 'blocked'}${result.harness_guard.source_exception ? ' source-exception' : ''}`);
1598
1618
  console.log(`Version: ${result.versioning.ok ? 'ok' : 'missing'}${result.versioning.enabled ? ` ${result.versioning.package_version || ''}` : ` ${result.versioning.reason || 'disabled'}`}`);
1599
1619
  console.log(`DB Guard: ${result.db_guard.ok ? 'ok' : 'blocked'} ${dbScan.findings?.length || 0} finding(s)`);
@@ -1610,13 +1630,13 @@ async function doctor(args) {
1610
1630
  if (result.harness_conflicts.hard_block) console.log(`\n${formatHarnessConflictReport(conflictScan)}`);
1611
1631
  if (!result.context7.ok) console.log('Context7 MCP missing. Run: sks context7 setup --scope project');
1612
1632
  if (!appRuntime.ok) console.log('Codex App or first-party MCP/plugin tools missing. Run: sks codex-app check');
1613
- if (!result.runtime.tmux.ok) console.log('tmux missing. Run: sks deps install tmux');
1633
+ if (!result.runtime.cmux.ok) console.log('cmux missing. Run: sks deps install cmux');
1614
1634
  if (!result.harness_guard.ok) console.log('Harness guard failed. Run: sks setup from a real terminal, then sks guard check.');
1615
1635
  if (!result.versioning.ok) console.log('Versioning hook missing. Run: sks versioning hook, or sks doctor --fix.');
1616
1636
  if (!result.skills.ok) console.log(`Missing skills: ${result.skills.missing.join(', ')}. Run: sks setup`);
1617
1637
  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.`);
1618
1638
  const blocked = [];
1619
- if (!result.runtime.tmux.ok) blocked.push(['tmux is missing', 'sks deps install tmux']);
1639
+ if (!result.runtime.cmux.ok) blocked.push(['cmux is missing', 'sks deps install cmux']);
1620
1640
  if (!appRuntime.ok) blocked.push(['Codex App or first-party MCP/plugin tools need setup', 'sks codex-app check']);
1621
1641
  if (blocked.length) {
1622
1642
  console.log('\nBlocked:');
@@ -2227,7 +2247,12 @@ async function selftest() {
2227
2247
  if (!bootstrapResult.project_setup?.ok || typeof bootstrapResult.ready !== 'boolean') throw new Error('selftest failed: bootstrap json did not report project setup and ready boolean');
2228
2248
  const depsCheck = await runProcess(process.execPath, [path.join(packageRoot(), 'bin', 'sks.mjs'), 'deps', 'check', '--json'], { cwd: bootstrapJsonTmp, env: { HOME: path.join(bootstrapJsonTmp, 'home') }, timeoutMs: 20000, maxOutputBytes: 256 * 1024 });
2229
2249
  const depsResult = JSON.parse(depsCheck.stdout);
2230
- if (!depsResult.node?.ok || !('tmux' in depsResult) || !('homebrew' in depsResult)) throw new Error('selftest failed: deps check json missing expected fields');
2250
+ if (!depsResult.node?.ok || !('cmux' in depsResult) || !('homebrew' in depsResult)) throw new Error('selftest failed: deps check json missing expected fields');
2251
+ const madProfilePath = path.join(tmp, 'mad-codex-config.toml');
2252
+ const madProfile = await enableMadHighProfile({ configPath: madProfilePath });
2253
+ const madProfileText = await safeReadText(madProfilePath);
2254
+ if (madProfile.profile_name !== 'sks-mad-high' || !madProfileText.includes('sandbox_mode = "danger-full-access"') || !madProfileText.includes('approval_policy = "never"') || !madProfileText.includes('model_reasoning_effort = "high"')) throw new Error('selftest failed: MAD high profile is not full-access high/fast');
2255
+ if (!isMadHighLaunch(['--mad', '--high']) || isMadHighLaunch(['db', '--mad'])) throw new Error('selftest failed: MAD high launch flag parsing is not top-level only');
2231
2256
  const guardBlocked = await checkHarnessModification(tmp, { tool_name: 'apply_patch', command: '*** Update File: .agents/skills/team/SKILL.md\n+tamper\n' });
2232
2257
  if (guardBlocked.action !== 'block') throw new Error('selftest failed: harness guard allowed skill tampering');
2233
2258
  const setupBlocked = await checkHarnessModification(tmp, { command: 'sks setup --force' });
@@ -2613,7 +2638,7 @@ async function selftest() {
2613
2638
  const codexConfigText = await safeReadText(path.join(tmp, '.codex', 'config.toml'));
2614
2639
  if (!codexConfigText.includes('multi_agent = true')) throw new Error('selftest failed: multi_agent not enabled');
2615
2640
  if (!hasContext7ConfigText(codexConfigText)) throw new Error('selftest failed: Context7 MCP not configured');
2616
- if (!codexConfigText.includes('[profiles.sks-task-medium]') || !codexConfigText.includes('[profiles.sks-logic-high]') || !codexConfigText.includes('[profiles.sks-research-xhigh]')) throw new Error('selftest failed: reasoning profiles not configured');
2641
+ if (!codexConfigText.includes('[profiles.sks-task-medium]') || !codexConfigText.includes('[profiles.sks-logic-high]') || !codexConfigText.includes('[profiles.sks-research-xhigh]') || !codexConfigText.includes('[profiles.sks-mad-high]')) throw new Error('selftest failed: reasoning profiles not configured');
2617
2642
  if (!codexConfigText.includes('[agents.analysis_scout]')) throw new Error('selftest failed: analysis_scout agent not configured');
2618
2643
  if (!codexConfigText.includes('[agents.team_consensus]')) throw new Error('selftest failed: team_consensus agent not configured');
2619
2644
  const autoReviewHome = path.join(tmp, 'auto-review-home');
@@ -2868,6 +2893,8 @@ async function selftest() {
2868
2893
  if (roleTeamPlan.roster.analysis_team.length !== 5) throw new Error('selftest failed: executor role count not reflected in analysis scout team');
2869
2894
  if (roleTeamPlan.roster.development_team.filter((agent) => agent.role === 'executor').length !== 5) throw new Error('selftest failed: executor role count not reflected in development team');
2870
2895
  if (!roleTeamPlan.roster.debate_team.some((agent) => /inconvenience/.test(agent.persona))) throw new Error('selftest failed: user friction persona missing from debate team');
2896
+ const cmuxTeam = await launchCmuxTeamView({ root: tmp, missionId: teamId, plan: roleTeamPlan, json: true });
2897
+ if (!cmuxTeam.agents?.length || !cmuxTeam.agents.some((entry) => entry.agent === 'analysis_scout_1') || !cmuxTeam.agents.every((entry) => String(entry.command || '').includes('team watch'))) throw new Error('selftest failed: Team cmux view did not expose agent live lanes');
2871
2898
  if (routeReasoning(routePrompt('$Research frontier idea'), '$Research frontier idea').effort !== 'xhigh') throw new Error('selftest failed: research reasoning not xhigh');
2872
2899
  if (routeReasoning(routePrompt('$DB migration'), '$DB migration').effort !== 'high') throw new Error('selftest failed: logical reasoning not high');
2873
2900
  if (routeReasoning(routePrompt('$DFix button label'), '$DFix button label').effort !== 'medium') throw new Error('selftest failed: simple reasoning not medium');
@@ -3514,7 +3541,7 @@ function userRequestSignal(prompt = '') {
3514
3541
  const topicRules = [
3515
3542
  ['ambiguity-questions', /모호|ambiguity|clarification|질문|답변|answers?\.json|decision-contract|추론|예측/],
3516
3543
  ['triwiki-priority-memory', /triwiki|wiki|메모리|memory|기억|우선|반복|자주|카운팅|count|frequency|weight/],
3517
- ['install-bootstrap', /bootstrap|postinstall|doctor|deps|tmux|homebrew|최초\s*설치|셋업|setup/],
3544
+ ['install-bootstrap', /bootstrap|postinstall|doctor|deps|cmux|homebrew|최초\s*설치|셋업|setup/],
3518
3545
  ['version-release', /버전|version|publish:dry|release|npm\s+pack/],
3519
3546
  ['qa-loop', /qa|e2e|검증|리포트|report/],
3520
3547
  ['team-pipeline', /team|subagent|세션|cleanup|reflection|회고|반성/],
@@ -3796,6 +3823,7 @@ async function team(args) {
3796
3823
  questions: path.join(dir, 'questions.md'),
3797
3824
  codex_agents: ['analysis_scout', 'team_consensus', 'implementation_worker', 'db_safety_reviewer', 'qa_reviewer']
3798
3825
  };
3826
+ result.cmux = await launchCmuxTeamView({ root, missionId: id, plan, promptFile: result.workflow, json: flag(args, '--json') });
3799
3827
  if (flag(args, '--json')) return console.log(JSON.stringify(result, null, 2));
3800
3828
  console.log(`Team mission created: ${id}`);
3801
3829
  console.log(`Plan: ${path.relative(root, result.plan)}`);
@@ -3805,8 +3833,10 @@ async function team(args) {
3805
3833
  console.log(`Runtime graph: ${path.relative(root, result.team_graph)}`);
3806
3834
  console.log(`Worker inbox: ${path.relative(root, result.worker_inbox_dir)}`);
3807
3835
  console.log(`Live: ${path.relative(root, result.live)}`);
3836
+ if (result.cmux.ready) console.log(`cmux: ${result.cmux.created ? 'opened' : 'ready'} ${result.cmux.agents.length} agent lane(s)`);
3837
+ else console.log(`cmux: blocked (${Array.from(new Set(result.cmux.blockers || [])).join('; ')})`);
3808
3838
  console.log(`Watch: sks team watch ${id}`);
3809
- console.log('Use $Team in Codex App to run the scout-first flow: parallel analysis scouts, TriWiki attention, debate/consensus, runtime graph/inbox handoff, then a fresh implementation team with disjoint ownership.');
3839
+ console.log('Use $Team in Codex App or the cmux lanes from this CLI flow to run scouts, debate/consensus, runtime graph/inbox handoff, then a fresh implementation team with disjoint ownership.');
3810
3840
  }
3811
3841
 
3812
3842
  function parseTeamCreateArgs(args) {
@@ -3952,6 +3982,7 @@ function buildTeamPlan(id, prompt, opts = {}) {
3952
3982
  markdown: 'team-live.md',
3953
3983
  transcript: 'team-transcript.jsonl',
3954
3984
  dashboard: 'team-dashboard.json',
3985
+ cmux: 'sks team opens a cmux workspace with one live multi-line lane per visible Team agent budget when cmux is available.',
3955
3986
  commands: [
3956
3987
  'sks team status <mission-id>',
3957
3988
  'sks team log <mission-id>',
@@ -6,6 +6,7 @@ export const AUTO_REVIEW_REVIEWER = 'guardian_subagent';
6
6
  export const LEGACY_AUTO_REVIEW_REVIEWER = 'auto_review';
7
7
  export const AUTO_REVIEW_PROFILE = 'sks-auto-review';
8
8
  export const AUTO_REVIEW_HIGH_PROFILE = 'sks-auto-review-high';
9
+ export const MAD_HIGH_PROFILE = 'sks-mad-high';
9
10
 
10
11
  export function codexHome(env = process.env) {
11
12
  return path.resolve(env.CODEX_HOME || path.join(env.HOME || os.homedir(), '.codex'));
@@ -56,6 +57,34 @@ export async function enableAutoReview(opts = {}) {
56
57
  };
57
58
  }
58
59
 
60
+ export async function enableMadHighProfile(opts = {}) {
61
+ const configPath = opts.configPath || codexConfigPath(opts.env || process.env);
62
+ await ensureDir(path.dirname(configPath));
63
+ const current = await readText(configPath, '');
64
+ let next = upsertTable(current, `profiles.${MAD_HIGH_PROFILE}`, [
65
+ `[profiles.${MAD_HIGH_PROFILE}]`,
66
+ 'model = "gpt-5.5"',
67
+ 'approval_policy = "never"',
68
+ 'sandbox_mode = "danger-full-access"',
69
+ 'model_reasoning_effort = "high"'
70
+ ].join('\n'));
71
+ if (!next.endsWith('\n')) next += '\n';
72
+ await writeTextAtomic(configPath, next);
73
+ return {
74
+ config_path: configPath,
75
+ profile_name: MAD_HIGH_PROFILE,
76
+ launch_args: ['--profile', MAD_HIGH_PROFILE],
77
+ sandbox_mode: 'danger-full-access',
78
+ approval_policy: 'never',
79
+ model_reasoning_effort: 'high',
80
+ scope: 'explicit_launch_only'
81
+ };
82
+ }
83
+
84
+ export function madHighProfileName() {
85
+ return MAD_HIGH_PROFILE;
86
+ }
87
+
59
88
  export async function disableAutoReview(opts = {}) {
60
89
  const configPath = opts.configPath || codexConfigPath(opts.env || process.env);
61
90
  const current = await readText(configPath, '');
@@ -0,0 +1,204 @@
1
+ import path from 'node:path';
2
+ import { spawnSync } from 'node:child_process';
3
+ import { exists, packageRoot, projectRoot, runProcess, sha256, which } from './fsx.mjs';
4
+ import { getCodexInfo } from './codex-adapter.mjs';
5
+ import { codexAppIntegrationStatus, formatCodexAppStatus } from './codex-app.mjs';
6
+
7
+ export const SKS_CMUX_LOGO = [
8
+ '+----------------------+',
9
+ '| ㅅㅋㅅ |',
10
+ '| SKS cmux |',
11
+ '+----------------------+'
12
+ ].join('\n');
13
+
14
+ export function sanitizeCmuxWorkspaceName(input) {
15
+ const base = String(input || 'sks').trim().replace(/[^A-Za-z0-9_.-]+/g, '-').replace(/^-+|-+$/g, '');
16
+ return (base || 'sks').slice(0, 80);
17
+ }
18
+
19
+ export function defaultCmuxWorkspaceName(root) {
20
+ const base = sanitizeCmuxWorkspaceName(path.basename(root || process.cwd()) || 'project');
21
+ const hash = sha256(path.resolve(root || process.cwd())).slice(0, 8);
22
+ return sanitizeCmuxWorkspaceName(`sks-${base}-${hash}`);
23
+ }
24
+
25
+ export function shellEscape(value) {
26
+ return `'${String(value).replace(/'/g, `'\\''`)}'`;
27
+ }
28
+
29
+ export function platformCmuxInstallHint() {
30
+ if (process.platform !== 'darwin') return 'cmux is a native macOS app; install it on macOS 14+ from https://cmux.com or https://github.com/manaflow-ai/cmux.';
31
+ return [
32
+ 'brew tap manaflow-ai/cmux && brew install --cask cmux',
33
+ 'then expose the CLI if needed:',
34
+ 'sudo ln -sf "/Applications/cmux.app/Contents/Resources/bin/cmux" /usr/local/bin/cmux'
35
+ ].join(' ');
36
+ }
37
+
38
+ export async function findCmuxBinary() {
39
+ const env = process.env.SKS_CMUX_BIN || process.env.CMUX_BIN;
40
+ if (env && await exists(env)) return env;
41
+ const onPath = await which('cmux').catch(() => null);
42
+ if (onPath) return onPath;
43
+ const appBin = '/Applications/cmux.app/Contents/Resources/bin/cmux';
44
+ if (process.platform === 'darwin' && await exists(appBin)) return appBin;
45
+ return null;
46
+ }
47
+
48
+ export async function cmuxAvailable() {
49
+ const bin = await findCmuxBinary();
50
+ if (!bin) return { ok: false, bin: null, version: null, error: 'cmux CLI not found' };
51
+ const probe = await runProcess(bin, ['list-workspaces', '--json'], { timeoutMs: 5000, maxOutputBytes: 16 * 1024 }).catch((err) => ({ code: 1, stderr: err.message, stdout: '' }));
52
+ const text = `${probe.stdout || ''}${probe.stderr || ''}`.trim();
53
+ return { ok: probe.code === 0, bin, version: text || 'cmux CLI', error: probe.code === 0 ? null : text || 'cmux workspace probe failed' };
54
+ }
55
+
56
+ export function codexLaunchCommand(root, codexBin, codexArgs = []) {
57
+ const extraArgs = Array.isArray(codexArgs) ? codexArgs : [];
58
+ return [
59
+ 'clear',
60
+ `printf '%s\\n' ${shellEscape(SKS_CMUX_LOGO)}`,
61
+ `printf '\\nProject: %s\\n' ${shellEscape(root)}`,
62
+ 'printf \'Runtime: cmux workspace for Codex CLI\\n\'',
63
+ 'printf \'Prompt: use canonical $ commands, for example $Team or $QA-LOOP\\n\\n\'',
64
+ 'sleep 1',
65
+ `exec ${[shellEscape(codexBin), ...extraArgs.map(shellEscape), '--cd', shellEscape(root)].join(' ')}`
66
+ ].join('; ');
67
+ }
68
+
69
+ export function teamAgentCommand(root, missionId, agentId, phase) {
70
+ return [
71
+ `printf '%s\\n' ${shellEscape(`${SKS_CMUX_LOGO}\n\nTeam mission: ${missionId}\nAgent: ${agentId}\nPhase: ${phase}\n`)}`,
72
+ `cd ${shellEscape(root)}`,
73
+ `node ${shellEscape(path.join(packageRoot(), 'bin', 'sks.mjs'))} team watch ${shellEscape(missionId)} --follow --lines 12`
74
+ ].join('; ');
75
+ }
76
+
77
+ export async function buildCmuxLaunchPlan(opts = {}) {
78
+ const root = path.resolve(opts.root || await projectRoot());
79
+ const workspace = sanitizeCmuxWorkspaceName(opts.workspace || opts.session || defaultCmuxWorkspaceName(root));
80
+ const sksBin = opts.sksBin || path.join(packageRoot(), 'bin', 'sks.mjs');
81
+ const codex = opts.codex || await getCodexInfo().catch(() => ({}));
82
+ const cmux = opts.cmux || await cmuxAvailable();
83
+ const app = opts.app || await codexAppIntegrationStatus({ codex });
84
+ const codexArgs = Array.isArray(opts.codexArgs) ? opts.codexArgs : [];
85
+ return {
86
+ root,
87
+ workspace,
88
+ sksBin,
89
+ codex,
90
+ cmux,
91
+ app,
92
+ codexArgs,
93
+ ready: Boolean(cmux.ok && codex.bin),
94
+ warnings: app.ok ? [] : app.guidance || [],
95
+ blockers: [
96
+ ...(!cmux.ok ? [`cmux missing. Install: ${platformCmuxInstallHint()}`] : []),
97
+ ...(!codex.bin ? ['Codex CLI missing. Install: npm i -g @openai/codex, or set SKS_CODEX_BIN.'] : [])
98
+ ]
99
+ };
100
+ }
101
+
102
+ export function formatCmuxBanner(status = null) {
103
+ const lines = [
104
+ SKS_CMUX_LOGO,
105
+ '',
106
+ 'ㅅㅋㅅ cmux runtime',
107
+ '',
108
+ 'Canonical prompt commands:',
109
+ ' $DFix $Answer $SKS $Team $QA-LOOP $Ralph $Research $AutoResearch $DB $GX $Wiki $Help',
110
+ '',
111
+ 'CLI-first runtime:',
112
+ ' sks open a cmux Codex CLI workspace',
113
+ ' sks --mad --high open one-shot MAD-SKS high reasoning workspace',
114
+ ' sks team "task" prepare Team mission and cmux multi-line agent view',
115
+ '',
116
+ 'Useful terminal commands:',
117
+ ' sks commands',
118
+ ' sks dollar-commands',
119
+ ' sks codex-app check',
120
+ ' sks doctor --fix'
121
+ ];
122
+ if (status) lines.push('', formatCodexAppStatus(status));
123
+ return lines.join('\n');
124
+ }
125
+
126
+ export async function launchCmuxUi(args = [], opts = {}) {
127
+ const rootArg = readOption(args, '--root', opts.root);
128
+ const workspaceArg = readOption(args, '--workspace', readOption(args, '--session', opts.workspace || opts.session));
129
+ const plan = await buildCmuxLaunchPlan({ ...opts, root: rootArg, workspace: workspaceArg });
130
+ if (args.includes('--json')) return { plan };
131
+ if (!plan.ready && !args.includes('--status-only')) {
132
+ console.log(formatCmuxBanner(plan.app));
133
+ console.log('\nLaunch blocked:\n');
134
+ for (const blocker of Array.from(new Set(plan.blockers))) console.log(`- ${blocker}`);
135
+ process.exitCode = 1;
136
+ return { plan };
137
+ }
138
+ if (!args.includes('--no-open')) await openCmuxApp().catch(() => null);
139
+ const command = codexLaunchCommand(plan.root, plan.codex.bin, plan.codexArgs);
140
+ const created = spawnSync(plan.cmux.bin, ['new-workspace', '--cwd', plan.root, '--command', command], { encoding: 'utf8', stdio: args.includes('--quiet') ? 'pipe' : 'inherit' });
141
+ if (created.status !== 0) {
142
+ process.exitCode = created.status || 1;
143
+ if (created.stderr) process.stderr.write(created.stderr);
144
+ return { plan };
145
+ }
146
+ if (args.includes('--no-open')) {
147
+ console.log(`SKS cmux workspace requested: ${plan.workspace}`);
148
+ }
149
+ return { plan, created: true };
150
+ }
151
+
152
+ export async function openCmuxApp() {
153
+ if (process.platform !== 'darwin') return { ok: false, reason: 'not_macos' };
154
+ const run = await runProcess('open', ['-a', 'cmux'], { timeoutMs: 5000, maxOutputBytes: 16 * 1024 }).catch((err) => ({ code: 1, stderr: err.message, stdout: '' }));
155
+ return { ok: run.code === 0, stdout: run.stdout || '', stderr: run.stderr || '' };
156
+ }
157
+
158
+ export async function launchCmuxTeamView({ root, missionId, plan = {}, promptFile = null, json = false } = {}) {
159
+ const launch = await buildCmuxLaunchPlan({ root, workspace: `sks-team-${missionId}` });
160
+ const agents = [
161
+ ...(plan.roster?.analysis_team || []),
162
+ ...(plan.roster?.debate_team || []),
163
+ ...(plan.roster?.development_team || []),
164
+ ...(plan.roster?.validation_team || [])
165
+ ];
166
+ const uniqueAgents = [];
167
+ const seen = new Set();
168
+ for (const agent of agents) {
169
+ const id = agent.id || String(agent);
170
+ if (seen.has(id)) continue;
171
+ seen.add(id);
172
+ uniqueAgents.push(id);
173
+ }
174
+ const commands = uniqueAgents.slice(0, Math.max(1, plan.agent_session_count || 3)).map((agentId, index) => ({
175
+ agent: agentId,
176
+ command: teamAgentCommand(launch.root, missionId, agentId, index === 0 ? 'analysis' : 'team', promptFile)
177
+ }));
178
+ const result = { ready: launch.ready, cmux: launch.cmux, workspace: launch.workspace, agents: commands, blockers: launch.blockers };
179
+ if (json || !launch.ready) return result;
180
+ const first = commands[0]?.command || teamAgentCommand(launch.root, missionId, 'parent_orchestrator', 'team', promptFile);
181
+ const created = spawnSync(launch.cmux.bin, ['new-workspace', '--cwd', launch.root, '--command', first], { encoding: 'utf8', stdio: 'ignore' });
182
+ result.created = created.status === 0;
183
+ for (const entry of commands.slice(1)) {
184
+ spawnSync(launch.cmux.bin, ['new-split', 'right'], { encoding: 'utf8', stdio: 'ignore' });
185
+ spawnSync(launch.cmux.bin, ['send', `${entry.command}\n`], { encoding: 'utf8', stdio: 'ignore' });
186
+ }
187
+ return result;
188
+ }
189
+
190
+ export async function runCmuxStatus(args = [], opts = {}) {
191
+ const once = args.includes('--once') || !args.includes('--watch');
192
+ do {
193
+ const app = await codexAppIntegrationStatus();
194
+ console.clear();
195
+ console.log(formatCmuxBanner(app));
196
+ if (once) return app;
197
+ await new Promise((resolve) => setTimeout(resolve, 5000));
198
+ } while (true);
199
+ }
200
+
201
+ function readOption(args, name, fallback = null) {
202
+ const i = args.indexOf(name);
203
+ return i >= 0 && args[i + 1] ? args[i + 1] : fallback;
204
+ }
@@ -118,7 +118,7 @@ export async function codexAppIntegrationStatus(opts = {}) {
118
118
  export function codexAppGuidance({ appInstalled, codex, mcpList, computerUseReady, browserUseReady }) {
119
119
  const lines = [];
120
120
  if (!appInstalled) {
121
- lines.push('Install and open Codex App first. SKS CLI blocks tmux launch until Codex App is present because first-party MCP/plugin tools are App-provisioned.');
121
+ lines.push('Install and open Codex App for first-party MCP/plugin tools. SKS cmux launch can still run with Codex CLI alone, but Browser Use and Computer Use evidence will be unavailable until Codex App is ready.');
122
122
  lines.push(`Docs: ${CODEX_APP_DOCS_URL}`);
123
123
  }
124
124
  if (!codex?.bin) lines.push('Install Codex CLI too: npm i -g @openai/codex, or set SKS_CODEX_BIN.');
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.60';
8
+ export const PACKAGE_VERSION = '0.6.62';
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
@@ -402,7 +402,13 @@ export async function initProject(root, opts = {}) {
402
402
  created.push('AGENTS.md managed block');
403
403
  }
404
404
 
405
- await writeTextAtomic(path.join(root, '.codex', 'config.toml'), `[features]\ncodex_hooks = true\nmulti_agent = true\n\n[agents]\nmax_threads = 6\nmax_depth = 1\n\n${context7ConfigToml()}\n[agents.analysis_scout]\ndescription = "Read-only SKS scout."\nconfig_file = "./agents/analysis-scout.toml"\nnickname_candidates = ["Scout", "Mapper"]\n\n[agents.team_consensus]\ndescription = "SKS planning/debate agent."\nconfig_file = "./agents/team-consensus.toml"\nnickname_candidates = ["Consensus", "Atlas"]\n\n[agents.implementation_worker]\ndescription = "SKS bounded implementation worker."\nconfig_file = "./agents/implementation-worker.toml"\nnickname_candidates = ["Builder", "Mason"]\n\n[agents.db_safety_reviewer]\ndescription = "Read-only DB safety reviewer."\nconfig_file = "./agents/db-safety-reviewer.toml"\nnickname_candidates = ["Sentinel", "Ledger"]\n\n[agents.qa_reviewer]\ndescription = "Read-only QA reviewer."\nconfig_file = "./agents/qa-reviewer.toml"\nnickname_candidates = ["Verifier", "Scout"]\n\n[profiles.sks-task-medium]\nmodel = "gpt-5.5"\napproval_policy = "on-request"\nsandbox_mode = "workspace-write"\nmodel_reasoning_effort = "medium"\n\n[profiles.sks-logic-high]\nmodel = "gpt-5.5"\napproval_policy = "on-request"\nsandbox_mode = "workspace-write"\nmodel_reasoning_effort = "high"\n\n[profiles.sks-research-xhigh]\nmodel = "gpt-5.5"\napproval_policy = "on-request"\nsandbox_mode = "workspace-write"\nmodel_reasoning_effort = "xhigh"\n\n[profiles.sks-ralph]\nmodel = "gpt-5.5"\napproval_policy = "never"\nsandbox_mode = "workspace-write"\nmodel_reasoning_effort = "high"\n\n[profiles.sks-research]\nmodel = "gpt-5.5"\napproval_policy = "never"\nsandbox_mode = "workspace-write"\nmodel_reasoning_effort = "xhigh"\n\n[profiles.sks-team]\nmodel = "gpt-5.5"\napproval_policy = "on-request"\nsandbox_mode = "workspace-write"\nmodel_reasoning_effort = "high"\n\n[profiles.sks-default]\nmodel = "gpt-5.5"\napproval_policy = "on-request"\nsandbox_mode = "workspace-write"\nmodel_reasoning_effort = "medium"\n`);
405
+ await writeTextAtomic(path.join(root, '.codex', 'config.toml'), `[features]\ncodex_hooks = true\nmulti_agent = true\n\n[agents]\nmax_threads = 6\nmax_depth = 1\n\n${context7ConfigToml()}\n[agents.analysis_scout]\ndescription = "Read-only SKS scout."\nconfig_file = "./agents/analysis-scout.toml"\nnickname_candidates = ["Scout", "Mapper"]\n\n[agents.team_consensus]\ndescription = "SKS planning/debate agent."\nconfig_file = "./agents/team-consensus.toml"\nnickname_candidates = ["Consensus", "Atlas"]\n\n[agents.implementation_worker]\ndescription = "SKS bounded implementation worker."\nconfig_file = "./agents/implementation-worker.toml"\nnickname_candidates = ["Builder", "Mason"]\n\n[agents.db_safety_reviewer]\ndescription = "Read-only DB safety reviewer."\nconfig_file = "./agents/db-safety-reviewer.toml"\nnickname_candidates = ["Sentinel", "Ledger"]\n\n[agents.qa_reviewer]\ndescription = "Read-only QA reviewer."\nconfig_file = "./agents/qa-reviewer.toml"\nnickname_candidates = ["Verifier", "Scout"]\n\n[profiles.sks-task-medium]\nmodel = "gpt-5.5"\napproval_policy = "on-request"\nsandbox_mode = "workspace-write"\nmodel_reasoning_effort = "medium"\n\n[profiles.sks-logic-high]\nmodel = "gpt-5.5"\napproval_policy = "on-request"\nsandbox_mode = "workspace-write"\nmodel_reasoning_effort = "high"\n\n[profiles.sks-research-xhigh]\nmodel = "gpt-5.5"\napproval_policy = "on-request"\nsandbox_mode = "workspace-write"\nmodel_reasoning_effort = "xhigh"\n\n[profiles.sks-ralph]\nmodel = "gpt-5.5"\napproval_policy = "never"\nsandbox_mode = "workspace-write"\nmodel_reasoning_effort = "high"\n\n[profiles.sks-research]\nmodel = "gpt-5.5"\napproval_policy = "never"\nsandbox_mode = "workspace-write"\nmodel_reasoning_effort = "xhigh"\n\n[profiles.sks-team]\nmodel = "gpt-5.5"\napproval_policy = "on-request"\nsandbox_mode = "workspace-write"\nmodel_reasoning_effort = "high"\n\n[profiles.sks-mad-high]
406
+ model = "gpt-5.5"
407
+ approval_policy = "never"
408
+ sandbox_mode = "danger-full-access"
409
+ model_reasoning_effort = "high"
410
+
411
+ [profiles.sks-default]\nmodel = "gpt-5.5"\napproval_policy = "on-request"\nsandbox_mode = "workspace-write"\nmodel_reasoning_effort = "medium"\n`);
406
412
  created.push('.codex/config.toml');
407
413
 
408
414
  await writeTextAtomic(path.join(root, '.codex', 'SNEAKOSCOPE.md'), codexAppQuickReference(installScope, hookCommandPrefix));
@@ -458,7 +464,7 @@ function codexAppQuickReference(scope, commandPrefix) {
458
464
  `Install scope: \`${scope}\``,
459
465
  `Command: \`${commandPrefix} <command>\``,
460
466
  'Files: AGENTS.md, .codex/hooks.json, .codex/config.toml, .codex/SNEAKOSCOPE.md, .agents/skills, .codex/agents, .sneakoscope/missions.',
461
- `Discover: ${commandPrefix} bootstrap; ${commandPrefix} deps check; ${commandPrefix} commands; ${commandPrefix} codex-app check; ${commandPrefix} tmux check; ${commandPrefix} dollar-commands; ${commandPrefix} pipeline status.`,
467
+ `Discover: ${commandPrefix} bootstrap; ${commandPrefix} deps check; ${commandPrefix} commands; ${commandPrefix} codex-app check; ${commandPrefix} cmux check; ${commandPrefix} dollar-commands; ${commandPrefix} pipeline status.`,
462
468
  'dollar-commands:',
463
469
  ...DOLLAR_COMMANDS.map((c) => `- \`${c.command}\`: ${c.route}`),
464
470
  `Picker skills: ${DOLLAR_COMMAND_ALIASES.map((x) => x.app_skill).join(', ')}.`,
@@ -466,7 +472,7 @@ function codexAppQuickReference(scope, commandPrefix) {
466
472
  `Full routes write reflection.md, record lessons to ${REFLECTION_MEMORY_PATH}, refresh/pack TriWiki, validate, then final-answer with a user-visible completion summary plus Honest Mode.`,
467
473
  `Context Tracking: TriWiki SSOT. Before each route phase read only the latest coordinate+voxel overlay pack at .sneakoscope/wiki/context-pack.json; coordinate-only legacy packs are invalid. Use attention.use_first for compact high-trust recall and hydrate attention.hydrate_first from source before risky/lower-trust decisions. During every stage hydrate low-trust claims from source/hash/RGBA anchors; after changes run ${commandPrefix} wiki refresh or pack; before handoff/final run ${commandPrefix} wiki validate .sneakoscope/wiki/context-pack.json.`,
468
474
  stackCurrentDocsPolicyText(commandPrefix),
469
- `Runtime: open Codex App once, then run ${commandPrefix} bootstrap, ${commandPrefix} deps check, or ${commandPrefix} deps install tmux.`,
475
+ `Runtime: open Codex App once, then run ${commandPrefix} bootstrap, ${commandPrefix} deps check, or ${commandPrefix} deps install cmux.`,
470
476
  `Guard: generated harness files are immutable outside the engine source repo; check ${commandPrefix} guard check; conflicts use ${commandPrefix} conflicts prompt with human approval.`
471
477
  ].join('\n') + '\n';
472
478
  }
@@ -304,6 +304,7 @@ async function prepareTeam(root, route, task, required) {
304
304
  markdown: 'team-live.md',
305
305
  transcript: 'team-transcript.jsonl',
306
306
  dashboard: 'team-dashboard.json',
307
+ cmux: 'CLI Team entrypoints open cmux live lanes for the visible Team agent budget when cmux is available.',
307
308
  commands: ['sks team status latest', 'sks team log latest', 'sks team tail latest', 'sks team watch latest', 'sks team event latest --agent <name> --phase <phase> --message "..."']
308
309
  },
309
310
  required_artifacts: ['team-roster.json', 'team-analysis.md', ...(fromChatImgRequired ? [FROM_CHAT_IMG_COVERAGE_ARTIFACT, FROM_CHAT_IMG_CHECKLIST_ARTIFACT, FROM_CHAT_IMG_TEMP_TRIWIKI_ARTIFACT, FROM_CHAT_IMG_QA_LOOP_ARTIFACT] : []), 'team-consensus.md', ...teamRuntimeRequiredArtifacts(), 'team-review.md', 'team-gate.json', TEAM_SESSION_CLEANUP_ARTIFACT, 'reflection.md', 'reflection-gate.json', 'team-live.md', 'team-transcript.jsonl', 'team-dashboard.json', '.sneakoscope/wiki/context-pack.json', 'context7-evidence.jsonl']
@@ -78,7 +78,7 @@ export function inferAnswersForPrompt(prompt, explicitAnswers = {}) {
78
78
  .trim();
79
79
  const version = String(text || '').match(/\bv?(\d+\.\d+\.\d+(?:[-+][0-9A-Za-z.-]+)?)\b/)?.[1] || null;
80
80
  const versionWork = /버전|version|bump|release|publish:dry|npm\s+pack/.test(lower);
81
- const installWork = /bootstrap|postinstall|doctor|deps|tmux|homebrew|first install|최초\s*설치|설치\s*ux|셋업|setup/.test(lower);
81
+ const installWork = /bootstrap|postinstall|doctor|deps|cmux|homebrew|first install|최초\s*설치|설치\s*ux|셋업|setup/.test(lower);
82
82
  const questionGateWork = /모호|ambiguity|clarification|질문|triwiki|추론|infer|predict|예측|answers?\.json|decision-contract/.test(lower);
83
83
  const prioritySignalWork = /화|짜증|답답|;;|!!|강력|기억|우선|자주|반복|카운팅|count|frequency|frequent|priority|weight/.test(lower);
84
84
  const cliSurfaceWork = /\b(cli|command|route|usage|help|sks)\b|명령|커맨드|사용법/.test(lower);
@@ -4,7 +4,7 @@ export const FROM_CHAT_IMG_CHECKLIST_ARTIFACT = 'from-chat-img-checklist.md';
4
4
  export const FROM_CHAT_IMG_TEMP_TRIWIKI_ARTIFACT = 'from-chat-img-temp-triwiki.json';
5
5
  export const FROM_CHAT_IMG_QA_LOOP_ARTIFACT = 'from-chat-img-qa-loop.json';
6
6
  export const FROM_CHAT_IMG_TEMP_TRIWIKI_SESSIONS = 5;
7
- export const USAGE_TOPICS = 'install|setup|bootstrap|deps|tmux|auto-review|team|qa-loop|ralph|research|db|codex-app|dfix|design|imagegen|dollar|context7|pipeline|reasoning|guard|conflicts|versioning|eval|hproof|gx|wiki';
7
+ export const USAGE_TOPICS = 'install|setup|bootstrap|deps|cmux|auto-review|team|qa-loop|ralph|research|db|codex-app|dfix|design|imagegen|dollar|context7|pipeline|reasoning|guard|conflicts|versioning|eval|hproof|gx|wiki';
8
8
 
9
9
  export const RECOMMENDED_MCP_SERVERS = [
10
10
  {
@@ -330,11 +330,12 @@ export const COMMAND_CATALOG = [
330
330
  { name: 'commands', usage: 'sks commands [--json]', description: 'List every user-facing command with a short description.' },
331
331
  { name: 'usage', usage: `sks usage [${USAGE_TOPICS}]`, description: 'Print copy-ready workflows for common tasks.' },
332
332
  { name: 'quickstart', usage: 'sks quickstart', description: 'Show the shortest safe setup and verification flow.' },
333
- { name: 'bootstrap', usage: 'sks bootstrap [--install-scope global|project] [--local-only] [--json]', description: 'Initialize the current project, install SKS Codex App files/skills, check Context7/Codex App/tmux, and print ready true/false.' },
334
- { name: 'deps', usage: 'sks deps check|install [tmux|codex|context7|all] [--yes]', description: 'Check or guided-install Node/npm PATH, Codex CLI/App, Context7, Browser Use, Computer Use, tmux, and Homebrew on macOS.' },
333
+ { name: 'bootstrap', usage: 'sks bootstrap [--install-scope global|project] [--local-only] [--json]', description: 'Initialize the current project, install SKS Codex App files/skills, check Context7/Codex App/cmux, and print ready true/false.' },
334
+ { name: 'deps', usage: 'sks deps check|install [cmux|codex|context7|all] [--yes]', description: 'Check or guided-install Node/npm PATH, Codex CLI/App, Context7, Browser Use, Computer Use, cmux, and Homebrew on macOS.' },
335
335
  { name: 'codex-app', usage: 'sks codex-app [check|open]', description: 'Check Codex App install and first-party MCP/plugin readiness, then show app setup files and examples.' },
336
- { name: 'tmux', usage: 'sks tmux [check|status] [--session name] [--no-attach]', description: 'Open the SKS tmux runtime with the ㅅㅋㅅ ASCII status pane and Codex CLI.' },
337
- { name: 'auto-review', usage: 'sks auto-review status|enable|start [--high] | sks --Auto-review --high', description: 'Enable Codex automatic approval review and launch SKS tmux with the auto-review profile.' },
336
+ { name: 'cmux', usage: 'sks cmux [check|status] [--workspace name]', description: 'Open the SKS cmux runtime with the ㅅㅋㅅ ASCII status pane and Codex CLI.' },
337
+ { name: 'mad-high', usage: 'sks --mad --high', description: 'Open a one-shot cmux Codex CLI workspace with the SKS MAD high full-access profile.' },
338
+ { name: 'auto-review', usage: 'sks auto-review status|enable|start [--high] | sks --Auto-review --high', description: 'Enable Codex automatic approval review and launch SKS cmux with the auto-review profile.' },
338
339
  { name: 'dollar-commands', usage: 'sks dollar-commands [--json]', description: 'List Codex App $ commands such as $DFix and $Team.' },
339
340
  { name: 'dfix', usage: 'sks dfix', description: 'Explain $DFix ultralight design/content fix mode.' },
340
341
  { name: 'qa-loop', usage: 'sks qa-loop prepare|answer|run|status ...', description: 'Dogfood UI/API as human proxy with safety gates, safe fixes, rechecks, Browser/Computer evidence, report.' },
@@ -93,7 +93,7 @@ ${prompt}
93
93
 
94
94
  ## How to Read
95
95
 
96
- - This file is the Codex App-visible replacement for tmux-style team panes.
96
+ - This file is the Codex App-visible replacement for cmux-style team panes.
97
97
  - Use at most ${spec.agentSessions} subagent sessions at a time unless the mission is recreated with a different budget.
98
98
  - Team mode has three bundles: parallel analysis scouts first, debate team second, then fresh parallel development team.
99
99
  - Use relevant TriWiki context before every stage, hydrate low-trust claims from source during the stage, refresh after findings/artifact changes, and validate before handoffs or final claims.
@@ -1,167 +0,0 @@
1
- import path from 'node:path';
2
- import { spawnSync } from 'node:child_process';
3
- import { exists, packageRoot, projectRoot, runProcess, sha256 } from './fsx.mjs';
4
- import { getCodexInfo } from './codex-adapter.mjs';
5
- import { codexAppIntegrationStatus, formatCodexAppStatus } from './codex-app.mjs';
6
-
7
- export const SKS_TMUX_LOGO = [
8
- '+----------------------+',
9
- '| ㅅㅋㅅ |',
10
- '| SKS CLI |',
11
- '+----------------------+'
12
- ].join('\n');
13
-
14
- export function sanitizeTmuxSessionName(input) {
15
- const base = String(input || 'sks').trim().replace(/[^A-Za-z0-9_.-]+/g, '-').replace(/^-+|-+$/g, '');
16
- return (base || 'sks').slice(0, 80);
17
- }
18
-
19
- export function defaultTmuxSessionName(root) {
20
- const base = sanitizeTmuxSessionName(path.basename(root || process.cwd()) || 'project');
21
- const hash = sha256(path.resolve(root || process.cwd())).slice(0, 8);
22
- return sanitizeTmuxSessionName(`sks-${base}-${hash}`);
23
- }
24
-
25
- export function shellEscape(value) {
26
- return `'${String(value).replace(/'/g, `'\\''`)}'`;
27
- }
28
-
29
- export function platformTmuxInstallHint() {
30
- if (process.platform === 'darwin') return 'brew install tmux';
31
- if (process.platform === 'win32') return 'Install WSL2 and run: sudo apt install tmux; native Windows may use psmux.';
32
- return 'Ubuntu/Debian: sudo apt install tmux; Fedora: sudo dnf install tmux; Arch: sudo pacman -S tmux';
33
- }
34
-
35
- export async function tmuxAvailable() {
36
- const out = await runProcess('tmux', ['-V'], { timeoutMs: 5000, maxOutputBytes: 16 * 1024 }).catch(() => null);
37
- return { ok: Boolean(out && out.code === 0), version: out ? `${out.stdout}${out.stderr}`.trim() : null };
38
- }
39
-
40
- export async function tmuxHasSession(sessionName) {
41
- const out = await runProcess('tmux', ['has-session', '-t', sessionName], { timeoutMs: 5000, maxOutputBytes: 16 * 1024 }).catch((err) => ({ code: 1, stderr: err.message, stdout: '' }));
42
- return out.code === 0;
43
- }
44
-
45
- export function tmuxSplashScript(root, codexBin, codexArgs = []) {
46
- const logo = SKS_TMUX_LOGO;
47
- const extraArgs = Array.isArray(codexArgs) ? codexArgs : [];
48
- const lines = [
49
- 'clear',
50
- `printf '%s\\n' ${shellEscape(logo)}`,
51
- `printf '\\nProject: %s\\n' ${shellEscape(root)}`,
52
- 'printf \'Engine: Codex CLI through SKS guardrails\\n\'',
53
- 'printf \'Tools: Prefer Browser Use + Computer Use MCP plugins for QA/UI evidence\\n\'',
54
- 'printf \'Prompt: use canonical $ commands only, for example $QA-LOOP\\n\\n\'',
55
- 'sleep 1',
56
- `exec ${[shellEscape(codexBin), ...extraArgs.map(shellEscape), '--cd', shellEscape(root)].join(' ')}`
57
- ];
58
- return lines.join('; ');
59
- }
60
-
61
- export function tmuxStatusScript(root, sksBin) {
62
- return `${shellEscape(process.execPath)} ${shellEscape(sksBin)} tmux status --watch --root ${shellEscape(root)}`;
63
- }
64
-
65
- export async function buildTmuxLaunchPlan(opts = {}) {
66
- const root = path.resolve(opts.root || await projectRoot());
67
- const session = sanitizeTmuxSessionName(opts.session || defaultTmuxSessionName(root));
68
- const sksBin = opts.sksBin || path.join(packageRoot(), 'bin', 'sks.mjs');
69
- const codex = opts.codex || await getCodexInfo().catch(() => ({}));
70
- const tmux = opts.tmux || await tmuxAvailable();
71
- const app = opts.app || await codexAppIntegrationStatus({ codex });
72
- const codexArgs = Array.isArray(opts.codexArgs) ? opts.codexArgs : [];
73
- return {
74
- root,
75
- session,
76
- sksBin,
77
- codex,
78
- tmux,
79
- app,
80
- codexArgs,
81
- ready: Boolean(tmux.ok && codex.bin && app.ok),
82
- blockers: [
83
- ...(!tmux.ok ? [`tmux missing. Install: ${platformTmuxInstallHint()}`] : []),
84
- ...(!codex.bin ? ['Codex CLI missing. Install: npm i -g @openai/codex, or set SKS_CODEX_BIN.'] : []),
85
- ...(!app.ok ? app.guidance : [])
86
- ]
87
- };
88
- }
89
-
90
- export function formatTmuxBanner(status = null) {
91
- const lines = [
92
- SKS_TMUX_LOGO,
93
- '',
94
- 'ㅅㅋㅅ tmux runtime',
95
- '',
96
- 'Canonical prompt commands:',
97
- ' $DFix $Answer $SKS $Team $QA-LOOP $Ralph $Research $AutoResearch $DB $GX $Wiki $Help',
98
- '',
99
- 'Preferred QA/UI tools:',
100
- ' Browser Use -> local browser targets, localhost, file://, current browser tab',
101
- ' Computer Use -> desktop apps, screenshots, browser/app interaction evidence',
102
- '',
103
- 'Useful terminal commands:',
104
- ' sks commands',
105
- ' sks dollar-commands',
106
- ' sks codex-app check',
107
- ' sks doctor --fix'
108
- ];
109
- if (status) lines.push('', formatCodexAppStatus(status));
110
- return lines.join('\n');
111
- }
112
-
113
- export async function launchTmuxUi(args = [], opts = {}) {
114
- const rootArg = readOption(args, '--root', opts.root);
115
- const sessionArg = readOption(args, '--session', opts.session);
116
- const plan = await buildTmuxLaunchPlan({ ...opts, root: rootArg, session: sessionArg });
117
- if (args.includes('--json')) return { plan };
118
- if (!plan.ready && !args.includes('--status-only')) {
119
- console.log(formatTmuxBanner(plan.app));
120
- console.log('\nLaunch blocked:\n');
121
- for (const blocker of Array.from(new Set(plan.blockers))) console.log(`- ${blocker}`);
122
- process.exitCode = 1;
123
- return { plan };
124
- }
125
- const existing = await tmuxHasSession(plan.session);
126
- if (!existing) {
127
- const splash = tmuxSplashScript(plan.root, plan.codex.bin, plan.codexArgs);
128
- const status = tmuxStatusScript(plan.root, plan.sksBin);
129
- const create = spawnSync('tmux', ['new-session', '-d', '-P', '-F', '#{window_id} #{pane_id}', '-s', plan.session, '-n', 'codex', '-c', plan.root, splash], { encoding: 'utf8' });
130
- if (create.status !== 0) {
131
- process.exitCode = create.status || 1;
132
- if (create.stderr) process.stderr.write(create.stderr);
133
- return { plan };
134
- }
135
- const [windowTarget, mainPaneTarget] = String(create.stdout || '').trim().split(/\s+/);
136
- const target = windowTarget || `${plan.session}:codex`;
137
- spawnSync('tmux', ['split-window', '-h', '-p', '34', '-t', target, '-c', plan.root, status], { stdio: 'ignore' });
138
- if (mainPaneTarget) spawnSync('tmux', ['select-pane', '-t', mainPaneTarget], { stdio: 'ignore' });
139
- spawnSync('tmux', ['set-option', '-t', plan.session, 'status-left', ' ㅅㅋㅅ #[bold]#S #[default]'], { stdio: 'ignore' });
140
- spawnSync('tmux', ['set-option', '-t', plan.session, 'status-right', ' #(date +%H:%M) '], { stdio: 'ignore' });
141
- }
142
- if (!args.includes('--no-attach')) {
143
- const attach = spawnSync('tmux', ['attach-session', '-t', plan.session], { stdio: 'inherit' });
144
- process.exitCode = attach.status || 0;
145
- } else {
146
- console.log(`SKS tmux session ready: ${plan.session}`);
147
- console.log(`Attach: tmux attach-session -t ${plan.session}`);
148
- }
149
- return { plan, existing };
150
- }
151
-
152
- export async function runTmuxStatus(args = [], opts = {}) {
153
- const root = path.resolve(readOption(args, '--root', opts.root || await projectRoot()));
154
- const once = args.includes('--once') || !args.includes('--watch');
155
- do {
156
- const app = await codexAppIntegrationStatus();
157
- console.clear();
158
- console.log(formatTmuxBanner(app));
159
- if (once) return app;
160
- await new Promise((resolve) => setTimeout(resolve, 5000));
161
- } while (true);
162
- }
163
-
164
- function readOption(args, name, fallback = null) {
165
- const i = args.indexOf(name);
166
- return i >= 0 && args[i + 1] ? args[i + 1] : fallback;
167
- }