sneakoscope 4.0.0 → 4.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -2
- package/crates/sks-core/Cargo.lock +1 -1
- package/crates/sks-core/Cargo.toml +1 -1
- package/crates/sks-core/src/main.rs +1 -1
- package/dist/bin/sks.js +1 -1
- package/dist/core/build/build-once-runner.js +5 -1
- package/dist/core/commands/check-command.js +3 -1
- package/dist/core/commands/mad-sks-command.js +7 -2
- package/dist/core/daemon/sksd-ipc.js +9 -0
- package/dist/core/daemon/sksd.js +37 -5
- package/dist/core/doctor/doctor-dirty-planner.js +70 -5
- package/dist/core/fsx.js +1 -1
- package/dist/core/probes/probe-memoization.js +40 -2
- package/dist/core/release/critical-path-ledger.js +12 -0
- package/dist/core/release/extreme-parallel-scheduler.js +53 -0
- package/dist/core/release/gate-pack-fixture-cache.js +39 -0
- package/dist/core/release/gate-pack-runner.js +145 -1
- package/dist/core/release/release-gate-cache-v2.js +6 -1
- package/dist/core/release/release-gate-dag.js +9 -2
- package/dist/core/triwiki/triwiki-affected-graph.js +63 -7
- package/dist/core/triwiki/triwiki-cache-key.js +27 -7
- package/dist/core/triwiki/triwiki-gate-impact-map.js +47 -2
- package/dist/core/triwiki/triwiki-invalidation.js +81 -0
- package/dist/core/triwiki/triwiki-module-card.js +48 -11
- package/dist/core/triwiki/triwiki-proof-bank.js +82 -4
- package/dist/core/triwiki/triwiki-proof-card.js +34 -3
- package/dist/core/triwiki/triwiki-sla-certificate.js +25 -2
- package/dist/core/version.js +1 -1
- package/dist/core/zellij/zellij-launcher.js +13 -0
- package/dist/core/zellij/zellij-worker-pane-manager.js +68 -17
- package/dist/scripts/release-4001-required-gates.js +13 -0
- package/dist/scripts/sizecheck.js +4 -2
- package/package.json +11 -2
package/README.md
CHANGED
|
@@ -35,9 +35,9 @@ Set up this agent project with Sneakoscope Codex. Use [[mandarange/Sneakoscope-C
|
|
|
35
35
|
|
|
36
36
|
## 🚀 Current Release
|
|
37
37
|
|
|
38
|
-
SKS **4.0.
|
|
38
|
+
SKS **4.0.1** is the TriWiki Turbo completion release. It moves default completion toward affected-scope, release-equivalent proof with reusable TriWiki proof cards, real gate pack execution, SLA scheduling, build-once proof, probe memoization, and explicit legacy-runtime migration instead of silent fallback aliases.
|
|
39
39
|
|
|
40
|
-
What changed in 4.0.
|
|
40
|
+
What changed in 4.0.1:
|
|
41
41
|
|
|
42
42
|
- **TriWiki proof bank.** Proof cards now bind reusable gate proof to input hash, implementation hash, package lock hash, environment allowlist, fixture version, and tool version.
|
|
43
43
|
- **Affected release-equivalent verification.** Changed files map to module cards, gate impact maps, and gate packs so small tasks can run fast without giving up scoped release confidence.
|
|
@@ -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.1"),
|
|
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
|
@@ -11,7 +11,7 @@ export function runBuildOnce(input) {
|
|
|
11
11
|
inputs: ['src/**/*.ts', 'package.json', 'package-lock.json', 'tsconfig.json'],
|
|
12
12
|
implementationFiles: ['tsconfig.json'],
|
|
13
13
|
envAllowlist: ['NODE_ENV', 'CI'],
|
|
14
|
-
fixtureVersion: 'sks-4.0.
|
|
14
|
+
fixtureVersion: 'sks-4.0.1'
|
|
15
15
|
});
|
|
16
16
|
const existing = readBuildOnceProof(input.root);
|
|
17
17
|
if (!input.force && existing?.ok === true && existing.cache_key === key.key) {
|
|
@@ -29,6 +29,10 @@ export function runBuildOnce(input) {
|
|
|
29
29
|
ok: run.status === 0,
|
|
30
30
|
mode,
|
|
31
31
|
cache_key: key.key,
|
|
32
|
+
source_hash: key.input_hash,
|
|
33
|
+
package_lock_hash: key.package_lock_hash,
|
|
34
|
+
tsconfig_hash: computeTriWikiCacheKey({ root: input.root, id: 'build-once:tsconfig', inputs: ['tsconfig.json'] }).input_hash,
|
|
35
|
+
dist_hash: computeTriWikiCacheKey({ root: input.root, id: 'build-once:dist', inputs: ['dist'] }).input_hash,
|
|
32
36
|
created_at: new Date().toISOString(),
|
|
33
37
|
status: run.status,
|
|
34
38
|
duration_ms: Math.max(0, Date.now() - started),
|
|
@@ -12,7 +12,8 @@ export async function checkCommand(args = []) {
|
|
|
12
12
|
const changedSince = readArg(args, '--changed-since', 'auto');
|
|
13
13
|
const json = flag(args, '--json');
|
|
14
14
|
const planOnly = flag(args, '--plan');
|
|
15
|
-
const
|
|
15
|
+
const triwiki = !flag(args, '--no-triwiki');
|
|
16
|
+
const plan = buildCheckPlan({ tier, sla, changedSince, triwiki });
|
|
16
17
|
if (planOnly) {
|
|
17
18
|
const result = { schema: CHECK_SCHEMA, ok: true, mode: 'plan', ...plan };
|
|
18
19
|
if (json)
|
|
@@ -73,6 +74,7 @@ function buildCheckPlan(input) {
|
|
|
73
74
|
return {
|
|
74
75
|
tier,
|
|
75
76
|
sla: input.sla,
|
|
77
|
+
triwiki: input.triwiki,
|
|
76
78
|
changed_since: input.changedSince,
|
|
77
79
|
build_once: tier === 'release' ? 'clean' : tier === 'real-check' || tier === 'instant' ? 'not_applicable' : 'incremental',
|
|
78
80
|
steps
|
|
@@ -234,10 +234,15 @@ export async function madHighCommand(args = [], deps = {}) {
|
|
|
234
234
|
SKS_MAD_SKS_PROTECTED_CORE_DIGEST: madLaunch.gate.protected_core_digest
|
|
235
235
|
};
|
|
236
236
|
const launchOpts = codexLbImmediateLaunchOpts(cleanArgs, launchLb, { codexArgs: profile.launch_args, conciseBlockers: true, madSksEnv, launchEnv: madSksEnv });
|
|
237
|
-
const
|
|
237
|
+
const explicitWorkspace = readOption(cleanArgs, '--workspace', readOption(cleanArgs, '--session', null));
|
|
238
|
+
// Only the auto-derived stable `sks-mad-<cwd>` name accumulates panes across
|
|
239
|
+
// runs; when the user names a session explicitly (or codex-lb already minted a
|
|
240
|
+
// fresh unique session) respect it and skip the reset.
|
|
241
|
+
const autoDerivedMadSession = !explicitWorkspace && !launchOpts.session;
|
|
242
|
+
const workspace = explicitWorkspace || launchOpts.session || `sks-mad-${sanitizeZellijSessionName(process.cwd())}`;
|
|
238
243
|
const launch = headlessZellij
|
|
239
244
|
? await writeMadHeadlessZellijFallback(madLaunch, workspace)
|
|
240
|
-
: await launchMadZellijUi([...cleanArgs, '--workspace', workspace], { ...launchOpts, missionId: madLaunch.mission_id, root: madLaunch.root, cwd: process.cwd(), ledgerRoot: path.join(madLaunch.dir, 'agents'), slotCount: 0, requireZellij: process.env.SKS_REQUIRE_ZELLIJ === '1' });
|
|
245
|
+
: await launchMadZellijUi([...cleanArgs, '--workspace', workspace], { ...launchOpts, missionId: madLaunch.mission_id, root: madLaunch.root, cwd: process.cwd(), ledgerRoot: path.join(madLaunch.dir, 'agents'), slotCount: 0, freshSession: autoDerivedMadSession, requireZellij: process.env.SKS_REQUIRE_ZELLIJ === '1' });
|
|
241
246
|
const afterLaunchUi = beforeUi ? await writeCodexAppUiSnapshot(launchRoot, `mad-after-launch-${uiSnapshotId}`).catch(() => null) : null;
|
|
242
247
|
const launchUiDiff = beforeUi && afterLaunchUi ? diffCodexAppUiSnapshots(beforeUi, afterLaunchUi) : null;
|
|
243
248
|
if (launchUiDiff) {
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import fs from 'node:fs';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
export function writeSksdIpcMessage(root, action) {
|
|
4
|
+
const file = path.join(root, '.sneakoscope', 'cache', 'sksd', 'last-message.json');
|
|
5
|
+
fs.mkdirSync(path.dirname(file), { recursive: true });
|
|
6
|
+
fs.writeFileSync(file, `${JSON.stringify({ schema: 'sks.sksd-ipc-message.v1', action, created_at: new Date().toISOString(), pid: process.pid }, null, 2)}\n`);
|
|
7
|
+
return file;
|
|
8
|
+
}
|
|
9
|
+
//# sourceMappingURL=sksd-ipc.js.map
|
package/dist/core/daemon/sksd.js
CHANGED
|
@@ -3,7 +3,14 @@ import path from 'node:path';
|
|
|
3
3
|
export const SKSD_STATE_SCHEMA = 'sks.sksd-state.v1';
|
|
4
4
|
export function sksdStatus(root) {
|
|
5
5
|
const state = readState(root);
|
|
6
|
-
|
|
6
|
+
if (!state)
|
|
7
|
+
return emptyState(root);
|
|
8
|
+
if (state.pid && !pidAlive(state.pid)) {
|
|
9
|
+
const stopped = { ...emptyState(root), stale_cleaned: true };
|
|
10
|
+
writeState(root, stopped);
|
|
11
|
+
return stopped;
|
|
12
|
+
}
|
|
13
|
+
return state;
|
|
7
14
|
}
|
|
8
15
|
export function sksdWarm(root) {
|
|
9
16
|
const state = {
|
|
@@ -11,15 +18,23 @@ export function sksdWarm(root) {
|
|
|
11
18
|
status: 'warm',
|
|
12
19
|
pid: process.pid,
|
|
13
20
|
warmed_at: new Date().toISOString(),
|
|
21
|
+
ipc_path: ipcPath(root),
|
|
14
22
|
proof_bank_ready: true,
|
|
15
|
-
build_proof_ready: fs.existsSync(path.join(root, 'dist', '.sks-build-proof.json'))
|
|
23
|
+
build_proof_ready: fs.existsSync(path.join(root, 'dist', '.sks-build-proof.json')),
|
|
24
|
+
triwiki_index_ready: fs.existsSync(path.join(root, '.sneakoscope', 'wiki', 'context-pack.json')),
|
|
25
|
+
probe_memoization_ready: fs.existsSync(path.join(root, '.sneakoscope', 'cache', 'probes'))
|
|
16
26
|
};
|
|
17
27
|
writeState(root, state);
|
|
28
|
+
fs.writeFileSync(ipcPath(root), `${JSON.stringify({ schema: 'sks.sksd-ipc.v1', pid: process.pid, command: 'warm', at: new Date().toISOString() }, null, 2)}\n`);
|
|
18
29
|
return state;
|
|
19
30
|
}
|
|
20
31
|
export function sksdStop(root) {
|
|
21
|
-
const state = { ...emptyState(), status: 'stopped' };
|
|
32
|
+
const state = { ...emptyState(root), status: 'stopped' };
|
|
22
33
|
writeState(root, state);
|
|
34
|
+
try {
|
|
35
|
+
fs.rmSync(ipcPath(root), { force: true });
|
|
36
|
+
}
|
|
37
|
+
catch { }
|
|
23
38
|
return state;
|
|
24
39
|
}
|
|
25
40
|
function readState(root) {
|
|
@@ -42,14 +57,31 @@ function writeState(root, state) {
|
|
|
42
57
|
function statePath(root) {
|
|
43
58
|
return path.join(root, '.sneakoscope', 'cache', 'sksd-state.json');
|
|
44
59
|
}
|
|
45
|
-
function emptyState() {
|
|
60
|
+
function emptyState(root = process.cwd()) {
|
|
46
61
|
return {
|
|
47
62
|
schema: SKSD_STATE_SCHEMA,
|
|
48
63
|
status: 'stopped',
|
|
49
64
|
pid: null,
|
|
50
65
|
warmed_at: null,
|
|
66
|
+
ipc_path: ipcPath(root),
|
|
51
67
|
proof_bank_ready: false,
|
|
52
|
-
build_proof_ready: false
|
|
68
|
+
build_proof_ready: false,
|
|
69
|
+
triwiki_index_ready: false,
|
|
70
|
+
probe_memoization_ready: false
|
|
53
71
|
};
|
|
54
72
|
}
|
|
73
|
+
function ipcPath(root) {
|
|
74
|
+
const dir = path.join(root, '.sneakoscope', 'cache', 'sksd');
|
|
75
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
76
|
+
return path.join(dir, 'sksd.ipc.json');
|
|
77
|
+
}
|
|
78
|
+
function pidAlive(pid) {
|
|
79
|
+
try {
|
|
80
|
+
process.kill(pid, 0);
|
|
81
|
+
return true;
|
|
82
|
+
}
|
|
83
|
+
catch {
|
|
84
|
+
return false;
|
|
85
|
+
}
|
|
86
|
+
}
|
|
55
87
|
//# sourceMappingURL=sksd.js.map
|
|
@@ -1,25 +1,37 @@
|
|
|
1
1
|
import fs from 'node:fs';
|
|
2
2
|
import path from 'node:path';
|
|
3
|
+
import { hashJson } from '../triwiki/triwiki-cache-key.js';
|
|
3
4
|
export const DOCTOR_DIRTY_PLAN_SCHEMA = 'sks.doctor-dirty-plan.v1';
|
|
4
5
|
export function planDoctorDirtyRepair(root, phaseIds) {
|
|
5
6
|
const phases = phaseIds.map((id) => {
|
|
6
7
|
const marker = markerPath(root, id);
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
8
|
+
const inputHash = phaseInputHash(root, id);
|
|
9
|
+
const postcheckRequired = phaseRequiresPostcheck(id);
|
|
10
|
+
const markerState = readMarker(marker);
|
|
11
|
+
if (!markerState)
|
|
12
|
+
return { id, status: 'dirty', reason: 'no_clean_marker', input_hash: inputHash, last_clean_proof_id: null, postcheck_required: postcheckRequired };
|
|
13
|
+
if (markerState.input_hash !== inputHash) {
|
|
14
|
+
return { id, status: 'dirty', reason: 'input_hash_changed', input_hash: inputHash, last_clean_proof_id: markerState.proof_id, postcheck_required: postcheckRequired };
|
|
15
|
+
}
|
|
16
|
+
if (postcheckRequired && !markerState.postcheck_passed) {
|
|
17
|
+
return { id, status: 'dirty', reason: 'postcheck_required', input_hash: inputHash, last_clean_proof_id: markerState.proof_id, postcheck_required: true };
|
|
18
|
+
}
|
|
19
|
+
return { id, status: 'clean', reason: 'matching_clean_proof', input_hash: inputHash, last_clean_proof_id: markerState.proof_id, postcheck_required: postcheckRequired };
|
|
10
20
|
});
|
|
11
|
-
|
|
21
|
+
const plan = {
|
|
12
22
|
schema: DOCTOR_DIRTY_PLAN_SCHEMA,
|
|
13
23
|
root,
|
|
14
24
|
phases,
|
|
15
25
|
dirty_count: phases.filter((phase) => phase.status === 'dirty').length,
|
|
16
26
|
clean_count: phases.filter((phase) => phase.status === 'clean').length
|
|
17
27
|
};
|
|
28
|
+
writeDirtyPlan(root, plan);
|
|
29
|
+
return plan;
|
|
18
30
|
}
|
|
19
31
|
export function markDoctorPhaseClean(root, id) {
|
|
20
32
|
const file = markerPath(root, id);
|
|
21
33
|
fs.mkdirSync(path.dirname(file), { recursive: true });
|
|
22
|
-
fs.writeFileSync(file, `${new Date().toISOString()}\n`);
|
|
34
|
+
fs.writeFileSync(file, `${JSON.stringify({ schema: 'sks.doctor-dirty-clean-proof.v1', proof_id: `doctor-${id}-${Date.now()}`, cleaned_at: new Date().toISOString(), input_hash: phaseInputHash(root, id), postcheck_passed: true }, null, 2)}\n`);
|
|
23
35
|
}
|
|
24
36
|
export function isDoctorPhaseClean(plan, id) {
|
|
25
37
|
return plan?.phases.find((phase) => phase.id === id)?.status === 'clean';
|
|
@@ -27,4 +39,57 @@ export function isDoctorPhaseClean(plan, id) {
|
|
|
27
39
|
function markerPath(root, id) {
|
|
28
40
|
return path.join(root, '.sneakoscope', 'cache', 'doctor-dirty', `${id.replace(/[^a-zA-Z0-9._-]+/g, '_')}.clean`);
|
|
29
41
|
}
|
|
42
|
+
function readMarker(file) {
|
|
43
|
+
try {
|
|
44
|
+
if (!fs.existsSync(file))
|
|
45
|
+
return null;
|
|
46
|
+
const raw = fs.readFileSync(file, 'utf8');
|
|
47
|
+
if (!raw.trim().startsWith('{'))
|
|
48
|
+
return { proof_id: null, input_hash: null, postcheck_passed: false };
|
|
49
|
+
const json = JSON.parse(raw);
|
|
50
|
+
return { proof_id: json.proof_id || null, input_hash: json.input_hash || null, postcheck_passed: json.postcheck_passed === true };
|
|
51
|
+
}
|
|
52
|
+
catch {
|
|
53
|
+
return null;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
function phaseInputHash(root, id) {
|
|
57
|
+
const files = phaseInputFiles(id).map((rel) => {
|
|
58
|
+
const file = path.join(root, rel);
|
|
59
|
+
if (!fs.existsSync(file))
|
|
60
|
+
return { rel, hash: 'missing' };
|
|
61
|
+
const stat = fs.statSync(file);
|
|
62
|
+
return { rel, hash: stat.isDirectory() ? `dir:${stat.mtimeMs}` : hashJson({ size: stat.size, mtimeMs: stat.mtimeMs, text: stat.size < 512_000 ? fs.readFileSync(file, 'utf8') : '' }) };
|
|
63
|
+
});
|
|
64
|
+
return hashJson({ id, files, env: phaseEnvPresence(id) });
|
|
65
|
+
}
|
|
66
|
+
function phaseInputFiles(id) {
|
|
67
|
+
if (id.includes('zellij'))
|
|
68
|
+
return ['src/core/zellij', 'src/core/doctor/doctor-zellij-repair.ts'];
|
|
69
|
+
if (id.includes('context7'))
|
|
70
|
+
return ['src/core/doctor/context7-mcp-repair.ts', '.codex/config.toml'];
|
|
71
|
+
if (id.includes('startup'))
|
|
72
|
+
return ['src/core/doctor/codex-startup-config-repair.ts', '.codex/config.toml'];
|
|
73
|
+
if (id.includes('supabase'))
|
|
74
|
+
return ['src/core/doctor/supabase-mcp-repair.ts', '.codex/config.toml'];
|
|
75
|
+
if (id.includes('skill'))
|
|
76
|
+
return ['.agents/skills', 'src/scripts/skill-registry-ledger-check.ts'];
|
|
77
|
+
if (id.includes('native'))
|
|
78
|
+
return ['src/core/codex-native', 'src/scripts/native-capability-postcheck-check.ts'];
|
|
79
|
+
if (id.includes('secret'))
|
|
80
|
+
return ['safety-mutation-allowlist.json', 'src/scripts/secret-preservation-check.ts'];
|
|
81
|
+
return ['package.json', 'src/core/doctor'];
|
|
82
|
+
}
|
|
83
|
+
function phaseEnvPresence(id) {
|
|
84
|
+
const keys = id.includes('supabase') ? ['SUPABASE_ACCESS_TOKEN'] : id.includes('context7') ? ['CONTEXT7_API_KEY'] : [];
|
|
85
|
+
return Object.fromEntries(keys.map((key) => [key, process.env[key] !== undefined]));
|
|
86
|
+
}
|
|
87
|
+
function phaseRequiresPostcheck(id) {
|
|
88
|
+
return /zellij|context7|startup|supabase|native|secret/i.test(id);
|
|
89
|
+
}
|
|
90
|
+
function writeDirtyPlan(root, plan) {
|
|
91
|
+
const file = path.join(root, '.sneakoscope', 'reports', 'doctor-dirty-plan.json');
|
|
92
|
+
fs.mkdirSync(path.dirname(file), { recursive: true });
|
|
93
|
+
fs.writeFileSync(file, `${JSON.stringify(plan, null, 2)}\n`);
|
|
94
|
+
}
|
|
30
95
|
//# sourceMappingURL=doctor-dirty-planner.js.map
|
package/dist/core/fsx.js
CHANGED
|
@@ -5,7 +5,7 @@ import os from 'node:os';
|
|
|
5
5
|
import crypto from 'node:crypto';
|
|
6
6
|
import { spawn } from 'node:child_process';
|
|
7
7
|
import { fileURLToPath } from 'node:url';
|
|
8
|
-
export const PACKAGE_VERSION = '4.0.
|
|
8
|
+
export const PACKAGE_VERSION = '4.0.1';
|
|
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() {
|
|
@@ -6,7 +6,8 @@ export function memoizeProbe(input) {
|
|
|
6
6
|
const key = hashJson({
|
|
7
7
|
probe_id: input.probeId,
|
|
8
8
|
version: input.version,
|
|
9
|
-
env: (input.envAllowlist || [])
|
|
9
|
+
env: envPresence(input.envAllowlist || []),
|
|
10
|
+
file_hash: input.fileHash || null
|
|
10
11
|
});
|
|
11
12
|
const file = probeCachePath(input.root, key);
|
|
12
13
|
const existing = readProbeRecord(file);
|
|
@@ -19,12 +20,41 @@ export function memoizeProbe(input) {
|
|
|
19
20
|
probe_id: input.probeId,
|
|
20
21
|
created_at: new Date().toISOString(),
|
|
21
22
|
expires_at: new Date(Date.now() + input.ttlMs).toISOString(),
|
|
22
|
-
value
|
|
23
|
+
value,
|
|
24
|
+
tool_version: input.version,
|
|
25
|
+
...(input.fileHash ? { file_hash: input.fileHash } : {}),
|
|
26
|
+
env_allowlist_hash: hashJson(envPresence(input.envAllowlist || []))
|
|
23
27
|
};
|
|
24
28
|
fs.mkdirSync(path.dirname(file), { recursive: true });
|
|
25
29
|
fs.writeFileSync(file, `${JSON.stringify(record, null, 2)}\n`);
|
|
26
30
|
return { value, reused: false, key };
|
|
27
31
|
}
|
|
32
|
+
export async function memoizeProbeAsync(input) {
|
|
33
|
+
const key = hashJson({ probe_id: input.probeId, version: input.version, env: envPresence(input.envAllowlist || []), file_hash: input.fileHash || null });
|
|
34
|
+
const file = probeCachePath(input.root, key);
|
|
35
|
+
const existing = readProbeRecord(file);
|
|
36
|
+
if (existing && new Date(existing.expires_at).getTime() > Date.now()) {
|
|
37
|
+
writeProbeReport(input.root, { repeated_probe_count: 1, reused_probe_count: 1, saved_ms_estimate: Math.max(1, input.ttlMs / 1000) });
|
|
38
|
+
return { value: existing.value, reused: true, key };
|
|
39
|
+
}
|
|
40
|
+
const started = Date.now();
|
|
41
|
+
const value = await input.run();
|
|
42
|
+
const record = {
|
|
43
|
+
schema: PROBE_MEMOIZATION_SCHEMA,
|
|
44
|
+
key,
|
|
45
|
+
probe_id: input.probeId,
|
|
46
|
+
created_at: new Date().toISOString(),
|
|
47
|
+
expires_at: new Date(Date.now() + input.ttlMs).toISOString(),
|
|
48
|
+
value,
|
|
49
|
+
tool_version: input.version,
|
|
50
|
+
...(input.fileHash ? { file_hash: input.fileHash } : {}),
|
|
51
|
+
env_allowlist_hash: hashJson(envPresence(input.envAllowlist || []))
|
|
52
|
+
};
|
|
53
|
+
fs.mkdirSync(path.dirname(file), { recursive: true });
|
|
54
|
+
fs.writeFileSync(file, `${JSON.stringify(record, null, 2)}\n`);
|
|
55
|
+
writeProbeReport(input.root, { repeated_probe_count: 1, reused_probe_count: 0, saved_ms_estimate: Math.max(0, Date.now() - started) });
|
|
56
|
+
return { value, reused: false, key };
|
|
57
|
+
}
|
|
28
58
|
function readProbeRecord(file) {
|
|
29
59
|
try {
|
|
30
60
|
if (!fs.existsSync(file))
|
|
@@ -39,4 +69,12 @@ function readProbeRecord(file) {
|
|
|
39
69
|
function probeCachePath(root, key) {
|
|
40
70
|
return path.join(root, '.sneakoscope', 'cache', 'probes', `${key}.json`);
|
|
41
71
|
}
|
|
72
|
+
function envPresence(keys) {
|
|
73
|
+
return [...new Set(keys)].sort().map((name) => ({ name, present: process.env[name] !== undefined }));
|
|
74
|
+
}
|
|
75
|
+
function writeProbeReport(root, report) {
|
|
76
|
+
const file = path.join(root, '.sneakoscope', 'reports', 'probe-memoization.json');
|
|
77
|
+
fs.mkdirSync(path.dirname(file), { recursive: true });
|
|
78
|
+
fs.writeFileSync(file, `${JSON.stringify({ schema: 'sks.probe-memoization-report.v1', ...report }, null, 2)}\n`);
|
|
79
|
+
}
|
|
42
80
|
//# sourceMappingURL=probe-memoization.js.map
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import fs from 'node:fs';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
export function buildCriticalPathLedger(input) {
|
|
4
|
+
return { schema: 'sks.critical-path-ledger.v1', ...input };
|
|
5
|
+
}
|
|
6
|
+
export function writeCriticalPathLedger(root, ledger) {
|
|
7
|
+
const file = path.join(root, '.sneakoscope', 'reports', 'critical-path-ledger.json');
|
|
8
|
+
fs.mkdirSync(path.dirname(file), { recursive: true });
|
|
9
|
+
fs.writeFileSync(file, `${JSON.stringify(ledger, null, 2)}\n`);
|
|
10
|
+
return file;
|
|
11
|
+
}
|
|
12
|
+
//# sourceMappingURL=critical-path-ledger.js.map
|
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
import { buildGatePackManifest } from './gate-pack-manifest.js';
|
|
2
|
+
import { executeGatePack } from './gate-pack-runner.js';
|
|
3
|
+
import { buildCriticalPathLedger, writeCriticalPathLedger } from './critical-path-ledger.js';
|
|
2
4
|
import { computeResourceClassBudget } from './resource-class-budget.js';
|
|
3
5
|
export const EXTREME_PARALLEL_SCHEDULER_SCHEMA = 'sks.extreme-parallel-scheduler.v1';
|
|
4
6
|
export function planExtremeParallelSchedule(root, graph, budget = computeResourceClassBudget()) {
|
|
@@ -30,4 +32,55 @@ export function planExtremeParallelSchedule(root, graph, budget = computeResourc
|
|
|
30
32
|
blockers
|
|
31
33
|
};
|
|
32
34
|
}
|
|
35
|
+
export async function executeExtremeSchedule(input) {
|
|
36
|
+
const planned = planExtremeParallelSchedule(input.root, input.graph, input.budget);
|
|
37
|
+
const started = Date.now();
|
|
38
|
+
const runId = `xs-${new Date().toISOString().replace(/[:.]/g, '-')}-${process.pid}`;
|
|
39
|
+
const reports = [];
|
|
40
|
+
let reused = 0;
|
|
41
|
+
let executedGates = 0;
|
|
42
|
+
let failedPacks = 0;
|
|
43
|
+
for (const batch of planned.batches) {
|
|
44
|
+
const results = await Promise.all(batch.packs.map((packId) => executeGatePack({
|
|
45
|
+
root: input.root,
|
|
46
|
+
packId,
|
|
47
|
+
mode: 'execute',
|
|
48
|
+
maxParallel: Math.max(1, Math.min(4, input.budget.cpu_light))
|
|
49
|
+
})));
|
|
50
|
+
for (const report of results) {
|
|
51
|
+
reports.push(report);
|
|
52
|
+
reused += report.reused_proof_count || report.reused || 0;
|
|
53
|
+
executedGates += report.executed_gate_count || report.executed || 0;
|
|
54
|
+
if (!report.ok)
|
|
55
|
+
failedPacks += 1;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
const wallMs = Math.max(0, Date.now() - started);
|
|
59
|
+
const criticalPathMs = reports.reduce((max, report) => Math.max(max, report.critical_path_ms || 0), planned.critical_path_ms);
|
|
60
|
+
const sequentialMs = reports.reduce((sum, report) => sum + (report.critical_path_ms || 0), planned.sequential_ms);
|
|
61
|
+
writeCriticalPathLedger(input.root, buildCriticalPathLedger({
|
|
62
|
+
run_id: runId,
|
|
63
|
+
sequential_ms: sequentialMs,
|
|
64
|
+
critical_path_ms: criticalPathMs,
|
|
65
|
+
wall_ms: wallMs,
|
|
66
|
+
parallelism_gain: wallMs > 0 ? Number((sequentialMs / wallMs).toFixed(2)) : 1,
|
|
67
|
+
resource_wait_ms: {},
|
|
68
|
+
top_blockers: reports.filter((report) => !report.ok).map((report) => ({ id: report.pack_id, wait_ms: 0, run_ms: report.critical_path_ms || 0 }))
|
|
69
|
+
}));
|
|
70
|
+
return {
|
|
71
|
+
...planned,
|
|
72
|
+
ok: planned.ok && failedPacks === 0 && wallMs <= input.slaMs,
|
|
73
|
+
run_id: runId,
|
|
74
|
+
mode: 'execute',
|
|
75
|
+
executed_packs: reports.map((report) => report.pack_id),
|
|
76
|
+
reused_proof_count: reused,
|
|
77
|
+
executed_gate_count: executedGates,
|
|
78
|
+
failed_pack_count: failedPacks,
|
|
79
|
+
wall_ms: wallMs,
|
|
80
|
+
critical_path_ms: criticalPathMs,
|
|
81
|
+
sequential_ms: sequentialMs,
|
|
82
|
+
pack_reports: reports,
|
|
83
|
+
blockers: [...planned.blockers, ...(wallMs > input.slaMs ? ['sla_actual_exceeds_budget'] : []), ...(failedPacks ? ['pack_execution_failed'] : [])]
|
|
84
|
+
};
|
|
85
|
+
}
|
|
33
86
|
//# sourceMappingURL=extreme-parallel-scheduler.js.map
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import fs from 'node:fs';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
export const GATE_PACK_FIXTURE_SCHEMA = 'sks.gate-pack-fixture.v1';
|
|
4
|
+
export async function prepareGatePackFixture(input) {
|
|
5
|
+
const base = path.join(input.root, '.sneakoscope', 'fixture-cache', 'gate-packs', safe(input.packId), safe(input.fixtureVersion));
|
|
6
|
+
const reusedBase = fs.existsSync(path.join(base, 'fixture.json'));
|
|
7
|
+
fs.mkdirSync(base, { recursive: true });
|
|
8
|
+
if (!reusedBase) {
|
|
9
|
+
fs.writeFileSync(path.join(base, 'fixture.json'), `${JSON.stringify({ schema: GATE_PACK_FIXTURE_SCHEMA, pack_id: input.packId, fixture_version: input.fixtureVersion, created_at: new Date().toISOString() }, null, 2)}\n`);
|
|
10
|
+
}
|
|
11
|
+
const runPath = path.join(input.root, '.sneakoscope', 'fixture-cache', 'runs', `${safe(input.packId)}-${process.pid}-${Date.now()}`);
|
|
12
|
+
fs.mkdirSync(path.dirname(runPath), { recursive: true });
|
|
13
|
+
copyDir(base, runPath);
|
|
14
|
+
return {
|
|
15
|
+
schema: GATE_PACK_FIXTURE_SCHEMA,
|
|
16
|
+
root: input.root,
|
|
17
|
+
pack_id: input.packId,
|
|
18
|
+
fixture_version: input.fixtureVersion,
|
|
19
|
+
base_path: base,
|
|
20
|
+
run_path: runPath,
|
|
21
|
+
reused_base: reusedBase,
|
|
22
|
+
setup_count: reusedBase ? 0 : 1
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
function copyDir(from, to) {
|
|
26
|
+
fs.mkdirSync(to, { recursive: true });
|
|
27
|
+
for (const entry of fs.readdirSync(from, { withFileTypes: true })) {
|
|
28
|
+
const src = path.join(from, entry.name);
|
|
29
|
+
const dst = path.join(to, entry.name);
|
|
30
|
+
if (entry.isDirectory())
|
|
31
|
+
copyDir(src, dst);
|
|
32
|
+
else if (entry.isFile())
|
|
33
|
+
fs.copyFileSync(src, dst);
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
function safe(value) {
|
|
37
|
+
return value.replace(/[^a-zA-Z0-9._-]+/g, '_');
|
|
38
|
+
}
|
|
39
|
+
//# sourceMappingURL=gate-pack-fixture-cache.js.map
|