sneakoscope 5.7.0 → 5.9.0

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 (88) hide show
  1. package/README.md +1 -1
  2. package/config/competitor-scorecard-baseline.json +97 -0
  3. package/config/perf-budgets.v1.json +10 -0
  4. package/crates/sks-core/Cargo.lock +1 -1
  5. package/crates/sks-core/Cargo.toml +1 -1
  6. package/crates/sks-core/src/main.rs +1 -1
  7. package/dist/bin/sks.js +61 -1
  8. package/dist/cli/command-registry.js +2 -3
  9. package/dist/cli/commands-fast.js +20 -0
  10. package/dist/cli/root-fast.js +48 -0
  11. package/dist/cli/router.js +3 -0
  12. package/dist/cli/super-search-command.js +221 -0
  13. package/dist/cli/xai-command.js +7 -7
  14. package/dist/commands/doctor.js +56 -24
  15. package/dist/config/skills-manifest.json +63 -70
  16. package/dist/core/agents/agent-codex-cockpit.js +3 -3
  17. package/dist/core/agents/agent-orchestrator.js +20 -2
  18. package/dist/core/agents/agent-wrongness.js +1 -1
  19. package/dist/core/agents/native-cli-session-swarm.js +14 -1
  20. package/dist/core/agents/parallel-runtime-proof.js +82 -8
  21. package/dist/core/agents/parallel-write-fixture.js +301 -0
  22. package/dist/core/commands/gc-command.js +12 -6
  23. package/dist/core/commands/run-command.js +20 -18
  24. package/dist/core/doctor/doctor-idempotence.js +93 -0
  25. package/dist/core/errors/blocker-humanizer.js +13 -0
  26. package/dist/core/errors/next-action-map.js +56 -0
  27. package/dist/core/feature-fixtures.js +15 -8
  28. package/dist/core/fsx.js +1 -1
  29. package/dist/core/init/skills.js +1 -2
  30. package/dist/core/install/installed-package-smoke.js +121 -0
  31. package/dist/core/mission.js +41 -15
  32. package/dist/core/naruto/naruto-active-pool.js +6 -2
  33. package/dist/core/perf/perf-budget.js +145 -0
  34. package/dist/core/quality/competitor-scorecard.js +116 -0
  35. package/dist/core/release/gate-timing.js +103 -0
  36. package/dist/core/release-parallel-full-coverage.js +1 -1
  37. package/dist/core/retention/retention-budget.js +62 -0
  38. package/dist/core/retention.js +1 -1
  39. package/dist/core/routes/constants.js +2 -2
  40. package/dist/core/routes.js +155 -53
  41. package/dist/core/source-intelligence/source-intelligence-policy.js +5 -5
  42. package/dist/core/source-intelligence/source-intelligence-proof.js +8 -8
  43. package/dist/core/source-intelligence/source-intelligence-runner.js +16 -16
  44. package/dist/core/strategy/strategy-gate.js +2 -1
  45. package/dist/core/super-search/doctor.js +63 -0
  46. package/dist/core/super-search/runtime-helpers.js +289 -0
  47. package/dist/core/super-search/runtime.js +270 -0
  48. package/dist/core/super-search/source-records.js +96 -0
  49. package/dist/core/super-search/types.js +3 -0
  50. package/dist/core/trust-kernel/trust-report.js +3 -3
  51. package/dist/core/verification/real-evidence-policy.js +55 -0
  52. package/dist/core/version.js +1 -1
  53. package/dist/scripts/agent-fast-mode-default-check.js +10 -1
  54. package/dist/scripts/agent-visual-consistency-check.js +1 -1
  55. package/dist/scripts/check-architecture.js +0 -1
  56. package/dist/scripts/competitor-scorecard-check.js +25 -0
  57. package/dist/scripts/doctor-idempotence-check.js +8 -0
  58. package/dist/scripts/gate-timing-check.js +8 -0
  59. package/dist/scripts/hook-latency-quantum-check.js +122 -0
  60. package/dist/scripts/installed-package-smoke-check.js +12 -0
  61. package/dist/scripts/lib/native-cli-session-swarm-check-lib.js +2 -0
  62. package/dist/scripts/mutation-callsite-coverage-check.js +7 -0
  63. package/dist/scripts/package-published-contract-check.js +7 -0
  64. package/dist/scripts/packlist-performance-check.js +31 -3
  65. package/dist/scripts/parallel-production-smoke-check.js +21 -0
  66. package/dist/scripts/perf-budget-check.js +14 -0
  67. package/dist/scripts/quantum-baseline-report.js +38 -0
  68. package/dist/scripts/release-check-stamp.js +117 -16
  69. package/dist/scripts/release-metadata-1-19-check.js +2 -2
  70. package/dist/scripts/release-parallel-check.js +2 -2
  71. package/dist/scripts/release-parallel-full-coverage-check.js +1 -1
  72. package/dist/scripts/retention-budget-check.js +8 -0
  73. package/dist/scripts/route-intent-regression-check.js +44 -0
  74. package/dist/scripts/sks-1-18-gate-lib.js +2 -2
  75. package/dist/scripts/source-intelligence-all-modes-check.js +2 -2
  76. package/dist/scripts/source-intelligence-policy-check.js +1 -1
  77. package/dist/scripts/super-search-live-smoke-check.js +70 -0
  78. package/dist/scripts/super-search-name-guard-check.js +98 -0
  79. package/dist/scripts/super-search-offline-contract-check.js +45 -0
  80. package/dist/scripts/{ultra-search-provider-interface-check.js → super-search-provider-interface-check.js} +9 -9
  81. package/dist/scripts/trust-fixture-check.js +19 -6
  82. package/package.json +26 -8
  83. package/schemas/agents/parallel-runtime-proof.schema.json +17 -1
  84. package/dist/cli/insane-search-command.js +0 -195
  85. package/dist/core/ultra-search/runtime.js +0 -502
  86. package/dist/core/ultra-search/types.js +0 -3
  87. package/dist/scripts/release-readiness-report.js +0 -1262
  88. /package/dist/core/{ultra-search → super-search}/index.js +0 -0
