sneakoscope 0.7.65 → 0.7.66
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 +8 -29
- package/package.json +1 -1
- package/src/cli/install-helpers.mjs +7 -1
- package/src/core/fsx.mjs +1 -1
- package/src/core/init.mjs +33 -1
package/README.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|

|
|
4
4
|
|
|
5
|
-
Sneakoscope Codex (`sks
|
|
5
|
+
Sneakoscope Codex (`sks`) is a Codex CLI/App harness for repeatable workflows. It adds terminal commands, Codex App `$` commands, tmux workspaces, Team/QA/Research routes, pipeline plans, Computer Use, imagegen UI/UX review, Goal, Context7, DB safety, TriWiki, design-system routing, skill dreaming, Honest Mode.
|
|
6
6
|
|
|
7
7
|
## Quick Start
|
|
8
8
|
|
|
@@ -50,15 +50,15 @@ sks selftest --mock
|
|
|
50
50
|
| Skill dreaming | Records cheap generated-skill usage counters in JSON and only periodically scans `.agents/skills` for keep, merge, prune, and improvement candidates. Reports are recommendation-only and never delete skills automatically. |
|
|
51
51
|
| From-Chat-IMG | Turns chat screenshots plus original attachments into source-bound work orders, then requires scoped QA evidence before completion. |
|
|
52
52
|
| QA loop | Dogfoods UI/API behavior with safety gates, Codex Computer Use-only UI evidence, safe fixes, and rechecks. |
|
|
53
|
-
| PPT pipeline | Uses `$PPT` for
|
|
54
|
-
| Image UX Review | Uses `$Image-UX-Review` / `$UX-Review` for UI/UX audits
|
|
53
|
+
| PPT pipeline | Uses `$PPT` for restrained HTML/PDF presentation artifacts with sealed delivery context, audience, STP, decision context, source research, design SSOT, export QA, editable source HTML, and real `$imagegen` assets when required. |
|
|
54
|
+
| Image UX Review | Uses `$Image-UX-Review` / `$UX-Review` for UI/UX audits that require generated annotated review images through Codex App `$imagegen`/`gpt-image-2` before issue extraction and optional rechecks. |
|
|
55
55
|
| Computer Use fast lane | Uses `$Computer-Use` / `$CU` for UI/browser/visual work that needs maximum speed: skip Team debate and upfront TriWiki loops, use Codex Computer Use directly, then refresh/validate TriWiki and run Honest Mode at final closeout. |
|
|
56
|
-
| Goal |
|
|
56
|
+
| Goal | Bridges Codex native `/goal` create, pause, resume, and clear controls while implementation continues through the selected SKS route. |
|
|
57
57
|
| TriWiki voxels | Maintains `.sneakoscope/wiki/context-pack.json` as the context SSOT with coordinate anchors, voxel metadata, `attention.use_first`, `attention.hydrate_first`, and prompt-bound mistake recall ledgers. |
|
|
58
58
|
| Context7 | Requires current docs for external packages, APIs, MCPs, SDKs, and framework/runtime behavior when correctness depends on current guidance. |
|
|
59
59
|
| Design SSOT | Treats `design.md` as the only design decision source of truth. `docs/Design-Sys-Prompt.md` is the builder prompt; getdesign.md, official getdesign docs, and curated DESIGN.md examples from `VoltAgent/awesome-design-md` are source inputs that must be fused into `design.md` or route-local style tokens instead of becoming parallel authorities. |
|
|
60
60
|
| DB safety | Treats SQL, migrations, Supabase, RLS, and destructive operations as high risk. |
|
|
61
|
-
| Release hygiene | Checks versioning, changelog, package
|
|
61
|
+
| Release hygiene | Checks versioning, changelog, package size, syntax, selftests. |
|
|
62
62
|
|
|
63
63
|
## Requirements
|
|
64
64
|
|
|
@@ -171,7 +171,7 @@ Bare `sks` creates or reuses the default named tmux session for Codex CLI and at
|
|
|
171
171
|
|
|
172
172
|
Before opening tmux, SKS checks the installed Codex CLI against npm `@openai/codex@latest`. If a newer version exists, it asks `Y/n`; answering `y` updates automatically with `npm i -g @openai/codex@latest` and then opens tmux with the updated Codex CLI.
|
|
173
173
|
|
|
174
|
-
|
|
174
|
+
For [codex-lb](https://github.com/Soju06/codex-lb), start the server, create a dashboard API key, then run:
|
|
175
175
|
|
|
176
176
|
```sh
|
|
177
177
|
sks codex-lb setup --host https://your-codex-lb.example.com --api-key "sk-clb-..."
|
|
@@ -179,30 +179,9 @@ sks codex-lb repair
|
|
|
179
179
|
sks
|
|
180
180
|
```
|
|
181
181
|
|
|
182
|
-
Bare `sks`
|
|
182
|
+
Bare `sks` can also prompt for codex-lb auth before launch; SKS stores the key in `~/.codex/sks-codex-lb.env`, syncs `codex login --with-api-key`, and loads it into a fresh tmux session.
|
|
183
183
|
|
|
184
|
-
|
|
185
|
-
Authenticate and route Codex through codex-lb? [y/N]
|
|
186
|
-
```
|
|
187
|
-
|
|
188
|
-
Answering `y` asks for the hosted domain and API key, writes `~/.codex/config.toml`, stores the key in `~/.codex/sks-codex-lb.env` with mode `0600`, syncs Codex CLI API-key auth through `codex login --with-api-key`, and sources that env file before launching Codex in tmux. When codex-lb is configured from this prompt, SKS opens a fresh tmux session for that launch so the new key is loaded by the Codex process immediately. SKS keeps Codex App Fast mode visible and defaulted by writing top-level `model = "gpt-5.5"`, `service_tier = "fast"`, `[features].fast_mode = true`, and the `sks-fast-high` profile while removing legacy top-level reasoning locks; route-specific reasoning stays in named profiles or explicit tmux launch args.
|
|
189
|
-
|
|
190
|
-
If Codex CLI auth drifts after a tmux/MAD launch, run `sks codex-lb repair` or `sks auth repair`. This reuses the stored `~/.codex/sks-codex-lb.env` key and re-syncs Codex CLI API-key auth without asking for the key again. To replace the key or host, run `sks codex-lb reconfigure --host <domain> --api-key <key>`.
|
|
191
|
-
|
|
192
|
-
The generated provider config follows the codex-lb README's Codex CLI API-key setup:
|
|
193
|
-
|
|
194
|
-
```toml
|
|
195
|
-
model_provider = "codex-lb"
|
|
196
|
-
service_tier = "fast"
|
|
197
|
-
|
|
198
|
-
[model_providers.codex-lb]
|
|
199
|
-
name = "OpenAI"
|
|
200
|
-
base_url = "http://127.0.0.1:2455/backend-api/codex"
|
|
201
|
-
wire_api = "responses"
|
|
202
|
-
env_key = "CODEX_LB_API_KEY"
|
|
203
|
-
supports_websockets = true
|
|
204
|
-
requires_openai_auth = true
|
|
205
|
-
```
|
|
184
|
+
If Codex CLI auth drifts after a launch or reinstall, run `sks codex-lb repair`; to replace it, run `sks codex-lb reconfigure --host <domain> --api-key <key>`.
|
|
206
185
|
|
|
207
186
|
### MAD tmux Launch
|
|
208
187
|
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "sneakoscope",
|
|
3
3
|
"displayName": "ㅅㅋㅅ",
|
|
4
|
-
"version": "0.7.
|
|
4
|
+
"version": "0.7.66",
|
|
5
5
|
"description": "Sneakoscope Codex: database-safe Codex CLI/App harness with Team, Goal, AutoResearch, TriWiki, and Honest Mode.",
|
|
6
6
|
"type": "module",
|
|
7
7
|
"homepage": "https://github.com/mandarange/Sneakoscope-Codex#readme",
|
|
@@ -6,7 +6,7 @@ import { stdin as input, stdout as output } from 'node:process';
|
|
|
6
6
|
import { ensureDir, exists, globalSksRoot, packageRoot, readText, runProcess, which, writeTextAtomic } from '../core/fsx.mjs';
|
|
7
7
|
import { getCodexInfo } from '../core/codex-adapter.mjs';
|
|
8
8
|
import { formatHarnessConflictReport, llmHarnessCleanupPrompt, scanHarnessConflicts } from '../core/harness-conflicts.mjs';
|
|
9
|
-
import { installSkills } from '../core/init.mjs';
|
|
9
|
+
import { initProject, installSkills } from '../core/init.mjs';
|
|
10
10
|
import { context7ConfigToml, DOLLAR_SKILL_NAMES, GETDESIGN_REFERENCE, hasContext7ConfigText, RECOMMENDED_SKILLS } from '../core/routes.mjs';
|
|
11
11
|
import { codexLaunchCommand, platformTmuxInstallHint, tmuxReadiness } from '../core/tmux-ui.mjs';
|
|
12
12
|
|
|
@@ -869,6 +869,12 @@ export async function selftestCodexLb(tmp) {
|
|
|
869
869
|
const codexLbEnv = await safeReadText(path.join(codexLbHome, '.codex', 'sks-codex-lb.env'));
|
|
870
870
|
const codexLbAuth = await safeReadText(path.join(codexLbHome, '.codex', 'auth.json'));
|
|
871
871
|
if (!codexLbSetupJson.ok || codexLbSetupJson.base_url !== 'https://lb.example.test/backend-api/codex' || !codexLbConfig.includes('model_provider = "codex-lb"') || !codexLbConfig.includes('[model_providers.codex-lb]') || !codexLbEnv.includes("CODEX_LB_API_KEY='sk-test'") || !/(\"auth_mode\"\s*:\s*\"apikey\")/.test(codexLbAuth)) throw new Error('selftest failed: codex-lb setup did not write provider config, env key, and Codex API-key auth');
|
|
872
|
+
await writeTextAtomic(path.join(codexLbHome, '.codex', 'config.toml'), `${codexLbConfig}\n[mcp_servers.supabase]\nurl = "https://mcp.supabase.com/mcp?project_ref=ref&read_only=true&features=database,docs"\n`);
|
|
873
|
+
const ptmp = path.join(tmp, 'codex-lb-project-config'), prevHome = process.env.HOME;
|
|
874
|
+
try { process.env.HOME = codexLbHome; await initProject(ptmp, { installScope: 'global' }); }
|
|
875
|
+
finally { if (prevHome === undefined) delete process.env.HOME; else process.env.HOME = prevHome; }
|
|
876
|
+
const pcfg = await safeReadText(path.join(ptmp, '.codex', 'config.toml'));
|
|
877
|
+
if (!pcfg.includes('model_provider = "codex-lb"') || !pcfg.includes('[model_providers.codex-lb]') || !pcfg.includes('[mcp_servers.supabase]') || !pcfg.includes('read_only=true')) throw new Error('selftest failed: project bootstrap lost global codex-lb or MCP config');
|
|
872
878
|
await writeTextAtomic(path.join(codexLbHome, '.codex', 'auth.json'), '{"auth_mode":"browser"}\n');
|
|
873
879
|
const codexLbRepair = await runProcess(process.execPath, [path.join(packageRoot(), 'bin', 'sks.mjs'), 'auth', 'repair', '--json'], { cwd: tmp, env: codexLbEnvForSelftest, timeoutMs: 15000, maxOutputBytes: 64 * 1024 });
|
|
874
880
|
if (codexLbRepair.code !== 0) throw new Error(`selftest failed: codex-lb repair exited ${codexLbRepair.code}: ${codexLbRepair.stderr}`);
|
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.
|
|
8
|
+
export const PACKAGE_VERSION = '0.7.66';
|
|
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
|
@@ -462,6 +462,34 @@ function mergeManagedCodexConfigToml(existingContent = '') {
|
|
|
462
462
|
return `${next.trim()}\n`;
|
|
463
463
|
}
|
|
464
464
|
|
|
465
|
+
async function mergeGlobalCodexConfigIfAvailable(configText = '', configPath = '') {
|
|
466
|
+
const selectedRe = /(^|\n)\s*model_provider\s*=\s*"codex-lb"\s*(?:#.*)?(?=\n|$)/;
|
|
467
|
+
const home = process.env.HOME || '';
|
|
468
|
+
if (!home) return configText;
|
|
469
|
+
const globalConfigPath = path.join(home, '.codex', 'config.toml');
|
|
470
|
+
if (configPath && path.resolve(configPath) === path.resolve(globalConfigPath)) return configText;
|
|
471
|
+
const globalConfig = await readText(globalConfigPath, '');
|
|
472
|
+
let next = mergeGlobalMcpServers(configText, globalConfig);
|
|
473
|
+
if (selectedRe.test(next) && /\[model_providers\.codex-lb\]/.test(next)) return `${String(next || '').trim()}\n`;
|
|
474
|
+
if (!(await exists(path.join(home, '.codex', 'sks-codex-lb.env')))) return next;
|
|
475
|
+
const baseUrl = globalConfig.match(/(^|\n)\[model_providers\.codex-lb\][\s\S]*?\n\s*base_url\s*=\s*"([^"]+)"/)?.[2];
|
|
476
|
+
if (!selectedRe.test(globalConfig) || !baseUrl) return next;
|
|
477
|
+
next = upsertTopLevelTomlString(next, 'model_provider', 'codex-lb');
|
|
478
|
+
next = upsertTomlTable(next, 'model_providers.codex-lb', `[model_providers.codex-lb]\nname = "OpenAI"\nbase_url = "${baseUrl}"\nwire_api = "responses"\nenv_key = "CODEX_LB_API_KEY"\nsupports_websockets = true\nrequires_openai_auth = true`);
|
|
479
|
+
return `${next.trim()}\n`;
|
|
480
|
+
}
|
|
481
|
+
|
|
482
|
+
function mergeGlobalMcpServers(configText = '', globalConfig = '') {
|
|
483
|
+
let next = configText;
|
|
484
|
+
const re = /(?:^|\n)(\[(mcp_servers\.[^\]\r\n]+)\][\s\S]*?)(?=\n\[[^\]]+\]|\s*$)/g;
|
|
485
|
+
for (const match of String(globalConfig || '').matchAll(re)) {
|
|
486
|
+
const block = match[1].trim();
|
|
487
|
+
const table = match[2].trim();
|
|
488
|
+
if (!new RegExp(`(^|\\n)\\[${escapeRegExp(table)}\\]`).test(next)) next = upsertTomlTable(next, table, block);
|
|
489
|
+
}
|
|
490
|
+
return next;
|
|
491
|
+
}
|
|
492
|
+
|
|
465
493
|
function removeLegacyTopLevelCodexModeLocks(text = '') {
|
|
466
494
|
const legacy = {
|
|
467
495
|
model_reasoning_effort: new Set(['high'])
|
|
@@ -619,7 +647,11 @@ function upsertTomlTable(text, table, block) {
|
|
|
619
647
|
|
|
620
648
|
const generatedCodexConfigPath = path.join(root, '.codex', 'config.toml');
|
|
621
649
|
const existingCodexConfig = await readText(generatedCodexConfigPath, '');
|
|
622
|
-
await
|
|
650
|
+
const managedCodexConfig = await mergeGlobalCodexConfigIfAvailable(
|
|
651
|
+
mergeManagedCodexConfigToml(existingCodexConfig),
|
|
652
|
+
generatedCodexConfigPath
|
|
653
|
+
);
|
|
654
|
+
await writeTextAtomic(generatedCodexConfigPath, managedCodexConfig);
|
|
623
655
|
created.push('.codex/config.toml');
|
|
624
656
|
|
|
625
657
|
await writeTextAtomic(path.join(root, '.codex', 'SNEAKOSCOPE.md'), codexAppQuickReference(installScope, hookCommandPrefix));
|