sneakoscope 0.6.35 → 0.6.36
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 +1 -1
- package/package.json +1 -1
- package/src/cli/main.mjs +4 -2
- package/src/core/auto-review.mjs +17 -7
- package/src/core/codex-app.mjs +18 -2
- package/src/core/fsx.mjs +1 -1
package/README.md
CHANGED
|
@@ -45,7 +45,7 @@ Prompt routes use one canonical name each: `$DFix`, `$Answer`, `$SKS`, `$Team`,
|
|
|
45
45
|
|
|
46
46
|
Run `sks setup` once. SKS creates hooks/skills plus `.sneakoscope/` mission/wiki/policy state. Hooks inject context/status or block a turn; Team status is mirrored to `team-live.md`, `team-transcript.jsonl`, and `sks team watch latest`.
|
|
47
47
|
|
|
48
|
-
Codex CLI parity is gated on Codex App because App-provisioned MCP/plugin tools are shared with CLI sessions. `sks` opens the tmux runtime after `sks codex-app check` and `sks tmux check` pass. `sks --Auto-review --high` enables Codex `
|
|
48
|
+
Codex CLI parity is gated on Codex App because App-provisioned MCP/plugin tools are shared with CLI sessions. `sks` opens the tmux runtime after `sks codex-app check` and `sks tmux check` pass. `sks --Auto-review --high` enables the Codex `guardian_subagent` approvals reviewer and launches the ㅅㅋㅅ tmux runtime with a high-reasoning profile. QA-LOOP prioritizes Browser Use for local browser targets and Computer Use for desktop/browser evidence.
|
|
49
49
|
|
|
50
50
|
## TriWiki
|
|
51
51
|
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "sneakoscope",
|
|
3
3
|
"displayName": "Sneakoscope Codex",
|
|
4
|
-
"version": "0.6.
|
|
4
|
+
"version": "0.6.36",
|
|
5
5
|
"description": "Sneakoscope Codex: update-aware, database-safe Codex CLI harness with multi-agent Team orchestration, Ralph no-question execution, autoresearch-style loops, and H-Proof gates.",
|
|
6
6
|
"type": "module",
|
|
7
7
|
"homepage": "https://github.com/mandarange/Sneakoscope-Codex#readme",
|
package/src/cli/main.mjs
CHANGED
|
@@ -1149,7 +1149,7 @@ Inspect or disable:
|
|
|
1149
1149
|
sks auto-review disable
|
|
1150
1150
|
|
|
1151
1151
|
Effect:
|
|
1152
|
-
Writes approvals_reviewer = "
|
|
1152
|
+
Writes approvals_reviewer = "guardian_subagent" to Codex config and creates sks-auto-review / sks-auto-review-high profiles.
|
|
1153
1153
|
Automatic review applies only to approval prompts that are already interactive under approval_policy = "on-request" or granular approval policies.
|
|
1154
1154
|
`,
|
|
1155
1155
|
team: `Team Workflow
|
|
@@ -2517,9 +2517,11 @@ async function selftest() {
|
|
|
2517
2517
|
const autoReviewEnabled = await enableAutoReview({ env: autoReviewEnv, high: true });
|
|
2518
2518
|
if (!autoReviewEnabled.enabled || autoReviewEnabled.profile_name !== 'sks-auto-review-high' || !autoReviewEnabled.high_profile) throw new Error('selftest failed: auto-review high profile was not enabled');
|
|
2519
2519
|
const autoReviewConfig = await safeReadText(path.join(autoReviewHome, '.codex', 'config.toml'));
|
|
2520
|
-
if (!autoReviewConfig.includes('approvals_reviewer = "auto_review"') || !autoReviewConfig.includes('[profiles.sks-auto-review-high]')) throw new Error('selftest failed: auto-review config not written');
|
|
2520
|
+
if (!autoReviewConfig.includes('approvals_reviewer = "guardian_subagent"') || autoReviewConfig.includes('approvals_reviewer = "auto_review"') || !autoReviewConfig.includes('[profiles.sks-auto-review-high]')) throw new Error('selftest failed: auto-review config not written');
|
|
2521
2521
|
const autoReviewDisabled = await disableAutoReview({ env: autoReviewEnv });
|
|
2522
2522
|
if (autoReviewDisabled.enabled || autoReviewDisabled.approvals_reviewer !== 'user') throw new Error('selftest failed: auto-review disable did not restore user reviewer');
|
|
2523
|
+
const autoReviewDisabledConfig = await safeReadText(path.join(autoReviewHome, '.codex', 'config.toml'));
|
|
2524
|
+
if (autoReviewDisabledConfig.includes('approvals_reviewer = "auto_review"')) throw new Error('selftest failed: auto-review disable left legacy invalid reviewer values');
|
|
2523
2525
|
const analysisAgentExists = await exists(path.join(tmp, '.codex', 'agents', 'analysis-scout.toml'));
|
|
2524
2526
|
if (!analysisAgentExists) throw new Error('selftest failed: analysis scout agent not installed');
|
|
2525
2527
|
const teamAgentExists = await exists(path.join(tmp, '.codex', 'agents', 'team-consensus.toml'));
|
package/src/core/auto-review.mjs
CHANGED
|
@@ -2,7 +2,8 @@ import os from 'node:os';
|
|
|
2
2
|
import path from 'node:path';
|
|
3
3
|
import { ensureDir, exists, readText, writeTextAtomic } from './fsx.mjs';
|
|
4
4
|
|
|
5
|
-
export const AUTO_REVIEW_REVIEWER = '
|
|
5
|
+
export const AUTO_REVIEW_REVIEWER = 'guardian_subagent';
|
|
6
|
+
export const LEGACY_AUTO_REVIEW_REVIEWER = 'auto_review';
|
|
6
7
|
export const AUTO_REVIEW_PROFILE = 'sks-auto-review';
|
|
7
8
|
export const AUTO_REVIEW_HIGH_PROFILE = 'sks-auto-review-high';
|
|
8
9
|
|
|
@@ -21,13 +22,17 @@ export function autoReviewProfileName(opts = {}) {
|
|
|
21
22
|
export async function autoReviewStatus(opts = {}) {
|
|
22
23
|
const configPath = opts.configPath || codexConfigPath(opts.env || process.env);
|
|
23
24
|
const text = await readText(configPath, '');
|
|
25
|
+
const approvalsReviewer = readTomlString(text, 'approvals_reviewer');
|
|
26
|
+
const profileReviewer = readTableString(text, `profiles.${AUTO_REVIEW_PROFILE}`, 'approvals_reviewer');
|
|
27
|
+
const highProfileReviewer = readTableString(text, `profiles.${AUTO_REVIEW_HIGH_PROFILE}`, 'approvals_reviewer');
|
|
24
28
|
return {
|
|
25
29
|
config_path: configPath,
|
|
26
30
|
exists: await exists(configPath),
|
|
27
|
-
approvals_reviewer:
|
|
28
|
-
enabled:
|
|
29
|
-
profile:
|
|
30
|
-
high_profile:
|
|
31
|
+
approvals_reviewer: approvalsReviewer,
|
|
32
|
+
enabled: approvalsReviewer === AUTO_REVIEW_REVIEWER,
|
|
33
|
+
profile: profileReviewer === AUTO_REVIEW_REVIEWER,
|
|
34
|
+
high_profile: highProfileReviewer === AUTO_REVIEW_REVIEWER,
|
|
35
|
+
legacy_invalid: [approvalsReviewer, profileReviewer, highProfileReviewer].includes(LEGACY_AUTO_REVIEW_REVIEWER),
|
|
31
36
|
policy: readTableString(text, 'auto_review', 'policy') || ''
|
|
32
37
|
};
|
|
33
38
|
}
|
|
@@ -55,6 +60,8 @@ export async function disableAutoReview(opts = {}) {
|
|
|
55
60
|
const configPath = opts.configPath || codexConfigPath(opts.env || process.env);
|
|
56
61
|
const current = await readText(configPath, '');
|
|
57
62
|
let next = upsertTopLevelString(current, 'approvals_reviewer', 'user');
|
|
63
|
+
if (tableBody(next, `profiles.${AUTO_REVIEW_PROFILE}`)) next = upsertProfile(next, AUTO_REVIEW_PROFILE, 'medium', 'user');
|
|
64
|
+
if (tableBody(next, `profiles.${AUTO_REVIEW_HIGH_PROFILE}`)) next = upsertProfile(next, AUTO_REVIEW_HIGH_PROFILE, 'high', 'user');
|
|
58
65
|
if (!next.endsWith('\n')) next += '\n';
|
|
59
66
|
await writeTextAtomic(configPath, next);
|
|
60
67
|
return autoReviewStatus({ configPath });
|
|
@@ -74,6 +81,9 @@ export function autoReviewSummary(status = {}) {
|
|
|
74
81
|
lines.push('', 'Enable with: sks auto-review enable');
|
|
75
82
|
lines.push('Launch high mode with: sks --Auto-review --high');
|
|
76
83
|
}
|
|
84
|
+
if (status.legacy_invalid) {
|
|
85
|
+
lines.push('', 'Legacy invalid reviewer value found: run sks auto-review enable or sks auto-review disable to rewrite Codex config.');
|
|
86
|
+
}
|
|
77
87
|
return lines.join('\n');
|
|
78
88
|
}
|
|
79
89
|
|
|
@@ -123,12 +133,12 @@ function upsertTopLevelString(text, key, value) {
|
|
|
123
133
|
return lines.join('\n').replace(/^\n+/, '').replace(/\n{3,}/g, '\n\n');
|
|
124
134
|
}
|
|
125
135
|
|
|
126
|
-
function upsertProfile(text, profile, effort) {
|
|
136
|
+
function upsertProfile(text, profile, effort, reviewer = AUTO_REVIEW_REVIEWER) {
|
|
127
137
|
const block = [
|
|
128
138
|
`[profiles.${profile}]`,
|
|
129
139
|
'model = "gpt-5.5"',
|
|
130
140
|
'approval_policy = "on-request"',
|
|
131
|
-
|
|
141
|
+
`approvals_reviewer = "${reviewer}"`,
|
|
132
142
|
'sandbox_mode = "workspace-write"',
|
|
133
143
|
`model_reasoning_effort = "${effort}"`
|
|
134
144
|
].join('\n');
|
package/src/core/codex-app.mjs
CHANGED
|
@@ -111,17 +111,21 @@ export async function codexAppIntegrationStatus(opts = {}) {
|
|
|
111
111
|
computer_use_cache: computerUsePath,
|
|
112
112
|
browser_use_cache: browserUsePath
|
|
113
113
|
},
|
|
114
|
-
guidance: codexAppGuidance({ appInstalled, codex, computerUseReady, browserUseReady })
|
|
114
|
+
guidance: codexAppGuidance({ appInstalled, codex, mcpList, computerUseReady, browserUseReady })
|
|
115
115
|
};
|
|
116
116
|
}
|
|
117
117
|
|
|
118
|
-
export function codexAppGuidance({ appInstalled, codex, computerUseReady, browserUseReady }) {
|
|
118
|
+
export function codexAppGuidance({ appInstalled, codex, mcpList, computerUseReady, browserUseReady }) {
|
|
119
119
|
const lines = [];
|
|
120
120
|
if (!appInstalled) {
|
|
121
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.');
|
|
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.');
|
|
125
|
+
if (mcpList?.checked && !mcpList.ok) {
|
|
126
|
+
lines.push(`Codex MCP/config check failed: ${summarizeCodexMcpError(mcpList.stderr || mcpList.stdout)}`);
|
|
127
|
+
lines.push('Verify with: codex mcp list');
|
|
128
|
+
}
|
|
125
129
|
if (appInstalled && (!computerUseReady || !browserUseReady)) {
|
|
126
130
|
lines.push('Open Codex App settings, enable recommended MCP/plugin tools, then restart Codex CLI sessions.');
|
|
127
131
|
lines.push('Required for SKS QA-LOOP priority order: Browser Use for local browser targets, Computer Use for desktop/app/browser evidence.');
|
|
@@ -146,3 +150,15 @@ export function formatCodexAppStatus(status, { includeRaw = false } = {}) {
|
|
|
146
150
|
if (includeRaw && status.mcp.stdout) lines.push('', status.mcp.stdout.trim());
|
|
147
151
|
return lines.join('\n');
|
|
148
152
|
}
|
|
153
|
+
|
|
154
|
+
function summarizeCodexMcpError(text) {
|
|
155
|
+
const cleanLines = String(text || '')
|
|
156
|
+
.split(/\r?\n/)
|
|
157
|
+
.map((line) => line.trim())
|
|
158
|
+
.filter(Boolean)
|
|
159
|
+
.filter((line) => !line.startsWith('WARNING: proceeding'));
|
|
160
|
+
const variantLine = cleanLines.find((line) => line.includes('unknown variant'));
|
|
161
|
+
const errorLine = cleanLines.find((line) => line.startsWith('Error:'));
|
|
162
|
+
if (errorLine && variantLine && errorLine !== variantLine) return `${errorLine}; ${variantLine}`;
|
|
163
|
+
return variantLine || errorLine || cleanLines[0] || 'codex mcp list failed';
|
|
164
|
+
}
|
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.
|
|
8
|
+
export const PACKAGE_VERSION = '0.6.36';
|
|
9
9
|
export const DEFAULT_PROCESS_TAIL_BYTES = 256 * 1024;
|
|
10
10
|
export const DEFAULT_PROCESS_TIMEOUT_MS = 30 * 60 * 1000;
|
|
11
11
|
|