@@ -0,0 +1,145 @@
1
+ import { performance } from 'node:perf_hooks';
2
+ import path from 'node:path';
3
+ import { runProcess, writeJsonAtomic } from '../fsx.js';
4
+ export async function runPerfBudgets(root, budgets, opts = {}) {
5
+ const warmupRuns = opts.warmupRuns ?? Number(process.env.SKS_PERF_WARMUP_RUNS || 2);
6
+ const measuredRuns = opts.measuredRuns ?? Number(process.env.SKS_PERF_MEASURED_RUNS || 15);
7
+ const timeoutMs = opts.timeoutMs ?? 30_000;
8
+ const timingRetries = Math.max(0, Number(process.env.SKS_PERF_TIMING_RETRIES || 2));
9
+ const retryCooldownMs = Math.max(0, Number(process.env.SKS_PERF_RETRY_COOLDOWN_MS || 3000));
10
+ const commands = [];
11
+ const blockers = [];
12
+ for (const budget of budgets) {
13
+ for (let index = 0; index < warmupRuns; index++) {
14
+ await runTimed(root, budget.argv, timeoutMs);
15
+ }
16
+ const attempts = [];
17
+ let measurement = await measureCommand(root, budget, measuredRuns, timeoutMs);
18
+ attempts.push(commandAttempt(1, measurement));
19
+ let selectedAttempt = 1;
20
+ for (let retry = 1; retry <= timingRetries && !measurement.ok && measurement.exitOk; retry++) {
21
+ if (retryCooldownMs)
22
+ await delay(retryCooldownMs);
23
+ await runTimed(root, budget.argv, timeoutMs);
24
+ const next = await measureCommand(root, budget, measuredRuns, timeoutMs);
25
+ attempts.push(commandAttempt(retry + 1, next));
26
+ if (isBetterMeasurement(next, measurement, budget)) {
27
+ measurement = next;
28
+ selectedAttempt = retry + 1;
29
+ }
30
+ if (measurement.ok)
31
+ break;
32
+ }
33
+ const { p50, p95, exitCodes, ok } = measurement;
34
+ blockers.push(...measurement.blockers.map((blocker) => `${budget.name}:${blocker}`));
35
+ commands.push({
36
+ name: budget.name,
37
+ argv: budget.argv,
38
+ runs: measuredRuns,
39
+ p50_ms: p50,
40
+ p95_ms: p95,
41
+ ...(budget.budget_p50_ms !== undefined ? { budget_p50_ms: budget.budget_p50_ms } : {}),
42
+ budget_p95_ms: budget.budget_p95_ms,
43
+ ok,
44
+ exit_codes: exitCodes,
45
+ ...(attempts.length > 1 ? { retry_count: attempts.length - 1, selected_attempt: selectedAttempt, attempts } : {})
46
+ });
47
+ }
48
+ return {
49
+ schema: 'sks.perf-budget.v1',
50
+ ok: blockers.length === 0,
51
+ generated_at: new Date().toISOString(),
52
+ warmup_runs: warmupRuns,
53
+ measured_runs: measuredRuns,
54
+ commands,
55
+ blockers: [...new Set(blockers)]
56
+ };
57
+ }
58
+ export async function writePerfBudgetReport(root, budgets, opts = {}) {
59
+ const report = await runPerfBudgets(root, budgets, opts);
60
+ await writeJsonAtomic(path.join(root, '.sneakoscope', 'reports', 'perf-budget.json'), report);
61
+ return report;
62
+ }
63
+ async function measureCommand(root, budget, measuredRuns, timeoutMs) {
64
+ const durations = [];
65
+ const exitCodes = [];
66
+ const blockers = [];
67
+ for (let index = 0; index < measuredRuns; index++) {
68
+ const result = await runTimed(root, budget.argv, timeoutMs);
69
+ durations.push(result.duration_ms);
70
+ exitCodes.push(result.code);
71
+ if (result.code !== 0)
72
+ blockers.push(`exit_${result.code}`);
73
+ }
74
+ durations.sort((a, b) => a - b);
75
+ const p50 = percentile(durations, 0.5);
76
+ const p95 = percentile(durations, 0.95);
77
+ const p50Ok = budget.budget_p50_ms === undefined || p50 <= budget.budget_p50_ms;
78
+ const p95Ok = p95 <= budget.budget_p95_ms;
79
+ const exitOk = exitCodes.every((code) => code === 0);
80
+ const ok = p50Ok && p95Ok && exitOk;
81
+ if (!p50Ok)
82
+ blockers.push('p50_budget_exceeded');
83
+ if (!p95Ok)
84
+ blockers.push('p95_budget_exceeded');
85
+ if (!exitOk)
86
+ blockers.push('process_failed');
87
+ return { p50, p95, p50Ok, p95Ok, exitOk, ok, exitCodes, blockers: [...new Set(blockers)] };
88
+ }
89
+ function commandAttempt(attempt, measurement) {
90
+ return {
91
+ attempt,
92
+ p50_ms: measurement.p50,
93
+ p95_ms: measurement.p95,
94
+ ok: measurement.ok,
95
+ exit_codes: measurement.exitCodes,
96
+ blockers: measurement.blockers
97
+ };
98
+ }
99
+ function isBetterMeasurement(next, current, budget) {
100
+ if (next.ok !== current.ok)
101
+ return next.ok;
102
+ if (next.exitOk !== current.exitOk)
103
+ return next.exitOk;
104
+ if (next.blockers.length !== current.blockers.length)
105
+ return next.blockers.length < current.blockers.length;
106
+ const nextOverage = timingOverage(next, budget);
107
+ const currentOverage = timingOverage(current, budget);
108
+ if (nextOverage !== currentOverage)
109
+ return nextOverage < currentOverage;
110
+ if (next.p95 !== current.p95)
111
+ return next.p95 < current.p95;
112
+ return next.p50 < current.p50;
113
+ }
114
+ function timingOverage(measurement, budget) {
115
+ const p50Overage = budget.budget_p50_ms === undefined ? 0 : Math.max(0, measurement.p50 - budget.budget_p50_ms);
116
+ const p95Overage = Math.max(0, measurement.p95 - budget.budget_p95_ms);
117
+ return p50Overage + p95Overage;
118
+ }
119
+ async function runTimed(root, argv, timeoutMs) {
120
+ const [command, ...args] = argv;
121
+ if (!command)
122
+ return { code: -1, duration_ms: 0 };
123
+ const started = performance.now();
124
+ const result = await runProcess(command, args, {
125
+ cwd: root,
126
+ timeoutMs,
127
+ maxOutputBytes: 64 * 1024,
128
+ env: {
129
+ SKS_DISABLE_NETWORK: '1',
130
+ SKS_PERF_MEASURE: '1',
131
+ SKS_DISABLE_UPDATE_CHECK: '1'
132
+ }
133
+ });
134
+ return { code: result.code, duration_ms: Math.round(performance.now() - started) };
135
+ }
136
+ function delay(ms) {
137
+ return new Promise((resolve) => setTimeout(resolve, ms));
138
+ }
139
+ function percentile(values, pct) {
140
+ if (!values.length)
141
+ return 0;
142
+ const index = Math.min(values.length - 1, Math.max(0, Math.ceil(values.length * pct) - 1));
143
+ return values[index] ?? 0;
144
+ }
145
+ //# sourceMappingURL=perf-budget.js.map
@@ -0,0 +1,116 @@
1
+ import fs from 'node:fs';
2
+ import path from 'node:path';
3
+ import { readJson } from '../fsx.js';
4
+ const scoreCategories = [
5
+ 'code_stability',
6
+ 'test_release_gates',
7
+ 'parallel_isolation',
8
+ 'speed_performance',
9
+ 'install_operations',
10
+ 'maintainability'
11
+ ];
12
+ export async function generateCompetitorScorecard(root, baseline) {
13
+ const pkg = await readJson(path.join(root, 'package.json'), {});
14
+ const evidence = Object.fromEntries(await Promise.all(scoreCategories.map(async (category) => {
15
+ const entries = baseline.categories[category] || [];
16
+ return [category, await Promise.all(entries.map((entry) => scoreEvidence(root, entry)))];
17
+ })));
18
+ const scores = Object.fromEntries(scoreCategories.map((category) => {
19
+ const results = evidence[category];
20
+ const totalPoints = results.reduce((sum, item) => sum + (item.points ?? 1), 0);
21
+ const earned = results.reduce((sum, item) => sum + item.score, 0);
22
+ return [category, totalPoints > 0 ? Math.round((earned / totalPoints) * 100) : 0];
23
+ }));
24
+ const total = Math.round(scoreCategories.reduce((sum, category) => sum + scores[category], 0) / scoreCategories.length);
25
+ const blockers = scoreCategories.flatMap((category) => evidence[category]
26
+ .filter((item) => item.status !== 'passed')
27
+ .map((item) => `${category}:${item.id}:${item.status}`));
28
+ for (const category of scoreCategories) {
29
+ if (scores[category] < baseline.target.each_min)
30
+ blockers.push(`${category}_below_${baseline.target.each_min}`);
31
+ }
32
+ if (total < baseline.target.total_min)
33
+ blockers.push(`total_below_${baseline.target.total_min}`);
34
+ const scorecard = {
35
+ schema: 'sks.competitor-scorecard.v1',
36
+ version: pkg.version || 'unknown',
37
+ generated_at: new Date().toISOString(),
38
+ scores: {
39
+ ...scores,
40
+ total
41
+ },
42
+ target: baseline.target,
43
+ blockers
44
+ };
45
+ return {
46
+ scorecard,
47
+ evidence,
48
+ ok: blockers.length === 0
49
+ };
50
+ }
51
+ async function scoreEvidence(root, entry) {
52
+ if (entry.path) {
53
+ const fullPath = path.isAbsolute(entry.path) ? entry.path : path.join(root, entry.path);
54
+ let data;
55
+ try {
56
+ data = await readJson(fullPath);
57
+ }
58
+ catch {
59
+ return { ...entry, score: 0, status: 'missing', blockers: ['artifact_missing_or_invalid_json'] };
60
+ }
61
+ const passed = artifactLooksPassing(data);
62
+ return {
63
+ ...entry,
64
+ score: passed ? (entry.points ?? 1) : 0,
65
+ status: passed ? 'passed' : 'failed',
66
+ blockers: passed ? [] : ['artifact_not_passing']
67
+ };
68
+ }
69
+ if (entry.command) {
70
+ return commandEvidence(root, entry);
71
+ }
72
+ return { ...entry, score: 0, status: 'unreadable', blockers: ['evidence_has_no_path_or_command'] };
73
+ }
74
+ function commandEvidence(root, entry) {
75
+ const pkgPath = path.join(root, 'package.json');
76
+ let scripts;
77
+ try {
78
+ const pkg = JSON.parse(fs.readFileSync(pkgPath, 'utf8'));
79
+ scripts = pkg.scripts || {};
80
+ }
81
+ catch {
82
+ return { ...entry, score: 0, status: 'unreadable', blockers: ['package_json_unreadable'] };
83
+ }
84
+ const ok = Boolean(scripts[entry.command || '']);
85
+ return {
86
+ ...entry,
87
+ score: ok ? (entry.points ?? 1) : 0,
88
+ status: ok ? 'passed' : 'missing',
89
+ blockers: ok ? [] : ['package_script_missing']
90
+ };
91
+ }
92
+ function artifactLooksPassing(data) {
93
+ if (!data || typeof data !== 'object')
94
+ return false;
95
+ const record = data;
96
+ if (record.ok === true || record.passed === true || record.success === true)
97
+ return noFailureSignals(record);
98
+ if (record.status === 'passed' || record.status === 'pass' || record.status === 'ok')
99
+ return noFailureSignals(record);
100
+ if (record.status === 'blocked' || record.ok === false || record.passed === false || record.success === false)
101
+ return false;
102
+ if (Array.isArray(record.failures) && record.failures.length > 0)
103
+ return false;
104
+ if (Array.isArray(record.errors) && record.errors.length > 0)
105
+ return false;
106
+ if (Array.isArray(record.blockers) && record.blockers.length > 0)
107
+ return false;
108
+ return false;
109
+ }
110
+ function noFailureSignals(record) {
111
+ return !((Array.isArray(record.failures) && record.failures.length > 0)
112
+ || (Array.isArray(record.errors) && record.errors.length > 0)
113
+ || (Array.isArray(record.blockers) && record.blockers.length > 0)
114
+ || record.status === 'blocked');
115
+ }
116
+ //# sourceMappingURL=competitor-scorecard.js.map
@@ -0,0 +1,103 @@
1
+ import fs from 'node:fs';
2
+ import path from 'node:path';
3
+ import { runProcess, writeJsonAtomic } from '../fsx.js';
4
+ export async function runGateTiming(root) {
5
+ const started = Date.now();
6
+ const res = await runProcess(process.execPath, ['./dist/scripts/release-gate-dag-runner.js', '--preset', 'affected', '--changed-since', 'auto', '--sla', '5m'], {
7
+ cwd: root,
8
+ timeoutMs: 5 * 60 * 1000,
9
+ maxOutputBytes: 512 * 1024,
10
+ env: {
11
+ SKS_RELEASE_GATE_CACHE_MEMOIZE: '1',
12
+ SKS_DISABLE_NETWORK: '1'
13
+ }
14
+ });
15
+ const totalMs = Date.now() - started;
16
+ const blockers = [];
17
+ if (res.code !== 0)
18
+ blockers.push(`release_gate_dag_exit_${res.code}`);
19
+ if (res.timedOut)
20
+ blockers.push('release_gate_timing_timeout');
21
+ const summary = latestReleaseSummary(root);
22
+ const slowest = parseSlowestGates(summary, res.stdout);
23
+ const redundantGateGroups = findRedundantBuildGroups(root);
24
+ if (redundantGateGroups.length > 0)
25
+ blockers.push('duplicate_builds_detected');
26
+ return {
27
+ schema: 'sks.gate-timing.v1',
28
+ ok: blockers.length === 0,
29
+ generated_at: new Date().toISOString(),
30
+ total_ms: totalMs,
31
+ slowest_gates: slowest,
32
+ duplicate_builds_detected: redundantGateGroups.length > 0,
33
+ redundant_gate_groups: redundantGateGroups,
34
+ blockers,
35
+ ...(res.code !== 0 || res.timedOut ? { failure_tail: { stdout: tail(res.stdout), stderr: tail(res.stderr) } } : {})
36
+ };
37
+ }
38
+ export async function writeGateTiming(root) {
39
+ const report = await runGateTiming(root);
40
+ await writeJsonAtomic(path.join(root, '.sneakoscope', 'reports', 'gate-timing.json'), report);
41
+ return report;
42
+ }
43
+ function parseSlowestGates(summary, stdout) {
44
+ if (Array.isArray(summary?.slowest_gates)) {
45
+ return summary.slowest_gates.slice(0, 10).map((row) => ({
46
+ id: String(row.id || row.gate_id || 'unknown'),
47
+ duration_ms: Math.round(Number(row.duration_ms || 0)),
48
+ cache_hit: Boolean(row.cached ?? row.cache_hit)
49
+ }));
50
+ }
51
+ const rows = [];
52
+ const text = String(stdout || '');
53
+ for (const match of text.matchAll(/\b([a-z0-9:_-]+)\b[^\n]*?(\d+(?:\.\d+)?)s/gi)) {
54
+ rows.push({ id: match[1] || 'unknown', duration_ms: Math.round(Number(match[2]) * 1000), cache_hit: /cache/i.test(match[0]) });
55
+ }
56
+ return rows.sort((a, b) => b.duration_ms - a.duration_ms).slice(0, 10);
57
+ }
58
+ function latestReleaseSummary(root) {
59
+ const dir = path.join(root, '.sneakoscope', 'reports', 'release-gates');
60
+ if (!fs.existsSync(dir))
61
+ return null;
62
+ const latest = fs.readdirSync(dir, { withFileTypes: true })
63
+ .filter((entry) => entry.isDirectory())
64
+ .map((entry) => path.join(dir, entry.name, 'summary.json'))
65
+ .filter((file) => fs.existsSync(file))
66
+ .map((file) => ({ file, mtimeMs: fs.statSync(file).mtimeMs }))
67
+ .sort((a, b) => b.mtimeMs - a.mtimeMs)[0]?.file;
68
+ if (!latest)
69
+ return null;
70
+ try {
71
+ return JSON.parse(fs.readFileSync(latest, 'utf8'));
72
+ }
73
+ catch {
74
+ return null;
75
+ }
76
+ }
77
+ function findRedundantBuildGroups(root) {
78
+ const manifestFile = path.join(root, 'release-gates.v2.json');
79
+ if (!fs.existsSync(manifestFile))
80
+ return [];
81
+ let manifest;
82
+ try {
83
+ manifest = JSON.parse(fs.readFileSync(manifestFile, 'utf8'));
84
+ }
85
+ catch {
86
+ return [];
87
+ }
88
+ const groups = new Map();
89
+ for (const gate of Array.isArray(manifest?.gates) ? manifest.gates : []) {
90
+ const command = String(gate.command || '').trim().replace(/\s+/g, ' ');
91
+ if (!/\b(?:npm run build(?::clean|:incremental)?|tsc -p tsconfig\.json)\b/.test(command))
92
+ continue;
93
+ const ids = groups.get(command) || [];
94
+ ids.push(String(gate.id || 'unknown'));
95
+ groups.set(command, ids);
96
+ }
97
+ return [...groups.entries()].filter(([, ids]) => ids.length > 1).map(([command, gate_ids]) => ({ command, gate_ids }));
98
+ }
99
+ function tail(value) {
100
+ const text = String(value || '');
101
+ return text.length > 4000 ? text.slice(text.length - 4000) : text;
102
+ }
103
+ //# sourceMappingURL=gate-timing.js.map
@@ -17,7 +17,7 @@ export const RELEASE_1_17_GATE_SNAPSHOT = Object.freeze([
17
17
  'release:readiness'
18
18
  ]);
