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.
Files changed (49) hide show
  1. package/README.md +2 -2
  2. package/crates/sks-core/Cargo.lock +1 -1
  3. package/crates/sks-core/Cargo.toml +1 -1
  4. package/crates/sks-core/src/main.rs +1 -1
  5. package/dist/bin/sks.js +1 -1
  6. package/dist/cli/command-registry.js +1 -0
  7. package/dist/core/commands/glm-command.js +8 -1
  8. package/dist/core/commands/naruto-command.js +25 -0
  9. package/dist/core/commands/stop-gate-command.js +63 -0
  10. package/dist/core/fsx.js +1 -1
  11. package/dist/core/pipeline-internals/runtime-gates.js +28 -4
  12. package/dist/core/providers/glm/glm-bench.js +4 -4
  13. package/dist/core/providers/glm/glm-direct-run.js +1 -1
  14. package/dist/core/providers/glm/glm-latency-trace.js +1 -1
  15. package/dist/core/providers/glm/glm-request-cache.js +10 -2
  16. package/dist/core/providers/glm/naruto/glm-naruto-artifacts.js +2 -0
  17. package/dist/core/providers/glm/naruto/glm-naruto-bench.js +68 -0
  18. package/dist/core/providers/glm/naruto/glm-naruto-budget.js +45 -0
  19. package/dist/core/providers/glm/naruto/glm-naruto-command.js +97 -0
  20. package/dist/core/providers/glm/naruto/glm-naruto-concurrency-governor.js +37 -0
  21. package/dist/core/providers/glm/naruto/glm-naruto-conflict-graph.js +74 -0
  22. package/dist/core/providers/glm/naruto/glm-naruto-decomposer.js +99 -0
  23. package/dist/core/providers/glm/naruto/glm-naruto-file-lease.js +23 -0
  24. package/dist/core/providers/glm/naruto/glm-naruto-finalizer.js +22 -0
  25. package/dist/core/providers/glm/naruto/glm-naruto-judge.js +84 -0
  26. package/dist/core/providers/glm/naruto/glm-naruto-merge-planner.js +57 -0
  27. package/dist/core/providers/glm/naruto/glm-naruto-orchestrator.js +277 -0
  28. package/dist/core/providers/glm/naruto/glm-naruto-patch-envelope.js +55 -0
  29. package/dist/core/providers/glm/naruto/glm-naruto-quorum.js +37 -0
  30. package/dist/core/providers/glm/naruto/glm-naruto-rate-limiter.js +18 -0
  31. package/dist/core/providers/glm/naruto/glm-naruto-repair-wave.js +21 -0
  32. package/dist/core/providers/glm/naruto/glm-naruto-shard-planner.js +32 -0
  33. package/dist/core/providers/glm/naruto/glm-naruto-trace.js +91 -0
  34. package/dist/core/providers/glm/naruto/glm-naruto-types.js +37 -0
  35. package/dist/core/providers/glm/naruto/glm-naruto-work-graph.js +2 -0
  36. package/dist/core/providers/glm/naruto/glm-naruto-worker-pool.js +79 -0
  37. package/dist/core/providers/glm/naruto/glm-naruto-worker-runtime.js +198 -0
  38. package/dist/core/providers/glm/naruto/glm-naruto-worker.js +2 -0
  39. package/dist/core/providers/glm/naruto/glm-naruto-worktree.js +48 -0
  40. package/dist/core/providers/openrouter/openrouter-provider-health.js +46 -0
  41. package/dist/core/providers/openrouter/openrouter-secret-store.js +33 -0
  42. package/dist/core/providers/openrouter/openrouter-stream.js +101 -8
  43. package/dist/core/stop-gate/stop-gate-check.js +208 -0
  44. package/dist/core/stop-gate/stop-gate-diagnostics.js +4 -0
  45. package/dist/core/stop-gate/stop-gate-resolver.js +122 -0
  46. package/dist/core/stop-gate/stop-gate-types.js +2 -0
  47. package/dist/core/stop-gate/stop-gate-writer.js +76 -0
  48. package/dist/core/version.js +1 -1
  49. 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.6** 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.
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.7:
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
 
@@ -76,7 +76,7 @@ dependencies = [
76
76
 
77
77
  [[package]]
78
78
  name = "sks-core"
79
- version = "4.0.6"
79
+ version = "4.0.9"
80
80
  dependencies = [
81
81
  "serde_json",
82
82
  ]
@@ -1,6 +1,6 @@
1
1
  [package]
2
2
  name = "sks-core"
3
- version = "4.0.6"
3
+ version = "4.0.9"
4
4
  edition = "2021"
5
5
 
6
6
  [dependencies]
@@ -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.6"),
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
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
- const FAST_PACKAGE_VERSION = '4.0.6';
2
+ const FAST_PACKAGE_VERSION = '4.0.9';
3
3
  const args = process.argv.slice(2);
4
4
  try {
5
5
  if (args[0] === '--agent' && args[1] === 'worker') {
@@ -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, '--bench')) {
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.6';
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
- const gate = await passedActiveGate(root, state);
237
- if (!gate.ok) {
238
- const missing = gate.missing?.length ? ` Missing gate fields: ${gate.missing.join(', ')}.` : '';
239
- 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 });
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.6',
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.6',
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.6',
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.6',
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 || GLM_52_OPENROUTER_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 });
@@ -3,7 +3,7 @@ import { nowIso, writeJsonAtomic } from '../../fsx.js';
3
3
  export function createEmptyGlmLatencyTrace(mode) {
4
4
  return {
5
5
  schema: 'sks.glm-latency-trace.v1',
6
- version: '4.0.6',
6
+ version: '4.0.9',
7
7
  mode,
8
8
  total_ms: 0,
9
9
  preflight_ms: 0,
@@ -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,2 @@
1
+ export { writeMissionArtifacts, createMissionTrace, recordWorkerTrace, buildMissionSummary } from './glm-naruto-trace.js';
2
+ //# sourceMappingURL=glm-naruto-artifacts.js.map
@@ -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