sneakoscope 4.0.7 → 4.0.8

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 (39) 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/core/commands/glm-command.js +8 -1
  7. package/dist/core/fsx.js +1 -1
  8. package/dist/core/providers/glm/glm-bench.js +4 -4
  9. package/dist/core/providers/glm/glm-latency-trace.js +1 -1
  10. package/dist/core/providers/glm/glm-request-cache.js +10 -2
  11. package/dist/core/providers/glm/naruto/glm-naruto-artifacts.js +2 -0
  12. package/dist/core/providers/glm/naruto/glm-naruto-bench.js +68 -0
  13. package/dist/core/providers/glm/naruto/glm-naruto-budget.js +45 -0
  14. package/dist/core/providers/glm/naruto/glm-naruto-command.js +97 -0
  15. package/dist/core/providers/glm/naruto/glm-naruto-concurrency-governor.js +37 -0
  16. package/dist/core/providers/glm/naruto/glm-naruto-conflict-graph.js +74 -0
  17. package/dist/core/providers/glm/naruto/glm-naruto-decomposer.js +99 -0
  18. package/dist/core/providers/glm/naruto/glm-naruto-file-lease.js +23 -0
  19. package/dist/core/providers/glm/naruto/glm-naruto-finalizer.js +22 -0
  20. package/dist/core/providers/glm/naruto/glm-naruto-judge.js +84 -0
  21. package/dist/core/providers/glm/naruto/glm-naruto-merge-planner.js +57 -0
  22. package/dist/core/providers/glm/naruto/glm-naruto-orchestrator.js +224 -0
  23. package/dist/core/providers/glm/naruto/glm-naruto-patch-envelope.js +55 -0
  24. package/dist/core/providers/glm/naruto/glm-naruto-quorum.js +37 -0
  25. package/dist/core/providers/glm/naruto/glm-naruto-rate-limiter.js +18 -0
  26. package/dist/core/providers/glm/naruto/glm-naruto-repair-wave.js +21 -0
  27. package/dist/core/providers/glm/naruto/glm-naruto-shard-planner.js +32 -0
  28. package/dist/core/providers/glm/naruto/glm-naruto-trace.js +51 -0
  29. package/dist/core/providers/glm/naruto/glm-naruto-types.js +37 -0
  30. package/dist/core/providers/glm/naruto/glm-naruto-work-graph.js +2 -0
  31. package/dist/core/providers/glm/naruto/glm-naruto-worker-pool.js +79 -0
  32. package/dist/core/providers/glm/naruto/glm-naruto-worker-runtime.js +196 -0
  33. package/dist/core/providers/glm/naruto/glm-naruto-worker.js +2 -0
  34. package/dist/core/providers/glm/naruto/glm-naruto-worktree.js +48 -0
  35. package/dist/core/providers/openrouter/openrouter-provider-health.js +46 -0
  36. package/dist/core/providers/openrouter/openrouter-secret-store.js +33 -0
  37. package/dist/core/providers/openrouter/openrouter-stream.js +73 -5
  38. package/dist/core/version.js +1 -1
  39. package/package.json +1 -1