19
19
  export const RELEASE_1_18_REQUIRED_GATES = Object.freeze([
20
- 'insane-search:provider-interface',
20
+ 'super-search:provider-interface',
21
21
  'source-intelligence:policy',
22
22
  'source-intelligence:all-modes',
23
23
  'codex-web:adapter',
@@ -0,0 +1,62 @@
1
+ import fs from 'node:fs/promises';
2
+ import path from 'node:path';
3
+ import { writeJsonAtomic } from '../fsx.js';
4
+ const DEFAULT_BUDGETS = [
5
+ { path: '.sneakoscope/state', max_bytes: 50 * 1024 * 1024 },
6
+ { path: '.sneakoscope/cache', max_bytes: 250 * 1024 * 1024 },
7
+ { path: '.sneakoscope/cache/super-search', max_bytes: 100 * 1024 * 1024 }
8
+ ];
9
+ export async function runRetentionBudget(root) {
10
+ const budgets = [];
11
+ const blockers = [];
12
+ for (const budget of DEFAULT_BUDGETS) {
13
+ const bytes = await sizeOf(path.join(root, budget.path));
14
+ const ok = bytes <= budget.max_bytes;
15
+ budgets.push({ path: budget.path, bytes, max_bytes: budget.max_bytes, ok });
16
+ if (!ok)
17
+ blockers.push(`retention_budget_exceeded:${budget.path}`);
18
+ }
19
+ const oversizedJsonl = await findOversizedJsonl(path.join(root, '.sneakoscope', 'missions'), 10 * 1024 * 1024);
20
+ for (const row of oversizedJsonl)
21
+ blockers.push(`jsonl_budget_exceeded:${row.path}`);
22
+ const report = {
23
+ schema: 'sks.retention-budget.v1',
24
+ ok: blockers.length === 0,
25
+ generated_at: new Date().toISOString(),
26
+ budgets,
27
+ oversized_jsonl: oversizedJsonl,
28
+ blockers
29
+ };
30
+ await writeJsonAtomic(path.join(root, '.sneakoscope', 'reports', 'retention-budget.json'), report);
31
+ return report;
32
+ }
33
+ async function sizeOf(file) {
34
+ const stat = await fs.stat(file).catch(() => null);
35
+ if (!stat)
36
+ return 0;
37
+ if (stat.isFile())
38
+ return stat.size;
39
+ if (!stat.isDirectory())
40
+ return 0;
41
+ const entries = await fs.readdir(file, { withFileTypes: true }).catch(() => []);
42
+ let total = 0;
43
+ for (const entry of entries)
44
+ total += await sizeOf(path.join(file, entry.name));
45
+ return total;
46
+ }
47
+ async function findOversizedJsonl(dir, maxBytes) {
48
+ const out = [];
49
+ const entries = await fs.readdir(dir, { withFileTypes: true }).catch(() => []);
50
+ for (const entry of entries) {
51
+ const child = path.join(dir, entry.name);
52
+ if (entry.isDirectory())
53
+ out.push(...await findOversizedJsonl(child, maxBytes));
54
+ else if (entry.isFile() && entry.name.endsWith('.jsonl')) {
55
+ const stat = await fs.stat(child).catch(() => null);
56
+ if (stat && stat.size > maxBytes)
57
+ out.push({ path: child, bytes: stat.size, max_bytes: maxBytes });
58
+ }
59
+ }
60
+ return out;
61
+ }
62
+ //# sourceMappingURL=retention-budget.js.map
@@ -109,7 +109,7 @@ export async function storageReport(root) {
109
109
  report.total_human = formatBytes(report.total_bytes);
110
110
  return report;
111
111
  }
112
- async function lightweightStorageReport(root) {
112
+ export async function lightweightStorageReport(root) {
113
113
  const sks = path.join(root, '.sneakoscope');
114
114
  const report = {
115
115
  root,
@@ -9,7 +9,7 @@ export const FROM_CHAT_IMG_CHECKLIST_ARTIFACT = 'from-chat-img-checklist.md';
9
9
  export const FROM_CHAT_IMG_TEMP_TRIWIKI_ARTIFACT = 'from-chat-img-temp-triwiki.json';
10
10
  export const FROM_CHAT_IMG_QA_LOOP_ARTIFACT = 'from-chat-img-qa-loop.json';
11
11
  export const FROM_CHAT_IMG_TEMP_TRIWIKI_SESSIONS = 5;
12
- export const USAGE_TOPICS = 'install|setup|bootstrap|root|deps|zellij|tmux|auto-review|team|qa-loop|ppt|image-ux-review|computer-use|goal|fast-mode|review|ui|research|seo-geo-optimizer|db|git|codex|codex-app|codex-native|hooks|features|all-features|dfix|commit|commit-and-push|design|imagegen|dollar|context7|insane-search|ultra-search|xai|pipeline|reasoning|guard|conflicts|versioning|eval|harness|hproof|gx|wiki|memory|wrongness|code-structure|proof-field|skill-dream|rust';
12
+ export const USAGE_TOPICS = 'install|setup|bootstrap|root|deps|zellij|tmux|auto-review|team|qa-loop|ppt|image-ux-review|computer-use|goal|fast-mode|review|ui|research|seo-geo-optimizer|db|git|codex|codex-app|codex-native|hooks|features|all-features|dfix|commit|commit-and-push|design|imagegen|dollar|context7|super-search|xai|pipeline|reasoning|guard|conflicts|versioning|eval|harness|hproof|gx|wiki|memory|wrongness|code-structure|proof-field|skill-dream|rust';
13
13
  export const RECOMMENDED_MCP_SERVERS = [
14
14
  {
15
15
  id: 'context7',
@@ -30,7 +30,7 @@ export const RECOMMENDED_SKILLS = [
30
30
  'pipeline-runner',
31
31
  'solution-scout',
32
32
  'context7-docs',
33
- 'ultra-search',
33
+ 'super-search',
34
34
  'search-visibility-core',
35
35
  'seo-geo-optimizer',
36
36
  'autoresearch-loop',