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.
Files changed (33) 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/build/build-once-runner.js +5 -1
  7. package/dist/core/commands/check-command.js +3 -1
  8. package/dist/core/commands/mad-sks-command.js +7 -2
  9. package/dist/core/daemon/sksd-ipc.js +9 -0
  10. package/dist/core/daemon/sksd.js +37 -5
  11. package/dist/core/doctor/doctor-dirty-planner.js +70 -5
  12. package/dist/core/fsx.js +1 -1
  13. package/dist/core/probes/probe-memoization.js +40 -2
  14. package/dist/core/release/critical-path-ledger.js +12 -0
  15. package/dist/core/release/extreme-parallel-scheduler.js +53 -0
  16. package/dist/core/release/gate-pack-fixture-cache.js +39 -0
  17. package/dist/core/release/gate-pack-runner.js +145 -1
  18. package/dist/core/release/release-gate-cache-v2.js +6 -1
  19. package/dist/core/release/release-gate-dag.js +9 -2
  20. package/dist/core/triwiki/triwiki-affected-graph.js +63 -7
  21. package/dist/core/triwiki/triwiki-cache-key.js +27 -7
  22. package/dist/core/triwiki/triwiki-gate-impact-map.js +47 -2
  23. package/dist/core/triwiki/triwiki-invalidation.js +81 -0
  24. package/dist/core/triwiki/triwiki-module-card.js +48 -11
  25. package/dist/core/triwiki/triwiki-proof-bank.js +82 -4
  26. package/dist/core/triwiki/triwiki-proof-card.js +34 -3
  27. package/dist/core/triwiki/triwiki-sla-certificate.js +25 -2
  28. package/dist/core/version.js +1 -1
  29. package/dist/core/zellij/zellij-launcher.js +13 -0
  30. package/dist/core/zellij/zellij-worker-pane-manager.js +68 -17
  31. package/dist/scripts/release-4001-required-gates.js +13 -0
  32. package/dist/scripts/sizecheck.js +4 -2
  33. 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.0** is the destructive TriWiki Parallel Turbo release. It moves default completion toward affected-scope, release-equivalent proof with reusable TriWiki proof cards, gate packs, SLA scheduling, build-once proof, probe memoization, and explicit legacy-runtime migration instead of silent fallback aliases.
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.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.
@@ -76,7 +76,7 @@ dependencies = [
76
76
 
77
77
  [[package]]
78
78
  name = "sks-core"
79
- version = "4.0.0"
79
+ version = "4.0.1"
80
80
  dependencies = [
81
81
  "serde_json",
82
82
  ]
@@ -1,6 +1,6 @@
1
1
  [package]
2
2
  name = "sks-core"
3
- version = "4.0.0"
3
+ version = "4.0.1"
4
4
  edition = "2021"
5
5
 
6
6
  [dependencies]
@@ -4,7 +4,7 @@ use std::io::{self, Read, Seek, SeekFrom};
4
4
  fn main() {
5
5
  let mut args = std::env::args().skip(1);
6
6
  match args.next().as_deref() {
7
- Some("--version") => println!("sks-rs 4.0.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
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
- const FAST_PACKAGE_VERSION = '4.0.0';
2
+ const FAST_PACKAGE_VERSION = '4.0.1';
3
3
  const args = process.argv.slice(2);
4
4
  try {
5
5
  if (args[0] === '--agent' && args[1] === 'worker') {
@@ -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.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 plan = buildCheckPlan({ tier, sla, changedSince });
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 workspace = readOption(cleanArgs, '--workspace', readOption(cleanArgs, '--session', launchOpts.session || `sks-mad-${sanitizeZellijSessionName(process.cwd())}`));
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
@@ -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
- return state || emptyState();
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
- if (!fs.existsSync(marker))
8
- return { id, status: 'dirty', reason: 'no_clean_marker' };
9
- return { id, status: 'clean', reason: 'clean_marker_present' };
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
- return {
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.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 || []).sort().map((name) => ({ name, present: process.env[name] !== undefined }))
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