@@ -0,0 +1,84 @@
1
+ import { buildGlm52Request } from '../glm-52-request.js';
2
+ import { sendOpenRouterChatCompletionStream } from '../../openrouter/openrouter-stream.js';
3
+ import { assertGlm52ActualModel } from '../glm-52-response-guard.js';
4
+ import { GLM_52_OPENROUTER_MODEL } from '../glm-52-settings.js';
5
+ export async function runGlmJudge(input) {
6
+ const validEnvelopes = input.envelopes.filter((e) => e.status === 'gate_passed');
7
+ if (validEnvelopes.length === 0) {
8
+ return {
9
+ schema: 'sks.glm-naruto-judge.v1',
10
+ ranked_patch_ids: [],
11
+ reject_patch_ids: [],
12
+ mergeable_sets: [],
13
+ risks: ['no_gate_passed_candidates'],
14
+ requires_repair_wave: false
15
+ };
16
+ }
17
+ const systemPrompt = `You are a GLM Naruto judge. Rank patch candidates by quality. Output strict JSON with schema: {"ranked_patch_ids":["id1","id2"],"reject_patch_ids":["id3"],"mergeable_sets":[["id1","id2"]],"risks":[],"requires_repair_wave":false}. Model: ${GLM_52_OPENROUTER_MODEL}. No GPT fallback.`;
18
+ const candidateDescriptions = validEnvelopes.map((e) => ({
19
+ patch_id: e.worker_id,
20
+ shard_id: e.shard_id,
21
+ target_paths: e.target_paths,
22
+ patch_sha256: e.patch_sha256.slice(0, 12),
23
+ strategy: e.strategy,
24
+ patch_size: e.patch.length
25
+ }));
26
+ const userContent = JSON.stringify({
27
+ mission_id: input.missionId,
28
+ candidates: candidateDescriptions,
29
+ instruction: 'Rank by: gate pass, minimal diff, correct target paths, no protected paths. Return mergeable non-conflicting sets.'
30
+ });
31
+ const messages = [
32
+ { role: 'system', content: systemPrompt },
33
+ { role: 'user', content: userContent }
34
+ ];
35
+ const request = buildGlm52Request({
36
+ profile: 'deep',
37
+ messages,
38
+ maxTokens: 8192,
39
+ reasoningEffort: 'high',
40
+ toolChoice: 'none',
41
+ parallelToolCalls: false
42
+ });
43
+ const response = await sendOpenRouterChatCompletionStream({
44
+ apiKey: input.apiKey,
45
+ request: { ...request, session_id: `sks-glm-naruto-judge-${input.missionId}` },
46
+ timeoutMs: input.timeoutMs || 120_000
47
+ });
48
+ if (!response.ok) {
49
+ return fallbackJudgeResult(validEnvelopes, [`judge_request_failed:${response.error.code}`]);
50
+ }
51
+ const modelGuard = assertGlm52ActualModel(response.value.model || GLM_52_OPENROUTER_MODEL);
52
+ if (!modelGuard.ok) {
53
+ return fallbackJudgeResult(validEnvelopes, [`judge_model_guard:${modelGuard.code}`]);
54
+ }
55
+ try {
56
+ const jsonMatch = response.value.content.match(/\{[\s\S]*\}/);
57
+ if (!jsonMatch)
58
+ return fallbackJudgeResult(validEnvelopes, ['judge_no_json_output']);
59
+ const parsed = JSON.parse(jsonMatch[0]);
60
+ return {
61
+ schema: 'sks.glm-naruto-judge.v1',
62
+ ranked_patch_ids: Array.isArray(parsed.ranked_patch_ids) ? parsed.ranked_patch_ids : [],
63
+ reject_patch_ids: Array.isArray(parsed.reject_patch_ids) ? parsed.reject_patch_ids : [],
64
+ mergeable_sets: Array.isArray(parsed.mergeable_sets) ? parsed.mergeable_sets : [],
65
+ risks: Array.isArray(parsed.risks) ? parsed.risks : [],
66
+ requires_repair_wave: Boolean(parsed.requires_repair_wave)
67
+ };
68
+ }
69
+ catch {
70
+ return fallbackJudgeResult(validEnvelopes, ['judge_json_parse_failed']);
71
+ }
72
+ }
73
+ function fallbackJudgeResult(envelopes, risks) {
74
+ const sorted = [...envelopes].sort((a, b) => a.patch.length - b.patch.length);
75
+ return {
76
+ schema: 'sks.glm-naruto-judge.v1',
77
+ ranked_patch_ids: sorted.map((e) => e.worker_id),
78
+ reject_patch_ids: [],
79
+ mergeable_sets: sorted.length > 0 ? [[sorted[0].worker_id]] : [],
80
+ risks,
81
+ requires_repair_wave: false
82
+ };
83
+ }
84
+ //# sourceMappingURL=glm-naruto-judge.js.map
@@ -0,0 +1,57 @@
1
+ import { getNonConflictingSets } from './glm-naruto-conflict-graph.js';
2
+ export function planMerge(input) {
3
+ const passedNodes = input.graph.nodes.filter((n) => n.gate_passed);
4
+ const nonConflictingSets = getNonConflictingSets(input.graph);
5
+ const candidates = nonConflictingSets.map((patchIds) => {
6
+ const nodes = passedNodes.filter((n) => patchIds.includes(n.patch_id));
7
+ const totalScore = nodes.reduce((sum, n) => sum + n.score, 0);
8
+ return { patch_ids: patchIds, total_score: totalScore, conflict_free: true };
9
+ });
10
+ candidates.sort((a, b) => b.total_score - a.total_score);
11
+ let selected = [];
12
+ let rationale = '';
13
+ if (input.strategy === 'judge' && input.judgeRanking && input.judgeRanking.length > 0) {
14
+ const ranked = input.judgeRanking.filter((id) => passedNodes.some((n) => n.patch_id === id));
15
+ const bestSet = candidates.find((set) => set.patch_ids.every((id) => ranked.includes(id))) || candidates[0];
16
+ selected = bestSet ? bestSet.patch_ids : [];
17
+ rationale = 'judge_ranked_deterministic_gated';
18
+ }
19
+ else if (input.strategy === 'quorum') {
20
+ const quorumMap = new Map();
21
+ for (const node of passedNodes) {
22
+ const key = node.shard_id;
23
+ quorumMap.set(key, (quorumMap.get(key) || 0) + 1);
24
+ }
25
+ const bestSet = candidates[0];
26
+ selected = bestSet ? bestSet.patch_ids : [];
27
+ rationale = 'quorum_consensus_deterministic_gated';
28
+ }
29
+ else {
30
+ const bestSet = candidates[0];
31
+ selected = bestSet ? bestSet.patch_ids : [];
32
+ rationale = 'highest_score_non_conflicting';
33
+ }
34
+ return {
35
+ schema: 'sks.glm-naruto-merge-plan.v1',
36
+ mission_id: input.missionId,
37
+ strategy: input.strategy,
38
+ selected_patches: selected,
39
+ candidates,
40
+ rationale
41
+ };
42
+ }
43
+ export function scoreCandidate(input) {
44
+ let score = 0;
45
+ if (input.node.gate_passed)
46
+ score += 100;
47
+ score -= input.patchSize / 100;
48
+ score -= input.touchedPathsCount * 5;
49
+ if (input.protectedPath)
50
+ score -= 200;
51
+ if (input.testFailure)
52
+ score -= 50;
53
+ if (input.judgeRank !== null && input.judgeRank !== undefined)
54
+ score += Math.max(0, 50 - input.judgeRank * 10);
55
+ return Math.round(score);
56
+ }
57
+ //# sourceMappingURL=glm-naruto-merge-planner.js.map
@@ -0,0 +1,224 @@
1
+ import path from 'node:path';
2
+ import { nowIso, writeJsonAtomic } from '../../../fsx.js';
3
+ import { GLM_52_OPENROUTER_MODEL } from '../glm-52-settings.js';
4
+ import { resolveOpenRouterApiKey } from '../../openrouter/openrouter-secret-store.js';
5
+ import { checkAndApplyGlmPatch } from '../glm-patch-apply.js';
6
+ import { decomposeTask, validateWorkGraph } from './glm-naruto-decomposer.js';
7
+ import { planShardCandidates, computeInitialLaneMix } from './glm-naruto-shard-planner.js';
8
+ import { runPatchWorkerPool } from './glm-naruto-worker-pool.js';
9
+ import { buildConflictGraph } from './glm-naruto-conflict-graph.js';
10
+ import { planMerge } from './glm-naruto-merge-planner.js';
11
+ import { finalizeMergePlan } from './glm-naruto-finalizer.js';
12
+ import { planRepairWave } from './glm-naruto-repair-wave.js';
13
+ import { createBudget, checkBudget, recordRequest } from './glm-naruto-budget.js';
14
+ import { createProviderHealthTracker } from '../../openrouter/openrouter-provider-health.js';
15
+ import { createMissionTrace, recordWorkerTrace, writeMissionArtifacts, buildMissionSummary } from './glm-naruto-trace.js';
16
+ import { runGlmJudge } from './glm-naruto-judge.js';
17
+ import { GLM_NARUTO_LIMITS } from './glm-naruto-types.js';
18
+ export async function runGlmNarutoMission(input) {
19
+ const missionId = input.missionId || `glm-naruto-${nowIso().replace(/[:.]/g, '-')}`;
20
+ const cwd = input.cwd;
21
+ const startedMs = Date.now();
22
+ const key = await resolveOpenRouterApiKey({ env: process.env });
23
+ if (!key.key) {
24
+ return missionResult(missionId, input.task, 'blocked', 'glm_missing_openrouter_key', 0, startedMs, [], [], ['glm_missing_openrouter_key'], []);
25
+ }
26
+ const mentionedPaths = extractMentionedPaths(input.task);
27
+ const gitStatus = await readGitStatus(cwd);
28
+ const graph = decomposeTask({
29
+ missionId,
30
+ task: input.task,
31
+ gitStatus,
32
+ mentionedPaths
33
+ });
34
+ const isVerifyOnly = input.task.trim().toLowerCase().startsWith('verify');
35
+ const validation = validateWorkGraph(graph, isVerifyOnly);
36
+ if (!validation.ok) {
37
+ return missionResult(missionId, input.task, 'blocked', validation.reason || 'invalid_work_graph', 0, startedMs, [], [], [validation.reason || 'invalid_work_graph'], []);
38
+ }
39
+ const budget = createBudget(missionId, input.deep || false);
40
+ const budgetCheck = checkBudget(budget);
41
+ if (!budgetCheck.ok) {
42
+ return missionResult(missionId, input.task, 'budget_exhausted', budgetCheck.reason, 0, startedMs, [], [], [budgetCheck.reason], []);
43
+ }
44
+ const laneMix = computeInitialLaneMix(graph);
45
+ const strategies = planShardCandidates(graph);
46
+ const strategyMap = new Map();
47
+ for (const entry of strategies) {
48
+ strategyMap.set(entry.shard.id, entry.strategies);
49
+ }
50
+ const healthTracker = createProviderHealthTracker();
51
+ let traceState = createMissionTrace(missionId);
52
+ // Wave 1: parallel patch candidate generation
53
+ const poolResult = await runPatchWorkerPool({
54
+ apiKey: key.key,
55
+ missionId,
56
+ cwd,
57
+ shards: graph.shards,
58
+ contextSummary: JSON.stringify({ task: input.task, git_status: gitStatus || '' }),
59
+ maxWorkers: input.maxWorkers || laneMix.patch_workers,
60
+ workerTimeoutMs: GLM_NARUTO_LIMITS.max_worker_runtime_ms,
61
+ strategies: strategyMap
62
+ });
63
+ for (const trace of poolResult.traces) {
64
+ traceState = recordWorkerTrace(traceState, trace);
65
+ }
66
+ healthTracker.record({ provider_slug: 'openrouter', model: GLM_52_OPENROUTER_MODEL, count_429: 0, count_5xx: 0 });
67
+ let envelopes = poolResult.envelopes;
68
+ let failedShardIds = poolResult.failedShardIds;
69
+ let repairWaves = 0;
70
+ // Repair wave if needed
71
+ if (failedShardIds.length > 0 && repairWaves < GLM_NARUTO_LIMITS.max_repair_waves) {
72
+ const repairPlan = planRepairWave({
73
+ failedEnvelopes: envelopes.filter((e) => e.status === 'gate_failed'),
74
+ shards: graph.shards,
75
+ repairWaveCount: repairWaves
76
+ });
77
+ if (repairPlan.canRepair && repairPlan.shardsToRepair.length > 0) {
78
+ repairWaves++;
79
+ const repairPool = await runPatchWorkerPool({
80
+ apiKey: key.key,
81
+ missionId,
82
+ cwd,
83
+ shards: repairPlan.shardsToRepair,
84
+ contextSummary: JSON.stringify({ task: input.task, repair: true }),
85
+ maxWorkers: input.maxWorkers || 3,
86
+ workerTimeoutMs: GLM_NARUTO_LIMITS.max_worker_runtime_ms,
87
+ strategies: new Map(repairPlan.shardsToRepair.map((s) => [s.id, [s.strategy]]))
88
+ });
89
+ envelopes = [...envelopes, ...repairPool.envelopes];
90
+ for (const trace of repairPool.traces) {
91
+ traceState = recordWorkerTrace(traceState, trace);
92
+ }
93
+ failedShardIds = [...failedShardIds, ...repairPool.failedShardIds];
94
+ }
95
+ }
96
+ // Build conflict graph and merge plan
97
+ const passedEnvelopes = envelopes.filter((e) => e.status === 'gate_passed');
98
+ const nodes = passedEnvelopes.map((env) => ({
99
+ patch_id: env.worker_id,
100
+ shard_id: env.shard_id,
101
+ target_paths: env.target_paths,
102
+ score: Math.max(0, 100 - Math.floor(env.patch.length / 100)),
103
+ gate_passed: true,
104
+ patch_sha256: env.patch_sha256
105
+ }));
106
+ const conflictGraph = buildConflictGraph(passedEnvelopes, nodes);
107
+ let judgeResult = null;
108
+ if (input.useJudge && passedEnvelopes.length > 1) {
109
+ judgeResult = await runGlmJudge({
110
+ apiKey: key.key,
111
+ missionId,
112
+ envelopes: passedEnvelopes,
113
+ timeoutMs: 120_000
114
+ });
115
+ }
116
+ const mergePlan = finalizeMergePlan({
117
+ missionId,
118
+ envelopes: passedEnvelopes,
119
+ ...(judgeResult ? { judgeResult } : {}),
120
+ useJudge: input.useJudge || false,
121
+ xhighFinalizer: input.xhighFinalizer || false
122
+ });
123
+ // Apply winning merge plan
124
+ let appliedPatches = 0;
125
+ let applyResult = null;
126
+ if (!input.noApply && mergePlan.selected_patches.length > 0) {
127
+ for (const patchId of mergePlan.selected_patches) {
128
+ const envelope = envelopes.find((e) => e.worker_id === patchId);
129
+ if (!envelope)
130
+ continue;
131
+ const applied = await checkAndApplyGlmPatch({ cwd, patch: envelope.patch, apply: true });
132
+ if (applied.ok) {
133
+ appliedPatches++;
134
+ }
135
+ }
136
+ applyResult = { ok: appliedPatches > 0, applied: mergePlan.selected_patches };
137
+ }
138
+ const terminalState = appliedPatches > 0 ? 'completed' : passedEnvelopes.length > 0 ? 'partial_candidates' : 'blocked';
139
+ const terminationReason = appliedPatches > 0 ? 'completed_merge_applied' : passedEnvelopes.length > 0 ? 'partial_no_apply' : 'no_gate_passed_candidates';
140
+ const summary = buildMissionSummary({
141
+ missionId,
142
+ startedMs,
143
+ workerTraces: traceState.workerTraces,
144
+ patchCandidates: envelopes.length,
145
+ gatePassed: passedEnvelopes.length,
146
+ mergeable: mergePlan.candidates.length,
147
+ appliedPatches,
148
+ failedShards: failedShardIds.length,
149
+ repairWaves
150
+ });
151
+ const result = {
152
+ schema: 'sks.glm-naruto-mission-result.v1',
153
+ ok: terminalState === 'completed',
154
+ status: terminalState,
155
+ mission_id: missionId,
156
+ task: input.task,
157
+ model: GLM_52_OPENROUTER_MODEL,
158
+ gpt_fallback_allowed: false,
159
+ termination_reason: terminationReason,
160
+ workers_started: summary.workers_started,
161
+ workers_completed: summary.workers_completed,
162
+ patch_candidates: summary.patch_candidates,
163
+ gate_passed_candidates: summary.gate_passed_candidates,
164
+ mergeable_candidates: summary.mergeable_candidates,
165
+ applied_patches: summary.applied_patches,
166
+ failed_shards: summary.failed_shards,
167
+ repair_waves: summary.repair_waves,
168
+ budget_used_ms: summary.budget_used_ms,
169
+ blockers: terminalState === 'blocked' ? ['no_gate_passed_candidates'] : [],
170
+ warnings: []
171
+ };
172
+ const artifactDir = await writeMissionArtifacts({
173
+ root: cwd,
174
+ missionId,
175
+ workGraph: graph,
176
+ conflictGraph,
177
+ mergePlan,
178
+ ...(judgeResult ? { judgeResult } : {}),
179
+ workerTraces: traceState.workerTraces,
180
+ providerHealth: healthTracker.snapshot(),
181
+ termination: { schema: 'sks.glm-naruto-termination.v1', mission_id: missionId, terminal_state: terminalState, reason: terminationReason, wall_clock_ms: summary.wall_clock_ms },
182
+ ...(applyResult ? { applyResult: { ...applyResult, schema: 'sks.glm-naruto-apply-result.v1' } } : {}),
183
+ verificationSummary: { schema: 'sks.glm-naruto-verification.v1', verified: passedEnvelopes.length, total: envelopes.length },
184
+ missionResult: result
185
+ });
186
+ return { ...result, artifact_dir: artifactDir };
187
+ }
188
+ function missionResult(missionId, task, status, reason, patchCandidates, startedMs, envelopes, traces, blockers, warnings) {
189
+ return {
190
+ schema: 'sks.glm-naruto-mission-result.v1',
191
+ ok: status === 'completed',
192
+ status,
193
+ mission_id: missionId,
194
+ task,
195
+ model: GLM_52_OPENROUTER_MODEL,
196
+ gpt_fallback_allowed: false,
197
+ termination_reason: reason,
198
+ workers_started: traces.length,
199
+ workers_completed: traces.filter((t) => t.status === 'completed').length,
200
+ patch_candidates: envelopes.length,
201
+ gate_passed_candidates: envelopes.filter((e) => e.status === 'gate_passed').length,
202
+ mergeable_candidates: 0,
203
+ applied_patches: 0,
204
+ failed_shards: 0,
205
+ repair_waves: 0,
206
+ budget_used_ms: Date.now() - startedMs,
207
+ blockers,
208
+ warnings
209
+ };
210
+ }
211
+ async function readGitStatus(cwd) {
212
+ const { spawn } = await import('node:child_process');
213
+ return new Promise((resolve) => {
214
+ const child = spawn('git', ['status', '--short'], { cwd, stdio: ['ignore', 'pipe', 'ignore'] });
215
+ let stdout = '';
216
+ child.stdout.on('data', (chunk) => { stdout += String(chunk); });
217
+ child.on('close', () => resolve(stdout.trim() || undefined));
218
+ });
219
+ }
220
+ function extractMentionedPaths(task) {
221
+ const matches = task.match(/(?:^|\s|[`"'])([A-Za-z0-9_.-]+\/[A-Za-z0-9_./-]+\.[A-Za-z0-9]+)(?:\s|[`"']|$)/g) || [];
222
+ return [...new Set(matches.map((value) => value.trim().replace(/^[`"']|[`"']$/g, '')))];
223
+ }
224
+ //# sourceMappingURL=glm-naruto-orchestrator.js.map
@@ -0,0 +1,55 @@
1
+ import crypto from 'node:crypto';
2
+ import { nowIso } from '../../../fsx.js';
3
+ import { GLM_52_OPENROUTER_MODEL } from '../glm-52-settings.js';
4
+ import { parseUnifiedDiffPatch } from '../glm-patch-parser.js';
5
+ export function createPatchEnvelope(input) {
6
+ const parsed = parseUnifiedDiffPatch(input.patch);
7
+ return {
8
+ schema: 'sks.glm-naruto-patch-envelope.v1',
9
+ mission_id: input.missionId,
10
+ worker_id: input.workerId,
11
+ shard_id: input.shardId,
12
+ base_digest: input.baseDigest,
13
+ target_paths: parsed.touchedPaths,
14
+ patch: input.patch,
15
+ patch_sha256: crypto.createHash('sha256').update(input.patch).digest('hex'),
16
+ model: GLM_52_OPENROUTER_MODEL,
17
+ provider: 'openrouter',
18
+ reasoning_effort: input.reasoningEffort,
19
+ gpt_fallback_allowed: false,
20
+ generated_at: nowIso(),
21
+ status: input.status || 'candidate',
22
+ blockers: input.blockers || [],
23
+ warnings: input.warnings || [],
24
+ strategy: input.strategy
25
+ };
26
+ }
27
+ export function normalizePatchForDigest(patch) {
28
+ return patch.replace(/\s+/g, ' ').trim();
29
+ }
30
+ export function digestPatch(patch) {
31
+ return crypto.createHash('sha256').update(normalizePatchForDigest(patch)).digest('hex');
32
+ }
33
+ export function parsePatchCandidateOutput(text) {
34
+ const patchStart = text.indexOf('<sks_patch_candidate>');
35
+ const patchEnd = text.indexOf('</sks_patch_candidate>');
36
+ if (patchStart >= 0 && patchEnd > patchStart) {
37
+ return { kind: 'patch', content: text.slice(patchStart + '<sks_patch_candidate>'.length, patchEnd).trim() };
38
+ }
39
+ const needStart = text.indexOf('<sks_need_context>');
40
+ const needEnd = text.indexOf('</sks_need_context>');
41
+ if (needStart >= 0 && needEnd > needStart) {
42
+ const body = text.slice(needStart + '<sks_need_context>'.length, needEnd).trim();
43
+ const paths = body.split(/\r?\n/).map((line) => line.match(/^\s*-\s*(.+?)\s*$/)?.[1]).filter((v) => Boolean(v));
44
+ return { kind: 'need_context', content: body, paths };
45
+ }
46
+ const blockedStart = text.indexOf('<sks_blocked>');
47
+ const blockedEnd = text.indexOf('</sks_blocked>');
48
+ if (blockedStart >= 0 && blockedEnd > blockedStart) {
49
+ const body = text.slice(blockedStart + '<sks_blocked>'.length, blockedEnd).trim();
50
+ const reason = body.match(/reason:\s*(.+)/i)?.[1]?.trim() || body;
51
+ return { kind: 'blocked', content: body, reason };
52
+ }
53
+ return { kind: 'malformed', content: text.trim(), reason: 'missing_glm_naruto_output_envelope' };
54
+ }
55
+ //# sourceMappingURL=glm-naruto-patch-envelope.js.map
@@ -0,0 +1,37 @@
1
+ import { digestPatch } from './glm-naruto-patch-envelope.js';
2
+ export function evaluateQuorum(envelopes) {
3
+ const byShard = new Map();
4
+ for (const env of envelopes) {
5
+ if (env.status !== 'gate_passed' && env.status !== 'candidate')
6
+ continue;
7
+ const list = byShard.get(env.shard_id) || [];
8
+ list.push(env);
9
+ byShard.set(env.shard_id, list);
10
+ }
11
+ const results = [];
12
+ for (const [shardId, envs] of byShard) {
13
+ const digestCounts = new Map();
14
+ for (const env of envs) {
15
+ const digest = digestPatch(env.patch);
16
+ const existing = digestCounts.get(digest) || { count: 0, patches: [] };
17
+ existing.count++;
18
+ existing.patches.push(env.patch);
19
+ digestCounts.set(digest, existing);
20
+ }
21
+ let best = null;
22
+ for (const [digest, info] of digestCounts) {
23
+ if (!best || info.count > best.count) {
24
+ best = { count: info.count, patches: info.patches, digest };
25
+ }
26
+ }
27
+ results.push({
28
+ shardId,
29
+ consensusDigest: best ? best.digest : null,
30
+ voteCount: best ? best.count : 0,
31
+ totalCandidates: envs.length,
32
+ consensusPatches: best ? best.patches : []
33
+ });
34
+ }
35
+ return results;
36
+ }
37
+ //# sourceMappingURL=glm-naruto-quorum.js.map
@@ -0,0 +1,18 @@
1
+ export function createRateLimitState() {
2
+ return { rateLimited: false, retryAfterMs: 0, consecutive429: 0, last429At: null };
3
+ }
4
+ export function handleRateLimit(state, retryAfterMs) {
5
+ return {
6
+ rateLimited: true,
7
+ retryAfterMs,
8
+ consecutive429: state.consecutive429 + 1,
9
+ last429At: Date.now()
10
+ };
11
+ }
12
+ export function clearRateLimit(state) {
13
+ return { rateLimited: false, retryAfterMs: 0, consecutive429: 0, last429At: state.last429At };
14
+ }
15
+ export function shouldBackoff(state) {
16
+ return state.consecutive429 > 3 || (state.last429At !== null && Date.now() - state.last429At < state.retryAfterMs);
17
+ }
18
+ //# sourceMappingURL=glm-naruto-rate-limiter.js.map
@@ -0,0 +1,21 @@
1
+ import { GLM_NARUTO_LIMITS } from './glm-naruto-types.js';
2
+ export function planRepairWave(input) {
3
+ if (input.repairWaveCount >= GLM_NARUTO_LIMITS.max_repair_waves) {
4
+ return { shardsToRepair: [], canRepair: false, reason: 'max_repair_waves_reached' };
5
+ }
6
+ const failedShardIds = new Set(input.failedEnvelopes.map((e) => e.shard_id));
7
+ const shardsToRepair = input.shards.filter((s) => failedShardIds.has(s.id));
8
+ if (shardsToRepair.length === 0) {
9
+ return { shardsToRepair: [], canRepair: false, reason: 'no_failed_shards_to_repair' };
10
+ }
11
+ return {
12
+ shardsToRepair: shardsToRepair.map((s) => ({
13
+ ...s,
14
+ strategy: 'defensive_fix',
15
+ patches_per_shard: 1
16
+ })),
17
+ canRepair: true,
18
+ reason: 'repair_wave_planned'
19
+ };
20
+ }
21
+ //# sourceMappingURL=glm-naruto-repair-wave.js.map
@@ -0,0 +1,32 @@
1
+ import { NARUTO_PATCH_STRATEGIES, GLM_NARUTO_DEFAULTS } from './glm-naruto-types.js';
2
+ export function planShardCandidates(graph) {
3
+ return graph.shards
4
+ .filter((shard) => shard.mutable)
5
+ .map((shard) => {
6
+ const strategies = assignStrategies(shard);
7
+ return {
8
+ shard,
9
+ strategies,
10
+ candidate_count: shard.patches_per_shard
11
+ };
12
+ });
13
+ }
14
+ function assignStrategies(shard) {
15
+ const base = Math.max(0, NARUTO_PATCH_STRATEGIES.indexOf(shard.strategy));
16
+ const result = [shard.strategy];
17
+ for (let i = 1; i < shard.patches_per_shard && i < NARUTO_PATCH_STRATEGIES.length; i++) {
18
+ const next = NARUTO_PATCH_STRATEGIES[(base + i) % NARUTO_PATCH_STRATEGIES.length] || 'minimal_patch';
19
+ if (!result.includes(next))
20
+ result.push(next);
21
+ }
22
+ return result;
23
+ }
24
+ export function computeInitialLaneMix(graph) {
25
+ const mutable = graph.mutable_shards.length;
26
+ const total = Math.max(mutable, GLM_NARUTO_DEFAULTS.safe_active_start);
27
+ const patchWorkers = Math.ceil(total * GLM_NARUTO_DEFAULTS.patch_worker_ratio);
28
+ const scouts = Math.max(0, Math.floor(total * GLM_NARUTO_DEFAULTS.scout_ratio));
29
+ const verifiers = Math.max(1, total - patchWorkers - scouts);
30
+ return { patch_workers: patchWorkers, scouts, verifiers };
31
+ }
32
+ //# sourceMappingURL=glm-naruto-shard-planner.js.map
@@ -0,0 +1,51 @@
1
+ import path from 'node:path';
2
+ import { nowIso, writeJsonAtomic } from '../../../fsx.js';
3
+ export function createMissionTrace(missionId) {
4
+ return {
5
+ missionId,
6
+ startedMs: Date.now(),
7
+ workerTraces: []
8
+ };
9
+ }
10
+ export function recordWorkerTrace(state, trace) {
11
+ return { ...state, workerTraces: [...state.workerTraces, trace] };
12
+ }
13
+ export async function writeMissionArtifacts(input) {
14
+ const dir = path.join(input.root, '.sneakoscope', 'glm-naruto', input.missionId);
15
+ if (input.workGraph)
16
+ await writeJsonAtomic(path.join(dir, 'work-graph.json'), input.workGraph);
17
+ if (input.conflictGraph)
18
+ await writeJsonAtomic(path.join(dir, 'conflict-graph.json'), input.conflictGraph);
19
+ if (input.mergePlan)
20
+ await writeJsonAtomic(path.join(dir, 'final-merge-plan.json'), input.mergePlan);
21
+ if (input.judgeResult)
22
+ await writeJsonAtomic(path.join(dir, 'judge-result.json'), input.judgeResult);
23
+ if (input.workerTraces.length > 0)
24
+ await writeJsonAtomic(path.join(dir, 'worker-traces.json'), input.workerTraces);
25
+ if (input.providerHealth)
26
+ await writeJsonAtomic(path.join(dir, 'provider-health.json'), input.providerHealth);
27
+ if (input.termination)
28
+ await writeJsonAtomic(path.join(dir, 'termination.json'), input.termination);
29
+ if (input.applyResult)
30
+ await writeJsonAtomic(path.join(dir, 'apply-result.json'), input.applyResult);
31
+ if (input.verificationSummary)
32
+ await writeJsonAtomic(path.join(dir, 'verification-summary.json'), input.verificationSummary);
33
+ if (input.missionResult)
34
+ await writeJsonAtomic(path.join(dir, 'mission-result.json'), input.missionResult);
35
+ return dir;
36
+ }
37
+ export function buildMissionSummary(input) {
38
+ return {
39
+ wall_clock_ms: Date.now() - input.startedMs,
40
+ workers_started: input.workerTraces.length,
41
+ workers_completed: input.workerTraces.filter((t) => t.status === 'completed').length,
42
+ patch_candidates: input.patchCandidates,
43
+ gate_passed_candidates: input.gatePassed,
44
+ mergeable_candidates: input.mergeable,
45
+ applied_patches: input.appliedPatches,
46
+ failed_shards: input.failedShards,
47
+ repair_waves: input.repairWaves,
48
+ budget_used_ms: Date.now() - input.startedMs
49
+ };
50
+ }
51
+ //# sourceMappingURL=glm-naruto-trace.js.map
@@ -0,0 +1,37 @@
1
+ import { GLM_52_OPENROUTER_MODEL } from '../glm-52-settings.js';
2
+ export const GLM_NARUTO_LIMITS = {
3
+ max_waves_speed: 3,
4
+ max_waves_deep: 5,
5
+ max_wall_clock_ms: 300_000,
6
+ max_worker_runtime_ms: 90_000,
7
+ max_total_requests: 128,
8
+ max_requests_per_shard: 4,
9
+ max_no_progress_waves: 1,
10
+ max_repeated_patch_digest: 1,
11
+ max_repair_waves: 1,
12
+ max_merge_attempts: 2
13
+ };
14
+ export const GLM_NARUTO_DEFAULTS = {
15
+ default_clones: 12,
16
+ safe_active_start: 6,
17
+ max_clones: 64,
18
+ patch_worker_ratio: 0.70,
19
+ scout_ratio: 0.10,
20
+ verifier_ratio: 0.20,
21
+ default_patches_per_shard: 2,
22
+ critical_patches_per_shard: 3,
23
+ default_max_tokens: 4096,
24
+ judge_max_tokens: 8192,
25
+ patch_temperature: 0.25,
26
+ patch_top_p: 0.85,
27
+ judge_temperature: 0.1,
28
+ judge_top_p: 0.8
29
+ };
30
+ export const NARUTO_PATCH_STRATEGIES = [
31
+ 'minimal_patch',
32
+ 'test_first_fix',
33
+ 'type_safe_fix',
34
+ 'refactor_local',
35
+ 'defensive_fix'
36
+ ];
37
+ //# sourceMappingURL=glm-naruto-types.js.map
@@ -0,0 +1,2 @@
1
+ export { decomposeTask, validateWorkGraph } from './glm-naruto-decomposer.js';
2
+ //# sourceMappingURL=glm-naruto-work-graph.js.map