sneakoscope 4.0.1 → 4.0.3
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 +7 -7
- package/crates/sks-core/Cargo.lock +1 -1
- package/crates/sks-core/Cargo.toml +1 -1
- package/crates/sks-core/src/main.rs +1 -1
- package/dist/bin/sks.js +1 -1
- package/dist/cli/command-registry.js +1 -0
- package/dist/cli/global-mode-router.js +25 -0
- package/dist/cli/router.js +12 -0
- package/dist/commands/codex-app.js +10 -1
- package/dist/commands/codex.js +15 -1
- package/dist/core/build/build-once-runner.js +49 -16
- package/dist/core/codex-app/glm-model-profile.js +2 -0
- package/dist/core/codex-app/glm-profile-installer.js +61 -0
- package/dist/core/codex-app/glm-profile-schema.js +24 -0
- package/dist/core/codex-control/codex-0141-capability.js +95 -0
- package/dist/core/commands/daemon-command.js +1 -1
- package/dist/core/commands/glm-command.js +5 -0
- package/dist/core/daemon/sksd-client.js +7 -2
- package/dist/core/daemon/sksd-ipc.js +13 -3
- package/dist/core/daemon/sksd.js +62 -3
- package/dist/core/doctor/doctor-dirty-planner.js +97 -7
- package/dist/core/doctor/doctor-transaction.js +21 -5
- package/dist/core/fsx.js +1 -1
- package/dist/core/providers/glm/glm-52-profile.js +30 -0
- package/dist/core/providers/glm/glm-52-request.js +34 -0
- package/dist/core/providers/glm/glm-52-response-guard.js +34 -0
- package/dist/core/providers/glm/glm-52-settings.js +26 -0
- package/dist/core/providers/glm/glm-mad-mode.js +242 -0
- package/dist/core/providers/openrouter/openrouter-client.js +44 -0
- package/dist/core/providers/openrouter/openrouter-error.js +37 -0
- package/dist/core/providers/openrouter/openrouter-secret-store.js +113 -0
- package/dist/core/providers/openrouter/openrouter-types.js +2 -0
- package/dist/core/release/extreme-parallel-scheduler.js +124 -11
- package/dist/core/release/gate-pack-assertion.js +58 -0
- package/dist/core/release/gate-pack-fixture-cache.js +38 -2
- package/dist/core/release/gate-pack-manifest.js +2 -2
- package/dist/core/release/gate-pack-runner.js +9 -93
- package/dist/core/release/release-gate-cache-v2.js +71 -0
- package/dist/core/release/release-gate-dag.js +50 -5
- package/dist/core/release/release-gate-node.js +2 -0
- package/dist/core/release/release-gate-resource-governor.js +2 -0
- package/dist/core/release/resource-class-budget.js +1 -0
- package/dist/core/results.js +2 -0
- package/dist/core/secret-redaction.js +4 -0
- package/dist/core/security/redact-secrets.js +15 -0
- package/dist/core/triwiki/triwiki-affected-graph.js +35 -3
- package/dist/core/triwiki/triwiki-gate-impact-map.js +2 -0
- package/dist/core/triwiki/triwiki-proof-bank.js +12 -2
- package/dist/core/triwiki/triwiki-sla-certificate.js +3 -0
- package/dist/core/version.js +1 -1
- package/dist/scripts/release-4002-required-gates.js +14 -0
- package/dist/scripts/release-gate-dag-runner.js +2 -1
- package/dist/scripts/release-gate-existence-audit.js +1 -2
- package/package.json +16 -3
package/README.md
CHANGED
|
@@ -35,15 +35,15 @@ Set up this agent project with Sneakoscope Codex. Use [[mandarange/Sneakoscope-C
|
|
|
35
35
|
|
|
36
36
|
## 🚀 Current Release
|
|
37
37
|
|
|
38
|
-
SKS **4.0.
|
|
38
|
+
SKS **4.0.3** adds a GLM 5.2-only MAD mode through OpenRouter while preserving the proof-first SKS pipeline. `sks --mad --glm` resolves the GLM profile, keeps GPT/OpenAI fallback disabled, and records model-lock proof; `sks --mad --glm --repair` rotates the OpenRouter API key outside project files.
|
|
39
39
|
|
|
40
|
-
What changed in 4.0.
|
|
40
|
+
What changed in 4.0.3:
|
|
41
41
|
|
|
42
|
-
- **
|
|
43
|
-
- **
|
|
44
|
-
- **
|
|
45
|
-
- **
|
|
46
|
-
- **
|
|
42
|
+
- **GLM 5.2 MAD mode.** `sks --mad --glm` enters a `mad-glm` profile using OpenRouter model `z-ai/glm-5.2`.
|
|
43
|
+
- **No GPT fallback.** GLM requests use `provider.allow_fallbacks: false`, omit fallback `models`, and reject non-GLM response model ids before mutation.
|
|
44
|
+
- **OpenRouter key lifecycle.** Keys resolve from `OPENROUTER_API_KEY`, `SKS_OPENROUTER_API_KEY`, or the user SKS secret store; stored keys use private permissions and redacted metadata.
|
|
45
|
+
- **Codex App profile.** `sks codex-app glm-profile install` writes the `sks/glm-5.2-mad` profile metadata for Codex App selection.
|
|
46
|
+
- **Codex 0.141 alignment.** SKS delegates remote relay, cwd/shell/path preservation, selected plugin MCP activation, App/MCP dedupe, bounded prompt-image cache, bounded feedback upload, and terminal resize behavior to Codex-native semantics where available.
|
|
47
47
|
|
|
48
48
|
SKS **3.1.16** was a launch-reliability patch on the 3.1.15 doctor-reliability release. It made `sks --mad` self-bootstrap a fresh project instead of dead-ending on a missing Codex config.
|
|
49
49
|
|
|
@@ -4,7 +4,7 @@ use std::io::{self, Read, Seek, SeekFrom};
|
|
|
4
4
|
fn main() {
|
|
5
5
|
let mut args = std::env::args().skip(1);
|
|
6
6
|
match args.next().as_deref() {
|
|
7
|
-
Some("--version") => println!("sks-rs 4.0.
|
|
7
|
+
Some("--version") => println!("sks-rs 4.0.3"),
|
|
8
8
|
Some("compact-info") => {
|
|
9
9
|
let mut input = String::new();
|
|
10
10
|
let _ = io::stdin().read_to_string(&mut input);
|
package/dist/bin/sks.js
CHANGED
|
@@ -111,6 +111,7 @@ export const COMMANDS = {
|
|
|
111
111
|
'zellij-slot-column-anchor': entry('beta', 'Render the compact SLOTS anchor pane for first-slot-down Zellij stacks', 'dist/commands/zellij-slot-column-anchor.js', directCommand(() => import('../commands/zellij-slot-column-anchor.js'), 'dist/commands/zellij-slot-column-anchor.js')),
|
|
112
112
|
zellij: entry('beta', 'Inspect Zellij runtime status and explain repair (no auto-install)', 'dist/commands/zellij.js', directCommand(() => import('../commands/zellij.js'), 'dist/commands/zellij.js')),
|
|
113
113
|
'mad-sks': entry('beta', 'MAD-SKS scoped permission modifier', 'dist/commands/mad-sks.js', directCommand(() => import('../commands/mad-sks.js'), 'dist/commands/mad-sks.js')),
|
|
114
|
+
glm: entry('beta', 'Run GLM 5.2 MAD mode through OpenRouter', 'dist/core/commands/glm-command.js', argsCommand(() => import('../core/commands/glm-command.js'), 'glmCommand', 'dist/core/commands/glm-command.js')),
|
|
114
115
|
'mad-db': entry('beta', 'Create or inspect one-cycle Mad-DB break-glass capability tokens', 'dist/commands/mad-db.js', directCommand(() => import('../commands/mad-db.js'), 'dist/commands/mad-db.js')),
|
|
115
116
|
'auto-review': entry('beta', 'Manage auto-review profile', 'dist/commands/auto-review.js', directCommand(() => import('../commands/auto-review.js'), 'dist/commands/auto-review.js')),
|
|
116
117
|
'dollar-commands': entry('stable', 'List Codex App dollar commands', 'dist/core/commands/basic-cli.js', basicArgs('dollarCommandsCommand')),
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
const RESERVED_COMMANDS = new Set(['help', '--help', '-h', 'version', '--version', '-v']);
|
|
2
|
+
export function detectGlobalMode(args = []) {
|
|
3
|
+
if (!args.length || RESERVED_COMMANDS.has(String(args[0])))
|
|
4
|
+
return null;
|
|
5
|
+
const hasMad = args.includes('--mad');
|
|
6
|
+
const hasGlm = args.includes('--glm');
|
|
7
|
+
if (hasMad && hasGlm)
|
|
8
|
+
return { kind: 'mad-glm', args: stripGlobalModeFlags(args) };
|
|
9
|
+
if (hasGlm && !hasMad)
|
|
10
|
+
return { kind: 'glm-without-mad', args: stripGlobalModeFlags(args) };
|
|
11
|
+
return null;
|
|
12
|
+
}
|
|
13
|
+
export function stripGlobalModeFlags(args) {
|
|
14
|
+
return args.filter((arg) => arg !== '--mad' && arg !== '--glm');
|
|
15
|
+
}
|
|
16
|
+
export function glmWithoutMadResult() {
|
|
17
|
+
return {
|
|
18
|
+
ok: false,
|
|
19
|
+
status: 'blocked',
|
|
20
|
+
mode: 'glm',
|
|
21
|
+
reason: 'glm_requires_mad',
|
|
22
|
+
hint: 'use sks --mad --glm'
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
//# sourceMappingURL=global-mode-router.js.map
|
package/dist/cli/router.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { COMMAND_ALIASES, COMMANDS, } from './command-registry.js';
|
|
2
|
+
import { detectGlobalMode, glmWithoutMadResult } from './global-mode-router.js';
|
|
2
3
|
export function isCommandName(value) {
|
|
3
4
|
return Object.prototype.hasOwnProperty.call(COMMANDS, value);
|
|
4
5
|
}
|
|
@@ -18,6 +19,17 @@ export function normalizeCommand(args = []) {
|
|
|
18
19
|
}
|
|
19
20
|
export async function dispatch(args) {
|
|
20
21
|
const argv = args ?? process.argv.slice(2);
|
|
22
|
+
const globalMode = detectGlobalMode(argv);
|
|
23
|
+
if (globalMode?.kind === 'mad-glm') {
|
|
24
|
+
const mod = await import('../core/commands/glm-command.js');
|
|
25
|
+
return mod.glmCommand(globalMode.args);
|
|
26
|
+
}
|
|
27
|
+
if (globalMode?.kind === 'glm-without-mad') {
|
|
28
|
+
const result = glmWithoutMadResult();
|
|
29
|
+
console.error(`GLM mode requires MAD: ${result.hint}`);
|
|
30
|
+
process.exitCode = 1;
|
|
31
|
+
return result;
|
|
32
|
+
}
|
|
21
33
|
const { command, rawCommand, args: rest } = normalizeCommand(argv);
|
|
22
34
|
if (!command) {
|
|
23
35
|
if (!argv.length) {
|
|
@@ -10,6 +10,7 @@ import { runCodexInitDeep } from '../core/codex-app/codex-init-deep.js';
|
|
|
10
10
|
import { buildCodexHookLifecycle } from '../core/codex-app/codex-hook-lifecycle.js';
|
|
11
11
|
import { resolveCodexAppExecutionProfile } from '../core/codex-app/codex-app-execution-profile.js';
|
|
12
12
|
import { repairCodexNativeManagedAssets } from '../core/codex-native/codex-native-repair-transaction.js';
|
|
13
|
+
import { doctorCodexAppGlmProfile, installCodexAppGlmProfile } from '../core/codex-app/glm-profile-installer.js';
|
|
13
14
|
export async function run(_command, args = []) {
|
|
14
15
|
const action = args[0] || 'check';
|
|
15
16
|
if (action === 'remote-control' || action === 'remote')
|
|
@@ -28,6 +29,14 @@ export async function run(_command, args = []) {
|
|
|
28
29
|
return printCodexAppResult(args, await buildCodexHookLifecycle({ root: await sksRoot(), apply: flag(args, '--apply') || flag(args, '--fix') }));
|
|
29
30
|
if (action === 'execution-profile')
|
|
30
31
|
return printCodexAppResult(args, await resolveCodexAppExecutionProfile({ root: await sksRoot() }));
|
|
32
|
+
if (action === 'glm-profile') {
|
|
33
|
+
const subcommand = args[1] || 'doctor';
|
|
34
|
+
const root = await sksRoot();
|
|
35
|
+
const result = subcommand === 'install' || subcommand === 'repair'
|
|
36
|
+
? await installCodexAppGlmProfile({ root, apply: true })
|
|
37
|
+
: await doctorCodexAppGlmProfile({ root });
|
|
38
|
+
return printCodexAppResult(args, result);
|
|
39
|
+
}
|
|
31
40
|
if (action === 'product-design' || action === 'design-product' || action === 'ensure-product-design') {
|
|
32
41
|
const checkOnly = flag(args, '--check-only') || flag(args, '--no-install');
|
|
33
42
|
const status = await codexProductDesignPluginStatus({
|
|
@@ -88,7 +97,7 @@ export async function run(_command, args = []) {
|
|
|
88
97
|
process.exitCode = 1;
|
|
89
98
|
return;
|
|
90
99
|
}
|
|
91
|
-
console.error('Usage: sks codex-app check|status|harness-matrix|skill-sync|agent-role-sync|init-deep|hook-lifecycle|execution-profile|product-design [--check-only]|ensure-product-design|chrome-extension|pat status|remote-control [--json]');
|
|
100
|
+
console.error('Usage: sks codex-app check|status|harness-matrix|skill-sync|agent-role-sync|init-deep|hook-lifecycle|execution-profile|glm-profile [install|doctor]|product-design [--check-only]|ensure-product-design|chrome-extension|pat status|remote-control [--json]');
|
|
92
101
|
process.exitCode = 1;
|
|
93
102
|
}
|
|
94
103
|
function printCodexAppResult(args = [], result) {
|
package/dist/commands/codex.js
CHANGED
|
@@ -3,6 +3,7 @@ import { printJson } from '../cli/output.js';
|
|
|
3
3
|
import { codexCompatibilityReport, codexDoctorReport } from '../core/codex-compat/codex-compat-report.js';
|
|
4
4
|
import { codexVersionReport } from '../core/codex-compat/codex-version.js';
|
|
5
5
|
import { codexSchemaSnapshotReport } from '../core/codex-compat/codex-schema-snapshot.js';
|
|
6
|
+
import { detectCodex0141Capability } from '../core/codex-control/codex-0141-capability.js';
|
|
6
7
|
export async function run(_command, args = []) {
|
|
7
8
|
const action = args[0] || 'compatibility';
|
|
8
9
|
if (action === 'compatibility' || action === 'compat') {
|
|
@@ -24,6 +25,19 @@ export async function run(_command, args = []) {
|
|
|
24
25
|
console.log(`Codex detected: ${result.detected.version || 'not installed'} (${result.policy.status})`);
|
|
25
26
|
return;
|
|
26
27
|
}
|
|
28
|
+
if (action === '0.141' || action === '0141' || action === 'rust-v0.141.0') {
|
|
29
|
+
const result = await detectCodex0141Capability();
|
|
30
|
+
if (flag(args, '--json'))
|
|
31
|
+
return printJson(result);
|
|
32
|
+
console.log(`Codex 0.141 compatibility: ${result.ok ? 'ok' : 'blocked'}`);
|
|
33
|
+
for (const blocker of result.blockers || [])
|
|
34
|
+
console.log(`- blocker: ${blocker}`);
|
|
35
|
+
for (const warning of result.warnings || [])
|
|
36
|
+
console.log(`- warning: ${warning}`);
|
|
37
|
+
if (!result.ok)
|
|
38
|
+
process.exitCode = 1;
|
|
39
|
+
return;
|
|
40
|
+
}
|
|
27
41
|
if (action === 'doctor') {
|
|
28
42
|
const result = await codexDoctorReport();
|
|
29
43
|
if (flag(args, '--json'))
|
|
@@ -42,7 +56,7 @@ export async function run(_command, args = []) {
|
|
|
42
56
|
process.exitCode = 1;
|
|
43
57
|
return;
|
|
44
58
|
}
|
|
45
|
-
console.error('Usage: sks codex compatibility|version|doctor|schema [--json]');
|
|
59
|
+
console.error('Usage: sks codex compatibility|version|doctor|schema|0.141 [--json]');
|
|
46
60
|
process.exitCode = 1;
|
|
47
61
|
}
|
|
48
62
|
//# sourceMappingURL=codex.js.map
|
|
@@ -4,42 +4,57 @@ import path from 'node:path';
|
|
|
4
4
|
import { computeTriWikiCacheKey } from '../triwiki/triwiki-cache-key.js';
|
|
5
5
|
export const BUILD_ONCE_PROOF_SCHEMA = 'sks.build-once-proof.v1';
|
|
6
6
|
export function runBuildOnce(input) {
|
|
7
|
+
const root = path.resolve(input.root);
|
|
7
8
|
const mode = input.mode || 'incremental';
|
|
8
9
|
const key = computeTriWikiCacheKey({
|
|
9
|
-
root
|
|
10
|
-
id:
|
|
11
|
-
inputs: ['src/**/*.ts', 'package.json', 'package-lock.json', 'tsconfig.json'],
|
|
12
|
-
implementationFiles: ['tsconfig.json'],
|
|
10
|
+
root,
|
|
11
|
+
id: 'build-once',
|
|
12
|
+
inputs: ['src/**/*.ts', 'package.json', 'package-lock.json', 'tsconfig.json', 'src/scripts/build*.ts', 'src/scripts/ensure-bin-executable.ts'],
|
|
13
|
+
implementationFiles: ['tsconfig.json', 'src/core/build/build-once-runner.ts', 'src/scripts/build-once-runner-check.ts'],
|
|
13
14
|
envAllowlist: ['NODE_ENV', 'CI'],
|
|
14
|
-
fixtureVersion: 'sks-4.0.
|
|
15
|
+
fixtureVersion: 'sks-4.0.2'
|
|
15
16
|
});
|
|
16
|
-
const existing = readBuildOnceProof(
|
|
17
|
-
if (!input.force && existing?.ok === true && existing.cache_key === key.key) {
|
|
18
|
-
return { ...existing, reused: true };
|
|
17
|
+
const existing = readBuildOnceProof(root);
|
|
18
|
+
if (!input.force && existing?.ok === true && existing.cache_key === key.key && distTargetsReady(root).length === 0) {
|
|
19
|
+
return { ...existing, mode, reused: true };
|
|
20
|
+
}
|
|
21
|
+
if (mode === 'clean') {
|
|
22
|
+
fs.rmSync(path.join(root, 'dist'), { recursive: true, force: true });
|
|
23
|
+
fs.rmSync(path.join(root, '.sneakoscope', 'cache', 'tsbuildinfo'), { recursive: true, force: true });
|
|
19
24
|
}
|
|
20
25
|
const started = Date.now();
|
|
26
|
+
const startedAt = new Date(started).toISOString();
|
|
21
27
|
const run = spawnSync('npm', ['run', mode === 'clean' ? 'build:clean' : 'build:incremental', '--silent'], {
|
|
22
|
-
cwd:
|
|
28
|
+
cwd: root,
|
|
23
29
|
encoding: 'utf8',
|
|
24
30
|
maxBuffer: 1024 * 1024 * 20,
|
|
25
|
-
env: { ...process.env, CI: process.env.CI || 'true' }
|
|
31
|
+
env: { ...process.env, ...(input.env || {}), CI: process.env.CI || input.env?.CI || 'true' }
|
|
26
32
|
});
|
|
33
|
+
const missingDistTargets = distTargetsReady(root);
|
|
34
|
+
const blockers = [
|
|
35
|
+
...(run.status === 0 ? [] : [`build_failed:${run.status ?? 'signal'}`]),
|
|
36
|
+
...missingDistTargets.map((target) => `dist_target_missing:${target}`)
|
|
37
|
+
];
|
|
38
|
+
const completedAt = new Date().toISOString();
|
|
27
39
|
const proof = {
|
|
28
40
|
schema: BUILD_ONCE_PROOF_SCHEMA,
|
|
29
|
-
ok: run.status === 0,
|
|
41
|
+
ok: run.status === 0 && missingDistTargets.length === 0,
|
|
42
|
+
root,
|
|
30
43
|
mode,
|
|
31
44
|
cache_key: key.key,
|
|
32
45
|
source_hash: key.input_hash,
|
|
33
46
|
package_lock_hash: key.package_lock_hash,
|
|
34
|
-
tsconfig_hash: computeTriWikiCacheKey({ root
|
|
35
|
-
dist_hash: computeTriWikiCacheKey({ root
|
|
36
|
-
|
|
47
|
+
tsconfig_hash: computeTriWikiCacheKey({ root, id: 'build-once:tsconfig', inputs: ['tsconfig.json'] }).input_hash,
|
|
48
|
+
dist_hash: computeTriWikiCacheKey({ root, id: 'build-once:dist', inputs: ['dist'] }).input_hash,
|
|
49
|
+
started_at: startedAt,
|
|
50
|
+
completed_at: completedAt,
|
|
51
|
+
created_at: completedAt,
|
|
37
52
|
status: run.status,
|
|
38
53
|
duration_ms: Math.max(0, Date.now() - started),
|
|
39
54
|
reused: false,
|
|
40
|
-
blockers
|
|
55
|
+
blockers
|
|
41
56
|
};
|
|
42
|
-
writeBuildOnceProof(
|
|
57
|
+
writeBuildOnceProof(root, proof);
|
|
43
58
|
return proof;
|
|
44
59
|
}
|
|
45
60
|
export function readBuildOnceProof(root) {
|
|
@@ -58,9 +73,27 @@ export function writeBuildOnceProof(root, proof) {
|
|
|
58
73
|
const file = buildProofPath(root);
|
|
59
74
|
fs.mkdirSync(path.dirname(file), { recursive: true });
|
|
60
75
|
fs.writeFileSync(file, `${JSON.stringify(proof, null, 2)}\n`);
|
|
76
|
+
const report = path.join(root, '.sneakoscope', 'reports', 'build-once-proof.json');
|
|
77
|
+
fs.mkdirSync(path.dirname(report), { recursive: true });
|
|
78
|
+
fs.writeFileSync(report, `${JSON.stringify(proof, null, 2)}\n`);
|
|
61
79
|
return file;
|
|
62
80
|
}
|
|
63
81
|
function buildProofPath(root) {
|
|
64
82
|
return path.join(root, 'dist', '.sks-build-proof.json');
|
|
65
83
|
}
|
|
84
|
+
function distTargetsReady(root) {
|
|
85
|
+
const required = new Set(['dist/bin/sks.js']);
|
|
86
|
+
try {
|
|
87
|
+
const pkg = JSON.parse(fs.readFileSync(path.join(root, 'package.json'), 'utf8'));
|
|
88
|
+
for (const command of Object.values(pkg.scripts || {})) {
|
|
89
|
+
const match = String(command).match(/node\s+\.\/dist\/scripts\/([^\s]+\.js)/);
|
|
90
|
+
if (match?.[1])
|
|
91
|
+
required.add(`dist/scripts/${match[1]}`);
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
catch {
|
|
95
|
+
required.add('dist/scripts/build-once-runner-check.js');
|
|
96
|
+
}
|
|
97
|
+
return [...required].sort().filter((rel) => !fs.existsSync(path.join(root, rel)));
|
|
98
|
+
}
|
|
66
99
|
//# sourceMappingURL=build-once-runner.js.map
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import path from 'node:path';
|
|
2
|
+
import { readJson, writeJsonAtomic, nowIso } from '../fsx.js';
|
|
3
|
+
import { buildGlmCodexAppModelProfile } from './glm-model-profile.js';
|
|
4
|
+
import { validateGlmCodexAppModelProfile } from './glm-profile-schema.js';
|
|
5
|
+
import { resolveOpenRouterApiKey } from '../providers/openrouter/openrouter-secret-store.js';
|
|
6
|
+
export async function installCodexAppGlmProfile(input) {
|
|
7
|
+
const root = path.resolve(input.root);
|
|
8
|
+
const profile = buildGlmCodexAppModelProfile();
|
|
9
|
+
const profilePath = path.join(root, '.sneakoscope', 'codex-app', 'glm-model-profile.json');
|
|
10
|
+
const reportPath = path.join(root, '.sneakoscope', 'reports', 'codex-app-glm-profile.json');
|
|
11
|
+
const key = await resolveOpenRouterApiKey({ env: input.env || process.env });
|
|
12
|
+
const warnings = [
|
|
13
|
+
...key.warnings,
|
|
14
|
+
...(key.key ? [] : ['openrouter_key_missing_until_sks_--mad_--glm_--repair'])
|
|
15
|
+
];
|
|
16
|
+
if (input.apply !== false)
|
|
17
|
+
await writeJsonAtomic(profilePath, profile);
|
|
18
|
+
const result = {
|
|
19
|
+
schema: 'sks.codex-app-glm-profile-result.v1',
|
|
20
|
+
generated_at: nowIso(),
|
|
21
|
+
ok: true,
|
|
22
|
+
status: input.apply === false ? 'valid' : 'installed',
|
|
23
|
+
profile,
|
|
24
|
+
profile_path: '.sneakoscope/codex-app/glm-model-profile.json',
|
|
25
|
+
report_path: '.sneakoscope/reports/codex-app-glm-profile.json',
|
|
26
|
+
openrouter_key_source: key.source,
|
|
27
|
+
blockers: [],
|
|
28
|
+
warnings
|
|
29
|
+
};
|
|
30
|
+
await writeJsonAtomic(reportPath, result).catch(() => undefined);
|
|
31
|
+
return result;
|
|
32
|
+
}
|
|
33
|
+
export async function doctorCodexAppGlmProfile(input) {
|
|
34
|
+
const root = path.resolve(input.root);
|
|
35
|
+
const profilePath = path.join(root, '.sneakoscope', 'codex-app', 'glm-model-profile.json');
|
|
36
|
+
const reportPath = path.join(root, '.sneakoscope', 'reports', 'codex-app-glm-profile.json');
|
|
37
|
+
const existing = await readJson(profilePath, null);
|
|
38
|
+
const validation = validateGlmCodexAppModelProfile(existing);
|
|
39
|
+
const key = await resolveOpenRouterApiKey({ env: input.env || process.env });
|
|
40
|
+
const profile = validation.profile || buildGlmCodexAppModelProfile();
|
|
41
|
+
const blockers = [...validation.blockers];
|
|
42
|
+
const warnings = [
|
|
43
|
+
...key.warnings,
|
|
44
|
+
...(key.key ? [] : ['openrouter_key_missing_until_sks_--mad_--glm_--repair'])
|
|
45
|
+
];
|
|
46
|
+
const result = {
|
|
47
|
+
schema: 'sks.codex-app-glm-profile-result.v1',
|
|
48
|
+
generated_at: nowIso(),
|
|
49
|
+
ok: blockers.length === 0,
|
|
50
|
+
status: blockers.length === 0 ? 'valid' : 'blocked',
|
|
51
|
+
profile,
|
|
52
|
+
profile_path: '.sneakoscope/codex-app/glm-model-profile.json',
|
|
53
|
+
report_path: '.sneakoscope/reports/codex-app-glm-profile.json',
|
|
54
|
+
openrouter_key_source: key.source,
|
|
55
|
+
blockers,
|
|
56
|
+
warnings
|
|
57
|
+
};
|
|
58
|
+
await writeJsonAtomic(reportPath, result).catch(() => undefined);
|
|
59
|
+
return result;
|
|
60
|
+
}
|
|
61
|
+
//# sourceMappingURL=glm-profile-installer.js.map
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { GLM_CODEX_APP_PROFILE_ID, buildGlmCodexAppModelProfile } from './glm-model-profile.js';
|
|
2
|
+
import { GLM_52_OPENROUTER_MODEL, GLM_MAD_MODE } from '../providers/glm/glm-52-settings.js';
|
|
3
|
+
export function validateGlmCodexAppModelProfile(value) {
|
|
4
|
+
if (!value || typeof value !== 'object' || Array.isArray(value)) {
|
|
5
|
+
return { ok: false, blockers: ['glm_codex_app_profile_missing'], profile: null };
|
|
6
|
+
}
|
|
7
|
+
const profile = value;
|
|
8
|
+
const expected = buildGlmCodexAppModelProfile();
|
|
9
|
+
const blockers = [
|
|
10
|
+
profile.schema === expected.schema ? null : 'glm_codex_app_profile_invalid_schema',
|
|
11
|
+
profile.id === GLM_CODEX_APP_PROFILE_ID ? null : 'glm_codex_app_profile_invalid_id',
|
|
12
|
+
profile.provider === 'openrouter' ? null : 'glm_codex_app_profile_invalid_provider',
|
|
13
|
+
profile.model === GLM_52_OPENROUTER_MODEL ? null : 'glm_codex_app_profile_invalid_model',
|
|
14
|
+
profile.mode === GLM_MAD_MODE ? null : 'glm_codex_app_profile_invalid_mode',
|
|
15
|
+
profile.strictModelLock === true ? null : 'glm_codex_app_profile_not_strict',
|
|
16
|
+
profile.gptFallbackAllowed === false ? null : 'glm_codex_app_profile_allows_gpt_fallback'
|
|
17
|
+
].filter((item) => Boolean(item));
|
|
18
|
+
return {
|
|
19
|
+
ok: blockers.length === 0,
|
|
20
|
+
blockers,
|
|
21
|
+
profile: blockers.length === 0 ? profile : null
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
//# sourceMappingURL=glm-profile-schema.js.map
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
import path from 'node:path';
|
|
2
|
+
import { findCodexBinary } from '../codex-adapter.js';
|
|
3
|
+
import { compareSemverLike, parseCodexVersionText } from '../codex-compat/codex-version-policy.js';
|
|
4
|
+
import { nowIso, runProcess, writeJsonAtomic } from '../fsx.js';
|
|
5
|
+
export const CODEX_0141_FEATURE_KEYS = [
|
|
6
|
+
'noise_relay_delegated',
|
|
7
|
+
'native_cwd_shell_path_preserved',
|
|
8
|
+
'permission_paths_preserved',
|
|
9
|
+
'selected_plugin_mcp_per_thread',
|
|
10
|
+
'auth_curated_marketplaces',
|
|
11
|
+
'child_threads_api',
|
|
12
|
+
'external_agent_import_results',
|
|
13
|
+
'rate_limit_reset_credits',
|
|
14
|
+
'realtime_startup_context_control',
|
|
15
|
+
'tui_prompt_auto_resolve',
|
|
16
|
+
'hook_trust_resume_persistence',
|
|
17
|
+
'post_tool_use_blocking_respected',
|
|
18
|
+
'plugin_app_mcp_dedupe',
|
|
19
|
+
'windows_sandbox_repairs_delegated',
|
|
20
|
+
'idle_exec_relay_keepalive',
|
|
21
|
+
'wait_agent_interrupt_native',
|
|
22
|
+
'sqlite_wal_reset_fix_delegated',
|
|
23
|
+
'tls_p521_native',
|
|
24
|
+
'tool_heavy_copy_reduction',
|
|
25
|
+
'prompt_image_cache_bound_64_mib',
|
|
26
|
+
'feedback_upload_bound_8_threads',
|
|
27
|
+
'terminal_resize_reflow_always'
|
|
28
|
+
];
|
|
29
|
+
export async function detectCodex0141Capability(input = {}) {
|
|
30
|
+
const fake = process.env.SKS_CODEX_0141_FAKE === '1';
|
|
31
|
+
const codexBin = fake ? input.codexBin || process.env.CODEX_BIN || 'codex' : input.codexBin || process.env.CODEX_BIN || await findCodexBinary();
|
|
32
|
+
const versionText = fake ? String(process.env.SKS_CODEX_VERSION_FAKE || 'codex-cli 0.141.0') : await readCodexVersionText(codexBin);
|
|
33
|
+
const parsed = parseCodexVersionText(versionText);
|
|
34
|
+
const supports0141 = Boolean(parsed && compareSemverLike(parsed, '0.141.0') >= 0);
|
|
35
|
+
const featureStates = Object.fromEntries(CODEX_0141_FEATURE_KEYS.map((key) => [key, featureStateFor(key, supports0141)]));
|
|
36
|
+
const blockers = [
|
|
37
|
+
...(!codexBin ? ['codex_cli_missing'] : []),
|
|
38
|
+
...(supports0141 ? [] : ['codex_0_141_required_for_0141_features'])
|
|
39
|
+
];
|
|
40
|
+
return {
|
|
41
|
+
schema: 'sks.codex-0141-capability.v1',
|
|
42
|
+
generated_at: nowIso(),
|
|
43
|
+
ok: blockers.length === 0,
|
|
44
|
+
codex_version: parsed,
|
|
45
|
+
supports_0141: supports0141,
|
|
46
|
+
feature_states: featureStates,
|
|
47
|
+
blockers,
|
|
48
|
+
warnings: supports0141
|
|
49
|
+
? CODEX_0141_FEATURE_KEYS.map((key) => `codex_0141_${key}_assumed_by_version`)
|
|
50
|
+
: [],
|
|
51
|
+
codex_bin: codexBin || null,
|
|
52
|
+
release_source: 'https://github.com/openai/codex/releases/tag/rust-v0.141.0'
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
export async function writeCodex0141CapabilityArtifacts(root, input = {}) {
|
|
56
|
+
const report = await detectCodex0141Capability({ codexBin: input.codexBin || null });
|
|
57
|
+
const rootArtifact = path.join(root, '.sneakoscope', 'codex-0141-capability.json');
|
|
58
|
+
await writeJsonAtomic(rootArtifact, report);
|
|
59
|
+
let missionArtifact = null;
|
|
60
|
+
if (input.missionId) {
|
|
61
|
+
missionArtifact = path.join(root, '.sneakoscope', 'missions', input.missionId, 'codex-0141-capability.json');
|
|
62
|
+
await writeJsonAtomic(missionArtifact, report);
|
|
63
|
+
}
|
|
64
|
+
return { report, root_artifact: rootArtifact, mission_artifact: missionArtifact };
|
|
65
|
+
}
|
|
66
|
+
function featureStateFor(key, supports0141) {
|
|
67
|
+
return {
|
|
68
|
+
supported: supports0141,
|
|
69
|
+
certainty: supports0141 ? 'assumed_by_version' : 'failed',
|
|
70
|
+
evidence: supports0141 ? ['codex_version>=0.141.0', `release:rust-v0.141.0:${key}`] : [],
|
|
71
|
+
blockers: supports0141 ? [] : ['codex_0_141_required_for_0141_features'],
|
|
72
|
+
sks_policy: sksPolicyFor(key)
|
|
73
|
+
};
|
|
74
|
+
}
|
|
75
|
+
function sksPolicyFor(key) {
|
|
76
|
+
if (key.includes('dedupe'))
|
|
77
|
+
return 'dedupe';
|
|
78
|
+
if (key.includes('bound') || key.includes('cache') || key.includes('feedback'))
|
|
79
|
+
return 'bound';
|
|
80
|
+
if (key.includes('blocking') || key.includes('trust'))
|
|
81
|
+
return 'respect';
|
|
82
|
+
return 'delegate';
|
|
83
|
+
}
|
|
84
|
+
async function readCodexVersionText(codexBin) {
|
|
85
|
+
if (!codexBin)
|
|
86
|
+
return null;
|
|
87
|
+
const result = await runProcess(codexBin, ['--version'], { timeoutMs: 10_000, maxOutputBytes: 16 * 1024 }).catch((err) => ({
|
|
88
|
+
code: 1,
|
|
89
|
+
stdout: '',
|
|
90
|
+
stderr: err instanceof Error ? err.message : String(err)
|
|
91
|
+
}));
|
|
92
|
+
const text = `${result.stdout || ''}${result.stderr || ''}`.trim();
|
|
93
|
+
return result.code === 0 ? text : text || null;
|
|
94
|
+
}
|
|
95
|
+
//# sourceMappingURL=codex-0141-capability.js.map
|
|
@@ -4,7 +4,7 @@ import { projectRoot } from '../fsx.js';
|
|
|
4
4
|
import { runSksdClient } from '../daemon/sksd-client.js';
|
|
5
5
|
export async function daemonCommand(args = []) {
|
|
6
6
|
const root = await projectRoot();
|
|
7
|
-
const action = args[0] === 'warm' || args[0] === 'stop' || args[0] === 'status' ? args[0] : 'status';
|
|
7
|
+
const action = args[0] === 'warm' || args[0] === 'stop' || args[0] === 'status' || args[0] === 'start' ? args[0] : 'status';
|
|
8
8
|
const state = runSksdClient(root, action);
|
|
9
9
|
if (flag(args, '--json'))
|
|
10
10
|
return printJson(state);
|
|
@@ -1,9 +1,14 @@
|
|
|
1
|
-
import { sksdStatus, sksdStop, sksdWarm } from './sksd.js';
|
|
2
|
-
|
|
1
|
+
import { handleSksdRequest, sksdStart, sksdStatus, sksdStop, sksdWarm } from './sksd.js';
|
|
2
|
+
import { writeSksdIpcMessage } from './sksd-ipc.js';
|
|
3
|
+
export function runSksdClient(root, action = 'status') {
|
|
4
|
+
writeSksdIpcMessage(root, action, action === 'warm' ? { type: 'warm', root } : action === 'stop' ? { type: 'stop' } : { type: 'status' });
|
|
5
|
+
if (action === 'start')
|
|
6
|
+
return sksdStart(root);
|
|
3
7
|
if (action === 'warm')
|
|
4
8
|
return sksdWarm(root);
|
|
5
9
|
if (action === 'stop')
|
|
6
10
|
return sksdStop(root);
|
|
7
11
|
return sksdStatus(root);
|
|
8
12
|
}
|
|
13
|
+
export { handleSksdRequest };
|
|
9
14
|
//# sourceMappingURL=sksd-client.js.map
|
|
@@ -1,9 +1,19 @@
|
|
|
1
1
|
import fs from 'node:fs';
|
|
2
2
|
import path from 'node:path';
|
|
3
|
-
export function writeSksdIpcMessage(root, action) {
|
|
4
|
-
const file = path.join(root, '
|
|
3
|
+
export function writeSksdIpcMessage(root, action, request) {
|
|
4
|
+
const file = path.join(ipcDir(root), 'last-message.json');
|
|
5
|
+
const responsePath = path.join(ipcDir(root), `response-${process.pid}-${Date.now()}.json`);
|
|
5
6
|
fs.mkdirSync(path.dirname(file), { recursive: true });
|
|
6
|
-
fs.writeFileSync(file, `${JSON.stringify({ schema: 'sks.sksd-ipc-message.v1', action, created_at: new Date().toISOString(), pid: process.pid }, null, 2)}\n`);
|
|
7
|
+
fs.writeFileSync(file, `${JSON.stringify({ schema: 'sks.sksd-ipc-message.v1', action, created_at: new Date().toISOString(), pid: process.pid, request, response_path: responsePath }, null, 2)}\n`);
|
|
7
8
|
return file;
|
|
8
9
|
}
|
|
10
|
+
export function writeSksdIpcResponse(root, request, response) {
|
|
11
|
+
const file = path.join(ipcDir(root), `response-${process.pid}-${Date.now()}.json`);
|
|
12
|
+
fs.mkdirSync(path.dirname(file), { recursive: true });
|
|
13
|
+
fs.writeFileSync(file, `${JSON.stringify({ schema: 'sks.sksd-ipc-response.v1', request, response, responded_at: new Date().toISOString() }, null, 2)}\n`);
|
|
14
|
+
return file;
|
|
15
|
+
}
|
|
16
|
+
function ipcDir(root) {
|
|
17
|
+
return path.join(root, '.sneakoscope', 'cache', 'sksd');
|
|
18
|
+
}
|
|
9
19
|
//# sourceMappingURL=sksd-ipc.js.map
|
package/dist/core/daemon/sksd.js
CHANGED
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
import fs from 'node:fs';
|
|
2
2
|
import path from 'node:path';
|
|
3
|
+
import { summarizeTriWikiProofBank } from '../triwiki/triwiki-proof-bank.js';
|
|
4
|
+
import { runBuildOnce } from '../build/build-once-runner.js';
|
|
5
|
+
import { writeSksdIpcResponse } from './sksd-ipc.js';
|
|
3
6
|
export const SKSD_STATE_SCHEMA = 'sks.sksd-state.v1';
|
|
4
7
|
export function sksdStatus(root) {
|
|
5
8
|
const state = readState(root);
|
|
@@ -13,21 +16,59 @@ export function sksdStatus(root) {
|
|
|
13
16
|
return state;
|
|
14
17
|
}
|
|
15
18
|
export function sksdWarm(root) {
|
|
19
|
+
const proofBank = summarizeTriWikiProofBank(root);
|
|
20
|
+
const buildProof = maybeWarmBuildOnce(root);
|
|
21
|
+
const probeDir = path.join(root, '.sneakoscope', 'cache', 'probes');
|
|
22
|
+
fs.mkdirSync(probeDir, { recursive: true });
|
|
23
|
+
fs.writeFileSync(path.join(probeDir, 'sksd-warm.json'), `${JSON.stringify({ schema: 'sks.sksd-probe-warm.v1', warmed_at: new Date().toISOString() }, null, 2)}\n`);
|
|
16
24
|
const state = {
|
|
17
25
|
schema: SKSD_STATE_SCHEMA,
|
|
18
26
|
status: 'warm',
|
|
19
27
|
pid: process.pid,
|
|
20
28
|
warmed_at: new Date().toISOString(),
|
|
21
29
|
ipc_path: ipcPath(root),
|
|
22
|
-
proof_bank_ready:
|
|
23
|
-
build_proof_ready: fs.existsSync(path.join(root, 'dist', '.sks-build-proof.json')),
|
|
30
|
+
proof_bank_ready: proofBank.ok,
|
|
31
|
+
build_proof_ready: buildProof || fs.existsSync(path.join(root, 'dist', '.sks-build-proof.json')),
|
|
24
32
|
triwiki_index_ready: fs.existsSync(path.join(root, '.sneakoscope', 'wiki', 'context-pack.json')),
|
|
25
|
-
probe_memoization_ready: fs.existsSync(path.join(root, '.sneakoscope', 'cache', 'probes'))
|
|
33
|
+
probe_memoization_ready: fs.existsSync(path.join(root, '.sneakoscope', 'cache', 'probes')),
|
|
34
|
+
protocol_ok: true,
|
|
35
|
+
last_response_path: null
|
|
26
36
|
};
|
|
27
37
|
writeState(root, state);
|
|
28
38
|
fs.writeFileSync(ipcPath(root), `${JSON.stringify({ schema: 'sks.sksd-ipc.v1', pid: process.pid, command: 'warm', at: new Date().toISOString() }, null, 2)}\n`);
|
|
29
39
|
return state;
|
|
30
40
|
}
|
|
41
|
+
export function sksdStart(root) {
|
|
42
|
+
const state = {
|
|
43
|
+
...sksdWarm(root),
|
|
44
|
+
status: 'running',
|
|
45
|
+
pid: process.pid,
|
|
46
|
+
protocol_ok: true
|
|
47
|
+
};
|
|
48
|
+
writeState(root, state);
|
|
49
|
+
return state;
|
|
50
|
+
}
|
|
51
|
+
export function handleSksdRequest(root, request) {
|
|
52
|
+
let response;
|
|
53
|
+
if (request.type === 'status')
|
|
54
|
+
response = sksdStatus(root);
|
|
55
|
+
else if (request.type === 'warm')
|
|
56
|
+
response = sksdWarm(request.root);
|
|
57
|
+
else if (request.type === 'proof-bank-status')
|
|
58
|
+
response = summarizeTriWikiProofBank(request.root);
|
|
59
|
+
else if (request.type === 'triwiki-index')
|
|
60
|
+
response = { schema: 'sks.sksd-triwiki-index.v1', ok: fs.existsSync(path.join(request.root, '.sneakoscope', 'wiki', 'context-pack.json')), path: path.join(request.root, '.sneakoscope', 'wiki', 'context-pack.json') };
|
|
61
|
+
else if (request.type === 'build-once')
|
|
62
|
+
response = runBuildOnce({ root: request.root, mode: request.mode });
|
|
63
|
+
else if (request.type === 'probe')
|
|
64
|
+
response = writeProbeResponse(request.root, request.probe_id);
|
|
65
|
+
else
|
|
66
|
+
response = sksdStop(root);
|
|
67
|
+
const responsePath = writeSksdIpcResponse(root, request, response);
|
|
68
|
+
const state = sksdStatus(root);
|
|
69
|
+
writeState(root, { ...state, protocol_ok: true, last_response_path: responsePath });
|
|
70
|
+
return response;
|
|
71
|
+
}
|
|
31
72
|
export function sksdStop(root) {
|
|
32
73
|
const state = { ...emptyState(root), status: 'stopped' };
|
|
33
74
|
writeState(root, state);
|
|
@@ -84,4 +125,22 @@ function pidAlive(pid) {
|
|
|
84
125
|
return false;
|
|
85
126
|
}
|
|
86
127
|
}
|
|
128
|
+
function maybeWarmBuildOnce(root) {
|
|
129
|
+
if (!fs.existsSync(path.join(root, 'tsconfig.json')) || !fs.existsSync(path.join(root, 'src')))
|
|
130
|
+
return false;
|
|
131
|
+
if (process.env.SKS_SKSD_SKIP_BUILD_ONCE === '1')
|
|
132
|
+
return fs.existsSync(path.join(root, 'dist', '.sks-build-proof.json'));
|
|
133
|
+
try {
|
|
134
|
+
return runBuildOnce({ root, mode: 'incremental' }).ok;
|
|
135
|
+
}
|
|
136
|
+
catch {
|
|
137
|
+
return false;
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
function writeProbeResponse(root, probeId) {
|
|
141
|
+
const file = path.join(root, '.sneakoscope', 'cache', 'probes', `${probeId.replace(/[^a-zA-Z0-9._-]+/g, '_')}.json`);
|
|
142
|
+
fs.mkdirSync(path.dirname(file), { recursive: true });
|
|
143
|
+
fs.writeFileSync(file, `${JSON.stringify({ schema: 'sks.sksd-probe-response.v1', probe_id: probeId, ok: true, at: new Date().toISOString() }, null, 2)}\n`);
|
|
144
|
+
return { schema: 'sks.sksd-probe-response.v1', ok: true, path: file };
|
|
145
|
+
}
|
|
87
146
|
//# sourceMappingURL=sksd.js.map
|