sneakoscope 0.7.11 → 0.7.13

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -29,7 +29,7 @@ import { PIPELINE_PLAN_ARTIFACT, validatePipelinePlan, writePipelinePlan } from
29
29
  import { GOAL_BRIDGE_ARTIFACT, GOAL_WORKFLOW_ARTIFACT, updateGoalWorkflow, writeGoalWorkflow } from '../core/goal-workflow.mjs';
30
30
  import { scanCodeStructure, writeCodeStructureReport } from '../core/code-structure.mjs';
31
31
  import { writeMemorySweepReport } from '../core/memory-governor.mjs';
32
- import { cleanupWarpTeamView, launchWarpTeamView } from '../core/warp-ui.mjs';
32
+ import { cleanupTmuxTeamView, launchTmuxTeamView } from '../core/tmux-ui.mjs';
33
33
  import { loadSkillDreamState, recordSkillDreamEvent, runSkillDream, writeSkillForgeReport } from '../core/skill-forge.mjs';
34
34
  import { writeMistakeMemoryReport } from '../core/mistake-memory.mjs';
35
35
  import { checkDbOperation, checkSqlFile, classifyCommand, classifySql, loadDbSafetyPolicy, safeSupabaseMcpConfig, scanDbSafety } from '../core/db-safety.mjs';
@@ -56,8 +56,8 @@ Use outside a project:
56
56
  sks deps check
57
57
  sks team "global mission"
58
58
 
59
- If warp is missing:
60
- sks deps install warp
59
+ If tmux is missing:
60
+ sks deps install tmux
61
61
 
62
62
  Initialize this project for CLI and Codex App:
63
63
  sks setup --bootstrap
@@ -70,7 +70,7 @@ Open from terminal:
70
70
  Verify:
71
71
  sks deps check
72
72
  sks codex-app check
73
- sks warp check
73
+ sks tmux check
74
74
  sks auto-review status
75
75
  sks doctor --fix
76
76
  sks context7 check
@@ -640,7 +640,7 @@ export async function harnessCommand(sub, args = []) {
640
640
  if (flag(args, '--json')) return console.log(JSON.stringify(report, null, 2));
641
641
  console.log('SKS Harness Growth');
642
642
  console.log(`Forgetting fixture: ${report.forgetting.fixture.passed ? 'pass' : 'fail'}`);
643
- console.log(`Warp views: ${report.warp.views.length}`);
643
+ console.log(`tmux views: ${report.tmux.views.length}`);
644
644
  console.log(`Tool taxonomy: ${report.reliability.tool_error_taxonomy.join(', ')}`);
645
645
  console.log(`Unknown errors recorded as bugs: ${report.reliability.unknown_errors_are_bugs ? 'yes' : 'no'}`);
646
646
  }
