sneakoscope 6.0.2 → 6.0.3
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 +3 -1
- package/crates/sks-core/Cargo.lock +1 -1
- package/crates/sks-core/Cargo.toml +1 -1
- package/dist/bin/fast-inline.js +5 -0
- package/dist/bin/sks-dispatch.js +2 -0
- package/dist/cli/install-helpers.js +41 -6
- package/dist/commands/codex-app.js +8 -3
- package/dist/commands/codex-lb.js +37 -12
- package/dist/config/skills-manifest.json +57 -57
- package/dist/core/agents/agent-effort-policy.js +46 -33
- package/dist/core/agents/agent-orchestrator.js +1 -1
- package/dist/core/agents/agent-proof-evidence.js +16 -2
- package/dist/core/agents/agent-roster.js +2 -2
- package/dist/core/agents/native-cli-session-swarm.js +18 -1
- package/dist/core/agents/native-worker-backend-router.js +179 -108
- package/dist/core/agents/parallel-write-fixture.js +15 -10
- package/dist/core/agents/runtime-proof-summary.js +21 -3
- package/dist/core/codex-app/codex-app-restart.js +38 -8
- package/dist/core/codex-app/sks-menubar.js +92 -37
- package/dist/core/codex-app.js +26 -4
- package/dist/core/codex-control/codex-model-metadata.js +8 -4
- package/dist/core/codex-lb/codex-lb-env.js +78 -0
- package/dist/core/commands/basic-cli.js +15 -0
- package/dist/core/commands/naruto-command.js +37 -9
- package/dist/core/naruto/naruto-write-e2e.js +3 -4
- package/dist/core/provider/model-router.js +64 -3
- package/dist/core/release/package-size-budget.js +2 -0
- package/dist/core/routes/constants.js +1 -1
- package/dist/core/routes/model-mode-router.js +3 -0
- package/dist/core/routes.js +7 -9
- package/dist/core/update/update-migration-state.js +1 -1
- package/dist/core/update/update-notice.js +23 -0
- package/dist/core/update-check.js +46 -10
- package/dist/core/version.js +1 -1
- package/dist/scripts/codex-app-provider-model-ui-check.js +17 -2
- package/dist/scripts/doctor-fix-proves-codex-read-check.js +1 -1
- package/dist/scripts/gate-policy-audit-check.js +2 -2
- package/dist/scripts/legacy-upgrade-matrix-check.js +1 -1
- package/dist/scripts/lib/native-cli-session-swarm-check-lib.js +2 -1
- package/dist/scripts/naruto-shadow-clone-swarm-check.js +88 -50
- package/dist/scripts/npm-publish-performance-check.js +2 -1
- package/dist/scripts/packlist-performance-check.js +5 -2
- package/dist/scripts/release-dag-full-coverage-check.js +7 -7
- package/dist/scripts/release-gate-existence-audit.js +8 -9
- package/dist/scripts/scheduler-batch-dispatch-check.js +1 -1
- package/dist/scripts/sizecheck.js +7 -2
- package/dist/scripts/sks-menubar-install-check.js +7 -0
- package/dist/scripts/update-default-command-check.js +4 -2
- package/package.json +3 -16
|
@@ -4,16 +4,75 @@ const CATEGORY_POLICY = {
|
|
|
4
4
|
agentic: { reasoning: 'high', serviceTier: 'fast' },
|
|
5
5
|
ultrabrain: { reasoning: 'xhigh', serviceTier: 'standard' },
|
|
6
6
|
verify: { reasoning: 'medium', serviceTier: 'fast' },
|
|
7
|
-
review: { reasoning: 'high', serviceTier: 'fast' }
|
|
7
|
+
review: { reasoning: 'high', serviceTier: 'fast' },
|
|
8
|
+
e2e: { reasoning: 'xhigh', serviceTier: 'fast' },
|
|
9
|
+
refactor: { reasoning: 'max', serviceTier: 'fast' },
|
|
10
|
+
strategy: { reasoning: 'max', serviceTier: 'fast' }
|
|
8
11
|
};
|
|
12
|
+
export const NARUTO_GPT56_MODELS = ['gpt-5.6-luna', 'gpt-5.6-terra', 'gpt-5.6-sol'];
|
|
13
|
+
const NARUTO_LUNA_WORK_RE = /(e2e|end[-\s]?to[-\s]?end|test_execution|ux_review|browser|chrome|computer[-\s]?use|computer\s+use|gui|visual\s+(?:qa|test|check)|cross[-\s]?app|playwright|selenium|puppeteer|브라우저|컴퓨터\s*유즈|화면\s*검증)/i;
|
|
14
|
+
const NARUTO_SOL_WORK_RE = /(refactor|re-?architect|architecture|architect|planning|\bplan\b|strategy|strategic|integrat|conflict[-_\s]?resolv|patch[-_\s]?rebase|rollback[-_\s]?plan|gpt[-_\s]?final|arbiter|리팩터|아키텍처|기획|전략|통합|충돌\s*해결|롤백\s*계획)/i;
|
|
15
|
+
const NARUTO_MAX_WORK_RE = /(complex|critical|high[-\s]?risk|security|database|migration|release|publish|forensic|flaky|failure|cross[-\s]?app|multi[-\s]?step|복잡|고위험|보안|데이터베이스|마이그레이션|릴리즈|포렌식|실패)/i;
|
|
9
16
|
export async function routeModel(category, opts = {}) {
|
|
17
|
+
if (opts.narutoOnly) {
|
|
18
|
+
return routeNarutoGpt56Model({
|
|
19
|
+
category,
|
|
20
|
+
...(opts.taskText !== undefined ? { taskText: opts.taskText } : {}),
|
|
21
|
+
...(opts.riskText !== undefined ? { riskText: opts.riskText } : {}),
|
|
22
|
+
...(opts.model !== undefined ? { explicitModel: opts.model } : {}),
|
|
23
|
+
...(opts.availableModels !== undefined ? { availableModels: opts.availableModels } : {}),
|
|
24
|
+
...(opts.availableModelEfforts !== undefined ? { availableModelEfforts: opts.availableModelEfforts } : {}),
|
|
25
|
+
degradedModels: opts.lbHealth?.degraded_models || []
|
|
26
|
+
});
|
|
27
|
+
}
|
|
10
28
|
const policy = CATEGORY_POLICY[category] || CATEGORY_POLICY.standard;
|
|
11
29
|
const model = String(opts.model || process.env.SKS_CODEX_MODEL || process.env.CODEX_MODEL || '').trim();
|
|
12
30
|
const reasoning = opts.lbHealth?.quota_low && policy.reasoning === 'xhigh' ? 'high' : policy.reasoning;
|
|
13
31
|
return { model, reasoning, serviceTier: policy.serviceTier };
|
|
14
32
|
}
|
|
15
|
-
export function
|
|
16
|
-
const
|
|
33
|
+
export function routeNarutoGpt56Model(input = {}) {
|
|
34
|
+
const category = input.category || 'agentic';
|
|
35
|
+
const text = `${category} ${String(input.taskText || '')}`;
|
|
36
|
+
const riskText = `${text} ${String(input.riskText || '')}`;
|
|
37
|
+
const explicit = normalizeNarutoGpt56Model(input.explicitModel);
|
|
38
|
+
const preferred = explicit
|
|
39
|
+
|| (category === 'refactor' || category === 'strategy' || category === 'ultrabrain' || NARUTO_SOL_WORK_RE.test(text)
|
|
40
|
+
? 'gpt-5.6-sol'
|
|
41
|
+
: category === 'e2e' || NARUTO_LUNA_WORK_RE.test(text)
|
|
42
|
+
? 'gpt-5.6-luna'
|
|
43
|
+
: 'gpt-5.6-terra');
|
|
44
|
+
const available = input.availableModels == null
|
|
45
|
+
? [...NARUTO_GPT56_MODELS]
|
|
46
|
+
: input.availableModels.map(normalizeNarutoGpt56Model).filter((model) => Boolean(model));
|
|
47
|
+
const degraded = new Set((input.degradedModels || []).map((model) => String(model).toLowerCase()));
|
|
48
|
+
const usable = available.filter((model) => !degraded.has(model));
|
|
49
|
+
const availableEfforts = input.availableModelEfforts == null ? null : input.availableModelEfforts[preferred] || [];
|
|
50
|
+
const maxWork = NARUTO_MAX_WORK_RE.test(riskText);
|
|
51
|
+
const intendedReasoning = preferred === 'gpt-5.6-sol'
|
|
52
|
+
? 'max'
|
|
53
|
+
: preferred === 'gpt-5.6-luna'
|
|
54
|
+
? maxWork ? 'max' : 'xhigh'
|
|
55
|
+
: preferred === 'gpt-5.6-terra'
|
|
56
|
+
? maxWork || category === 'review' ? 'max' : 'xhigh'
|
|
57
|
+
: 'xhigh';
|
|
58
|
+
const model = usable.includes(preferred) && (availableEfforts == null || availableEfforts.includes(intendedReasoning)) ? preferred : '';
|
|
59
|
+
return { model, reasoning: intendedReasoning, serviceTier: 'fast' };
|
|
60
|
+
}
|
|
61
|
+
export function isNarutoGpt56Model(value) {
|
|
62
|
+
return normalizeNarutoGpt56Model(value) !== null;
|
|
63
|
+
}
|
|
64
|
+
function normalizeNarutoGpt56Model(value) {
|
|
65
|
+
const model = String(value || '').trim().toLowerCase();
|
|
66
|
+
return NARUTO_GPT56_MODELS.includes(model) ? model : null;
|
|
67
|
+
}
|
|
68
|
+
export function categoryForWorkerRole(role, taskText = '') {
|
|
69
|
+
const text = `${String(role || '')} ${String(taskText || '')}`.toLowerCase();
|
|
70
|
+
if (NARUTO_LUNA_WORK_RE.test(text))
|
|
71
|
+
return 'e2e';
|
|
72
|
+
if (/(refactor|re-?architect|리팩터|아키텍처)/i.test(text))
|
|
73
|
+
return 'refactor';
|
|
74
|
+
if (/(planning|\bplan\b|strategy|strategic|기획|전략)/i.test(text))
|
|
75
|
+
return 'strategy';
|
|
17
76
|
if (/verif|test|qa/.test(text))
|
|
18
77
|
return 'verify';
|
|
19
78
|
if (/review|critic|judge/.test(text))
|
|
@@ -28,6 +87,8 @@ export function modelRouteReason(category, choice, opts = {}) {
|
|
|
28
87
|
const model = choice.model || 'codex-selected';
|
|
29
88
|
if (opts.explicit)
|
|
30
89
|
return `${category}->${model} (explicit model preserved)`;
|
|
90
|
+
if (isNarutoGpt56Model(choice.model))
|
|
91
|
+
return `${category}->${model}@${choice.reasoning} (Naruto GPT-5.6 family policy)`;
|
|
31
92
|
const suffix = opts.quotaLow ? 'quota discipline' : 'Codex catalog passthrough';
|
|
32
93
|
return `${category}->${model} (${suffix})`;
|
|
33
94
|
}
|
|
@@ -47,5 +47,5 @@ export const RECOMMENDED_SKILLS = [
|
|
|
47
47
|
// Route-level effort names are scheduling intents, not model compatibility
|
|
48
48
|
// claims. Actual per-model options come from Codex runtime metadata; SKS never
|
|
49
49
|
// derives them from a model slug.
|
|
50
|
-
export const ALLOWED_REASONING_EFFORTS = new Set(['low', 'medium', 'high', 'xhigh', 'ultra']);
|
|
50
|
+
export const ALLOWED_REASONING_EFFORTS = new Set(['low', 'medium', 'high', 'xhigh', 'max', 'ultra']);
|
|
51
51
|
//# sourceMappingURL=constants.js.map
|
|
@@ -3,6 +3,9 @@ export function resolveSksModelMode(args = []) {
|
|
|
3
3
|
const hasGlm = normalized.includes('--glm');
|
|
4
4
|
const hasMad = normalized.includes('--mad') || normalized.includes('--MAD') || normalized.includes('--mad-sks');
|
|
5
5
|
const hasNaruto = normalized.includes('--naruto') || normalized.includes('naruto');
|
|
6
|
+
if (hasGlm && hasNaruto && !hasMad) {
|
|
7
|
+
return decision('classic-naruto', false, true, 'naruto_command_glm_override_forbidden', normalized);
|
|
8
|
+
}
|
|
6
9
|
if (hasGlm && hasNaruto) {
|
|
7
10
|
return decision('glm-naruto', true, false, 'explicit_--glm_with_naruto', normalized);
|
|
8
11
|
}
|
package/dist/core/routes.js
CHANGED
|
@@ -1162,19 +1162,17 @@ export function routeReasoning(route, prompt = '') {
|
|
|
1162
1162
|
return reasoning('medium', 'simple_fulfillment');
|
|
1163
1163
|
}
|
|
1164
1164
|
function narutoRouteReasoning(text = '') {
|
|
1165
|
-
if (/(frontier|autoresearch|novelty|hypothesis|falsify|forensic|from-chat-img
|
|
1166
|
-
return reasoning('
|
|
1167
|
-
|
|
1168
|
-
return reasoning('high', 'naruto_knowledge_safety_or_release_signal');
|
|
1169
|
-
if (/(tmux|zellij|terminal|cli|cmd|warp|tool(?:\s|-)?call|hook|router|routing|pipeline|multi[-\s]?pane|pane|process|config|터미널|라우팅|파이프라인|훅|도구|툴)/i.test(text))
|
|
1170
|
-
return reasoning('medium', 'naruto_tooling_or_runtime_signal');
|
|
1171
|
-
if (/(tiny|simple|small|one[-\s]?line|typo|copy|label|spacing|rename|text|readme|docs?|간단|단순|오타|문구|라벨|간격|색상)/i.test(text))
|
|
1172
|
-
return reasoning('low', 'naruto_simple_bounded_work_signal');
|
|
1173
|
-
return reasoning('medium', 'naruto_default_balanced_reasoning');
|
|
1165
|
+
if (/(frontier|autoresearch|novelty|hypothesis|falsify|forensic|from-chat-img|research|current docs?|library|framework|sdk|api|database|supabase|sql|migration|security|permission|mad|release|publish|deploy|commit|push|architecture|algorithm|strategy|planning|integration|refactor|가설|포렌식|리서치|문서|데이터베이스|마이그레이션|보안|권한|배포|커밋|푸쉬|전략|기획|통합|리팩터)/i.test(text))
|
|
1166
|
+
return reasoning('max', 'naruto_complex_or_high_risk_signal');
|
|
1167
|
+
return reasoning('xhigh', 'naruto_gpt56_baseline');
|
|
1174
1168
|
}
|
|
1175
1169
|
export function reasoningProfileName(effort) {
|
|
1176
1170
|
if (effort === 'low')
|
|
1177
1171
|
return 'sks-task-low';
|
|
1172
|
+
if (effort === 'ultra')
|
|
1173
|
+
return 'sks-research-ultra';
|
|
1174
|
+
if (effort === 'max')
|
|
1175
|
+
return 'sks-research-max';
|
|
1178
1176
|
if (effort === 'xhigh')
|
|
1179
1177
|
return 'sks-research-xhigh';
|
|
1180
1178
|
if (effort === 'high')
|
|
@@ -342,7 +342,7 @@ async function runMenubarRetargetStage(root) {
|
|
|
342
342
|
if (typeof text !== 'string')
|
|
343
343
|
return { ok: true, status: 'ok', actions: ['menubar_action_script_absent'], blockers: [], warnings: [] };
|
|
344
344
|
const desired = path.join(packageRoot(), 'dist', 'bin', 'sks.js');
|
|
345
|
-
const line = `SKS_ENTRY
|
|
345
|
+
const line = `SKS_ENTRY='${desired.replace(/'/g, `'\\''`)}'`;
|
|
346
346
|
const actions = [];
|
|
347
347
|
const next = /^\s*SKS_ENTRY\s*=.*$/m.test(text)
|
|
348
348
|
? text.replace(/^\s*SKS_ENTRY\s*=.*$/m, line)
|
|
@@ -3,6 +3,29 @@ import os from 'node:os';
|
|
|
3
3
|
import path from 'node:path';
|
|
4
4
|
import { ensureDir, nowIso, readJson, writeJsonAtomic } from '../fsx.js';
|
|
5
5
|
export const SKS_UPDATE_NOTICE_SCHEMA = 'sks.update-notice.v1';
|
|
6
|
+
export async function persistSksUpdateNoticeFromVersions(input) {
|
|
7
|
+
const packageName = input.packageName || 'sneakoscope';
|
|
8
|
+
const latestVersion = input.latestVersion || null;
|
|
9
|
+
const updateAvailable = Boolean(latestVersion && compareVersions(latestVersion, input.currentVersion) > 0);
|
|
10
|
+
const notice = {
|
|
11
|
+
schema: SKS_UPDATE_NOTICE_SCHEMA,
|
|
12
|
+
checked_at: nowIso(),
|
|
13
|
+
package_name: packageName,
|
|
14
|
+
current_version: input.currentVersion,
|
|
15
|
+
latest_version: latestVersion,
|
|
16
|
+
update_available: updateAvailable,
|
|
17
|
+
source: input.error ? 'error' : 'cache',
|
|
18
|
+
cache_ttl_ms: 6 * 60 * 60 * 1000,
|
|
19
|
+
message: updateAvailable
|
|
20
|
+
? `SKS ${latestVersion} is available; current ${input.currentVersion}.`
|
|
21
|
+
: `SKS ${input.currentVersion} is current enough.`,
|
|
22
|
+
...(input.error ? { error: input.error } : {})
|
|
23
|
+
};
|
|
24
|
+
const cachePath = path.join(os.homedir(), '.sneakoscope', 'cache', 'update-notice.json');
|
|
25
|
+
await ensureDir(path.dirname(cachePath));
|
|
26
|
+
await writeJsonAtomic(cachePath, notice);
|
|
27
|
+
return notice;
|
|
28
|
+
}
|
|
6
29
|
export async function checkSksUpdateNotice(input = {}) {
|
|
7
30
|
const env = input.env || process.env;
|
|
8
31
|
const packageName = input.packageName || env.SKS_UPDATE_NOTICE_PACKAGE || 'sneakoscope';
|
|
@@ -6,7 +6,7 @@ import { PACKAGE_VERSION, packageRoot, readJson, runProcess, throttleLines, whic
|
|
|
6
6
|
import { createRequestedScopeContract } from './safety/requested-scope-contract.js';
|
|
7
7
|
import { guardedPackageInstall, guardContextForRoute } from './safety/mutation-guard.js';
|
|
8
8
|
import { isUpdateMigrationReceiptCurrent, resolveInstalledSksEntrypoint, runPackageLocalDoctor, writeProjectUpdateMigrationReceipt } from './update/update-migration-state.js';
|
|
9
|
-
import { installSksMenuBar } from './codex-app/sks-menubar.js';
|
|
9
|
+
import { installSksMenuBar, sksMenuBarPaths } from './codex-app/sks-menubar.js';
|
|
10
10
|
import { reconcileSkills } from './init/skills.js';
|
|
11
11
|
import { codexHookTrustDoctor } from './codex-hooks/codex-hook-trust-doctor.js';
|
|
12
12
|
import { readCodexHookActualState } from './codex-hooks/codex-hook-actual-discovery.js';
|
|
@@ -367,7 +367,7 @@ export async function runSksUpdateNow(options = {}) {
|
|
|
367
367
|
migrationCurrent = isUpdateMigrationReceiptCurrent(projectReceipt);
|
|
368
368
|
stage('project_receipt', migrationCurrent, migrationCurrent ? 'current' : 'failed', { root: projectReceiptRoot });
|
|
369
369
|
if (migrationCurrent)
|
|
370
|
-
sksMenuBar = await installUpdateSksMenuBar({ root: projectReceiptRoot, env, stage, quiet: machineOutput });
|
|
370
|
+
sksMenuBar = await installUpdateSksMenuBar({ root: projectReceiptRoot, env, stage, quiet: machineOutput, entrypoint: newBinary });
|
|
371
371
|
await runUpdateGlobalSkillsReconcile(stage, {
|
|
372
372
|
quiet: machineOutput,
|
|
373
373
|
newPackageRoot: newBinary ? path.resolve(path.dirname(newBinary), '..', '..') : null
|
|
@@ -709,18 +709,20 @@ function buildUpdateNowResult(input) {
|
|
|
709
709
|
error: input.error
|
|
710
710
|
};
|
|
711
711
|
}
|
|
712
|
-
async function installUpdateSksMenuBar(input) {
|
|
712
|
+
export async function installUpdateSksMenuBar(input) {
|
|
713
713
|
if (input.env.SKS_UPDATE_SKIP_SKS_MENUBAR === '1') {
|
|
714
714
|
input.stage('sks_menubar', true, 'skipped', { reason: 'SKS_UPDATE_SKIP_SKS_MENUBAR=1' });
|
|
715
715
|
return null;
|
|
716
716
|
}
|
|
717
|
-
const work =
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
717
|
+
const work = (input.entrypoint
|
|
718
|
+
? installSksMenuBarFromEntrypoint(input.entrypoint, input)
|
|
719
|
+
: installSksMenuBar({
|
|
720
|
+
root: input.root,
|
|
721
|
+
apply: true,
|
|
722
|
+
launch: true,
|
|
723
|
+
env: input.env,
|
|
724
|
+
quiet: input.quiet === true
|
|
725
|
+
})).catch((err) => ({
|
|
724
726
|
schema: 'sks.codex-app-sks-menubar.v1',
|
|
725
727
|
ok: false,
|
|
726
728
|
apply: true,
|
|
@@ -753,6 +755,30 @@ async function installUpdateSksMenuBar(input) {
|
|
|
753
755
|
});
|
|
754
756
|
return result;
|
|
755
757
|
}
|
|
758
|
+
async function installSksMenuBarFromEntrypoint(entrypoint, input) {
|
|
759
|
+
const run = await runProcess(process.execPath, [entrypoint, 'menubar', 'install', '--json'], {
|
|
760
|
+
cwd: input.root,
|
|
761
|
+
env: {
|
|
762
|
+
...input.env,
|
|
763
|
+
SKS_DISABLE_UPDATE_CHECK: '1',
|
|
764
|
+
SKS_UPDATE_MIGRATION_GATE_DISABLED: '1'
|
|
765
|
+
},
|
|
766
|
+
timeoutMs: updateDoctorTimeoutMs(input.env),
|
|
767
|
+
maxOutputBytes: 128 * 1024
|
|
768
|
+
});
|
|
769
|
+
const output = String(run.stdout || '').trim();
|
|
770
|
+
let parsed = null;
|
|
771
|
+
try {
|
|
772
|
+
parsed = JSON.parse(output);
|
|
773
|
+
}
|
|
774
|
+
catch {
|
|
775
|
+
parsed = null;
|
|
776
|
+
}
|
|
777
|
+
if (run.code !== 0 || parsed?.schema !== 'sks.codex-app-sks-menubar.v1') {
|
|
778
|
+
throw new Error(String(run.stderr || output || `updated SKS menu bar installer exited ${run.code}`).trim());
|
|
779
|
+
}
|
|
780
|
+
return parsed;
|
|
781
|
+
}
|
|
756
782
|
async function detectNpmGlobalRoot(npmBin, env, opts = {}) {
|
|
757
783
|
const result = await runProcess(npmBin, ['root', '--global', '--silent'], {
|
|
758
784
|
env,
|
|
@@ -820,6 +846,16 @@ async function runFinalUpdateVerification(input) {
|
|
|
820
846
|
detail: `expected ${input.installVersion}, got ${skillsManifest?.version || 'missing'}`,
|
|
821
847
|
remediation: 'Run: sks doctor --fix --yes'
|
|
822
848
|
});
|
|
849
|
+
if (process.platform === 'darwin' && input.env.SKS_UPDATE_SKIP_SKS_MENUBAR !== '1') {
|
|
850
|
+
const menuStampPath = sksMenuBarPaths(home, input.projectReceiptRoot).build_stamp_path;
|
|
851
|
+
const menuStamp = await readJson(menuStampPath, null).catch(() => null);
|
|
852
|
+
verification.push({
|
|
853
|
+
id: 'sks_menubar_version',
|
|
854
|
+
ok: menuStamp?.package_version === input.installVersion,
|
|
855
|
+
detail: `expected ${input.installVersion}, got ${menuStamp?.package_version || 'missing'}`,
|
|
856
|
+
remediation: `Run: ${process.execPath} ${input.newBinary} menubar install --json`
|
|
857
|
+
});
|
|
858
|
+
}
|
|
823
859
|
return verification;
|
|
824
860
|
}
|
|
825
861
|
function verificationError(verification) {
|
package/dist/core/version.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export const PACKAGE_VERSION = '6.0.
|
|
1
|
+
export const PACKAGE_VERSION = '6.0.3';
|
|
2
2
|
//# sourceMappingURL=version.js.map
|
|
@@ -17,7 +17,19 @@ await fs.writeFile(path.join(home, '.codex', 'sks-codex-lb.env'), "export CODEX_
|
|
|
17
17
|
const ready = await codexProviderModelUiStatus({
|
|
18
18
|
home,
|
|
19
19
|
cwd,
|
|
20
|
-
env: { HOME: home, OPENROUTER_API_KEY: 'sk-or-fixture' }
|
|
20
|
+
env: { HOME: home, OPENROUTER_API_KEY: 'sk-or-fixture' },
|
|
21
|
+
codexLbModelCatalog: {
|
|
22
|
+
schema: 'sks.codex-lb-model-catalog.v1',
|
|
23
|
+
ok: true,
|
|
24
|
+
status: 'ready',
|
|
25
|
+
models: ['gpt-5.6-sol', 'gpt-5.6-terra', 'gpt-5.6-luna'],
|
|
26
|
+
model_efforts: {
|
|
27
|
+
'gpt-5.6-sol': ['xhigh', 'max', 'ultra'],
|
|
28
|
+
'gpt-5.6-terra': ['xhigh', 'max', 'ultra'],
|
|
29
|
+
'gpt-5.6-luna': ['xhigh', 'max']
|
|
30
|
+
},
|
|
31
|
+
blockers: []
|
|
32
|
+
}
|
|
21
33
|
});
|
|
22
34
|
const readyText = formatCodexAppStatus(statusFixture(ready));
|
|
23
35
|
const ok = missing.ok === false
|
|
@@ -34,7 +46,10 @@ const ok = missing.ok === false
|
|
|
34
46
|
&& ready.glm.profiles_present.length === GLM_CODEX_CONFIG_REASONING_PROFILES.length
|
|
35
47
|
&& ready.codex_lb.provider_present === true
|
|
36
48
|
&& ready.codex_lb.key_present === true
|
|
37
|
-
&&
|
|
49
|
+
&& ready.codex_lb.model_catalog_ok === true
|
|
50
|
+
&& ready.codex_lb.expected_models_present === true
|
|
51
|
+
&& /Provider UI:\s*config\/catalog ready/.test(readyText)
|
|
52
|
+
&& ready.desktop_picker_verified === false
|
|
38
53
|
&& readyText.includes(`GLM Model: ok ${GLM_52_OPENROUTER_MODEL}`)
|
|
39
54
|
&& /codex-lb Key:\s*configured/.test(readyText)
|
|
40
55
|
&& !JSON.stringify({ missing, ready, missingText, readyText }).includes('sk-codex-lb-fixture');
|
|
@@ -49,7 +49,7 @@ const c7Fixture = await fs.mkdtemp(path.join(os.tmpdir(), 'sks-doctor-fix-c7-'))
|
|
|
49
49
|
const c7Home = path.join(c7Fixture, 'home');
|
|
50
50
|
await fs.mkdir(path.join(c7Fixture, '.codex'), { recursive: true });
|
|
51
51
|
await fs.mkdir(c7Home, { recursive: true });
|
|
52
|
-
await fs.writeFile(path.join(c7Fixture, '.codex', 'config.toml'), '[mcp_servers.context7]\ncommand = "npx"\nargs = ["-y", "@upstash/context7-mcp@latest"]\n');
|
|
52
|
+
await fs.writeFile(path.join(c7Fixture, '.codex', 'config.toml'), '# Sneakoscope managed fixture\n[mcp_servers.context7]\ncommand = "npx"\nargs = ["-y", "@upstash/context7-mcp@latest"]\n');
|
|
53
53
|
const c7Run = runDoctorFix(c7Fixture, c7Home, { SKS_FAKE_CODEX_CONFIG_CONTEXT7_STDIO_CONFLICT: '1' });
|
|
54
54
|
const c7Parsed = parseLastJson(c7Run.stdout || '{}');
|
|
55
55
|
const c7ConfigText = await fs.readFile(path.join(c7Fixture, '.codex', 'config.toml'), 'utf8').catch(() => '');
|
|
@@ -26,9 +26,9 @@ const directCodexConfigWrites = scanDirectCodexConfigWrites();
|
|
|
26
26
|
const commandGateContract = scanCommandGateContract();
|
|
27
27
|
const directMkdtempCalls = scanDirectMkdtempCalls();
|
|
28
28
|
const rustTempdirCalls = scanRustTempdirCalls();
|
|
29
|
-
if (releaseGates.length >
|
|
29
|
+
if (releaseGates.length > 200)
|
|
30
30
|
blockers.push(`release_preset_gate_budget_exceeded:${releaseGates.length}`);
|
|
31
|
-
if (gates.length >
|
|
31
|
+
if (gates.length > 200)
|
|
32
32
|
blockers.push(`release_manifest_gate_budget_exceeded:${gates.length}`);
|
|
33
33
|
if (Object.keys(pkg.scripts || {}).length > 100)
|
|
34
34
|
blockers.push(`package_script_budget_exceeded:${Object.keys(pkg.scripts || {}).length}`);
|
|
@@ -121,7 +121,7 @@ try {
|
|
|
121
121
|
const projectConfigPath = path.join(projectCodexDir, 'config.toml');
|
|
122
122
|
// Machine-local keys/tables (model_provider, [profiles.*]) move out to CODEX_HOME;
|
|
123
123
|
// project-scoped settings (sandbox_mode, [features]) must be PRESERVED in place.
|
|
124
|
-
fs.writeFileSync(projectConfigPath, '
|
|
124
|
+
fs.writeFileSync(projectConfigPath, '# Sneakoscope managed fixture\nmodel_provider = "codex-lb"\nsandbox_mode = "workspace-write"\n\n[features]\nhooks = true\n', 'utf8');
|
|
125
125
|
const result = await policy.splitCodexProjectConfigPolicy(projectRoot, {
|
|
126
126
|
apply: true,
|
|
127
127
|
codexHome: tmpHome2,
|
|
@@ -63,7 +63,8 @@ export function runNativeCliSwarmCheck({ agents, workItems = agents, reportName,
|
|
|
63
63
|
assertGate(result.ok === true, 'native CLI session swarm run must pass', report);
|
|
64
64
|
assertGate(proof.spawned_worker_process_count >= agents, 'spawned native worker process count below requested agents', report);
|
|
65
65
|
assertGate(proof.unique_worker_session_count >= agents, 'unique worker session count below requested agents', report);
|
|
66
|
-
|
|
66
|
+
const expectedSlots = Math.min(agents, Number(proof.target_active_slots || agents));
|
|
67
|
+
assertGate(proof.unique_slot_count >= expectedSlots, 'unique slot count below effective concurrency target', report);
|
|
67
68
|
assertGate(Array.isArray(proof.process_ids) && proof.process_ids.length >= agents, 'process ids missing from native CLI proof', report);
|
|
68
69
|
assertGate(proof.close_report_count >= agents, 'worker close report count below requested agents', report);
|
|
69
70
|
assertGate(noSubagent.ok === true && noSubagent.subagent_events_counted_as_worker_sessions === false, 'no-subagent scaling policy must pass', report);
|
|
@@ -29,31 +29,30 @@ assertGate(fullRoster.max_agents === 100, 'clone roster max_agents must be 100',
|
|
|
29
29
|
// 4) Over-cap is clamped, not crashed.
|
|
30
30
|
const overCap = roster.buildNarutoCloneRoster({ clones: 500, maxAgentCount: schema.MAX_NARUTO_AGENT_COUNT });
|
|
31
31
|
assertGate(overCap.agent_count === 100, 'clones above the ceiling clamp to 100', { agent_count: overCap.agent_count });
|
|
32
|
-
// 4b)
|
|
33
|
-
// A neutral/no-tool prompt yields a low/medium MIX: read-only personas -> low, writers -> medium.
|
|
32
|
+
// 4b) Naruto-only GPT-5.6 family policy. The old low/medium cap is gone.
|
|
34
33
|
const effortRoster = roster.buildNarutoCloneRoster({ clones: 24, prompt: 'review and summarize the current findings', maxAgentCount: schema.MAX_NARUTO_AGENT_COUNT });
|
|
35
34
|
const efforts = new Set(effortRoster.roster.map((row) => row.reasoning_effort));
|
|
36
35
|
const modelTiers = new Set(effortRoster.roster.map((row) => row.model_tier));
|
|
37
36
|
const modelEfforts = new Set(effortRoster.roster.map((row) => row.model_reasoning_effort));
|
|
38
37
|
const tiers = new Set(effortRoster.roster.map((row) => row.service_tier));
|
|
39
38
|
const fastFlags = new Set(effortRoster.roster.map((row) => row.fast_mode));
|
|
40
|
-
assertGate([...efforts].every((
|
|
41
|
-
assertGate(
|
|
42
|
-
assertGate([...modelTiers].every((tier) =>
|
|
43
|
-
assertGate(
|
|
44
|
-
assertGate([...modelEfforts].every((effort) => effort === 'low' || effort === 'medium'), 'ordinary Naruto clone model reasoning must stay low/medium', { modelEfforts: [...modelEfforts] });
|
|
39
|
+
assertGate([...efforts].every((effort) => effort === 'xhigh' || effort === 'max'), 'Naruto clone efforts must use only xhigh/max', { efforts: [...efforts] });
|
|
40
|
+
assertGate([...effortRoster.roster].every((row) => ['gpt-5.6-luna', 'gpt-5.6-terra', 'gpt-5.6-sol'].includes(row.model)), 'Naruto workers must use only the GPT-5.6 trio', { models: [...new Set(effortRoster.roster.map((row) => row.model))] });
|
|
41
|
+
assertGate([...modelTiers].every((tier) => /gpt-5\.6-(?:luna|terra|sol)-(?:xhigh|max)/.test(tier)), 'Naruto model tiers must record exact GPT-5.6 model and effort', { modelTiers: [...modelTiers] });
|
|
42
|
+
assertGate([...modelEfforts].every((effort) => effort === 'xhigh' || effort === 'max'), 'Naruto model reasoning must use xhigh/max', { modelEfforts: [...modelEfforts] });
|
|
45
43
|
assertGate([...tiers].length === 1 && tiers.has('fast'), 'every naruto clone must be fast service tier', { tiers: [...tiers] });
|
|
46
44
|
assertGate([...fastFlags].length === 1 && fastFlags.has(true), 'every naruto clone must have fast_mode=true', { fastFlags: [...fastFlags] });
|
|
47
|
-
// 4c)
|
|
48
|
-
const
|
|
49
|
-
const
|
|
50
|
-
const
|
|
51
|
-
const
|
|
52
|
-
|
|
53
|
-
assertGate(
|
|
54
|
-
assertGate(
|
|
55
|
-
assertGate(
|
|
56
|
-
assertGate(
|
|
45
|
+
// 4c) Deterministic work-kind matrix.
|
|
46
|
+
const coding = effortPolicy.decideNarutoCloneEffort({ persona: { role: 'implementer', naruto_role: 'implementer' }, prompt: 'implement a normal coding feature' });
|
|
47
|
+
const criticalCoding = effortPolicy.decideNarutoCloneEffort({ persona: { role: 'implementer', naruto_role: 'implementer' }, prompt: 'implement a critical security migration' });
|
|
48
|
+
const refactor = effortPolicy.decideNarutoCloneEffort({ persona: { role: 'integrator', naruto_role: 'integrator' }, prompt: 'refactor the architecture and integration plan' });
|
|
49
|
+
const e2e = effortPolicy.decideNarutoCloneEffort({ persona: { role: 'browser e2e verifier', naruto_role: 'verifier' }, prompt: 'run browser e2e tests' });
|
|
50
|
+
const forensicGui = effortPolicy.decideNarutoCloneEffort({ persona: { role: 'Computer Use GUI verifier', naruto_role: 'verifier' }, prompt: 'forensic cross-app failure verification' });
|
|
51
|
+
assertGate(coding.model === 'gpt-5.6-terra' && coding.model_reasoning_effort === 'xhigh', 'ordinary coding must use Terra xhigh', { coding });
|
|
52
|
+
assertGate(criticalCoding.model === 'gpt-5.6-terra' && criticalCoding.model_reasoning_effort === 'max', 'critical coding must use Terra max', { criticalCoding });
|
|
53
|
+
assertGate(refactor.model === 'gpt-5.6-sol' && refactor.model_reasoning_effort === 'max', 'refactor/architecture/integration must use Sol max', { refactor });
|
|
54
|
+
assertGate(e2e.model === 'gpt-5.6-luna' && e2e.model_reasoning_effort === 'xhigh', 'browser E2E must use Luna xhigh', { e2e });
|
|
55
|
+
assertGate(forensicGui.model === 'gpt-5.6-luna' && forensicGui.model_reasoning_effort === 'max', 'forensic Computer Use GUI verification must use Luna max', { forensicGui });
|
|
57
56
|
// 5) System-safe concurrency: never spawn the whole count at once; throttle to host capacity.
|
|
58
57
|
const fakeSafe = roster.systemSafeNarutoConcurrency({ backend: 'fake' });
|
|
59
58
|
const heavySafe = roster.systemSafeNarutoConcurrency({ backend: 'codex-sdk' });
|
|
@@ -91,47 +90,60 @@ const run = spawnSync(process.execPath, [
|
|
|
91
90
|
'--json',
|
|
92
91
|
'--no-open-zellij'
|
|
93
92
|
], { cwd: root, env: childEnv, encoding: 'utf8', timeout: 780000, maxBuffer: 8 * 1024 * 1024 });
|
|
94
|
-
assertGate(run.status === 0, 'sks naruto run must exit 0', { status: run.status, stderr: tail(run.stderr) });
|
|
95
93
|
const parsed = parseJson(run.stdout);
|
|
96
|
-
assertGate(parsed !== null, 'sks naruto run must emit JSON', { stdout: tail(run.stdout) });
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
assertGate(
|
|
100
|
-
assertGate(parsed.
|
|
101
|
-
assertGate(parsed.
|
|
102
|
-
|
|
103
|
-
assertGate(parsed.
|
|
104
|
-
assertGate(parsed.
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
assertGate(
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
assertGate(
|
|
112
|
-
assertGate(
|
|
113
|
-
assertGate(parsed.
|
|
114
|
-
assertGate(
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
assertGate(
|
|
119
|
-
|
|
120
|
-
const
|
|
121
|
-
|
|
122
|
-
assertGate(
|
|
94
|
+
assertGate(parsed !== null, 'sks naruto run must emit JSON', { stdout: tail(run.stdout), stderr: tail(run.stderr) });
|
|
95
|
+
let state = {};
|
|
96
|
+
withMissionRouteClose(parsed, childEnv, () => {
|
|
97
|
+
assertGate(run.status === 0, 'sks naruto run must exit 0', { status: run.status, stderr: tail(run.stderr) });
|
|
98
|
+
assertGate(parsed.ok === true, 'naruto run must be ok', { ok: parsed.ok });
|
|
99
|
+
assertGate(parsed.mode === 'NARUTO' && parsed.jutsu === 'kage_bunshin_no_jutsu', 'naruto run must report NARUTO mode', { mode: parsed.mode, jutsu: parsed.jutsu });
|
|
100
|
+
assertGate(parsed.clones === proofClones, 'clone fan-out must use the requested queued count', { clones: parsed.clones });
|
|
101
|
+
assertGate(parsed.max_clones === 100, 'naruto run must advertise the 100 ceiling', { max_clones: parsed.max_clones });
|
|
102
|
+
assertGate(parsed.proof === 'passed', 'naruto run proof must pass', { proof: parsed.proof });
|
|
103
|
+
// Throttle invariant: active concurrency never exceeds the requested count nor the host cap.
|
|
104
|
+
assertGate(parsed.target_active_slots >= 1 && parsed.target_active_slots <= proofClones, 'active slots must be in [1, clones]', { target_active_slots: parsed.target_active_slots });
|
|
105
|
+
assertGate(parsed.target_active_slots <= fakeSafe.cap, 'active slots must be throttled to the system-safe cap', { target_active_slots: parsed.target_active_slots, cap: fakeSafe.cap });
|
|
106
|
+
assertGate(parsed.target_active_slots <= proofConcurrency && parsed.target_active_slots <= 4, 'release proof must keep Naruto live slots desktop-safe while queued fan-out remains larger', { target_active_slots: parsed.target_active_slots, proofConcurrency });
|
|
107
|
+
// Task 9.1: fan-out (clones) and live concurrency (target_active_slots) are reported
|
|
108
|
+
// distinctly, and concurrency_capped truthfully reflects "N clones, running M at a time".
|
|
109
|
+
assertGate(typeof parsed.concurrency_capped === 'boolean', 'naruto run must report concurrency_capped', { concurrency_capped: parsed.concurrency_capped });
|
|
110
|
+
assertGate(parsed.concurrency_capped === (parsed.clones > parsed.target_active_slots), 'concurrency_capped must reflect clones > live slots', { clones: parsed.clones, target_active_slots: parsed.target_active_slots, concurrency_capped: parsed.concurrency_capped });
|
|
111
|
+
assertGate(parsed.system && Number(parsed.system.safe_concurrency) >= 1, 'naruto run must report system safe_concurrency (host-derived cap)', { system: parsed.system });
|
|
112
|
+
assertGate(parsed.work_graph?.write_allowed_count > 0 && parsed.work_graph?.mixed_work_kinds?.length > 1, 'naruto run must report a mixed work graph with write-capable items', { work_graph: parsed.work_graph });
|
|
113
|
+
assertGate(Number(parsed.work_graph?.parallel_write_wave_count || 0) > 0, 'naruto run must expose at least one parallel write-capable wave with non-overlapping leases', { work_graph: parsed.work_graph });
|
|
114
|
+
assertGate(parsed.role_distribution?.verifier_only === false, 'naruto run proof/status must distinguish active worker roles beyond verifier-only', { role_distribution: parsed.role_distribution });
|
|
115
|
+
assertGate(Number(parsed.role_distribution?.implementation_like_ratio || 0) >= 0.4, 'naruto run must include implementation-like role distribution', { role_distribution: parsed.role_distribution });
|
|
116
|
+
assertGate(parsed.local_worker?.auto_select_eligible === false, 'normal Naruto must never auto-select a local/Ollama backend', { local_worker: parsed.local_worker });
|
|
117
|
+
const commandGraphPath = path.join(root, '.sneakoscope', 'missions', parsed.mission_id, 'agents', 'naruto-work-graph.json');
|
|
118
|
+
const commandGraph = JSON.parse(fs.readFileSync(commandGraphPath, 'utf8'));
|
|
119
|
+
const writePaths = commandGraph.work_items.filter((row) => row.write_allowed).flatMap((row) => row.write_paths);
|
|
120
|
+
assertGate(new Set(writePaths).size > 1, 'naruto command default patch-envelope leases must be per work item, not one shared write path', { sample: writePaths.slice(0, 8), unique: new Set(writePaths).size });
|
|
121
|
+
assertGate(commandGraph.active_waves.some((wave) => wave.write_paths.length > 1), 'naruto command graph must contain a parallel write wave when route-local patch envelopes do not overlap', { waves: commandGraph.active_waves.slice(0, 3) });
|
|
122
|
+
state = parsed.run?.scheduler?.state || parsed.run?.scheduler || {};
|
|
123
|
+
assertGate(Number(state.completed_count) === Number(parsed.work_graph?.total_work_items || 0) && Number(state.completed_count) >= proofClones, 'all clone work items must complete despite throttling', { completed_count: state.completed_count, total_work_items: parsed.work_graph?.total_work_items, proofClones });
|
|
124
|
+
assertGate(parsed.target_active_slots <= 4, 'explicit --concurrency cannot bypass the desktop-safe cap', { target_active_slots: parsed.target_active_slots });
|
|
125
|
+
});
|
|
123
126
|
// 7) A small request is never inflated; live pressure may still reduce it.
|
|
124
127
|
const small = spawnSync(process.execPath, [cli, 'naruto', 'run', 'tiny', '--clones', '2', '--backend', 'fake', '--work-items', '2', '--json', '--no-open-zellij'], { cwd: root, env: childEnv, encoding: 'utf8', timeout: 600000, maxBuffer: 4 * 1024 * 1024 });
|
|
125
128
|
const smallParsed = parseJson(small.stdout);
|
|
126
|
-
|
|
129
|
+
withMissionRouteClose(smallParsed, childEnv, () => {
|
|
130
|
+
assertGate(small.status === 0 && smallParsed?.target_active_slots >= 1 && smallParsed?.target_active_slots <= 2, 'a 2-clone run must stay within [1, 2] active workers', {
|
|
131
|
+
status: small.status,
|
|
132
|
+
target_active_slots: smallParsed?.target_active_slots,
|
|
133
|
+
stdout: tail(small.stdout),
|
|
134
|
+
stderr: tail(small.stderr)
|
|
135
|
+
});
|
|
136
|
+
});
|
|
127
137
|
// 8) Naruto clones always run fast. Per-route --no-fast / standard-tier requests
|
|
128
138
|
// are intentionally not honored for shadow clones.
|
|
129
139
|
const standardOptOut = spawnSync(process.execPath, [cli, 'naruto', 'run', 'fast opt-out ignored', '--clones', '2', '--backend', 'fake', '--work-items', '2', '--no-fast', '--service-tier', 'standard', '--json', '--no-open-zellij'], { cwd: root, env: childEnv, encoding: 'utf8', timeout: 600000, maxBuffer: 4 * 1024 * 1024 });
|
|
130
140
|
const standardOptOutParsed = parseJson(standardOptOut.stdout);
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
141
|
+
withMissionRouteClose(standardOptOutParsed, childEnv, () => {
|
|
142
|
+
assertGate(standardOptOut.status === 0 && standardOptOutParsed?.fast_mode_policy?.fast_mode === true && standardOptOutParsed?.fast_mode_policy?.service_tier === 'fast', 'naruto --no-fast / --service-tier standard must still run clones in fast mode', {
|
|
143
|
+
status: standardOptOut.status,
|
|
144
|
+
fast_mode_policy: standardOptOutParsed?.fast_mode_policy,
|
|
145
|
+
stderr: tail(standardOptOut.stderr)
|
|
146
|
+
});
|
|
135
147
|
});
|
|
136
148
|
emitGate('naruto:shadow-clone-swarm', {
|
|
137
149
|
max_naruto_agent_count: schema.MAX_NARUTO_AGENT_COUNT,
|
|
@@ -162,4 +174,30 @@ function tail(value, limit = 2000) {
|
|
|
162
174
|
const text = String(value || '');
|
|
163
175
|
return text.length <= limit ? text : text.slice(-limit);
|
|
164
176
|
}
|
|
177
|
+
function closeMission(missionId, env) {
|
|
178
|
+
assertGate(Boolean(missionId), 'naruto proof mission id missing before route close', { missionId });
|
|
179
|
+
const closed = spawnSync(process.execPath, [cli, 'route', 'close', '--mission', String(missionId), '--json'], {
|
|
180
|
+
cwd: root,
|
|
181
|
+
env,
|
|
182
|
+
encoding: 'utf8',
|
|
183
|
+
timeout: 30000,
|
|
184
|
+
maxBuffer: 1024 * 1024
|
|
185
|
+
});
|
|
186
|
+
const parsedClose = parseJson(closed.stdout);
|
|
187
|
+
assertGate(closed.status === 0 && parsedClose?.ok === true, 'naruto proof mission route close must succeed', {
|
|
188
|
+
missionId,
|
|
189
|
+
status: closed.status,
|
|
190
|
+
stdout: tail(closed.stdout),
|
|
191
|
+
stderr: tail(closed.stderr)
|
|
192
|
+
});
|
|
193
|
+
}
|
|
194
|
+
function withMissionRouteClose(parsedResult, env, verify) {
|
|
195
|
+
try {
|
|
196
|
+
return verify();
|
|
197
|
+
}
|
|
198
|
+
finally {
|
|
199
|
+
if (parsedResult?.mission_id)
|
|
200
|
+
closeMission(parsedResult.mission_id, env);
|
|
201
|
+
}
|
|
202
|
+
}
|
|
165
203
|
//# sourceMappingURL=naruto-shadow-clone-swarm-check.js.map
|
|
@@ -3,9 +3,10 @@
|
|
|
3
3
|
import fs from 'node:fs';
|
|
4
4
|
import path from 'node:path';
|
|
5
5
|
import { spawnSync } from 'node:child_process';
|
|
6
|
+
import { DEFAULT_MAX_PACK_BYTES } from '../core/release/package-size-budget.js';
|
|
6
7
|
import { assertGate, emitGate, root } from './sks-1-18-gate-lib.js';
|
|
7
8
|
const MAX_FILES = Number(process.env.SKS_MAX_PACK_FILES || 2100);
|
|
8
|
-
const MAX_PACKED = Number(process.env.SKS_MAX_PACK_BYTES ||
|
|
9
|
+
const MAX_PACKED = Number(process.env.SKS_MAX_PACK_BYTES || DEFAULT_MAX_PACK_BYTES);
|
|
9
10
|
const BUDGET_MS = Number(process.env.SKS_PACK_BUDGET_MS || 30000);
|
|
10
11
|
function runNpmPack() {
|
|
11
12
|
const npmCli = process.env.npm_execpath; // set when invoked via `npm run`
|
|
@@ -4,6 +4,7 @@ import fs from 'node:fs';
|
|
|
4
4
|
import os from 'node:os';
|
|
5
5
|
import path from 'node:path';
|
|
6
6
|
import { spawnSync } from 'node:child_process';
|
|
7
|
+
import { DEFAULT_MAX_PACK_BYTES } from '../core/release/package-size-budget.js';
|
|
7
8
|
import { assertGate, emitGate, root } from './sks-1-18-gate-lib.js';
|
|
8
9
|
const MAX_FILES = Number(process.env.SKS_MAX_PACK_FILES || 2100);
|
|
9
10
|
const MAX_UNPACKED = Number(process.env.SKS_MAX_UNPACKED_BYTES || 10 * 1024 * 1024);
|
|
@@ -22,8 +23,10 @@ const MAX_UNPACKED = Number(process.env.SKS_MAX_UNPACKED_BYTES || 10 * 1024 * 10
|
|
|
22
23
|
// checks; keep those scripts publishable because package contract validation
|
|
23
24
|
// rejects scripts that point at files absent from the tarball. 5.12.0 adds ops
|
|
24
25
|
// maturity diagnostics, migration/recovery smokes, and their package-referenced
|
|
25
|
-
// gates, pushing the packed tarball to ~2400 KiB.
|
|
26
|
-
|
|
26
|
+
// gates, pushing the packed tarball to ~2400 KiB. 6.0.3 adds the menu restart
|
|
27
|
+
// lifecycle and Naruto GPT-5.6 routing enforcement, bringing the measured
|
|
28
|
+
// packed size to ~2411 KiB; keep the next 1 KiB boundary as the narrow cap.
|
|
29
|
+
const MAX_PACKED = Number(process.env.SKS_MAX_PACK_BYTES || DEFAULT_MAX_PACK_BYTES);
|
|
27
30
|
const SURFACE_MAX_PACKED = Number(process.env.SKS_PACKAGE_SURFACE_MAX_PACK_BYTES || 25_000_000);
|
|
28
31
|
const SURFACE_MAX_FILES = Number(process.env.SKS_PACKAGE_SURFACE_MAX_FILES || 2500);
|
|
29
32
|
function runNpmPack() {
|