sneakoscope 4.0.13 → 4.0.14
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 +10 -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/global-mode-router.js +2 -1
- package/dist/core/commands/mad-sks-command.js +3 -0
- package/dist/core/fsx.js +1 -1
- package/dist/core/providers/glm/bench/glm-bench-model-lock-proof.js +32 -3
- package/dist/core/providers/glm/bench/glm-benchmark-runner.js +29 -5
- package/dist/core/providers/glm/bench/glm-benchmark-types.js +1 -1
- package/dist/core/providers/glm/naruto/glm-naruto-critical-path.js +51 -0
- package/dist/core/providers/glm/naruto/glm-naruto-final-seal.js +9 -2
- package/dist/core/providers/glm/naruto/glm-naruto-orchestrator.js +101 -15
- package/dist/core/providers/glm/naruto/glm-naruto-parallelism-summary.js +55 -0
- package/dist/core/providers/glm/naruto/glm-naruto-requirement-coverage.js +92 -0
- package/dist/core/providers/glm/naruto/glm-naruto-requirement-ledger.js +42 -0
- package/dist/core/providers/glm/naruto/glm-naruto-stage-scheduler.js +85 -0
- package/dist/core/providers/glm/naruto/glm-naruto-task-size-classifier.js +12 -0
- package/dist/core/providers/glm/naruto/glm-naruto-trace.js +4 -0
- package/dist/core/providers/glm/naruto/glm-naruto-verifier-output.js +5 -0
- package/dist/core/providers/glm/naruto/glm-naruto-worker-pool.js +130 -44
- package/dist/core/providers/glm/naruto/glm-naruto-worker-runtime.js +6 -2
- package/dist/core/routes/model-mode-router.js +44 -0
- package/dist/core/version.js +1 -1
- package/package.json +24 -1
- package/dist/scripts/agent-dynamic-pool-fixture.js +0 -80
- package/dist/scripts/agent-native-release-gate.js +0 -274
- package/dist/scripts/agent-patch-swarm-gate-lib.js +0 -113
- package/dist/scripts/agent-real-codex-patch-envelope-smoke.js +0 -126
- package/dist/scripts/agent-route-blackbox-lib.js +0 -132
- package/dist/scripts/blackbox-command-import-smoke.js +0 -143
- package/dist/scripts/blackbox-global-shim.js +0 -77
- package/dist/scripts/blackbox-matrix.js +0 -70
- package/dist/scripts/blackbox-npx-one-shot.js +0 -69
- package/dist/scripts/blackbox-pack-install.js +0 -174
- package/dist/scripts/build-dist.js +0 -64
- package/dist/scripts/check-architecture.js +0 -135
- package/dist/scripts/check-cli-entrypoint.js +0 -43
- package/dist/scripts/check-command-module-budget.js +0 -25
- package/dist/scripts/check-dist-runtime.js +0 -100
- package/dist/scripts/check-feature-quality.js +0 -53
- package/dist/scripts/check-legacy-free.js +0 -66
- package/dist/scripts/check-package-boundary.js +0 -108
- package/dist/scripts/check-pipeline-budget.js +0 -69
- package/dist/scripts/check-pipeline-runtime.js +0 -25
- package/dist/scripts/check-publish-tag.js +0 -30
- package/dist/scripts/check-route-modularity.js +0 -82
- package/dist/scripts/check-runtime-schemas.js +0 -87
- package/dist/scripts/check-source-runtime.js +0 -4
- package/dist/scripts/check-ts-contracts.js +0 -69
- package/dist/scripts/check-ts-suppressions.js +0 -58
- package/dist/scripts/clean-dist.js +0 -8
- package/dist/scripts/codex-0140-feature-gate-lib.js +0 -14
- package/dist/scripts/codex-config-eperm-fixture.js +0 -32
- package/dist/scripts/codex-lb-missing-env-regression.js +0 -40
- package/dist/scripts/codex-native-runtime-e2e-fixture.js +0 -75
- package/dist/scripts/codex-project-config-policy-merge-regression.js +0 -92
- package/dist/scripts/core-skill-legacy-promotion-api-audit.js +0 -54
- package/dist/scripts/ensure-bin-executable.js +0 -10
- package/dist/scripts/fixtures/fake-codex-config-loader.js +0 -51
- package/dist/scripts/github-release-body-helper.js +0 -65
- package/dist/scripts/gpt-image-2-real-file-smoke.js +0 -448
- package/dist/scripts/hooks-no-unsupported-handlers.js +0 -15
- package/dist/scripts/hooks-runtime-replay-warning-zero-v2.js +0 -26
- package/dist/scripts/hooks-runtime-replay-warning-zero.js +0 -10
- package/dist/scripts/hooks-trust-warning-zero.js +0 -14
- package/dist/scripts/lib/codex-sdk-gate-lib.js +0 -92
- package/dist/scripts/lib/ensure-dist-fresh.js +0 -142
- package/dist/scripts/lib/git-worktree-fixture.js +0 -33
- package/dist/scripts/lib/mad-sks-actual-executor-check-lib.js +0 -255
- package/dist/scripts/lib/native-cli-session-swarm-check-lib.js +0 -79
- package/dist/scripts/lib/real-codex-parallel-gate.js +0 -94
- package/dist/scripts/lib/real-codex-parallel-proof-fixture.js +0 -55
- package/dist/scripts/lib/valid-png-fixture.js +0 -25
- package/dist/scripts/mad-sks-live-protected-core-smoke.js +0 -5
- package/dist/scripts/naruto-real-local-gpt-final-smoke.js +0 -25
- package/dist/scripts/perf-gate.js +0 -39
- package/dist/scripts/prepublish-release-check-or-fast.js +0 -121
- package/dist/scripts/release-3112-required-gates.js +0 -30
- package/dist/scripts/release-3113-required-gates.js +0 -25
- package/dist/scripts/release-4000-required-gates.js +0 -36
- package/dist/scripts/release-4001-required-gates.js +0 -13
- package/dist/scripts/release-4002-required-gates.js +0 -14
- package/dist/scripts/release-check-dynamic-execute.js +0 -259
- package/dist/scripts/release-check-dynamic.js +0 -107
- package/dist/scripts/release-check-stamp.js +0 -261
- package/dist/scripts/release-gate-dag-runner.js +0 -56
- package/dist/scripts/release-gate-existence-audit.js +0 -111
- package/dist/scripts/release-gate-planner.js +0 -34
- package/dist/scripts/release-gate-worker.js +0 -10
- package/dist/scripts/release-speed-summary.js +0 -67
- package/dist/scripts/repo-audit.js +0 -83
- package/dist/scripts/rust-smoke.js +0 -5
- package/dist/scripts/sizecheck.js +0 -146
- package/dist/scripts/sks-1-11-gate-lib.js +0 -78
- package/dist/scripts/sks-1-18-gate-lib.js +0 -55
- package/dist/scripts/tmux-removal-inventory.js +0 -36
- package/dist/scripts/write-build-manifest.js +0 -71
- package/dist/scripts/zellij-dashboard-watch.js +0 -41
- package/dist/scripts/zellij-right-column-geometry-proof.js +0 -162
package/README.md
CHANGED
|
@@ -35,9 +35,17 @@ 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.14** seals GLM Naruto real parallelism while preserving the existing GPT/Codex/MAD `sks --mad` route. GLM mode stays locked to OpenRouter `z-ai/glm-5.2`; non-GLM MAD does not require OpenRouter, does not select GLM, and does not enter the GLM Naruto scheduler.
|
|
39
39
|
|
|
40
|
-
What changed in 4.0.
|
|
40
|
+
What changed in 4.0.14:
|
|
41
|
+
|
|
42
|
+
- **Real stage parallelism evidence.** GLM Naruto records bounded parallel stage timelines, overlap ratios, parallelism summaries, critical-path metrics, and speed diagnosis artifacts.
|
|
43
|
+
- **Parallel gate/verifier/worktree stages.** Candidate gate, worktree materialization, and verifier checks no longer have to run candidate-by-candidate when multiple candidates are available.
|
|
44
|
+
- **Requirement coverage seal.** GLM Naruto writes a requirement ledger and candidate coverage artifacts, and the final seal blocks when required requirements remain uncovered.
|
|
45
|
+
- **MAD route isolation.** `sks --mad` without `--glm` remains the GPT/Codex/MAD route and does not resolve OpenRouter or run GLM-specific benchmark/Naruto code.
|
|
46
|
+
- **Benchmark proof honesty.** GLM benchmark proof now reports request-summary availability separately from case-level model lock checks and fixes the no-mutation proof boolean.
|
|
47
|
+
|
|
48
|
+
What changed in 4.0.13:
|
|
41
49
|
|
|
42
50
|
- **Extracted worktree patches.** `--worktree` parses `<sks_patch_candidate>` and records candidate/extracted patch hashes before any worker worktree apply.
|
|
43
51
|
- **Adaptive scheduler.** Patch workers use a finite launch queue with provider-health backpressure and retry-once handling for retryable 429/5xx/idle-timeout failures.
|
|
@@ -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.14"),
|
|
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
|
@@ -6,8 +6,9 @@ export function detectGlobalMode(args = []) {
|
|
|
6
6
|
const hasGlm = args.includes('--glm');
|
|
7
7
|
if (hasMad && hasGlm)
|
|
8
8
|
return { kind: 'mad-glm', args: stripGlobalModeFlags(args) };
|
|
9
|
-
if (hasGlm && !hasMad)
|
|
9
|
+
if (hasGlm && !hasMad && String(args[0]).startsWith('-')) {
|
|
10
10
|
return { kind: 'glm-without-mad', args: stripGlobalModeFlags(args) };
|
|
11
|
+
}
|
|
11
12
|
return null;
|
|
12
13
|
}
|
|
13
14
|
export function stripGlobalModeFlags(args) {
|
|
@@ -26,12 +26,15 @@ import { resolveCodexNativeInvocationPlan } from '../codex-native/codex-native-i
|
|
|
26
26
|
import { repairZellijForSks } from '../zellij/zellij-self-heal.js';
|
|
27
27
|
import { buildMadGlmLaunchArtifact, buildMadGlmLaunchProfileNoWrite, resolveMadGlmLaunchKey, writeMadGlmCodexWrapper } from '../providers/glm/glm-mad-launch.js';
|
|
28
28
|
import { GLM_MAD_MODE } from '../providers/glm/glm-52-settings.js';
|
|
29
|
+
import { assertNonGlmMadRoute } from '../routes/model-mode-router.js';
|
|
29
30
|
export async function madHighCommand(args = [], deps = {}) {
|
|
30
31
|
const subcommand = firstSubcommand(args);
|
|
31
32
|
if (subcommand)
|
|
32
33
|
return madSksSubcommand(subcommand, args.filter((arg) => String(arg) !== subcommand));
|
|
33
34
|
const rawArgs = (args || []).map((arg) => String(arg));
|
|
34
35
|
const glmMadLaunch = isMadGlmLaunch(rawArgs, deps);
|
|
36
|
+
if (!glmMadLaunch)
|
|
37
|
+
assertNonGlmMadRoute(rawArgs.includes('--mad') ? rawArgs : ['--mad', ...rawArgs]);
|
|
35
38
|
const glmOnlyFlagBlockers = findGlmOnlyMadFlagBlockers(rawArgs, glmMadLaunch);
|
|
36
39
|
if (glmOnlyFlagBlockers.length) {
|
|
37
40
|
const result = {
|
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.14';
|
|
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() {
|
|
@@ -1,7 +1,10 @@
|
|
|
1
1
|
import { GLM_52_OPENROUTER_MODEL } from '../glm-52-settings.js';
|
|
2
|
-
export function buildGlmBenchModelLockProof(cases) {
|
|
2
|
+
export function buildGlmBenchModelLockProof(cases, proofInput = {}) {
|
|
3
3
|
const checkedCases = cases.map((c) => c.runner_id);
|
|
4
4
|
const mismatches = [];
|
|
5
|
+
const requestSummaries = proofInput.requestSummaries ?? [];
|
|
6
|
+
let fallbackArraysFound = 0;
|
|
7
|
+
let openaiKeyUsed = false;
|
|
5
8
|
for (const caseResult of cases) {
|
|
6
9
|
if (caseResult.model !== GLM_52_OPENROUTER_MODEL) {
|
|
7
10
|
mismatches.push(`${caseResult.runner_id}: model is ${caseResult.model}, expected ${GLM_52_OPENROUTER_MODEL}`);
|
|
@@ -10,13 +13,39 @@ export function buildGlmBenchModelLockProof(cases) {
|
|
|
10
13
|
mismatches.push(`${caseResult.runner_id}: gpt_fallback_allowed is not false`);
|
|
11
14
|
}
|
|
12
15
|
}
|
|
16
|
+
for (const summary of requestSummaries) {
|
|
17
|
+
if (summary.model !== undefined && summary.model !== GLM_52_OPENROUTER_MODEL) {
|
|
18
|
+
mismatches.push(`request-summary:${String(summary.worker_id ?? summary.runner_id ?? 'unknown')}: model is ${String(summary.model)}`);
|
|
19
|
+
}
|
|
20
|
+
const models = Array.isArray(summary.models) ? summary.models : [];
|
|
21
|
+
const fallbackModelsCount = typeof summary.fallback_models_count === 'number' ? summary.fallback_models_count : models.length;
|
|
22
|
+
if (fallbackModelsCount > 0)
|
|
23
|
+
fallbackArraysFound += 1;
|
|
24
|
+
if (summary.openai_key_used === true || summary.authorization_source === 'openai')
|
|
25
|
+
openaiKeyUsed = true;
|
|
26
|
+
if (summary.gpt_fallback_allowed !== undefined && summary.gpt_fallback_allowed !== false) {
|
|
27
|
+
mismatches.push(`request-summary:${String(summary.worker_id ?? summary.runner_id ?? 'unknown')}: gpt_fallback_allowed is not false`);
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
if (fallbackArraysFound > 0)
|
|
31
|
+
mismatches.push(`fallback_arrays_found:${fallbackArraysFound}`);
|
|
32
|
+
if (openaiKeyUsed)
|
|
33
|
+
mismatches.push('openai_key_used');
|
|
34
|
+
const requestSummaryStatus = requestSummaries.length > 0 ? 'checked' : 'unavailable';
|
|
13
35
|
return {
|
|
14
36
|
schema: 'sks.glm-bench-model-lock-proof.v1',
|
|
15
37
|
checked_cases: checkedCases,
|
|
16
38
|
model: GLM_52_OPENROUTER_MODEL,
|
|
17
39
|
gpt_fallback_allowed: false,
|
|
18
|
-
|
|
19
|
-
|
|
40
|
+
request_summary_status: requestSummaryStatus,
|
|
41
|
+
request_summaries_checked: requestSummaries.length,
|
|
42
|
+
request_summaries_unavailable: Math.max(0, cases.length - requestSummaries.length),
|
|
43
|
+
naruto_request_summaries_checked: requestSummaries.filter((summary) => String(summary.worker_id ?? '').startsWith('worker-')).length,
|
|
44
|
+
direct_trace_checked: proofInput.directTraceChecked === true,
|
|
45
|
+
fallback_arrays_found: fallbackArraysFound,
|
|
46
|
+
openai_key_used: openaiKeyUsed,
|
|
47
|
+
fallback_array_scan: requestSummaryStatus,
|
|
48
|
+
openai_key_usage_scan: requestSummaryStatus,
|
|
20
49
|
mismatches,
|
|
21
50
|
passed: mismatches.length === 0
|
|
22
51
|
};
|
|
@@ -115,19 +115,22 @@ export async function runGlmBenchmark(root, args = [], deps = {}) {
|
|
|
115
115
|
}
|
|
116
116
|
await cleanupFixture(sharedFixture);
|
|
117
117
|
const comparison = computeGlmBenchmarkComparison(cases);
|
|
118
|
-
const modelLockProof = buildGlmBenchModelLockProof(cases
|
|
118
|
+
const modelLockProof = buildGlmBenchModelLockProof(cases, {
|
|
119
|
+
requestSummaries: await collectRequestSummaries(cases),
|
|
120
|
+
directTraceChecked: cases.some((c) => c.runner_id === 'direct-glm-speed' && c.artifacts.trace_path !== null)
|
|
121
|
+
});
|
|
119
122
|
const userCwdAfter = await captureGitStatus(userCwd);
|
|
120
123
|
const userCwdUnchanged = userCwdBefore === userCwdAfter;
|
|
121
124
|
const noMutationProof = {
|
|
122
125
|
schema: 'sks.glm-bench-no-mutation-proof.v1',
|
|
123
|
-
user_cwd_unchanged: userCwdUnchanged
|
|
126
|
+
user_cwd_unchanged: userCwdUnchanged,
|
|
124
127
|
fixture_mutated_only_under_apply_temp: !applyTemp,
|
|
125
128
|
cases_report_no_mutation: true,
|
|
126
129
|
passed: userCwdUnchanged && cases.every((c) => c.mutation_performed === false)
|
|
127
130
|
};
|
|
128
131
|
const result = {
|
|
129
132
|
schema: 'sks.glm-benchmark-result.v1',
|
|
130
|
-
version: '4.0.
|
|
133
|
+
version: '4.0.14',
|
|
131
134
|
generated_at: nowIso(),
|
|
132
135
|
status: 'live',
|
|
133
136
|
model: GLM_52_OPENROUTER_MODEL,
|
|
@@ -154,7 +157,7 @@ export async function runGlmBenchmark(root, args = [], deps = {}) {
|
|
|
154
157
|
function dryRunResult(root, startedMs) {
|
|
155
158
|
return {
|
|
156
159
|
schema: 'sks.glm-benchmark-result.v1',
|
|
157
|
-
version: '4.0.
|
|
160
|
+
version: '4.0.14',
|
|
158
161
|
generated_at: nowIso(),
|
|
159
162
|
status: 'dry_run',
|
|
160
163
|
model: GLM_52_OPENROUTER_MODEL,
|
|
@@ -177,7 +180,7 @@ function dryRunResult(root, startedMs) {
|
|
|
177
180
|
function blockedResult(root, warnings) {
|
|
178
181
|
return {
|
|
179
182
|
schema: 'sks.glm-benchmark-result.v1',
|
|
180
|
-
version: '4.0.
|
|
183
|
+
version: '4.0.14',
|
|
181
184
|
generated_at: nowIso(),
|
|
182
185
|
status: 'blocked',
|
|
183
186
|
model: GLM_52_OPENROUTER_MODEL,
|
|
@@ -207,6 +210,27 @@ async function readWorkerTraces(artifactDir) {
|
|
|
207
210
|
return [];
|
|
208
211
|
}
|
|
209
212
|
}
|
|
213
|
+
async function collectRequestSummaries(cases) {
|
|
214
|
+
const summaries = [];
|
|
215
|
+
for (const caseResult of cases) {
|
|
216
|
+
const dir = caseResult.artifacts.mission_artifact_dir;
|
|
217
|
+
if (!dir)
|
|
218
|
+
continue;
|
|
219
|
+
try {
|
|
220
|
+
const workerRoot = path.join(dir, 'workers');
|
|
221
|
+
const workerIds = await fsp.readdir(workerRoot);
|
|
222
|
+
for (const workerId of workerIds) {
|
|
223
|
+
try {
|
|
224
|
+
const summary = JSON.parse(await fsp.readFile(path.join(workerRoot, workerId, 'request-summary.json'), 'utf8'));
|
|
225
|
+
summaries.push(summary);
|
|
226
|
+
}
|
|
227
|
+
catch { }
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
catch { }
|
|
231
|
+
}
|
|
232
|
+
return summaries;
|
|
233
|
+
}
|
|
210
234
|
async function captureGitStatus(cwd) {
|
|
211
235
|
return new Promise((resolve) => {
|
|
212
236
|
const child = spawn('git', ['status', '--short'], { cwd, stdio: ['ignore', 'pipe', 'ignore'] });
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export const GLM_BENCHMARK_VERSION = '4.0.
|
|
1
|
+
export const GLM_BENCHMARK_VERSION = '4.0.14';
|
|
2
2
|
//# sourceMappingURL=glm-benchmark-types.js.map
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import path from 'node:path';
|
|
2
|
+
import { writeJsonAtomic, writeTextAtomic } from '../../../fsx.js';
|
|
3
|
+
export function buildGlmNarutoCriticalPathMetrics(input) {
|
|
4
|
+
const stageMs = (stage) => {
|
|
5
|
+
const matches = input.stages.filter((metric) => metric.stage === stage);
|
|
6
|
+
if (!matches.length)
|
|
7
|
+
return null;
|
|
8
|
+
return matches.reduce((sum, metric) => sum + metric.wall_clock_ms, 0);
|
|
9
|
+
};
|
|
10
|
+
const values = {
|
|
11
|
+
decomposition: input.decompositionMs,
|
|
12
|
+
patch_generation: stageMs('patch_generation') ?? 0,
|
|
13
|
+
worktree_materialization: stageMs('worktree_materialization'),
|
|
14
|
+
candidate_gate: stageMs('candidate_gate') ?? 0,
|
|
15
|
+
verifier: stageMs('verifier'),
|
|
16
|
+
conflict_merge: input.conflictMergeMs,
|
|
17
|
+
final_apply: input.finalApplyMs,
|
|
18
|
+
final_seal: input.finalSealMs
|
|
19
|
+
};
|
|
20
|
+
const slowest = Object.entries(values)
|
|
21
|
+
.filter(([, value]) => typeof value === 'number')
|
|
22
|
+
.sort((a, b) => Number(b[1]) - Number(a[1]))[0]?.[0] ?? 'unknown';
|
|
23
|
+
return {
|
|
24
|
+
schema: 'sks.glm-naruto-critical-path.v1',
|
|
25
|
+
total_wall_clock_ms: Math.max(0, input.totalWallClockMs),
|
|
26
|
+
stage_wall_clock_ms: values,
|
|
27
|
+
slowest_stage: slowest,
|
|
28
|
+
parallelism_warnings: input.parallelismWarnings
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
export async function writeGlmNarutoCriticalPathArtifacts(input) {
|
|
32
|
+
const dir = path.join(input.root, '.sneakoscope', 'glm-naruto', input.missionId);
|
|
33
|
+
await writeJsonAtomic(path.join(dir, 'critical-path.json'), input.metrics);
|
|
34
|
+
await writeTextAtomic(path.join(dir, 'speed-diagnosis.md'), renderSpeedDiagnosis(input.metrics));
|
|
35
|
+
}
|
|
36
|
+
function renderSpeedDiagnosis(metrics) {
|
|
37
|
+
return [
|
|
38
|
+
'# GLM Naruto Speed Diagnosis',
|
|
39
|
+
'',
|
|
40
|
+
`Total wall clock: ${metrics.total_wall_clock_ms}ms`,
|
|
41
|
+
`Slowest stage: ${metrics.slowest_stage}`,
|
|
42
|
+
'',
|
|
43
|
+
'## Stage Wall Clock',
|
|
44
|
+
...Object.entries(metrics.stage_wall_clock_ms).map(([stage, ms]) => `- ${stage}: ${ms === null ? 'not_run' : `${ms}ms`}`),
|
|
45
|
+
'',
|
|
46
|
+
'## Parallelism Warnings',
|
|
47
|
+
metrics.parallelism_warnings.length ? metrics.parallelism_warnings.map((warning) => `- ${warning}`).join('\n') : '- none',
|
|
48
|
+
''
|
|
49
|
+
].join('\n');
|
|
50
|
+
}
|
|
51
|
+
//# sourceMappingURL=glm-naruto-critical-path.js.map
|
|
@@ -12,7 +12,8 @@ export async function writeGlmNarutoFinalSeal(input) {
|
|
|
12
12
|
secretOk: input.secretAudit.ok,
|
|
13
13
|
mismatches,
|
|
14
14
|
isolationViolations,
|
|
15
|
-
queueDrained: input.scheduler.queue_drained
|
|
15
|
+
queueDrained: input.scheduler.queue_drained,
|
|
16
|
+
requirementCoveragePassed: input.requirementCoverage?.passed ?? true
|
|
16
17
|
});
|
|
17
18
|
const seal = {
|
|
18
19
|
schema: 'sks.glm-naruto-final-seal.v1',
|
|
@@ -41,6 +42,12 @@ export async function writeGlmNarutoFinalSeal(input) {
|
|
|
41
42
|
verifier_passed: input.envelopes.filter((env) => env.verification_passed === true).length,
|
|
42
43
|
selected: input.selectedPatchIds
|
|
43
44
|
},
|
|
45
|
+
requirement_coverage: {
|
|
46
|
+
required_total: input.requirementCoverage?.required_total ?? 0,
|
|
47
|
+
required_covered: input.requirementCoverage?.required_covered ?? 0,
|
|
48
|
+
passed: input.requirementCoverage?.passed ?? true,
|
|
49
|
+
uncovered_required_requirements: input.requirementCoverage?.uncovered_required_requirements ?? []
|
|
50
|
+
},
|
|
44
51
|
apply: {
|
|
45
52
|
attempted: input.applyTransaction !== null,
|
|
46
53
|
transaction_path: input.applyTransaction ? path.join(input.artifactDir, 'apply-transaction.json') : null,
|
|
@@ -62,7 +69,7 @@ export async function writeGlmNarutoFinalSeal(input) {
|
|
|
62
69
|
return { seal, path: out, passed: seal.status === 'passed' };
|
|
63
70
|
}
|
|
64
71
|
function finalSealStatus(input) {
|
|
65
|
-
if (!input.secretOk || input.mismatches.length > 0 || input.isolationViolations.length > 0 || !input.queueDrained)
|
|
72
|
+
if (!input.secretOk || input.mismatches.length > 0 || input.isolationViolations.length > 0 || !input.queueDrained || !input.requirementCoveragePassed)
|
|
66
73
|
return 'blocked';
|
|
67
74
|
if (input.result.ok)
|
|
68
75
|
return 'passed';
|
|
@@ -21,6 +21,11 @@ import { buildGlmNarutoCandidateScoreboard } from './glm-naruto-scoreboard.js';
|
|
|
21
21
|
import { runGlmNarutoApplyTransaction } from './glm-naruto-apply-transaction.js';
|
|
22
22
|
import { finalizeGlmNarutoTerminal } from './glm-naruto-terminal.js';
|
|
23
23
|
import { writeGlmNarutoFinalSeal } from './glm-naruto-final-seal.js';
|
|
24
|
+
import { runGlmNarutoStageScheduler } from './glm-naruto-stage-scheduler.js';
|
|
25
|
+
import { buildGlmNarutoParallelismSummary, metricFromStageResult, writeGlmNarutoParallelismArtifacts } from './glm-naruto-parallelism-summary.js';
|
|
26
|
+
import { buildGlmNarutoRequirementCoverageSummary, enrichGlmNarutoCandidateRequirementCoverage, inferCandidateRequirementCoverage } from './glm-naruto-requirement-coverage.js';
|
|
27
|
+
import { buildGlmNarutoRequirementLedger } from './glm-naruto-requirement-ledger.js';
|
|
28
|
+
import { buildGlmNarutoCriticalPathMetrics, writeGlmNarutoCriticalPathArtifacts } from './glm-naruto-critical-path.js';
|
|
24
29
|
import { GLM_NARUTO_LIMITS } from './glm-naruto-types.js';
|
|
25
30
|
export async function runGlmNarutoMission(input) {
|
|
26
31
|
const missionId = input.missionId || `glm-naruto-${nowIso().replace(/[:.]/g, '-')}`;
|
|
@@ -34,8 +39,15 @@ export async function runGlmNarutoMission(input) {
|
|
|
34
39
|
result: missionResult(missionId, input.task, 'blocked', 'glm_missing_openrouter_key', 0, startedMs, [], [], ['glm_missing_openrouter_key'], [])
|
|
35
40
|
});
|
|
36
41
|
}
|
|
42
|
+
const decompositionStartedMs = Date.now();
|
|
37
43
|
const mentionedPaths = extractMentionedPaths(input.task);
|
|
38
44
|
const gitStatus = await readGitStatus(cwd);
|
|
45
|
+
const requirementLedger = buildGlmNarutoRequirementLedger({
|
|
46
|
+
missionId,
|
|
47
|
+
task: input.task,
|
|
48
|
+
mentionedPaths,
|
|
49
|
+
...(gitStatus !== undefined ? { gitStatus } : {})
|
|
50
|
+
});
|
|
39
51
|
const gitRoot = await getGitRoot(cwd);
|
|
40
52
|
const baseCommit = gitRoot ? await getGitHead(cwd) : null;
|
|
41
53
|
const isolationPolicy = resolveGlmNarutoIsolationPolicy({
|
|
@@ -76,6 +88,7 @@ export async function runGlmNarutoMission(input) {
|
|
|
76
88
|
});
|
|
77
89
|
}
|
|
78
90
|
const laneMix = computeInitialLaneMix(graph);
|
|
91
|
+
const decompositionMs = Date.now() - decompositionStartedMs;
|
|
79
92
|
const strategies = planShardCandidates(graph);
|
|
80
93
|
const strategyMap = new Map();
|
|
81
94
|
for (const entry of strategies) {
|
|
@@ -115,6 +128,8 @@ export async function runGlmNarutoMission(input) {
|
|
|
115
128
|
let failedShardIds = poolResult.failedShardIds;
|
|
116
129
|
let repairWaves = 0;
|
|
117
130
|
let schedulerSummary = poolResult.schedulerSummary;
|
|
131
|
+
const stageMetrics = [...poolResult.stageMetrics];
|
|
132
|
+
const stageEvents = [...poolResult.stageEvents];
|
|
118
133
|
// Repair wave if needed
|
|
119
134
|
if (failedShardIds.length > 0 && repairWaves < GLM_NARUTO_LIMITS.max_repair_waves) {
|
|
120
135
|
const repairPlan = planRepairWave({
|
|
@@ -136,9 +151,12 @@ export async function runGlmNarutoMission(input) {
|
|
|
136
151
|
isolationMode: isolationPolicy.selected,
|
|
137
152
|
cleanupWorktrees: input.cleanupWorktrees ?? !input.keepWorktrees,
|
|
138
153
|
baseCommit,
|
|
139
|
-
health: healthTracker
|
|
154
|
+
health: healthTracker,
|
|
155
|
+
stageName: 'repair_generation'
|
|
140
156
|
});
|
|
141
157
|
envelopes = [...envelopes, ...repairPool.envelopes];
|
|
158
|
+
stageMetrics.push(...repairPool.stageMetrics);
|
|
159
|
+
stageEvents.push(...repairPool.stageEvents);
|
|
142
160
|
schedulerSummary = {
|
|
143
161
|
max_observed_active_workers: Math.max(schedulerSummary.max_observed_active_workers, repairPool.schedulerSummary.max_observed_active_workers),
|
|
144
162
|
backpressure_events: schedulerSummary.backpressure_events + repairPool.schedulerSummary.backpressure_events,
|
|
@@ -156,13 +174,22 @@ export async function runGlmNarutoMission(input) {
|
|
|
156
174
|
if (passedEnvelopes.length > 0 && !input.skipVerifier) {
|
|
157
175
|
verifierWaveRun = true;
|
|
158
176
|
const verifyApiKey = key.key;
|
|
159
|
-
const
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
177
|
+
const verifierStage = await runGlmNarutoStageScheduler({
|
|
178
|
+
stage: 'verifier',
|
|
179
|
+
jobs: passedEnvelopes.map((env) => ({ id: env.worker_id, stage: 'verifier', input: env })),
|
|
180
|
+
max_active: Math.min(8, passedEnvelopes.length),
|
|
181
|
+
timeout_ms: 120_000,
|
|
182
|
+
runJob: (job) => runVerifierWorker({
|
|
183
|
+
apiKey: verifyApiKey,
|
|
184
|
+
missionId,
|
|
185
|
+
workerId: job.input.worker_id,
|
|
186
|
+
envelope: job.input,
|
|
187
|
+
timeoutMs: 120_000,
|
|
188
|
+
})
|
|
189
|
+
});
|
|
190
|
+
stageMetrics.push(metricFromStageResult(verifierStage));
|
|
191
|
+
stageEvents.push(...verifierStage.events);
|
|
192
|
+
const verifyResults = verifierStage.results;
|
|
166
193
|
const verifiedEnvelopes = [];
|
|
167
194
|
for (let vi = 0; vi < passedEnvelopes.length; vi++) {
|
|
168
195
|
const env = passedEnvelopes[vi];
|
|
@@ -192,8 +219,11 @@ export async function runGlmNarutoMission(input) {
|
|
|
192
219
|
});
|
|
193
220
|
passedEnvelopes = envelopes.filter((e) => e.status === 'gate_passed');
|
|
194
221
|
}
|
|
195
|
-
|
|
222
|
+
envelopes = envelopes.map((env) => enrichGlmNarutoCandidateRequirementCoverage({ envelope: env, ledger: requirementLedger }));
|
|
223
|
+
passedEnvelopes = envelopes.filter((e) => e.status === 'gate_passed');
|
|
224
|
+
const verifierWarnings = input.skipVerifier && passedEnvelopes.length > 0 ? ['verifier_skipped_by_flag'] : [];
|
|
196
225
|
// Build conflict graph and merge plan
|
|
226
|
+
const conflictMergeStartedMs = Date.now();
|
|
197
227
|
const nodes = passedEnvelopes.map((env) => ({
|
|
198
228
|
patch_id: env.worker_id,
|
|
199
229
|
shard_id: env.shard_id,
|
|
@@ -227,32 +257,59 @@ export async function runGlmNarutoMission(input) {
|
|
|
227
257
|
useJudge: input.useJudge || false,
|
|
228
258
|
xhighFinalizer: input.xhighFinalizer || false
|
|
229
259
|
});
|
|
260
|
+
const conflictMergeMs = Date.now() - conflictMergeStartedMs;
|
|
261
|
+
const candidateRequirementCoverage = envelopes.map((env) => inferCandidateRequirementCoverage({ envelope: env, ledger: requirementLedger }));
|
|
262
|
+
const preliminarySelectedPatchIds = mergePlan.selected_patches;
|
|
263
|
+
const requirementCoverageSummary = buildGlmNarutoRequirementCoverageSummary({
|
|
264
|
+
missionId,
|
|
265
|
+
ledger: requirementLedger,
|
|
266
|
+
envelopes,
|
|
267
|
+
selectedPatchIds: preliminarySelectedPatchIds
|
|
268
|
+
});
|
|
269
|
+
const selectedPatchIds = requirementCoverageSummary.passed ? preliminarySelectedPatchIds : [];
|
|
230
270
|
// Apply winning merge plan
|
|
231
271
|
let appliedPatches = 0;
|
|
232
272
|
let applyResult = null;
|
|
233
273
|
let applyTransaction = null;
|
|
234
274
|
const artifactDir = path.join(cwd, '.sneakoscope', 'glm-naruto', missionId);
|
|
235
|
-
|
|
275
|
+
let finalApplyMs = null;
|
|
276
|
+
if (!input.noApply && selectedPatchIds.length > 0) {
|
|
277
|
+
const finalApplyStartedMs = Date.now();
|
|
236
278
|
const transactionResult = await runGlmNarutoApplyTransaction({
|
|
237
279
|
cwd,
|
|
238
280
|
missionId,
|
|
239
281
|
envelopes,
|
|
240
|
-
selectedPatchIds
|
|
282
|
+
selectedPatchIds,
|
|
241
283
|
artifactDir,
|
|
242
284
|
...(input.allowDirtyApply !== undefined ? { allowDirtyApply: input.allowDirtyApply } : {}),
|
|
243
285
|
...(input.noRollback !== undefined ? { noRollback: input.noRollback } : {}),
|
|
244
286
|
...(input.strictChecks !== undefined ? { strictChecks: input.strictChecks } : {})
|
|
245
287
|
});
|
|
288
|
+
finalApplyMs = Date.now() - finalApplyStartedMs;
|
|
246
289
|
applyTransaction = transactionResult.transaction;
|
|
247
290
|
appliedPatches = transactionResult.ok ? transactionResult.applied.length : 0;
|
|
248
291
|
applyResult = { ok: transactionResult.ok, applied: transactionResult.applied, ...(transactionResult.transaction.blockers[0] ? { blocker: transactionResult.transaction.blockers[0] } : {}) };
|
|
249
292
|
}
|
|
250
|
-
const
|
|
293
|
+
const coverageBlocked = !requirementCoverageSummary.passed;
|
|
294
|
+
const terminalState = appliedPatches > 0
|
|
295
|
+
? 'completed'
|
|
296
|
+
: passedEnvelopes.length > 0 ? 'partial_candidates' : 'blocked';
|
|
251
297
|
const terminationReason = appliedPatches > 0
|
|
252
298
|
? 'completed_merge_applied'
|
|
253
299
|
: applyResult && !applyResult.ok
|
|
254
300
|
? 'apply_transaction_failed'
|
|
255
|
-
:
|
|
301
|
+
: coverageBlocked
|
|
302
|
+
? 'required_requirement_coverage_missing'
|
|
303
|
+
: passedEnvelopes.length > 0 ? 'partial_no_apply' : 'no_gate_passed_candidates';
|
|
304
|
+
const parallelismSummary = buildGlmNarutoParallelismSummary({
|
|
305
|
+
metrics: stageMetrics,
|
|
306
|
+
totalWallClockMs: Date.now() - startedMs
|
|
307
|
+
});
|
|
308
|
+
const warnings = [
|
|
309
|
+
...verifierWarnings,
|
|
310
|
+
...parallelismSummary.blockers,
|
|
311
|
+
...(coverageBlocked ? ['required_requirement_coverage_missing'] : [])
|
|
312
|
+
];
|
|
256
313
|
const summary = buildMissionSummary({
|
|
257
314
|
missionId,
|
|
258
315
|
startedMs,
|
|
@@ -282,7 +339,9 @@ export async function runGlmNarutoMission(input) {
|
|
|
282
339
|
failed_shards: summary.failed_shards,
|
|
283
340
|
repair_waves: summary.repair_waves,
|
|
284
341
|
budget_used_ms: summary.budget_used_ms,
|
|
285
|
-
blockers:
|
|
342
|
+
blockers: coverageBlocked
|
|
343
|
+
? requirementCoverageSummary.uncovered_required_requirements.map((id) => `required_requirement_uncovered:${id}`)
|
|
344
|
+
: terminalState === 'blocked' ? ['no_gate_passed_candidates'] : (applyResult && !applyResult.ok ? [applyResult.blocker || 'apply_transaction_failed'] : []),
|
|
286
345
|
warnings
|
|
287
346
|
};
|
|
288
347
|
const writtenArtifactDir = await writeMissionArtifacts({
|
|
@@ -304,6 +363,15 @@ export async function runGlmNarutoMission(input) {
|
|
|
304
363
|
missionResult: result,
|
|
305
364
|
envelopes
|
|
306
365
|
});
|
|
366
|
+
await writeJsonAtomic(path.join(writtenArtifactDir, 'requirement-ledger.json'), requirementLedger).catch(() => undefined);
|
|
367
|
+
await writeJsonAtomic(path.join(writtenArtifactDir, 'candidate-requirement-coverage.json'), candidateRequirementCoverage).catch(() => undefined);
|
|
368
|
+
await writeJsonAtomic(path.join(writtenArtifactDir, 'requirement-coverage-summary.json'), requirementCoverageSummary).catch(() => undefined);
|
|
369
|
+
await writeGlmNarutoParallelismArtifacts({
|
|
370
|
+
root: cwd,
|
|
371
|
+
missionId,
|
|
372
|
+
summary: parallelismSummary,
|
|
373
|
+
events: stageEvents
|
|
374
|
+
}).catch(() => undefined);
|
|
307
375
|
const secretAudit = await auditGlmNarutoArtifactsForSecrets(path.join(cwd, '.sneakoscope', 'glm-naruto', missionId)).catch((err) => ({
|
|
308
376
|
schema: 'sks.glm-naruto-secret-audit.v1',
|
|
309
377
|
ok: false,
|
|
@@ -313,6 +381,7 @@ export async function runGlmNarutoMission(input) {
|
|
|
313
381
|
}));
|
|
314
382
|
await writeJsonAtomic(path.join(writtenArtifactDir, 'secret-audit.json'), secretAudit).catch(() => undefined);
|
|
315
383
|
const predictedStopGatePath = path.join(cwd, '.sneakoscope', 'missions', missionId, 'stop-gate.json');
|
|
384
|
+
const finalSealStartedMs = Date.now();
|
|
316
385
|
const finalSeal = await writeGlmNarutoFinalSeal({
|
|
317
386
|
artifactDir: writtenArtifactDir,
|
|
318
387
|
missionId,
|
|
@@ -321,7 +390,8 @@ export async function runGlmNarutoMission(input) {
|
|
|
321
390
|
traces: traceState.workerTraces,
|
|
322
391
|
isolationPolicy,
|
|
323
392
|
scheduler: schedulerSummary,
|
|
324
|
-
selectedPatchIds
|
|
393
|
+
selectedPatchIds,
|
|
394
|
+
requirementCoverage: requirementCoverageSummary,
|
|
325
395
|
applyTransaction,
|
|
326
396
|
secretAudit,
|
|
327
397
|
stopGatePath: predictedStopGatePath,
|
|
@@ -332,6 +402,17 @@ export async function runGlmNarutoMission(input) {
|
|
|
332
402
|
passed: false,
|
|
333
403
|
error: err instanceof Error ? err.message : String(err)
|
|
334
404
|
}));
|
|
405
|
+
const finalSealMs = Date.now() - finalSealStartedMs;
|
|
406
|
+
const criticalPath = buildGlmNarutoCriticalPathMetrics({
|
|
407
|
+
totalWallClockMs: Date.now() - startedMs,
|
|
408
|
+
stages: parallelismSummary.stages,
|
|
409
|
+
decompositionMs,
|
|
410
|
+
conflictMergeMs,
|
|
411
|
+
finalApplyMs,
|
|
412
|
+
finalSealMs,
|
|
413
|
+
parallelismWarnings: parallelismSummary.blockers
|
|
414
|
+
});
|
|
415
|
+
await writeGlmNarutoCriticalPathArtifacts({ root: cwd, missionId, metrics: criticalPath }).catch(() => undefined);
|
|
335
416
|
// 4.0.9: Write canonical stop-gate artifacts for hook resolution.
|
|
336
417
|
await writeFinalStopGate({
|
|
337
418
|
root: cwd,
|
|
@@ -350,6 +431,11 @@ export async function runGlmNarutoMission(input) {
|
|
|
350
431
|
model_guard_enforced: true,
|
|
351
432
|
final_seal_passed: finalSeal.passed,
|
|
352
433
|
final_seal_path: finalSeal.path,
|
|
434
|
+
required_coverage_passed: requirementCoverageSummary.passed,
|
|
435
|
+
uncovered_required_count: requirementCoverageSummary.uncovered_required_requirements.length,
|
|
436
|
+
coverage_ledger_path: path.join(writtenArtifactDir, 'requirement-coverage-summary.json'),
|
|
437
|
+
parallelism_summary_path: path.join(writtenArtifactDir, 'parallelism-summary.json'),
|
|
438
|
+
critical_path_path: path.join(writtenArtifactDir, 'critical-path.json'),
|
|
353
439
|
proof_required: false,
|
|
354
440
|
proof_passed: true,
|
|
355
441
|
reflection_required: false,
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import path from 'node:path';
|
|
2
|
+
import { writeJsonAtomic, writeTextAtomic } from '../../../fsx.js';
|
|
3
|
+
export function metricFromStageResult(result) {
|
|
4
|
+
return {
|
|
5
|
+
stage: result.stage,
|
|
6
|
+
job_count: result.results.length,
|
|
7
|
+
max_observed_active: result.max_observed_active,
|
|
8
|
+
wall_clock_ms: result.wall_clock_ms,
|
|
9
|
+
sum_job_duration_ms: result.sum_job_duration_ms,
|
|
10
|
+
overlap_ratio: result.overlap_ratio
|
|
11
|
+
};
|
|
12
|
+
}
|
|
13
|
+
export function createStageParallelismMetric(input) {
|
|
14
|
+
return {
|
|
15
|
+
...input,
|
|
16
|
+
wall_clock_ms: Math.max(0, input.wall_clock_ms),
|
|
17
|
+
sum_job_duration_ms: Math.max(0, input.sum_job_duration_ms),
|
|
18
|
+
overlap_ratio: input.wall_clock_ms > 0 ? input.sum_job_duration_ms / input.wall_clock_ms : input.overlap_ratio
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
export function buildGlmNarutoParallelismSummary(input) {
|
|
22
|
+
const grouped = new Map();
|
|
23
|
+
for (const metric of input.metrics) {
|
|
24
|
+
const current = grouped.get(metric.stage);
|
|
25
|
+
if (!current) {
|
|
26
|
+
grouped.set(metric.stage, createStageParallelismMetric(metric));
|
|
27
|
+
continue;
|
|
28
|
+
}
|
|
29
|
+
grouped.set(metric.stage, createStageParallelismMetric({
|
|
30
|
+
stage: metric.stage,
|
|
31
|
+
job_count: current.job_count + metric.job_count,
|
|
32
|
+
max_observed_active: Math.max(current.max_observed_active, metric.max_observed_active),
|
|
33
|
+
wall_clock_ms: current.wall_clock_ms + metric.wall_clock_ms,
|
|
34
|
+
sum_job_duration_ms: current.sum_job_duration_ms + metric.sum_job_duration_ms,
|
|
35
|
+
overlap_ratio: 1
|
|
36
|
+
}));
|
|
37
|
+
}
|
|
38
|
+
const stages = [...grouped.values()];
|
|
39
|
+
const blockers = stages
|
|
40
|
+
.filter((stage) => stage.job_count > 1 && stage.overlap_ratio <= 1.1)
|
|
41
|
+
.map((stage) => `glm_parallelism_not_effective:${stage.stage}`);
|
|
42
|
+
return {
|
|
43
|
+
schema: 'sks.glm-naruto-parallelism-summary.v1',
|
|
44
|
+
stages,
|
|
45
|
+
total_wall_clock_ms: Math.max(0, input.totalWallClockMs),
|
|
46
|
+
parallelism_effective: blockers.length === 0,
|
|
47
|
+
blockers
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
export async function writeGlmNarutoParallelismArtifacts(input) {
|
|
51
|
+
const dir = path.join(input.root, '.sneakoscope', 'glm-naruto', input.missionId);
|
|
52
|
+
await writeTextAtomic(path.join(dir, 'stage-timeline.jsonl'), input.events.map((event) => JSON.stringify(event)).join('\n') + (input.events.length ? '\n' : ''));
|
|
53
|
+
await writeJsonAtomic(path.join(dir, 'parallelism-summary.json'), input.summary);
|
|
54
|
+
}
|
|
55
|
+
//# sourceMappingURL=glm-naruto-parallelism-summary.js.map
|