@@ -1172,7 +1172,7 @@ function userRequestSignal(prompt = '') {
1172
1172
  const topicRules = [
1173
1173
  ['ambiguity-questions', /모호|ambiguity|clarification|질문|답변|answers?\.json|decision-contract|추론|예측/],
1174
1174
  ['triwiki-priority-memory', /triwiki|wiki|메모리|memory|기억|우선|반복|자주|카운팅|count|frequency|weight/],
1175
- ['install-bootstrap', /bootstrap|postinstall|doctor|deps|warp|homebrew|최초\s*설치|셋업|setup/],
1175
+ ['install-bootstrap', /bootstrap|postinstall|doctor|deps|tmux|homebrew|최초\s*설치|셋업|setup/],
1176
1176
  ['version-release', /버전|version|publish:dry|release|npm\s+pack/],
1177
1177
  ['qa-loop', /qa|e2e|검증|리포트|report/],
1178
1178
  ['team-pipeline', /team|subagent|세션|cleanup|reflection|회고|반성/],
@@ -1416,15 +1416,15 @@ export async function gxCommand(sub, args) {
1416
1416
  }
1417
1417
 
1418
1418
  export async function team(args) {
1419
- const teamSubcommands = new Set(['log', 'tail', 'watch', 'lane', 'status', 'dashboard', 'event', 'message', 'cleanup-warp']);
1419
+ const teamSubcommands = new Set(['log', 'tail', 'watch', 'lane', 'status', 'dashboard', 'event', 'message', 'cleanup-tmux']);
1420
1420
  if (teamSubcommands.has(args[0])) return teamCommand(args[0], args.slice(1));
1421
- const openWarp = flag(args, '--open-warp') || flag(args, '--warp-open');
1422
- const cleanCreateArgs = args.filter((arg) => !['--open-warp', '--warp-open'].includes(String(arg)));
1421
+ const openTmux = flag(args, '--open-tmux') || flag(args, '--tmux-open');
1422
+ const cleanCreateArgs = args.filter((arg) => !['--open-tmux', '--tmux-open'].includes(String(arg)));
1423
1423
  const opts = parseTeamCreateArgs(cleanCreateArgs);
1424
1424
  const { prompt, agentSessions, roleCounts, roster } = opts;
1425
1425
  if (!prompt) {
1426
- console.error('Usage: sks team "task" [executor:5 reviewer:2 user:1] [--agents N] [--open-warp] [--json]');
1427
- console.error(' sks team log|tail|watch|lane|status|message|cleanup-warp [mission-id|latest]');
1426
+ console.error('Usage: sks team "task" [executor:5 reviewer:2 user:1] [--agents N] [--open-tmux] [--json]');
1427
+ console.error(' sks team log|tail|watch|lane|status|message|cleanup-tmux [mission-id|latest]');
1428
1428
  console.error(' sks team event [mission-id|latest] --agent <name> --phase <phase> --message "..."');
1429
1429
  console.error(' sks team message [mission-id|latest] --from <agent> --to <agent|all> --message "..."');
1430
1430
  process.exitCode = 1;
@@ -1490,7 +1490,7 @@ export async function team(args) {
1490
1490
  questions: path.join(dir, 'questions.md'),
1491
1491
  codex_agents: ['analysis_scout', 'team_consensus', 'implementation_worker', 'db_safety_reviewer', 'qa_reviewer']
1492
1492
  };
1493
- result.warp = await launchWarpTeamView({ root, missionId: id, plan, promptFile: result.workflow, json: flag(args, '--json') || !openWarp });
1493
+ result.tmux = await launchTmuxTeamView({ root, missionId: id, plan, promptFile: result.workflow, json: flag(args, '--json') || !openTmux });
1494
1494
  if (flag(args, '--json')) return console.log(JSON.stringify(result, null, 2));
1495
1495
  console.log(`Team mission created: ${id}`);
1496
1496
  console.log(`Plan: ${path.relative(root, result.plan)}`);
@@ -1501,13 +1501,13 @@ export async function team(args) {
1501
1501
  console.log(`Runtime graph: ${path.relative(root, result.team_graph)}`);
1502
1502
  console.log(`Worker inbox: ${path.relative(root, result.worker_inbox_dir)}`);
1503
1503
  console.log(`Live: ${path.relative(root, result.live)}`);
1504
- if (result.warp.ready) {
1505
- const warpState = result.warp.created ? 'opened' : 'not opened; use --open-warp for a launch configuration';
1506
- console.log(`warp: ${warpState} ${result.warp.opened_lane_count || result.warp.agents.length} agent lane(s) in ${result.warp.workspace_ref || result.warp.workspace}`);
1504
+ if (result.tmux.ready) {
1505
+ const tmuxState = result.tmux.created ? 'opened' : 'not opened; use --open-tmux for a tmux session';
1506
+ console.log(`tmux: ${tmuxState} ${result.tmux.opened_lane_count || result.tmux.agents.length} agent lane(s) in ${result.tmux.session || result.tmux.workspace}`);
1507
1507
  }
1508
- else console.log(`warp: blocked (${Array.from(new Set(result.warp.blockers || [])).join('; ')})`);
1508
+ else console.log(`tmux: blocked (${Array.from(new Set(result.tmux.blockers || [])).join('; ')})`);
1509
1509
  console.log(`Watch: sks team watch ${id}`);
1510
- console.log('Use $Team in Codex App or the Warp launch view from this CLI flow to run scouts, debate/consensus, runtime graph/inbox handoff, then a fresh implementation team with disjoint ownership.');
1510
+ console.log('Use $Team in Codex App or the tmux launch view from this CLI flow to run scouts, debate/consensus, runtime graph/inbox handoff, then a fresh implementation team with disjoint ownership.');
1511
1511
  }
1512
1512
 
1513
1513
  export function parseTeamCreateArgs(args) {
@@ -1654,7 +1654,7 @@ export function buildTeamPlan(id, prompt, opts = {}) {
1654
1654
  markdown: 'team-live.md',
1655
1655
  transcript: 'team-transcript.jsonl',
1656
1656
  dashboard: 'team-dashboard.json',
1657
- warp: 'sks team opens a warp workspace with one live multi-line lane per visible Team agent budget when warp is available.',
1657
+ tmux: 'sks team opens a tmux workspace with one live multi-line lane per visible Team agent budget when tmux is available.',
1658
1658
  commands: [
1659
1659
  'sks team status <mission-id>',
1660
1660
  'sks team log <mission-id>',
@@ -1663,7 +1663,7 @@ export function buildTeamPlan(id, prompt, opts = {}) {
1663
1663
  'sks team lane <mission-id> --agent <name> --follow',
1664
1664
  'sks team event <mission-id> --agent <name> --phase <phase> --message "..."',
1665
1665
  'sks team message <mission-id> --from <agent> --to <agent|all> --message "..."',
1666
- 'sks team cleanup-warp <mission-id>'
1666
+ 'sks team cleanup-tmux <mission-id>'
1667
1667
  ]
1668
1668
  },
1669
1669
  required_artifacts: requiredArtifacts,
@@ -1774,19 +1774,19 @@ async function teamCommand(sub, args) {
1774
1774
  artifact: readFlagValue(args, '--artifact', ''),
1775
1775
  message
1776
1776
  });
1777
- const warpCleanup = /^session_cleanup$|^team_cleanup$|^cleanup$/i.test(String(phase || ''))
1777
+ const tmuxCleanup = /^session_cleanup$|^team_cleanup$|^cleanup$/i.test(String(phase || ''))
1778
1778
  ? await requestTeamSessionCleanup(dir, {
1779
1779
  missionId: id,
1780
1780
  agent: readFlagValue(args, '--agent', 'parent_orchestrator'),
1781
1781
  reason: message,
1782
- finalMessage: 'Team cleanup event received. Follow panes may stop; Warp panes remain user-controlled.'
1783
- }).then(() => cleanupWarpTeamView({ root, missionId: id, closeWorkspace: flag(args, '--close-workspace') })).catch((err) => ({ ok: false, reason: err.message || 'warp cleanup failed' }))
1782
+ finalMessage: 'Team cleanup event received. Follow panes may stop; tmux panes remain user-controlled.'
1783
+ }).then(() => cleanupTmuxTeamView({ root, missionId: id, closeSession: flag(args, '--close-session') || flag(args, '--close') })).catch((err) => ({ ok: false, reason: err.message || 'tmux cleanup failed' }))
1784
1784
  : null;
1785
1785
  if (flag(args, '--json')) return console.log(JSON.stringify(record, null, 2));
1786
1786
  console.log(`${record.ts} [${record.phase}] ${record.agent}: ${record.message}`);
1787
- if (warpCleanup) {
1788
- if (warpCleanup.ok) console.log(`warp cleanup: marked complete (${warpCleanup.reason || 'record updated'})`);
1789
- else console.log(`warp cleanup: skipped (${warpCleanup.reason || 'not available'})`);
1787
+ if (tmuxCleanup) {
1788
+ if (tmuxCleanup.ok) console.log(`tmux cleanup: marked complete (${tmuxCleanup.reason || 'record updated'})`);
1789
+ else console.log(`tmux cleanup: skipped (${tmuxCleanup.reason || 'not available'})`);
1790
1790
  }
1791
1791
  return;
1792
1792
  }
@@ -1810,12 +1810,12 @@ async function teamCommand(sub, args) {
1810
1810
  console.log(`${record.ts} [${record.phase}] ${record.agent} -> ${record.to}: ${record.message}`);
1811
1811
  return;
1812
1812
  }
1813
- if (sub === 'cleanup-warp') {
1813
+ if (sub === 'cleanup-tmux') {
1814
1814
  const control = await requestTeamSessionCleanup(dir, {
1815
1815
  missionId: id,
1816
1816
  agent: readFlagValue(args, '--agent', 'parent_orchestrator'),
1817
1817
  reason: readFlagValue(args, '--reason', 'Team session ended; clean up live follow panes.'),
1818
- finalMessage: 'Team session ended. Lane/watch follow loops will stop after showing this cleanup summary; Warp panes remain user-controlled.'
1818
+ finalMessage: 'Team session ended. Lane/watch follow loops will stop after showing this cleanup summary; tmux panes remain user-controlled.'
1819
1819
  });
1820
1820
  await appendTeamEvent(dir, {
1821
1821
  agent: readFlagValue(args, '--agent', 'parent_orchestrator'),
@@ -1823,16 +1823,16 @@ async function teamCommand(sub, args) {
1823
1823
  type: 'cleanup',
1824
1824
  message: control.cleanup_reason || 'Team session cleanup requested.'
1825
1825
  });
1826
- const cleanup = await cleanupWarpTeamView({ root, missionId: id, closeWorkspace: flag(args, '--close-workspace') || flag(args, '--close') });
1826
+ const cleanup = await cleanupTmuxTeamView({ root, missionId: id, closeSession: flag(args, '--close-session') || flag(args, '--close') });
1827
1827
  cleanup.control = control;
1828
1828
  if (flag(args, '--json')) return console.log(JSON.stringify(cleanup, null, 2));
1829
1829
  if (!cleanup.ok) {
1830
- console.error(`warp cleanup skipped: ${cleanup.reason || 'not available'}`);
1830
+ console.error(`tmux cleanup skipped: ${cleanup.reason || 'not available'}`);
1831
1831
  process.exitCode = cleanup.skipped ? 0 : 2;
1832
1832
  return;
1833
1833
  }
1834
- if (cleanup.removed_config) console.log(`warp cleanup: removed generated launch config ${cleanup.config_path}`);
1835
- else console.log(`warp cleanup: marked complete (${cleanup.reason || 'record updated'})`);
1834
+ if (cleanup.killed_session) console.log(`tmux cleanup: killed session ${cleanup.session}`);
1835
+ else console.log(`tmux cleanup: marked complete (${cleanup.reason || 'record updated'})`);
1836
1836
  console.log(renderTeamCleanupSummary(control));
1837
1837
  return;
1838
1838
  }
@@ -20,7 +20,7 @@ export const ARTIFACT_FILES = {
20
20
  harness_growth_report: 'harness-growth-report.json',
21
21
  code_structure_report: 'code-structure-report.json',
22
22
  team_dashboard_state: 'team-dashboard-state.json',
23
- warp_pane_plan: 'warp-pane-plan.json',
23
+ tmux_pane_plan: 'tmux-pane-plan.json',
24
24
  final_honest_mode_report: 'final-honest-mode-report.json'
25
25
  };
26
26
 
@@ -170,12 +170,12 @@ export function validateHarnessGrowthReport(data = {}) {
170
170
  pushMissing(errors, isObj(data.skills), 'skills_missing');
171
171
  pushMissing(errors, isObj(data.experiments), 'experiments_missing');
172
172
  pushMissing(errors, isObj(data.codex_native), 'codex_native_missing');
173
- pushMissing(errors, isObj(data.warp), 'warp_missing');
173
+ pushMissing(errors, isObj(data.tmux), 'tmux_missing');
174
174
  pushMissing(errors, isObj(data.reliability), 'reliability_missing');
175
175
  if (data.forgetting?.fixture?.passed !== true) errors.push('forgetting_fixture_failed');
176
176
  if (!Array.isArray(data.reliability?.tool_error_taxonomy) || !data.reliability.tool_error_taxonomy.includes('Unknown')) errors.push('tool_error_taxonomy_missing_unknown');
177
177
  if (data.reliability?.unknown_errors_are_bugs !== true) errors.push('unknown_errors_not_marked_bug');
178
- if (!Array.isArray(data.warp?.views) || data.warp.views.length < 10) errors.push('warp_views_incomplete');
178
+ if (!Array.isArray(data.tmux?.views) || data.tmux.views.length < 10) errors.push('tmux_views_incomplete');
179
179
  return validationResult('HarnessGrowthReport', errors);
180
180
  }
181
181
 
@@ -202,12 +202,12 @@ export function validateTeamDashboardState(data = {}) {
202
202
  return validationResult('TeamDashboardState', errors);
203
203
  }
204
204
 
205
- export function validateWarpPanePlan(data = {}) {
205
+ export function validateTmuxPanePlan(data = {}) {
206
206
  const errors = [];
207
207
  pushMissing(errors, nonEmpty(data.mission_id), 'mission_id_missing');
208
208
  pushMissing(errors, Array.isArray(data.panes), 'panes_not_array');
209
209
  if (arr(data.panes).some((pane) => !nonEmpty(pane.name) || !nonEmpty(pane.command))) errors.push('pane_missing_name_or_command');
210
- return validationResult('WarpPanePlan', errors);
210
+ return validationResult('TmuxPanePlan', errors);
211
211
  }
212
212
 
213
213
  export function validateFinalHonestModeReport(data = {}) {
@@ -233,7 +233,7 @@ export const ARTIFACT_VALIDATORS = {
233
233
  harness_growth_report: validateHarnessGrowthReport,
234
234
  code_structure_report: validateCodeStructureReport,
235
235
  team_dashboard_state: validateTeamDashboardState,
236
- warp_pane_plan: validateWarpPanePlan,
236
+ tmux_pane_plan: validateTmuxPanePlan,
237
237
  final_honest_mode_report: validateFinalHonestModeReport
238
238
  };
239
239
 
@@ -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 for first-party MCP/plugin tools. SKS warp launch can still run with Codex CLI alone, but Codex Computer Use evidence will be unavailable until Codex App is ready.');
121
+ lines.push('Install and open Codex App for first-party MCP/plugin tools. SKS tmux launch can still run with Codex CLI alone, but Codex 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.');
@@ -82,7 +82,7 @@ export const DEFAULT_MULTIAGENT_V2 = Object.freeze({
82
82
  subagent_output: 'structured_summary_only'
83
83
  });
84
84
 
85
- export const WARP_COCKPIT_VIEWS = Object.freeze([
85
+ export const TMUX_COCKPIT_VIEWS = Object.freeze([
86
86
  'Mission / Goal View',
87
87
  'Agent Grid View',
88
88
  'MultiAgentV2 Graph View',
@@ -287,8 +287,8 @@ export function harnessGrowthReport(input = {}) {
287
287
  goal_checkpoint_required_fields: ['goal_id', 'phase', 'summary', 'completed_checkboxes', 'open_checkboxes', 'blockers', 'evidence'],
288
288
  external_session_import: 'structured_summary_only_with_utility_score_and_forgetting_metadata'
289
289
  },
290
- warp: {
291
- views: WARP_COCKPIT_VIEWS,
290
+ tmux: {
291
+ views: TMUX_COCKPIT_VIEWS,
292
292
  status_terms: ['idle', 'planning', 'exploring', 'implementing', 'waiting_for_tool', 'waiting_for_approval', 'dogfooding', 'verifying', 'summarizing', 'blocked', 'failed', 'completed', 'paused', 'resuming']
293
293
  },
294
294
  reliability: {
package/src/core/fsx.mjs CHANGED
@@ -5,7 +5,7 @@ import os from 'node:os';
5
5
  import crypto from 'node:crypto';
6
6
  import { spawn } from 'node:child_process';
7
7
 
8
- export const PACKAGE_VERSION = '0.7.11';
8
+ export const PACKAGE_VERSION = '0.7.13';
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
@@ -91,7 +91,7 @@ function isSksManagedHook(hook) {
91
91
  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);
92
92
  }
93
93
 
94
- const AGENTS_BLOCK = "\n# Sneakoscope Codex Managed Rules\n\nThis repository uses Sneakoscope Codex.\n\n## Core Rules\n\n- Codex native `/goal` workflows are the persisted continuation surface; Ralph is removed from the user-facing SKS surface.\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- Do not create unrequested fallback implementation code. If the requested path is impossible, block with evidence instead of inventing substitute behavior.\n\n## Routes\n\n- General execution/code-changing prompts default to `$Team`: analysis scouts, TriWiki refresh/validate, read-only debate, consensus, concrete runtime task graph/inboxes, fresh executor team, review, integration, Honest Mode.\n- `$Computer-Use` / `$CU` is the maximum-speed Codex Computer Use lane for UI/browser/visual tasks: skip Team debate and upfront TriWiki loops, use Codex Computer Use directly, then refresh/validate TriWiki and run Honest Mode at final closeout.\n- `$Goal` is a fast bridge/overlay for Codex native `/goal` create/pause/resume/clear persistence controls; implementation continues through the selected SKS execution route.\n- TriWiki recall must stay bounded. Use `sks wiki sweep` to record demote, soft-forget, archive, delete, promote-to-skill, and promote-to-rule candidates instead of injecting every old claim.\n- Team missions must keep schema-backed evidence current: `work-order-ledger.json`, `effort-decision.json`, `team-dashboard-state.json`, and route-specific visual/dogfood artifacts where applicable. Use `sks validate-artifacts latest` before claiming those artifacts pass.\n- `$DFix` is only for tiny design/content edits and bypasses the main pipeline, Team, TriWiki/TriFix/reflection recording, and persistent route state; it still uses a one-line DFix-specific Honest check before final. `$PPT` is the restrained, information-first HTML/PDF presentation route and must seal delivery context, audience profile, STP, decision context, and 3+ pain-point/solution/aha mappings before design/render work. It must avoid over-designed visuals, carry detail through hierarchy, spacing, alignment, thin rules, source clarity, and subtle accents, preserve editable source HTML under `source-html/`, and clean PPT-only temporary build files before completion. `$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`. Design-system and presentation-like HTML/PDF work consults getdesign.md / getdesign-reference first; image/logo/raster assets use `imagegen`, which must prefer official Codex App built-in image generation via `$imagegen` / `gpt-image-2` before API generation.\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- Treat handwritten files above 3000 lines as split-review risks. Run `sks code-structure scan` and prefer extraction before adding substantial logic.\n- Skill dreaming stays lightweight: route use records JSON counters in `.sneakoscope/skills/dream-state.json`, and full skill inventory/recommendation runs only after the configured count/cooldown threshold. Reports are recommendation-only; deleting or merging skills needs explicit user approval.\n\n## Evidence And Context\n\n- Context7 is required for external libraries, APIs, MCPs, package managers, SDKs, and generated docs: resolve-library-id then query-docs.\n- When tech stack, framework, package, runtime, or deployment-platform versions change, use Context7 or official vendor web docs, record current syntax/security/limit guidance as high-priority TriWiki claims, then refresh and validate before coding.\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, use `attention.use_first` for compact high-trust recall, hydrate `attention.hydrate_first` from source before risky or lower-trust decisions, 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- Final response before stop: summarize what was done, what changed for the user/repo, what was verified, and what remains unverified or blocked; then run Honest Mode. Say what passed and what was not verified.\n- `$From-Chat-IMG` uses forensic visual effort, not ordinary Team effort. Completion is blocked until source inventory, visual mapping, work-order coverage, scoped dogfood/QA, and post-fix verification artifacts are present and valid.\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- MAD and MAD-SKS widen only explicit scoped permissions; they still do not authorize unrequested fallback implementation code.\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`, `$computer-use`, `$cu`, `$ppt`, `$goal`, `$dfix`, `$qa-loop`, etc.) as the app control surface.\n";
94
+ const AGENTS_BLOCK = "\n# Sneakoscope Codex Managed Rules\n\nThis repository uses Sneakoscope Codex.\n\n## Core Rules\n\n- Codex native `/goal` workflows are the persisted continuation surface; Ralph is removed from the user-facing SKS surface.\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- Do not create unrequested fallback implementation code. If the requested path is impossible, block with evidence instead of inventing substitute behavior.\n\n## Routes\n\n- General execution/code-changing prompts default to `$Team`: analysis scouts, TriWiki refresh/validate, read-only debate, consensus, concrete runtime task graph/inboxes, fresh executor team, review, integration, Honest Mode.\n- `$Computer-Use` / `$CU` is the maximum-speed Codex Computer Use lane for UI/browser/visual tasks: skip Team debate and upfront TriWiki loops, use Codex Computer Use directly, then refresh/validate TriWiki and run Honest Mode at final closeout.\n- `$Goal` is a fast bridge/overlay for Codex native `/goal` create/pause/resume/clear persistence controls; implementation continues through the selected SKS execution route.\n- TriWiki recall must stay bounded. Use `sks wiki sweep` to record demote, soft-forget, archive, delete, promote-to-skill, and promote-to-rule candidates instead of injecting every old claim.\n- Team missions must keep schema-backed evidence current: `work-order-ledger.json`, `effort-decision.json`, `team-dashboard-state.json`, and route-specific visual/dogfood artifacts where applicable. Use `sks validate-artifacts latest` before claiming those artifacts pass.\n- `$DFix` is only for tiny design/content edits and bypasses the main pipeline, Team, TriWiki/TriFix/reflection recording, and persistent route state; it still uses a one-line DFix-specific Honest check before final. `$PPT` is the restrained, information-first HTML/PDF presentation route and must seal delivery context, audience profile, STP, decision context, and 3+ pain-point/solution/aha mappings before design/render work. It must avoid over-designed visuals, carry detail through hierarchy, spacing, alignment, thin rules, source clarity, and subtle accents, preserve editable source HTML under `source-html/`, record `ppt-parallel-report.json`, and clean PPT-only temporary build files before completion. `$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`. Design-system and presentation-like HTML/PDF work consults getdesign.md / getdesign-reference first; image/logo/raster assets use `imagegen`, which must prefer official Codex App built-in image generation via `$imagegen` / `gpt-image-2` before API generation.\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- Treat handwritten files above 3000 lines as split-review risks. Run `sks code-structure scan` and prefer extraction before adding substantial logic.\n- Skill dreaming stays lightweight: route use records JSON counters in `.sneakoscope/skills/dream-state.json`, and full skill inventory/recommendation runs only after the configured count/cooldown threshold. Reports are recommendation-only; deleting or merging skills needs explicit user approval.\n\n## Evidence And Context\n\n- Context7 is required for external libraries, APIs, MCPs, package managers, SDKs, and generated docs: resolve-library-id then query-docs.\n- When tech stack, framework, package, runtime, or deployment-platform versions change, use Context7 or official vendor web docs, record current syntax/security/limit guidance as high-priority TriWiki claims, then refresh and validate before coding.\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, use `attention.use_first` for compact high-trust recall, hydrate `attention.hydrate_first` from source before risky or lower-trust decisions, 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- Final response before stop: summarize what was done, what changed for the user/repo, what was verified, and what remains unverified or blocked; then run Honest Mode. Say what passed and what was not verified.\n- `$From-Chat-IMG` uses forensic visual effort, not ordinary Team effort. Completion is blocked until source inventory, visual mapping, work-order coverage, scoped dogfood/QA, and post-fix verification artifacts are present and valid.\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- MAD and MAD-SKS widen only explicit scoped permissions; they still do not authorize unrequested fallback implementation code.\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`, `$computer-use`, `$cu`, `$ppt`, `$goal`, `$dfix`, `$qa-loop`, etc.) as the app control surface.\n";
95
95
 
96
96
  export async function initProject(root, opts = {}) {
97
97
  const created = [];
@@ -522,7 +522,7 @@ function codexAppQuickReference(scope, commandPrefix) {
522
522
  `Install scope: \`${scope}\``,
523
523
  `Command: \`${commandPrefix} <command>\``,
524
524
  'Files: AGENTS.md, .codex/hooks.json, .codex/config.toml, .codex/SNEAKOSCOPE.md, .agents/skills, .codex/agents, .sneakoscope/missions.',
525
- `Discover: ${commandPrefix} bootstrap; ${commandPrefix} deps check; ${commandPrefix} commands; ${commandPrefix} codex-app check; ${commandPrefix} warp check; ${commandPrefix} dollar-commands; ${commandPrefix} pipeline status; ${commandPrefix} pipeline plan.`,
525
+ `Discover: ${commandPrefix} bootstrap; ${commandPrefix} deps check; ${commandPrefix} commands; ${commandPrefix} codex-app check; ${commandPrefix} tmux check; ${commandPrefix} dollar-commands; ${commandPrefix} pipeline status; ${commandPrefix} pipeline plan.`,
526
526
  'dollar-commands:',
527
527
  ...DOLLAR_COMMANDS.map((c) => `- \`${c.command}\`: ${c.route}`),
528
528
  `Picker skills: ${DOLLAR_COMMAND_ALIASES.map((x) => x.app_skill).join(', ')}.`,
@@ -532,8 +532,8 @@ function codexAppQuickReference(scope, commandPrefix) {
532
532
  `Runtime root: ${commandPrefix} root shows whether SKS is using the nearest project root or the per-user global SKS runtime root; outside any project marker, runtime commands use the global root instead of writing .sneakoscope into the current random directory.`,
533
533
  `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.`,
534
534
  stackCurrentDocsPolicyText(commandPrefix),
535
- `Team Warp view: ${commandPrefix} team "task" prepares live watch/lane commands without opening Warp by default; add --open-warp when you explicitly want a Warp Launch Configuration with an overview watch pane plus color-coded split per-agent lanes; ${commandPrefix} team lane latest --agent analysis_scout_1 --follow shows one agent's status, assigned runtime tasks, recent agent events, direct messages, and fallback global tail; ${commandPrefix} team message latest --from analysis_scout_1 --to executor_1 --message "handoff note" mirrors bounded agent communication into transcript/lane panes; ${commandPrefix} team cleanup-warp latest marks the SKS launch record complete and asks follow panes to show a cleanup summary then stop.`,
536
- `Runtime: open Codex App once, then run ${commandPrefix} bootstrap, ${commandPrefix} deps check, or ${commandPrefix} warp open when you explicitly want a Warp/Codex CLI launch.`,
535
+ `Team tmux view: ${commandPrefix} team "task" prepares live watch/lane commands without opening tmux by default; add --open-tmux when you explicitly want a named tmux session with an overview watch pane plus color-coded split per-agent lanes; ${commandPrefix} team lane latest --agent analysis_scout_1 --follow shows one agent's status, assigned runtime tasks, recent agent events, direct messages, and fallback global tail; ${commandPrefix} team message latest --from analysis_scout_1 --to executor_1 --message "handoff note" mirrors bounded agent communication into transcript/lane panes; ${commandPrefix} team cleanup-tmux latest marks the SKS session record complete and asks follow panes to show a cleanup summary then stop.`,
536
+ `Runtime: open Codex App once, then run ${commandPrefix} bootstrap, ${commandPrefix} deps check, or ${commandPrefix} tmux open when you explicitly want a tmux/Codex CLI launch.`,
537
537
  `Guard: generated harness files are immutable outside the engine source repo; check ${commandPrefix} guard check; conflicts use ${commandPrefix} conflicts prompt with human approval.`
538
538
  ].join('\n') + '\n';
539
539
  }
@@ -544,10 +544,10 @@ export async function installSkills(root) {
544
544
  'answer': `---\nname: answer\ndescription: Answer-only research route for ordinary questions that should not start implementation.\n---\n\nUse for explanations, comparisons, status, facts, source-backed research, or docs guidance. Use repo/TriWiki first for project-local facts; hydrate low-trust claims from source. Browse or use Context7 for current external package/API/framework/MCP docs. End with a concise answer summary plus Honest Mode; do not create missions, subagents, or file edits.\n`,
545
545
  'sks': `---\nname: sks\ndescription: General Sneakoscope Codex command route for $SKS or $sks usage, setup, status, and workflow help.\n---\n\nUse local SKS commands: bootstrap, deps, commands, quickstart, codex-app, context7, guard, conflicts, reasoning, wiki, pipeline status, pipeline plan, skill-dream. Promote code-changing work to Team unless Answer/DFix/Help/Wiki/safety route fits. Surface route/guard/scope, use TriWiki, do not edit installed harness files outside this engine repo, and require human-approved conflict cleanup. ${skillDreamPolicyText()}\n`,
546
546
  'wiki': `---\nname: wiki\ndescription: Dollar-command route for $Wiki TriWiki refresh, pack, validate, and prune commands.\n---\n\nUse for $Wiki or Korean wiki-refresh requests. Refresh/update/갱신: run sks wiki refresh, then validate .sneakoscope/wiki/context-pack.json. Pack: run sks wiki pack, then validate. Prune/clean/정리: use sks wiki refresh --prune, or sks wiki prune --dry-run for inspection. Report claims, anchors, trust, attention.use_first/hydrate_first, validation, and blockers. Do not start ambiguity-gated implementation, subagents, or unrelated work.\n`,
547
- 'team': `---\nname: team\ndescription: SKS Team orchestration for $Team/code work; $From-Chat-IMG is the explicit chat-image alias.\n---\n\nUse for $Team/code work. Ambiguity gate first. Read pipeline-plan.json or run sks pipeline plan to see the runtime lane, kept/skipped stages, and verification before implementation. Write team-roster.json; team-gate.json needs team_roster_confirmed=true. executor:N means N scouts, N debate voices, then fresh N executors. After consensus, compile team-graph.json, team-runtime-tasks.json, team-decomposition-report.json, and team-inbox/ so worker handoff uses concrete runtime task ids with role/path/domain/lane hints. Refresh/validate TriWiki before debate, implementation, review, and final; consume attention.use_first and hydrate attention.hydrate_first before risky decisions. ${outcomeRubricPolicyText()} ${speedLanePolicyText()} ${skillDreamPolicyText()} Log events and use sks team message for bounded inter-agent communication in transcript/lane panes. Color-coded Warp lanes distinguish overview/scout/planning/execution/review/safety sessions. End with cleanup-warp or a cleanup event so follow panes show cleanup and stop; pass team-session-cleanup.json, then reflection and Honest Mode. Parent integrates/verifies.\n\n${chatCaptureIntakeText()}\n`,
547
+ 'team': `---\nname: team\ndescription: SKS Team orchestration for $Team/code work; $From-Chat-IMG is the explicit chat-image alias.\n---\n\nUse for $Team/code work. Ambiguity gate first. Read pipeline-plan.json or run sks pipeline plan to see the runtime lane, kept/skipped stages, and verification before implementation. Write team-roster.json; team-gate.json needs team_roster_confirmed=true. executor:N means N scouts, N debate voices, then fresh N executors. After consensus, compile team-graph.json, team-runtime-tasks.json, team-decomposition-report.json, and team-inbox/ so worker handoff uses concrete runtime task ids with role/path/domain/lane hints. Refresh/validate TriWiki before debate, implementation, review, and final; consume attention.use_first and hydrate attention.hydrate_first before risky decisions. ${outcomeRubricPolicyText()} ${speedLanePolicyText()} ${skillDreamPolicyText()} Log events and use sks team message for bounded inter-agent communication in transcript/lane panes. Color-coded tmux lanes distinguish overview/scout/planning/execution/review/safety sessions. End with cleanup-tmux or a cleanup event so follow panes show cleanup and stop; pass team-session-cleanup.json, then reflection and Honest Mode. Parent integrates/verifies.\n\n${chatCaptureIntakeText()}\n`,
548
548
  'from-chat-img': `---\nname: from-chat-img\ndescription: Explicit $From-Chat-IMG Team alias for chat screenshot plus attachment analysis.\n---\n\nUse only for From-Chat-IMG/$From-Chat-IMG. It enters the normal Team pipeline. Treat uploads as chat screenshot plus originals. Use Codex Computer Use visual inspection when available, list requirements first, match regions to attachments with confidence, write ${FROM_CHAT_IMG_COVERAGE_ARTIFACT}, ${FROM_CHAT_IMG_CHECKLIST_ARTIFACT}, ${FROM_CHAT_IMG_TEMP_TRIWIKI_ARTIFACT}, and ${FROM_CHAT_IMG_QA_LOOP_ARTIFACT}, then continue Team gates, review, reflection, and Honest Mode. ${CODEX_COMPUTER_USE_ONLY_POLICY} The ledger must account for every visible customer request, screenshot image region, and separate attachment; ${FROM_CHAT_IMG_CHECKLIST_ARTIFACT} must have a checked item for each request, image-region/attachment match, work item, scoped QA-LOOP, and verification step; ${FROM_CHAT_IMG_TEMP_TRIWIKI_ARTIFACT} stores temporary TriWiki-backed session context with expires_after_sessions=${FROM_CHAT_IMG_TEMP_TRIWIKI_SESSIONS}. ${FROM_CHAT_IMG_QA_LOOP_ARTIFACT} must prove QA-LOOP ran over the exact customer-request work-order range after implementation, with every work item covered, post-fix verification complete, and zero unresolved findings. team-gate.json cannot pass From-Chat-IMG completion until unresolved_items is empty, every checklist box is checked, and scoped_qa_loop_completed=true.\n`,
549
549
  'qa-loop': `---\nname: qa-loop\ndescription: $QA-LOOP dogfoods UI/API as human proxy with safety gates, Codex Computer Use-only UI evidence, safe fixes, rechecks, and a QA report.\n---\n\nUse only $QA-LOOP. Ask scope, target, mutation, login. Credentials are runtime-only; never save secrets. UI-level E2E needs Codex Computer Use evidence or must be marked unverified; Chrome MCP, Browser Use, Playwright, Selenium, Puppeteer, and other browser automation do not satisfy UI/browser verification. Deployed targets are read-only; destructive removal is forbidden. After answer/run, dogfood real flows, apply safe contract-allowed code/test/docs fixes, recheck, and do not pass qa-gate.json with unresolved findings or without post_fix_verification_complete. Finish qa-ledger, date/version report, gate, completion summary, and Honest Mode.\n`,
550
- 'ppt': `---\nname: ppt\ndescription: $PPT information-first HTML/PDF presentation pipeline with STP, audience, pain-point, format, research, design-system, and verification questions.\n---\n\nUse only when the user invokes $PPT or asks to create a presentation, deck, slides, pitch deck, proposal deck, HTML presentation, or PDF presentation artifact. Before artifact work, seal presentation-specific ambiguity answers: delivery context, target audience profile including role/average age/job/industry/topic familiarity/decision power, STP strategy, decision context and objections, and 3+ pain-point to solution mappings with expected aha moments. Presentation design must be simple, restrained, and information-first: avoid over-designed decoration, ornamental gradients, nested cards, and effects that compete with the message. Design detail should be embedded through typography hierarchy, spacing, alignment, thin rules, source clarity, and subtle accents. Use getdesign-reference and design-artifact-expert for design-system grounding. If generated image assets are needed, use imagegen and prefer Codex App built-in image generation (${CODEX_APP_IMAGE_GENERATION_DOC_URL}) before API generation. Use web or Context7 evidence when external facts/libraries are involved, then create the PDF plus editable source HTML under source-html/, verify readability, overlap, format fit, source coverage, export state, and temporary build files cleanup. Finish with reflection and Honest Mode; do not skip STP/audience questions for presentation artifacts.\n`,
550
+ 'ppt': `---\nname: ppt\ndescription: $PPT information-first HTML/PDF presentation pipeline with STP, audience, pain-point, format, research, design-system, and verification questions.\n---\n\nUse only when the user invokes $PPT or asks to create a presentation, deck, slides, pitch deck, proposal deck, HTML presentation, or PDF presentation artifact. Before artifact work, seal presentation-specific ambiguity answers: delivery context, target audience profile including role/average age/job/industry/topic familiarity/decision power, STP strategy, decision context and objections, and 3+ pain-point to solution mappings with expected aha moments. Presentation design must be simple, restrained, and information-first: avoid over-designed decoration, ornamental gradients, nested cards, and effects that compete with the message. Design detail should be embedded through typography hierarchy, spacing, alignment, thin rules, source clarity, and subtle accents. Use getdesign-reference and design-artifact-expert for design-system grounding. If generated image assets are needed, use imagegen and prefer Codex App built-in image generation (${CODEX_APP_IMAGE_GENERATION_DOC_URL}) before API generation. Use web or Context7 evidence when external facts/libraries are involved, then create the PDF plus editable source HTML under source-html/, keep independent strategy/render/file-write phases parallel where inputs allow, record ppt-parallel-report.json, and verify readability, overlap, format fit, source coverage, export state, and temporary build files cleanup. Finish with reflection and Honest Mode; do not skip STP/audience questions for presentation artifacts.\n`,
551
551
  'computer-use': `---\nname: computer-use\ndescription: Maximum-speed $Computer-Use/$CU lane for Codex Computer Use UI/browser/visual tasks.\n---\n\nUse only when the user invokes $Computer-Use/$CU or asks for a Computer Use-specific fast lane. Skip Team debate, QA-LOOP clarification, upfront TriWiki refresh, Context7, subagents, and reflection unless explicitly requested. Infer the smallest target, use Codex Computer Use directly, and never substitute Playwright, Chrome MCP, Browser Use, Selenium, Puppeteer, or other browser automation for UI/browser evidence. If Computer Use is unavailable, mark UI/browser evidence unverified and stop with the blocker. At the end only, refresh or pack TriWiki, validate it, then provide a concise completion summary plus Honest Mode.\n`,
552
552
  'computer-use-fast': `---\nname: computer-use-fast\ndescription: Alias for the maximum-speed $Computer-Use/$CU Codex Computer Use lane.\n---\n\nUse the same rules as computer-use: skip Team debate, QA-LOOP clarification, upfront TriWiki refresh, Context7, subagents, and reflection unless explicitly requested. Use Codex Computer Use directly; never substitute Playwright, Chrome MCP, Browser Use, Selenium, Puppeteer, or other browser automation for UI/browser evidence. At the end only, refresh/pack TriWiki, validate it, then provide a concise completion summary plus Honest Mode.\n`,
553
553
  'cu': `---\nname: cu\ndescription: Short alias for the maximum-speed $Computer-Use Codex Computer Use lane.\n---\n\nUse the same rules as computer-use. This is a speed lane for focused UI/browser/visual tasks that require Codex Computer Use evidence, with TriWiki refresh/validate and Honest Mode deferred to final closeout.\n`,
@@ -245,7 +245,7 @@ export function promptPipelineContext(prompt, route = routePrompt(prompt)) {
245
245
  if (reflectionRequiredForRoute(route)) lines.push(reflectionInstructionText());
246
246
  if (route?.id === 'Team') lines.push(`Team route: scouts, TriWiki refresh, debate, consensus, runtime graph compile with concrete task ids and worker inboxes, close planning agents, fresh executors, review/integration, ${TEAM_SESSION_CLEANUP_ARTIFACT}, reflection, and Honest Mode.`);
247
247
  if (route?.id === 'Goal') lines.push('Goal route: write SKS goal bridge artifacts, then use Codex native /goal persistence for create, pause, resume, and clear continuation controls.');
248
- if (route?.id === 'PPT') lines.push(`PPT route: before design or PDF work, seal delivery context, audience profile including average age/job/industry, STP strategy, decision context, and at least three pain-point to solution mappings. Keep the visual system simple, restrained, and information-first; design detail should come from hierarchy, spacing, alignment, rules, and subtle accents rather than decorative overdesign. If generated image assets are needed, prefer Codex App built-in image generation through the imagegen skill (${CODEX_APP_IMAGE_GENERATION_DOC_URL}). Then build source ledger, storyboard with aha moments, style tokens, editable source HTML under source-html/, PDF artifact, render QA, PPT-only temporary build file cleanup, reflection, and Honest Mode.`);
248
+ if (route?.id === 'PPT') lines.push(`PPT route: before design or PDF work, seal delivery context, audience profile including average age/job/industry, STP strategy, decision context, and at least three pain-point to solution mappings. Keep the visual system simple, restrained, and information-first; design detail should come from hierarchy, spacing, alignment, rules, and subtle accents rather than decorative overdesign. If generated image assets are needed, prefer Codex App built-in image generation through the imagegen skill (${CODEX_APP_IMAGE_GENERATION_DOC_URL}). Then build source ledger, storyboard with aha moments, style tokens, editable source HTML under source-html/, PDF artifact, render QA, PPT-only temporary build file cleanup, and ppt-parallel-report.json so independent strategy/render/file-write phases stay parallel-friendly, then reflection and Honest Mode.`);
249
249
  if (route?.id === 'AutoResearch') lines.push('AutoResearch route: load autoresearch-loop plus seo-geo-optimizer when SEO/GEO, discoverability, README, npm, GitHub stars, ranking, or AI-search visibility is relevant.');
250
250
  if (route?.id === 'DB') lines.push('DB route: scan/check database risk first; destructive DB operations remain forbidden.');
251
251
  if (route?.id === 'GX') lines.push('GX route: use deterministic vgraph/beta render, validate, drift, and snapshot artifacts.');
@@ -584,7 +584,7 @@ async function prepareTeam(root, route, task, required) {
584
584
  markdown: 'team-live.md',
585
585
  transcript: 'team-transcript.jsonl',
586
586
  dashboard: 'team-dashboard.json',
587
- warp: 'CLI Team entrypoints open warp live lanes for the visible Team agent budget when warp is available.',
587
+ tmux: 'CLI Team entrypoints open tmux live lanes for the visible Team agent budget when tmux is available.',
588
588
  commands: ['sks team status latest', 'sks team log latest', 'sks team tail latest', 'sks team watch latest', 'sks team lane latest --agent <name> --follow', 'sks team event latest --agent <name> --phase <phase> --message "..."']
589
589
  },
590
590
  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']
package/src/core/ppt.mjs CHANGED
@@ -12,6 +12,7 @@ export const PPT_HTML_ARTIFACT = `${PPT_SOURCE_HTML_DIR}/artifact.html`;
12
12
  export const PPT_PDF_ARTIFACT = 'artifact.pdf';
13
13
  export const PPT_RENDER_REPORT_ARTIFACT = 'ppt-render-report.json';
14
14
  export const PPT_CLEANUP_REPORT_ARTIFACT = 'ppt-cleanup-report.json';
15
+ export const PPT_PARALLEL_REPORT_ARTIFACT = 'ppt-parallel-report.json';
15
16
  export const PPT_TEMP_DIR = 'ppt-tmp';
16
17
 
17
18
  export const PPT_REQUIRED_GATE_FIELDS = Object.freeze([
@@ -20,6 +21,7 @@ export const PPT_REQUIRED_GATE_FIELDS = Object.freeze([
20
21
  'source_ledger_created',
21
22
  'storyboard_created',
22
23
  'style_tokens_created',
24
+ 'parallel_build_recorded',
23
25
  'html_artifact_created',
24
26
  'source_html_preserved',
25
27
  'pdf_exported_or_explicitly_deferred',
@@ -83,6 +85,62 @@ function normalizePainpoints(answers = {}) {
83
85
  });
84
86
  }
85
87
 
88
+ function msSince(startedAt) {
89
+ return Math.max(0, Date.now() - startedAt);
90
+ }
91
+
92
+ export function createPptParallelReporter(contract = {}) {
93
+ const report = {
94
+ schema_version: 1,
95
+ created_at: nowIso(),
96
+ contract_hash: contract.sealed_hash || null,
97
+ strategy: 'parallelize_independent_ppt_artifact_phases_without_changing_output_semantics',
98
+ parallel_groups: [],
99
+ dependency_graph: [
100
+ { id: 'strategy_inputs', depends_on: ['sealed_decision_contract'], can_run_parallel: ['audience_strategy', 'source_ledger', 'style_tokens'] },
101
+ { id: 'storyboard_phase', depends_on: ['audience_strategy'] },
102
+ { id: 'render_targets', depends_on: ['storyboard', 'style_tokens', 'source_ledger'], can_run_parallel: ['html_source', 'pdf_export'] },
103
+ { id: 'artifact_writes', depends_on: ['strategy_inputs', 'storyboard_phase', 'render_targets'], can_run_parallel: ['json_artifacts', 'html_source_write', 'pdf_write'] },
104
+ { id: 'final_reports', depends_on: ['artifact_writes', 'cleanup'], can_run_parallel: ['cleanup_report_write', 'parallel_report_write'] }
105
+ ],
106
+ notes: [
107
+ 'This report records deterministic Promise.all groups used by the built-in PPT builder.',
108
+ 'External web research, image generation, and design critique should use the same split: sources, STP/audience synthesis, style tokens, storyboard, assets, render QA, and cleanup as separable lanes when their inputs are available.'
109
+ ]
110
+ };
111
+ return {
112
+ async group(id, tasks = {}) {
113
+ const entries = Object.entries(tasks);
114
+ const started = Date.now();
115
+ const startedAt = nowIso();
116
+ const values = await Promise.all(entries.map(async ([taskId, task]) => {
117
+ const taskStarted = Date.now();
118
+ const value = await task();
119
+ return [taskId, value, { id: taskId, duration_ms: msSince(taskStarted) }];
120
+ }));
121
+ report.parallel_groups.push({
122
+ id,
123
+ started_at: startedAt,
124
+ duration_ms: msSince(started),
125
+ task_count: entries.length,
126
+ tasks: values.map(([, , meta]) => meta),
127
+ executed_in_parallel: entries.length > 1
128
+ });
129
+ return Object.fromEntries(values.map(([taskId, value]) => [taskId, value]));
130
+ },
131
+ report() {
132
+ const groups = report.parallel_groups;
133
+ return {
134
+ ...report,
135
+ completed_at: nowIso(),
136
+ total_groups: groups.length,
137
+ parallel_group_count: groups.filter((group) => group.executed_in_parallel).length,
138
+ passed: groups.some((group) => group.executed_in_parallel)
139
+ };
140
+ }
141
+ };
142
+ }
143
+
86
144
  export function buildPptAudienceStrategy(contract = {}) {
87
145
  const answers = contract.answers || {};
88
146
  const painpoints = normalizePainpoints(answers);
@@ -414,6 +472,7 @@ export function buildPptRenderReport({ contract = {}, audience, sourceLedger, st
414
472
  unsupported_external_claims: 0
415
473
  },
416
474
  editable_source_html: PPT_HTML_ARTIFACT,
475
+ parallel_build_report: PPT_PARALLEL_REPORT_ARTIFACT,
417
476
  output_files: [PPT_HTML_ARTIFACT, PPT_PDF_ARTIFACT],
418
477
  notes: [
419
478
  'This build is deterministic and dependency-free. Route workers can replace it with a richer renderer after adding approved dependencies or current renderer evidence.'
@@ -491,7 +550,8 @@ export async function buildPptCleanupReport(dir) {
491
550
  PPT_HTML_ARTIFACT,
492
551
  PPT_PDF_ARTIFACT,
493
552
  PPT_RENDER_REPORT_ARTIFACT,
494
- PPT_CLEANUP_REPORT_ARTIFACT
553
+ PPT_CLEANUP_REPORT_ARTIFACT,
554
+ PPT_PARALLEL_REPORT_ARTIFACT
495
555
  ],
496
556
  notes: [
497
557
  'The editable HTML source is retained under source-html/ so future PDF revisions do not depend on transient build files.'
@@ -519,6 +579,7 @@ export function defaultPptGate(contract = {}) {
519
579
  source_ledger_created: false,
520
580
  storyboard_created: false,
521
581
  style_tokens_created: false,
582
+ parallel_build_recorded: false,
522
583
  html_artifact_created: false,
523
584
  source_html_preserved: false,
524
585
  pdf_exported_or_explicitly_deferred: false,
@@ -533,12 +594,14 @@ export function defaultPptGate(contract = {}) {
533
594
  PPT_HTML_ARTIFACT,
534
595
  'artifact.pdf or explicit PDF deferral note',
535
596
  'ppt-render-report.json',
536
- 'ppt-cleanup-report.json'
597
+ 'ppt-cleanup-report.json',
598
+ 'ppt-parallel-report.json'
537
599
  ],
538
600
  notes: [
539
601
  'Do not pass this gate until the HTML/PDF artifact work is actually complete or the PDF export is explicitly deferred with evidence.',
540
602
  'Audience strategy must stay linked to STP, target pain points, proof, and three or more aha moments.',
541
- 'Preserve the editable HTML source under source-html/ and remove PPT-only temporary build files before completion.'
603
+ 'Preserve the editable HTML source under source-html/ and remove PPT-only temporary build files before completion.',
604
+ 'Record independent PPT build phases in ppt-parallel-report.json so research/design/render work can stay parallel-friendly.'
542
605
  ]
543
606
  };
544
607
  }
@@ -556,30 +619,45 @@ export async function writePptRouteArtifacts(dir, contract = {}) {
556
619
 
557
620
  export async function writePptBuildArtifacts(dir, contract = null) {
558
621
  const sealed = contract || await readJson(path.join(dir, 'decision-contract.json'));
559
- const audience = buildPptAudienceStrategy(sealed);
560
- const sourceLedger = buildPptSourceLedger(sealed);
561
- const storyboard = buildPptStoryboard(sealed, audience);
562
- const styleTokens = buildPptStyleTokens(sealed);
563
- const html = buildPptHtml({ contract: sealed, audience, sourceLedger, storyboard, styleTokens });
564
- const pdfBytes = makePdf(storyboard, styleTokens);
622
+ const parallel = createPptParallelReporter(sealed);
623
+ const initial = await parallel.group('strategy_inputs', {
624
+ audience: async () => buildPptAudienceStrategy(sealed),
625
+ sourceLedger: async () => buildPptSourceLedger(sealed),
626
+ styleTokens: async () => buildPptStyleTokens(sealed)
627
+ });
628
+ const { audience, sourceLedger, styleTokens } = initial;
629
+ const { storyboard } = await parallel.group('storyboard_phase', {
630
+ storyboard: async () => buildPptStoryboard(sealed, audience)
631
+ });
632
+ const { html, pdfBytes } = await parallel.group('render_targets', {
633
+ html: async () => buildPptHtml({ contract: sealed, audience, sourceLedger, storyboard, styleTokens }),
634
+ pdfBytes: async () => makePdf(storyboard, styleTokens)
635
+ });
565
636
  const report = buildPptRenderReport({ contract: sealed, audience, sourceLedger, storyboard, styleTokens, html, pdfBytes });
566
- await writeJsonAtomic(path.join(dir, PPT_AUDIENCE_STRATEGY_ARTIFACT), audience);
567
- await writeJsonAtomic(path.join(dir, PPT_SOURCE_LEDGER_ARTIFACT), sourceLedger);
568
- await writeJsonAtomic(path.join(dir, PPT_STORYBOARD_ARTIFACT), storyboard);
569
- await writeJsonAtomic(path.join(dir, PPT_STYLE_TOKENS_ARTIFACT), styleTokens);
570
- await writeTextAtomic(path.join(dir, PPT_HTML_ARTIFACT), html);
571
- await fsp.writeFile(path.join(dir, PPT_PDF_ARTIFACT), pdfBytes);
572
- await writeJsonAtomic(path.join(dir, PPT_RENDER_REPORT_ARTIFACT), report);
637
+ await parallel.group('artifact_writes', {
638
+ audience_strategy: async () => writeJsonAtomic(path.join(dir, PPT_AUDIENCE_STRATEGY_ARTIFACT), audience),
639
+ source_ledger: async () => writeJsonAtomic(path.join(dir, PPT_SOURCE_LEDGER_ARTIFACT), sourceLedger),
640
+ storyboard: async () => writeJsonAtomic(path.join(dir, PPT_STORYBOARD_ARTIFACT), storyboard),
641
+ style_tokens: async () => writeJsonAtomic(path.join(dir, PPT_STYLE_TOKENS_ARTIFACT), styleTokens),
642
+ html_source: async () => writeTextAtomic(path.join(dir, PPT_HTML_ARTIFACT), html),
643
+ pdf: async () => fsp.writeFile(path.join(dir, PPT_PDF_ARTIFACT), pdfBytes),
644
+ render_report: async () => writeJsonAtomic(path.join(dir, PPT_RENDER_REPORT_ARTIFACT), report)
645
+ });
573
646
  const cleanupReport = await buildPptCleanupReport(dir);
574
- await writeJsonAtomic(path.join(dir, PPT_CLEANUP_REPORT_ARTIFACT), cleanupReport);
647
+ const parallelReport = parallel.report();
648
+ await parallel.group('final_reports', {
649
+ cleanup_report: async () => writeJsonAtomic(path.join(dir, PPT_CLEANUP_REPORT_ARTIFACT), cleanupReport),
650
+ parallel_report: async () => writeJsonAtomic(path.join(dir, PPT_PARALLEL_REPORT_ARTIFACT), parallelReport)
651
+ });
575
652
  const baseGate = defaultPptGate(sealed);
576
653
  const gate = {
577
654
  ...baseGate,
578
- passed: report.passed && cleanupReport.source_html_preserved && cleanupReport.temp_cleanup_completed,
655
+ passed: report.passed && cleanupReport.source_html_preserved && cleanupReport.temp_cleanup_completed && parallelReport.passed,
579
656
  audience_strategy_sealed: baseGate.audience_strategy_sealed,
580
657
  source_ledger_created: true,
581
658
  storyboard_created: true,
582
659
  style_tokens_created: true,
660
+ parallel_build_recorded: parallelReport.passed,
583
661
  html_artifact_created: true,
584
662
  source_html_preserved: cleanupReport.source_html_preserved,
585
663
  pdf_exported_or_explicitly_deferred: true,
@@ -588,7 +666,8 @@ export async function writePptBuildArtifacts(dir, contract = null) {
588
666
  honest_mode_complete: true,
589
667
  render_report_passed: report.passed,
590
668
  cleanup_report_passed: cleanupReport.source_html_preserved && cleanupReport.temp_cleanup_completed,
591
- output_files: [PPT_HTML_ARTIFACT, PPT_PDF_ARTIFACT, PPT_RENDER_REPORT_ARTIFACT, PPT_CLEANUP_REPORT_ARTIFACT],
669
+ parallel_report_passed: parallelReport.passed,
670
+ output_files: [PPT_HTML_ARTIFACT, PPT_PDF_ARTIFACT, PPT_RENDER_REPORT_ARTIFACT, PPT_CLEANUP_REPORT_ARTIFACT, PPT_PARALLEL_REPORT_ARTIFACT],
592
671
  updated_at: nowIso()
593
672
  };
594
673
  await writeJsonAtomic(path.join(dir, PPT_GATE_ARTIFACT), gate);
@@ -597,6 +676,7 @@ export async function writePptBuildArtifacts(dir, contract = null) {
597
676
  gate,
598
677
  report,
599
678
  cleanup_report: cleanupReport,
679
+ parallel_report: parallelReport,
600
680
  files: {
601
681
  audience_strategy: path.join(dir, PPT_AUDIENCE_STRATEGY_ARTIFACT),
602
682
  source_ledger: path.join(dir, PPT_SOURCE_LEDGER_ARTIFACT),
@@ -607,6 +687,7 @@ export async function writePptBuildArtifacts(dir, contract = null) {
607
687
  pdf: path.join(dir, PPT_PDF_ARTIFACT),
608
688
  render_report: path.join(dir, PPT_RENDER_REPORT_ARTIFACT),
609
689
  cleanup_report: path.join(dir, PPT_CLEANUP_REPORT_ARTIFACT),
690
+ parallel_report: path.join(dir, PPT_PARALLEL_REPORT_ARTIFACT),
610
691
  gate: path.join(dir, PPT_GATE_ARTIFACT)
611
692
  }
612
693
  };
@@ -87,7 +87,7 @@ export function inferAnswersForPrompt(prompt, explicitAnswers = {}) {
87
87
  .trim();
88
88
  const version = String(text || '').match(/\bv?(\d+\.\d+\.\d+(?:[-+][0-9A-Za-z.-]+)?)\b/)?.[1] || null;
89
89
  const versionWork = /버전|version|bump|release|publish:dry|npm\s+pack/.test(lower);
90
- const installWork = /bootstrap|postinstall|doctor|deps|warp|homebrew|first install|최초\s*설치|설치\s*ux|셋업|setup/.test(lower);
90
+ const installWork = /bootstrap|postinstall|doctor|deps|tmux|homebrew|first install|최초\s*설치|설치\s*ux|셋업|setup/.test(lower);
91
91
  const questionGateWork = /모호|ambiguity|clarification|질문|triwiki|추론|infer|predict|예측|answers?\.json|decision-contract/.test(lower);
92
92
  const uiuxWork = /\b(ui|modal|screen|button|visual|design|layout|component|prototype|frontend)\b|화면|버튼|모달|디자인|레이아웃|컴포넌트|프론트|시각|발표자료|디자인\s*시스템/.test(lower);
93
93
  const presentationWork = looksLikePresentationArtifactPrompt(lower);