sneakoscope 4.0.7 → 4.0.9
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 +2 -2
- 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/core/commands/glm-command.js +8 -1
- package/dist/core/commands/naruto-command.js +25 -0
- package/dist/core/commands/stop-gate-command.js +63 -0
- package/dist/core/fsx.js +1 -1
- package/dist/core/pipeline-internals/runtime-gates.js +28 -4
- package/dist/core/providers/glm/glm-bench.js +4 -4
- package/dist/core/providers/glm/glm-direct-run.js +1 -1
- package/dist/core/providers/glm/glm-latency-trace.js +1 -1
- package/dist/core/providers/glm/glm-request-cache.js +10 -2
- package/dist/core/providers/glm/naruto/glm-naruto-artifacts.js +2 -0
- package/dist/core/providers/glm/naruto/glm-naruto-bench.js +68 -0
- package/dist/core/providers/glm/naruto/glm-naruto-budget.js +45 -0
- package/dist/core/providers/glm/naruto/glm-naruto-command.js +97 -0
- package/dist/core/providers/glm/naruto/glm-naruto-concurrency-governor.js +37 -0
- package/dist/core/providers/glm/naruto/glm-naruto-conflict-graph.js +74 -0
- package/dist/core/providers/glm/naruto/glm-naruto-decomposer.js +99 -0
- package/dist/core/providers/glm/naruto/glm-naruto-file-lease.js +23 -0
- package/dist/core/providers/glm/naruto/glm-naruto-finalizer.js +22 -0
- package/dist/core/providers/glm/naruto/glm-naruto-judge.js +84 -0
- package/dist/core/providers/glm/naruto/glm-naruto-merge-planner.js +57 -0
- package/dist/core/providers/glm/naruto/glm-naruto-orchestrator.js +277 -0
- package/dist/core/providers/glm/naruto/glm-naruto-patch-envelope.js +55 -0
- package/dist/core/providers/glm/naruto/glm-naruto-quorum.js +37 -0
- package/dist/core/providers/glm/naruto/glm-naruto-rate-limiter.js +18 -0
- package/dist/core/providers/glm/naruto/glm-naruto-repair-wave.js +21 -0
- package/dist/core/providers/glm/naruto/glm-naruto-shard-planner.js +32 -0
- package/dist/core/providers/glm/naruto/glm-naruto-trace.js +91 -0
- package/dist/core/providers/glm/naruto/glm-naruto-types.js +37 -0
- package/dist/core/providers/glm/naruto/glm-naruto-work-graph.js +2 -0
- package/dist/core/providers/glm/naruto/glm-naruto-worker-pool.js +79 -0
- package/dist/core/providers/glm/naruto/glm-naruto-worker-runtime.js +198 -0
- package/dist/core/providers/glm/naruto/glm-naruto-worker.js +2 -0
- package/dist/core/providers/glm/naruto/glm-naruto-worktree.js +48 -0
- package/dist/core/providers/openrouter/openrouter-provider-health.js +46 -0
- package/dist/core/providers/openrouter/openrouter-secret-store.js +33 -0
- package/dist/core/providers/openrouter/openrouter-stream.js +101 -8
- package/dist/core/stop-gate/stop-gate-check.js +208 -0
- package/dist/core/stop-gate/stop-gate-diagnostics.js +4 -0
- package/dist/core/stop-gate/stop-gate-resolver.js +122 -0
- package/dist/core/stop-gate/stop-gate-types.js +2 -0
- package/dist/core/stop-gate/stop-gate-writer.js +76 -0
- package/dist/core/version.js +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -35,9 +35,9 @@ 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.8** makes the GLM 5.2 MAD path bounded by default: `sks --mad --glm` now returns readiness/status and exits when no task is supplied, while task forms use a direct GLM-only speed path with loop guards, request timeouts, and deterministic patch gates. Ordinary `sks --mad`, Naruto/Team, and non-GLM Codex paths keep their existing defaults.
|
|
39
39
|
|
|
40
|
-
What changed in 4.0.
|
|
40
|
+
What changed in 4.0.8:
|
|
41
41
|
|
|
42
42
|
- **`--open` alias for interactive GLM launch.** `sks --mad --glm --open` now opens the GLM interactive Zellij runtime, equivalent to `sks --mad --glm --interactive`.
|
|
43
43
|
|
|
@@ -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.9"),
|
|
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
|
@@ -123,6 +123,7 @@ export const COMMANDS = {
|
|
|
123
123
|
agent: entry('beta', 'Run native multi-session agent missions', 'dist/core/commands/agent-command.js', argsCommand(() => import('../core/commands/agent-command.js'), 'agentCommand', 'dist/core/commands/agent-command.js')),
|
|
124
124
|
'with-local-llm': entry('beta', 'Enable or inspect local Ollama worker backend', 'dist/core/commands/local-model-command.js', argsCommand(() => import('../core/commands/local-model-command.js'), 'localModelCommand', 'dist/core/commands/local-model-command.js')),
|
|
125
125
|
naruto: entry('labs', 'Run $Naruto shadow-clone swarm (up to 100 parallel sessions)', 'dist/core/commands/naruto-command.js', argsCommand(() => import('../core/commands/naruto-command.js'), 'narutoCommand', 'dist/core/commands/naruto-command.js')),
|
|
126
|
+
'stop-gate': entry('beta', 'Check canonical stop-gate resolution for a route/mission', 'dist/core/commands/stop-gate-command.js', commandArgsCommand(() => import('../core/commands/stop-gate-command.js'), 'stopGateCommand', 'dist/core/commands/stop-gate-command.js')),
|
|
126
127
|
loop: entry('labs', 'Dynamic Loop Runtime: plan/run/status/proof loop graphs.', 'dist/core/commands/loop-command.js', subcommand(() => import('../core/commands/loop-command.js'), 'loopCommand', 'dist/core/commands/loop-command.js', 'help')),
|
|
127
128
|
'qa-loop': entry('beta', 'Run QA loop missions', 'dist/core/commands/qa-loop-command.js', subcommand(() => import('../core/commands/qa-loop-command.js'), 'qaLoopCommand', 'dist/core/commands/qa-loop-command.js')),
|
|
128
129
|
research: entry('labs', 'Run research missions', 'dist/core/commands/research-command.js', subcommand(() => import('../core/commands/research-command.js'), 'researchCommand', 'dist/core/commands/research-command.js')),
|
|
@@ -4,8 +4,13 @@ import { printJson } from '../../cli/output.js';
|
|
|
4
4
|
import { runGlmDirectSpeedRun } from '../providers/glm/glm-direct-run.js';
|
|
5
5
|
import { runGlmReadinessAndExit } from '../providers/glm/glm-readiness.js';
|
|
6
6
|
import { runGlmInteractiveLaunch } from '../providers/glm/glm-interactive-launch.js';
|
|
7
|
+
import { glmNarutoCommand } from '../providers/glm/naruto/glm-naruto-command.js';
|
|
7
8
|
export async function glmCommand(args = []) {
|
|
8
|
-
if (flag(args, '--
|
|
9
|
+
if (flag(args, '--naruto') || positionalArgs(args)[0] === 'naruto') {
|
|
10
|
+
const narutoArgs = args.filter((a) => a !== '--naruto' && a !== 'naruto');
|
|
11
|
+
return glmNarutoCommand(narutoArgs);
|
|
12
|
+
}
|
|
13
|
+
if (flag(args, '--bench') && !flag(args, '--naruto')) {
|
|
9
14
|
const result = await runGlmBench(process.cwd(), args);
|
|
10
15
|
if (result.status === 'blocked')
|
|
11
16
|
process.exitCode = 1;
|
|
@@ -50,6 +55,8 @@ function extractGlmTask(args) {
|
|
|
50
55
|
return positional.slice(1).join(' ').trim() || null;
|
|
51
56
|
if (positional[0] === 'session')
|
|
52
57
|
return null;
|
|
58
|
+
if (positional[0] === 'naruto')
|
|
59
|
+
return null;
|
|
53
60
|
return positional.join(' ').trim() || null;
|
|
54
61
|
}
|
|
55
62
|
//# sourceMappingURL=glm-command.js.map
|
|
@@ -25,6 +25,7 @@ import { evaluateGitWorktreeCapability } from '../git/git-worktree-capability.js
|
|
|
25
25
|
import { buildRuntimeProofSummary, renderRuntimeProofSummary } from '../agents/runtime-proof-summary.js';
|
|
26
26
|
import { writeCodex0138CapabilityArtifacts } from '../codex-control/codex-0138-capability.js';
|
|
27
27
|
import { writeCodex0139CapabilityArtifacts } from '../codex-control/codex-0139-capability.js';
|
|
28
|
+
import { writeFinalStopGate } from '../stop-gate/stop-gate-writer.js';
|
|
28
29
|
const NARUTO_RESULT_SCHEMA = 'sks.naruto-command-result.v1';
|
|
29
30
|
const NARUTO_ROUTE = '$Naruto';
|
|
30
31
|
// $Naruto — Shadow Clone Swarm (影分身 / Kage Bunshin no Jutsu).
|
|
@@ -34,6 +35,11 @@ const NARUTO_ROUTE = '$Naruto';
|
|
|
34
35
|
// writes). The standard 20-agent ceiling is lifted only for this route.
|
|
35
36
|
export async function narutoCommand(commandOrArgs = 'naruto', maybeArgs = []) {
|
|
36
37
|
const args = Array.isArray(commandOrArgs) ? commandOrArgs : maybeArgs;
|
|
38
|
+
// 4.0.9: `sks naruto --glm` delegates to GLM Naruto before legacy Naruto starts.
|
|
39
|
+
if (args.includes('--glm')) {
|
|
40
|
+
const { glmNarutoCommand } = await import('../providers/glm/naruto/glm-naruto-command.js');
|
|
41
|
+
return glmNarutoCommand(args.filter((arg) => arg !== '--glm'));
|
|
42
|
+
}
|
|
37
43
|
const parsed = parseNarutoArgs(args);
|
|
38
44
|
if (parsed.action === 'help')
|
|
39
45
|
return narutoHelp(parsed);
|
|
@@ -450,6 +456,25 @@ async function narutoRun(parsed) {
|
|
|
450
456
|
stop_gate: 'naruto-gate.json',
|
|
451
457
|
prompt: parsed.prompt
|
|
452
458
|
});
|
|
459
|
+
// 4.0.9: Write canonical stop-gate artifacts for hook resolution.
|
|
460
|
+
const narutoGatePassed = result.ok === true && nativeProofOk && finalAccepted && parallelRuntimeOk;
|
|
461
|
+
await writeFinalStopGate({
|
|
462
|
+
root,
|
|
463
|
+
missionId: mission.id,
|
|
464
|
+
route: 'Naruto',
|
|
465
|
+
routeCommand: '$Naruto',
|
|
466
|
+
status: summaryOk ? 'passed' : 'blocked',
|
|
467
|
+
terminal: summaryOk,
|
|
468
|
+
terminalState: summaryOk ? 'completed' : 'blocked',
|
|
469
|
+
evidence: {
|
|
470
|
+
build_passed: summaryOk,
|
|
471
|
+
tests_passed: summaryOk,
|
|
472
|
+
route_evidence_passed: nativeProofOk && finalAccepted,
|
|
473
|
+
native_session_split_evidence: nativeProofOk ? 'native_agent_proof' : null,
|
|
474
|
+
},
|
|
475
|
+
blockers: summaryOk ? [] : [...(result.proof?.blockers || []), ...(parallelRuntimeOk ? [] : ['naruto_parallel_runtime_proof_below_gate'])],
|
|
476
|
+
nativeGateFile: 'naruto-gate.json',
|
|
477
|
+
}).catch(() => null);
|
|
453
478
|
const summary = {
|
|
454
479
|
schema: NARUTO_RESULT_SCHEMA,
|
|
455
480
|
ok: summaryOk,
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import { sksRoot } from '../fsx.js';
|
|
2
|
+
import { checkStopGate } from '../stop-gate/stop-gate-check.js';
|
|
3
|
+
export async function stopGateCommand(command, args) {
|
|
4
|
+
const subcommand = args[0] === 'check' ? 'check' : (args[0] || 'check');
|
|
5
|
+
const rest = subcommand === 'check' ? args.slice(1) : args;
|
|
6
|
+
const json = rest.includes('--json');
|
|
7
|
+
const route = readOption(rest, '--route');
|
|
8
|
+
const missionId = readOption(rest, '--mission');
|
|
9
|
+
const gatePath = readOption(rest, '--gate');
|
|
10
|
+
if (subcommand !== 'check') {
|
|
11
|
+
const result = {
|
|
12
|
+
schema: 'sks.stop-gate-command.v1',
|
|
13
|
+
ok: false,
|
|
14
|
+
action: 'continue',
|
|
15
|
+
error: `Unknown subcommand: ${subcommand}. Available: check`,
|
|
16
|
+
};
|
|
17
|
+
if (json)
|
|
18
|
+
console.log(JSON.stringify(result, null, 2));
|
|
19
|
+
else
|
|
20
|
+
console.error(`Unknown stop-gate subcommand: ${subcommand}. Use: sks stop-gate check --route Naruto --json`);
|
|
21
|
+
return result;
|
|
22
|
+
}
|
|
23
|
+
const root = await sksRoot();
|
|
24
|
+
const result = await checkStopGate({
|
|
25
|
+
root,
|
|
26
|
+
...(route ? { route } : {}),
|
|
27
|
+
...(missionId ? { missionId } : {}),
|
|
28
|
+
...(gatePath ? { explicitGatePath: gatePath } : {}),
|
|
29
|
+
});
|
|
30
|
+
if (json) {
|
|
31
|
+
console.log(JSON.stringify(result, null, 2));
|
|
32
|
+
}
|
|
33
|
+
else {
|
|
34
|
+
if (result.action === 'allow_stop') {
|
|
35
|
+
console.log(`stop-gate: allow_stop — gate passed at ${result.gate_path}`);
|
|
36
|
+
}
|
|
37
|
+
else if (result.action === 'hard_blocked') {
|
|
38
|
+
console.log(`stop-gate: hard_blocked — ${result.feedback}`);
|
|
39
|
+
}
|
|
40
|
+
else {
|
|
41
|
+
console.error(`stop-gate: continue — ${result.feedback}`);
|
|
42
|
+
}
|
|
43
|
+
if (result.diagnostics.checked_paths.length > 0) {
|
|
44
|
+
console.log('Checked paths:');
|
|
45
|
+
for (const p of result.diagnostics.checked_paths)
|
|
46
|
+
console.log(` ${p}`);
|
|
47
|
+
}
|
|
48
|
+
if (result.diagnostics.selected_gate_path) {
|
|
49
|
+
console.log(`Selected gate: ${result.diagnostics.selected_gate_path}`);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
if (result.action === 'continue')
|
|
53
|
+
process.exitCode = 1;
|
|
54
|
+
return result;
|
|
55
|
+
}
|
|
56
|
+
function readOption(args, name) {
|
|
57
|
+
const index = args.indexOf(name);
|
|
58
|
+
if (index >= 0 && args[index + 1] && !String(args[index + 1]).startsWith('--'))
|
|
59
|
+
return args[index + 1];
|
|
60
|
+
const prefixed = args.find((arg) => String(arg).startsWith(name + '='));
|
|
61
|
+
return prefixed ? prefixed.slice(name.length + 1) : undefined;
|
|
62
|
+
}
|
|
63
|
+
//# sourceMappingURL=stop-gate-command.js.map
|
package/dist/core/fsx.js
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
|
import { fileURLToPath } from 'node:url';
|
|
8
|
-
export const PACKAGE_VERSION = '4.0.
|
|
8
|
+
export const PACKAGE_VERSION = '4.0.9';
|
|
9
9
|
export const DEFAULT_PROCESS_TAIL_BYTES = 256 * 1024;
|
|
10
10
|
export const DEFAULT_PROCESS_TIMEOUT_MS = 30 * 60 * 1000;
|
|
11
11
|
export function nowIso() {
|
|
@@ -17,6 +17,7 @@ import { readAgentGateStatus } from '../agents/agent-gate.js';
|
|
|
17
17
|
import { MISTAKE_RECALL_ARTIFACT, mistakeRecallGateStatus } from '../mistake-recall.js';
|
|
18
18
|
import { SSOT_GUARD_ARTIFACT, validateSsotGuardArtifact } from '../safety/ssot-guard.js';
|
|
19
19
|
import { validateTeamRuntimeArtifacts } from '../team-dag.js';
|
|
20
|
+
import { checkStopGate } from '../stop-gate/stop-gate-check.js';
|
|
20
21
|
import { clarificationStopReason, context7Evidence, hasContext7DocsEvidence, hasSubagentEvidence, subagentEvidence, } from './runtime-core.js';
|
|
21
22
|
const REFLECTION_ARTIFACT = 'reflection.md';
|
|
22
23
|
const REFLECTION_GATE = 'reflection-gate.json';
|
|
@@ -233,10 +234,33 @@ export async function evaluateStop(root, state, payload, opts = {}) {
|
|
|
233
234
|
return complianceBlock(root, state, `SKS no-question run is not done. Continue autonomously, fix failing checks, update ${gate.file || 'the active gate file'}, and do not ask the user.${missing}`, { gate: gate.file || 'active-gate', missing: gate.missing });
|
|
234
235
|
}
|
|
235
236
|
if (state?.mission_id && state?.stop_gate && !['none', 'honest_mode', 'clarification-gate'].includes(state.stop_gate)) {
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
237
|
+
// 4.0.9: Use canonical stop-gate resolver first for NARUTO/GLM_NARUTO routes.
|
|
238
|
+
const modeUpper = String(state?.mode || '').toUpperCase();
|
|
239
|
+
if (modeUpper === 'NARUTO' || state.stop_gate === 'stop-gate.json' || state.stop_gate === 'naruto-gate.json') {
|
|
240
|
+
const stopCheck = await checkStopGate({
|
|
241
|
+
root,
|
|
242
|
+
route: state.route || state.mode,
|
|
243
|
+
missionId: state.mission_id,
|
|
244
|
+
explicitGatePath: typeof state.stop_gate_abs_path === 'string' && state.stop_gate_abs_path ? state.stop_gate_abs_path : undefined,
|
|
245
|
+
});
|
|
246
|
+
if (stopCheck.action === 'allow_stop') {
|
|
247
|
+
// Gate passed via canonical resolver; fall through to remaining checks.
|
|
248
|
+
}
|
|
249
|
+
else if (stopCheck.action === 'hard_blocked') {
|
|
250
|
+
return { continue: true, systemMessage: `SKS: ${stopCheck.feedback}` };
|
|
251
|
+
}
|
|
252
|
+
else {
|
|
253
|
+
const missing = stopCheck.diagnostics.missing_fields?.length ? ` Missing gate fields: ${stopCheck.diagnostics.missing_fields.join(', ')}.` : '';
|
|
254
|
+
const checkedPaths = stopCheck.diagnostics.checked_paths?.length ? ` Checked: ${stopCheck.diagnostics.checked_paths.join(', ')}.` : '';
|
|
255
|
+
return complianceBlock(root, state, `SKS ${state.route_command || state.mode} route cannot stop yet. Pass ${stopCheck.gate_path || state.stop_gate} or record a hard blocker with evidence before finishing.${missing}${checkedPaths}`, { gate: stopCheck.gate_path || state.stop_gate, missing: stopCheck.diagnostics.missing_fields });
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
else {
|
|
259
|
+
const gate = await passedActiveGate(root, state);
|
|
260
|
+
if (!gate.ok) {
|
|
261
|
+
const missing = gate.missing?.length ? ` Missing gate fields: ${gate.missing.join(', ')}.` : '';
|
|
262
|
+
return complianceBlock(root, state, `SKS ${state.route_command || state.mode} route cannot stop yet. Pass ${gate.file || state.stop_gate} or record a hard blocker with evidence before finishing.${missing}`, { gate: gate.file || state.stop_gate, missing: gate.missing });
|
|
263
|
+
}
|
|
240
264
|
}
|
|
241
265
|
}
|
|
242
266
|
const proofGate = await routeProofGateStatus(root, state);
|
|
@@ -14,7 +14,7 @@ export async function runGlmBench(root, args = []) {
|
|
|
14
14
|
if (execute && !live) {
|
|
15
15
|
const blocked = {
|
|
16
16
|
schema: 'sks.glm-bench-result.v1',
|
|
17
|
-
version: '4.0.
|
|
17
|
+
version: '4.0.9',
|
|
18
18
|
generated_at: nowIso(),
|
|
19
19
|
status: 'blocked',
|
|
20
20
|
dry_run: true,
|
|
@@ -32,7 +32,7 @@ export async function runGlmBench(root, args = []) {
|
|
|
32
32
|
if (live) {
|
|
33
33
|
const blocked = {
|
|
34
34
|
schema: 'sks.glm-bench-result.v1',
|
|
35
|
-
version: '4.0.
|
|
35
|
+
version: '4.0.9',
|
|
36
36
|
generated_at: nowIso(),
|
|
37
37
|
status: 'blocked',
|
|
38
38
|
dry_run: false,
|
|
@@ -50,7 +50,7 @@ export async function runGlmBench(root, args = []) {
|
|
|
50
50
|
if (execute) {
|
|
51
51
|
const blocked = {
|
|
52
52
|
schema: 'sks.glm-bench-result.v1',
|
|
53
|
-
version: '4.0.
|
|
53
|
+
version: '4.0.9',
|
|
54
54
|
generated_at: nowIso(),
|
|
55
55
|
status: 'blocked',
|
|
56
56
|
dry_run: true,
|
|
@@ -69,7 +69,7 @@ export async function runGlmBench(root, args = []) {
|
|
|
69
69
|
const deepTotals = SYNTHETIC_CASES.map((row) => row.deep.total_ms);
|
|
70
70
|
const result = {
|
|
71
71
|
schema: 'sks.glm-bench-result.v1',
|
|
72
|
-
version: '4.0.
|
|
72
|
+
version: '4.0.9',
|
|
73
73
|
generated_at: nowIso(),
|
|
74
74
|
status: 'dry_run',
|
|
75
75
|
dry_run: true,
|
|
@@ -60,7 +60,7 @@ export async function runGlmDirectSpeedRun(input) {
|
|
|
60
60
|
return result(reason === 'glm_request_timeout' ? 'timeout' : 'failed', controller.state().run_id, input.task, termination.reason, artifactDir, [], [response.error.code], []);
|
|
61
61
|
}
|
|
62
62
|
controller.transition('model_guard');
|
|
63
|
-
const modelGuard = assertGlm52ActualModel(response.value.model
|
|
63
|
+
const modelGuard = assertGlm52ActualModel(response.value.model);
|
|
64
64
|
if (!modelGuard.ok) {
|
|
65
65
|
const termination = controller.terminate('blocked', 'glm_model_mismatch', [modelGuard.code]);
|
|
66
66
|
const artifactDir = await writeGlmRunArtifacts({ cwd: input.cwd, state: controller.state(), termination, contextOmissions: context.omitted });
|
|
@@ -6,9 +6,17 @@ export function createGlmEncodedRequestCache(maxEntries = 128) {
|
|
|
6
6
|
export function encodeGlmRequestWithCache(request, cache = defaultEncodedRequestCache) {
|
|
7
7
|
const key = digestRequestForCache(request);
|
|
8
8
|
const hit = cache.get(key);
|
|
9
|
+
// Fix 18.2: On cache hit, return stored body without JSON.stringify
|
|
10
|
+
if (hit) {
|
|
11
|
+
if (hit.bodyStored) {
|
|
12
|
+
return { body: hit.body, entry: hit, cacheHit: true };
|
|
13
|
+
}
|
|
14
|
+
// Even for non-stored bodies, skip re-stringifying by computing from request
|
|
15
|
+
const body = JSON.stringify(request);
|
|
16
|
+
return { body, entry: hit, cacheHit: true };
|
|
17
|
+
}
|
|
18
|
+
// Cache miss: stringify once
|
|
9
19
|
const body = JSON.stringify(request);
|
|
10
|
-
if (hit)
|
|
11
|
-
return { body: hit.bodyStored ? hit.body : body, entry: hit, cacheHit: true };
|
|
12
20
|
if (containsSecretLikeContent(body)) {
|
|
13
21
|
const entry = {
|
|
14
22
|
key,
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import { nowIso, writeJsonAtomic } from '../../../fsx.js';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
import { GLM_52_OPENROUTER_MODEL } from '../glm-52-settings.js';
|
|
4
|
+
export async function runGlmNarutoBench(root, args = []) {
|
|
5
|
+
const live = args.includes('--live');
|
|
6
|
+
const execute = args.includes('--execute');
|
|
7
|
+
const started = Date.now();
|
|
8
|
+
if (execute && !live) {
|
|
9
|
+
return blocked(root, ['execute_requires_live_flag']);
|
|
10
|
+
}
|
|
11
|
+
if (!live) {
|
|
12
|
+
return {
|
|
13
|
+
schema: 'sks.glm-naruto-bench.v1',
|
|
14
|
+
version: '4.0.9',
|
|
15
|
+
generated_at: nowIso(),
|
|
16
|
+
status: 'dry_run',
|
|
17
|
+
model: GLM_52_OPENROUTER_MODEL,
|
|
18
|
+
gpt_fallback_allowed: false,
|
|
19
|
+
summary: {
|
|
20
|
+
simulated_workers: 12,
|
|
21
|
+
simulated_waves: 3,
|
|
22
|
+
simulated_patch_candidates: 24,
|
|
23
|
+
simulated_gate_passed: 18,
|
|
24
|
+
simulated_mergeable: 12,
|
|
25
|
+
wall_clock_ms: Date.now() - started
|
|
26
|
+
},
|
|
27
|
+
warnings: ['dry_run_no_live_api_calls']
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
// Live bench would require OpenRouter key and real API calls
|
|
31
|
+
return {
|
|
32
|
+
schema: 'sks.glm-naruto-bench.v1',
|
|
33
|
+
version: '4.0.9',
|
|
34
|
+
generated_at: nowIso(),
|
|
35
|
+
status: 'blocked',
|
|
36
|
+
model: GLM_52_OPENROUTER_MODEL,
|
|
37
|
+
gpt_fallback_allowed: false,
|
|
38
|
+
summary: {
|
|
39
|
+
simulated_workers: 0,
|
|
40
|
+
simulated_waves: 0,
|
|
41
|
+
simulated_patch_candidates: 0,
|
|
42
|
+
simulated_gate_passed: 0,
|
|
43
|
+
simulated_mergeable: 0,
|
|
44
|
+
wall_clock_ms: Date.now() - started
|
|
45
|
+
},
|
|
46
|
+
warnings: ['live_bench_requires_openrouter_key_and_task']
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
function blocked(root, warnings) {
|
|
50
|
+
return {
|
|
51
|
+
schema: 'sks.glm-naruto-bench.v1',
|
|
52
|
+
version: '4.0.9',
|
|
53
|
+
generated_at: nowIso(),
|
|
54
|
+
status: 'blocked',
|
|
55
|
+
model: GLM_52_OPENROUTER_MODEL,
|
|
56
|
+
gpt_fallback_allowed: false,
|
|
57
|
+
summary: {
|
|
58
|
+
simulated_workers: 0,
|
|
59
|
+
simulated_waves: 0,
|
|
60
|
+
simulated_patch_candidates: 0,
|
|
61
|
+
simulated_gate_passed: 0,
|
|
62
|
+
simulated_mergeable: 0,
|
|
63
|
+
wall_clock_ms: 0
|
|
64
|
+
},
|
|
65
|
+
warnings
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
//# sourceMappingURL=glm-naruto-bench.js.map
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { GLM_NARUTO_LIMITS } from './glm-naruto-types.js';
|
|
2
|
+
export function createBudget(missionId, deep) {
|
|
3
|
+
return {
|
|
4
|
+
missionId,
|
|
5
|
+
startedMs: Date.now(),
|
|
6
|
+
wavesCompleted: 0,
|
|
7
|
+
totalRequests: 0,
|
|
8
|
+
requestsPerShard: new Map(),
|
|
9
|
+
noProgressWaves: 0,
|
|
10
|
+
repairWaves: 0,
|
|
11
|
+
mergeAttempts: 0,
|
|
12
|
+
maxWaves: deep ? GLM_NARUTO_LIMITS.max_waves_deep : GLM_NARUTO_LIMITS.max_waves_speed
|
|
13
|
+
};
|
|
14
|
+
}
|
|
15
|
+
export function checkBudget(budget) {
|
|
16
|
+
const elapsed = Date.now() - budget.startedMs;
|
|
17
|
+
if (elapsed >= GLM_NARUTO_LIMITS.max_wall_clock_ms) {
|
|
18
|
+
return { ok: false, reason: 'budget_wall_clock_exceeded' };
|
|
19
|
+
}
|
|
20
|
+
if (budget.totalRequests >= GLM_NARUTO_LIMITS.max_total_requests) {
|
|
21
|
+
return { ok: false, reason: 'budget_total_requests_exceeded' };
|
|
22
|
+
}
|
|
23
|
+
if (budget.wavesCompleted >= budget.maxWaves) {
|
|
24
|
+
return { ok: false, reason: 'budget_max_waves_reached' };
|
|
25
|
+
}
|
|
26
|
+
if (budget.noProgressWaves > GLM_NARUTO_LIMITS.max_no_progress_waves) {
|
|
27
|
+
return { ok: false, reason: 'budget_no_progress_waves_exceeded' };
|
|
28
|
+
}
|
|
29
|
+
if (budget.repairWaves > GLM_NARUTO_LIMITS.max_repair_waves) {
|
|
30
|
+
return { ok: false, reason: 'budget_max_repair_waves_exceeded' };
|
|
31
|
+
}
|
|
32
|
+
if (budget.mergeAttempts > GLM_NARUTO_LIMITS.max_merge_attempts) {
|
|
33
|
+
return { ok: false, reason: 'budget_max_merge_attempts_exceeded' };
|
|
34
|
+
}
|
|
35
|
+
return { ok: true };
|
|
36
|
+
}
|
|
37
|
+
export function recordRequest(budget, shardId) {
|
|
38
|
+
const newPerShard = new Map(budget.requestsPerShard);
|
|
39
|
+
newPerShard.set(shardId, (newPerShard.get(shardId) || 0) + 1);
|
|
40
|
+
return { ...budget, totalRequests: budget.totalRequests + 1, requestsPerShard: newPerShard };
|
|
41
|
+
}
|
|
42
|
+
export function canRequestShard(budget, shardId) {
|
|
43
|
+
return (budget.requestsPerShard.get(shardId) || 0) < GLM_NARUTO_LIMITS.max_requests_per_shard;
|
|
44
|
+
}
|
|
45
|
+
//# sourceMappingURL=glm-naruto-budget.js.map
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
import { flag, readOption, positionalArgs } from '../../../../cli/args.js';
|
|
2
|
+
import { printJson } from '../../../../cli/output.js';
|
|
3
|
+
import { runGlmNarutoMission } from './glm-naruto-orchestrator.js';
|
|
4
|
+
import { runGlmNarutoBench } from './glm-naruto-bench.js';
|
|
5
|
+
import { resolveOpenRouterApiKey } from '../../openrouter/openrouter-secret-store.js';
|
|
6
|
+
export async function glmNarutoCommand(args = []) {
|
|
7
|
+
if (flag(args, '--bench')) {
|
|
8
|
+
const result = await runGlmNarutoBench(process.cwd(), args);
|
|
9
|
+
if (flag(args, '--json'))
|
|
10
|
+
printJson(result);
|
|
11
|
+
else if (result.status === 'blocked')
|
|
12
|
+
console.error(`GLM Naruto bench blocked: ${result.warnings.join(', ')}`);
|
|
13
|
+
else
|
|
14
|
+
console.log(`GLM Naruto bench: ${result.status} workers=${result.summary.simulated_workers} candidates=${result.summary.simulated_patch_candidates}`);
|
|
15
|
+
return result;
|
|
16
|
+
}
|
|
17
|
+
const positional = positionalArgs(args).map(String);
|
|
18
|
+
const task = positional.join(' ').trim();
|
|
19
|
+
if (!task && !flag(args, '--repair') && !flag(args, '--status')) {
|
|
20
|
+
const result = {
|
|
21
|
+
schema: 'sks.glm-naruto-result.v1',
|
|
22
|
+
ok: false,
|
|
23
|
+
status: 'blocked',
|
|
24
|
+
mission_id: 'none',
|
|
25
|
+
task: '',
|
|
26
|
+
model: 'z-ai/glm-5.2',
|
|
27
|
+
gpt_fallback_allowed: false,
|
|
28
|
+
termination_reason: 'no_task_provided',
|
|
29
|
+
blockers: ['glm_naruto_no_task'],
|
|
30
|
+
warnings: []
|
|
31
|
+
};
|
|
32
|
+
if (flag(args, '--json'))
|
|
33
|
+
printJson(result);
|
|
34
|
+
else
|
|
35
|
+
console.error('GLM Naruto requires a task. Usage: sks --mad --glm --naruto "<task>"');
|
|
36
|
+
process.exitCode = 1;
|
|
37
|
+
return result;
|
|
38
|
+
}
|
|
39
|
+
const key = await resolveOpenRouterApiKey({ env: process.env });
|
|
40
|
+
if (!key.key) {
|
|
41
|
+
const result = {
|
|
42
|
+
schema: 'sks.glm-naruto-result.v1',
|
|
43
|
+
ok: false,
|
|
44
|
+
status: 'blocked',
|
|
45
|
+
mission_id: 'none',
|
|
46
|
+
task,
|
|
47
|
+
model: 'z-ai/glm-5.2',
|
|
48
|
+
gpt_fallback_allowed: false,
|
|
49
|
+
termination_reason: 'glm_missing_openrouter_key',
|
|
50
|
+
blockers: ['glm_missing_openrouter_key'],
|
|
51
|
+
warnings: ['set_OPENROUTER_API_KEY_or_run_sks_--mad_--glm_--repair']
|
|
52
|
+
};
|
|
53
|
+
if (flag(args, '--json'))
|
|
54
|
+
printJson(result);
|
|
55
|
+
else
|
|
56
|
+
console.error('GLM Naruto blocked: missing OpenRouter API key. Run: sks --mad --glm --repair');
|
|
57
|
+
process.exitCode = 1;
|
|
58
|
+
return result;
|
|
59
|
+
}
|
|
60
|
+
const maxWorkers = parseInt(readOption(args, '--clones', readOption(args, '--workers', '12')), 10) || 12;
|
|
61
|
+
const deep = flag(args, '--deep');
|
|
62
|
+
const useJudge = flag(args, '--judge');
|
|
63
|
+
const xhighFinalizer = flag(args, '--xhigh-finalizer');
|
|
64
|
+
const useWorktree = flag(args, '--worktree');
|
|
65
|
+
const patchEnvelopeOnly = flag(args, '--patch-envelope-only');
|
|
66
|
+
const noApply = flag(args, '--no-apply');
|
|
67
|
+
const mergeStrategy = readOption(args, '--merge-strategy', 'deterministic');
|
|
68
|
+
const result = await runGlmNarutoMission({
|
|
69
|
+
cwd: process.cwd(),
|
|
70
|
+
task,
|
|
71
|
+
args,
|
|
72
|
+
maxWorkers,
|
|
73
|
+
deep,
|
|
74
|
+
useJudge,
|
|
75
|
+
xhighFinalizer,
|
|
76
|
+
useWorktree: useWorktree && !patchEnvelopeOnly,
|
|
77
|
+
noApply: noApply || flag(args, '--dry-run'),
|
|
78
|
+
mergeStrategy
|
|
79
|
+
});
|
|
80
|
+
if (flag(args, '--json')) {
|
|
81
|
+
printJson(result);
|
|
82
|
+
}
|
|
83
|
+
else {
|
|
84
|
+
const r = result;
|
|
85
|
+
if (r.ok) {
|
|
86
|
+
console.log(`GLM Naruto completed: ${r.applied_patches} patches applied, ${r.patch_candidates} candidates, ${r.gate_passed_candidates} gate-passed, ${r.repair_waves} repair waves`);
|
|
87
|
+
if (r.artifact_dir)
|
|
88
|
+
console.log(`Artifacts: ${r.artifact_dir}`);
|
|
89
|
+
}
|
|
90
|
+
else {
|
|
91
|
+
console.error(`GLM Naruto ${r.status}: ${r.termination_reason} — blockers: ${r.blockers.join(', ')}`);
|
|
92
|
+
process.exitCode = 1;
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
return result;
|
|
96
|
+
}
|
|
97
|
+
//# sourceMappingURL=glm-naruto-command.js.map
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { GLM_NARUTO_DEFAULTS } from './glm-naruto-types.js';
|
|
2
|
+
export function decideConcurrency(input) {
|
|
3
|
+
const maxClones = Math.min(input.operatorMax || GLM_NARUTO_DEFAULTS.max_clones, GLM_NARUTO_DEFAULTS.max_clones);
|
|
4
|
+
const requested = Math.min(input.requestedClones || GLM_NARUTO_DEFAULTS.default_clones, maxClones);
|
|
5
|
+
if (input.rateLimited429 > 0.05 || input.ttftP90Ms > 15_000) {
|
|
6
|
+
return {
|
|
7
|
+
target_active_workers: Math.max(1, Math.floor(input.activeWorkers * 0.5)),
|
|
8
|
+
burst_workers: 0,
|
|
9
|
+
backpressure: true,
|
|
10
|
+
reason: 'scale_down_high_latency_or_rate_limit'
|
|
11
|
+
};
|
|
12
|
+
}
|
|
13
|
+
if (input.failureRate > 0.3) {
|
|
14
|
+
return {
|
|
15
|
+
target_active_workers: Math.max(1, Math.floor(input.activeWorkers * 0.7)),
|
|
16
|
+
burst_workers: 0,
|
|
17
|
+
backpressure: true,
|
|
18
|
+
reason: 'scale_down_high_failure_rate'
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
if (input.ttftP90Ms < 5_000 && input.rateLimited429 === 0 && input.activeWorkers < requested) {
|
|
22
|
+
const target = Math.min(requested, input.activeWorkers + Math.max(1, Math.floor(requested * 0.2)));
|
|
23
|
+
return {
|
|
24
|
+
target_active_workers: target,
|
|
25
|
+
burst_workers: Math.min(2, requested - target),
|
|
26
|
+
backpressure: false,
|
|
27
|
+
reason: 'scale_up_low_latency_no_rate_limit'
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
return {
|
|
31
|
+
target_active_workers: Math.min(input.activeWorkers, requested),
|
|
32
|
+
burst_workers: 0,
|
|
33
|
+
backpressure: false,
|
|
34
|
+
reason: 'steady_state'
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
//# sourceMappingURL=glm-naruto-concurrency-governor.js.map
|