sneakoscope 5.6.0 → 5.7.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.
- package/README.md +1 -1
- package/crates/sks-core/Cargo.lock +1 -1
- package/crates/sks-core/Cargo.toml +1 -1
- package/crates/sks-core/src/main.rs +1 -1
- package/dist/bin/sks.js +1 -1
- package/dist/cli/command-registry.js +1 -1
- package/dist/cli/install-helpers.js +21 -15
- package/dist/commands/doctor.js +44 -22
- package/dist/config/skills-manifest.json +58 -58
- package/dist/core/codex/agent-config-file-repair.js +2 -1
- package/dist/core/codex/codex-config-guard.js +10 -0
- package/dist/core/codex-app/sks-menubar.js +113 -21
- package/dist/core/commands/run-command.js +5 -1
- package/dist/core/commands/wiki-command.js +19 -1
- package/dist/core/feature-fixtures.js +11 -11
- package/dist/core/fsx.js +1 -1
- package/dist/core/hooks-runtime/code-pack-freshness-preflight.js +48 -0
- package/dist/core/hooks-runtime.js +4 -0
- package/dist/core/triwiki-attention.js +16 -8
- package/dist/core/triwiki-wrongness/wrongness-schema.js +18 -1
- package/dist/core/update/update-migration-state.js +178 -33
- package/dist/core/version.js +1 -1
- package/dist/scripts/codex-lb-gpt55-fast-profile-check.js +3 -2
- package/dist/scripts/packlist-performance-check.js +4 -2
- package/dist/scripts/release-metadata-1-19-check.js +12 -1
- package/dist/scripts/sks-menubar-install-check.js +83 -0
- package/package.json +14 -5
|
@@ -8,6 +8,7 @@ import { COMMANDS } from '../../cli/command-registry.js';
|
|
|
8
8
|
import { reconcileSkills } from '../init/skills.js';
|
|
9
9
|
import { codexHookTrustDoctor } from '../codex-hooks/codex-hook-trust-doctor.js';
|
|
10
10
|
import { writeCodexConfigGuarded } from '../codex/codex-config-guard.js';
|
|
11
|
+
import { REQUIRED_CODEX_MODEL } from '../codex-model-guard.js';
|
|
11
12
|
export const UPDATE_MIGRATION_SCHEMA = 'sks.project-migration-receipt.v2';
|
|
12
13
|
export const INSTALLATION_EPOCH_SCHEMA = 'sks.installation-epoch.v1';
|
|
13
14
|
export function installationEpochPath() {
|
|
@@ -343,53 +344,71 @@ async function runMenubarRetargetStage(root) {
|
|
|
343
344
|
return { ok: true, status: 'ok', actions: ['menubar_action_script_absent'], blockers: [], warnings: [] };
|
|
344
345
|
const desired = path.join(packageRoot(), 'dist', 'bin', 'sks.js');
|
|
345
346
|
const line = `SKS_ENTRY=${JSON.stringify(desired)}`;
|
|
347
|
+
const actions = [];
|
|
346
348
|
const next = /^\s*SKS_ENTRY\s*=.*$/m.test(text)
|
|
347
349
|
? text.replace(/^\s*SKS_ENTRY\s*=.*$/m, line)
|
|
348
350
|
: `${line}\n${text}`;
|
|
349
351
|
if (next !== text) {
|
|
350
352
|
await writeTextAtomic(actionScript, next);
|
|
351
|
-
|
|
353
|
+
actions.push('retargeted_menubar_action_script');
|
|
354
|
+
}
|
|
355
|
+
const stat = await fsp.stat(actionScript).catch(() => null);
|
|
356
|
+
if (!stat || (stat.mode & 0o111) === 0) {
|
|
357
|
+
await fsp.chmod(actionScript, 0o755);
|
|
358
|
+
actions.push('restored_menubar_action_executable_bit');
|
|
352
359
|
}
|
|
353
|
-
return {
|
|
360
|
+
return {
|
|
361
|
+
ok: true,
|
|
362
|
+
status: 'ok',
|
|
363
|
+
actions: actions.length ? actions : ['menubar_action_script_current'],
|
|
364
|
+
blockers: [],
|
|
365
|
+
warnings: [],
|
|
366
|
+
detail: { action_script: actionScript }
|
|
367
|
+
};
|
|
354
368
|
}
|
|
355
369
|
async function runConfigFastModeNormalizeStage() {
|
|
356
370
|
const configPath = path.join(os.homedir(), '.codex', 'config.toml');
|
|
357
371
|
const text = await readText(configPath, null);
|
|
358
372
|
if (typeof text !== 'string')
|
|
359
373
|
return { ok: true, status: 'ok', actions: ['codex_config_absent'], blockers: [], warnings: [] };
|
|
360
|
-
const
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
374
|
+
const normalized = normalizeLegacyFastModeConfigForUpdate(text);
|
|
375
|
+
if (normalized.text === ensureTrailingNewline(text)) {
|
|
376
|
+
return {
|
|
377
|
+
ok: true,
|
|
378
|
+
status: 'ok',
|
|
379
|
+
actions: ['fastmode_config_current'],
|
|
380
|
+
blockers: [],
|
|
381
|
+
warnings: [],
|
|
382
|
+
detail: { config_path: configPath, default_profile: normalized.defaultProfile }
|
|
383
|
+
};
|
|
384
|
+
}
|
|
371
385
|
let guardResult = null;
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
};
|
|
390
|
-
}
|
|
386
|
+
guardResult = await writeCodexConfigGuarded({
|
|
387
|
+
configPath,
|
|
388
|
+
before: text,
|
|
389
|
+
mutate: () => normalized.text,
|
|
390
|
+
cause: 'project-update-fastmode-normalize',
|
|
391
|
+
backupTag: 'project-update-fastmode-normalize',
|
|
392
|
+
preserveFastUiKeys: true
|
|
393
|
+
});
|
|
394
|
+
if (!guardResult.ok) {
|
|
395
|
+
return {
|
|
396
|
+
ok: false,
|
|
397
|
+
status: 'failed',
|
|
398
|
+
actions: ['normalize_fastmode_config_blocked'],
|
|
399
|
+
blockers: [`codex_config_guard:${guardResult.status}`],
|
|
400
|
+
warnings: [],
|
|
401
|
+
detail: { config_path: configPath, default_profile: normalized.defaultProfile, guard: guardResult }
|
|
402
|
+
};
|
|
391
403
|
}
|
|
392
|
-
return {
|
|
404
|
+
return {
|
|
405
|
+
ok: true,
|
|
406
|
+
status: 'ok',
|
|
407
|
+
actions: normalized.actions.length ? normalized.actions : ['fastmode_config_current'],
|
|
408
|
+
blockers: [],
|
|
409
|
+
warnings: [],
|
|
410
|
+
detail: { config_path: configPath, default_profile: normalized.defaultProfile, guard: guardResult }
|
|
411
|
+
};
|
|
393
412
|
}
|
|
394
413
|
async function runHookTrustRefreshStage(root) {
|
|
395
414
|
const result = await codexHookTrustDoctor(root, { fix: true, managed: true, actual: true });
|
|
@@ -456,6 +475,132 @@ function insertTopLevelTomlKey(text, line) {
|
|
|
456
475
|
return `${line}\n${raw}`.trim() + '\n';
|
|
457
476
|
return `${raw.slice(0, firstTable).trimEnd()}\n${line}\n\n${raw.slice(firstTable).trimStart()}`.trim() + '\n';
|
|
458
477
|
}
|
|
478
|
+
function normalizeLegacyFastModeConfigForUpdate(text) {
|
|
479
|
+
let next = String(text || '');
|
|
480
|
+
const actions = [];
|
|
481
|
+
const misplaced = tomlTableString(next, 'user.fast_mode', 'default_profile');
|
|
482
|
+
const topLevel = topLevelTomlString(next, 'default_profile');
|
|
483
|
+
if (misplaced) {
|
|
484
|
+
next = removeTomlTableKeyLocal(next, 'user.fast_mode', 'default_profile');
|
|
485
|
+
actions.push('normalized_fastmode_default_profile_location');
|
|
486
|
+
}
|
|
487
|
+
if (topLevel && topLevel !== 'sks-fast-high' && !tomlTableBlock(next, `profiles.${topLevel}`)) {
|
|
488
|
+
next = upsertTopLevelTomlStringLocal(next, 'default_profile', 'sks-fast-high');
|
|
489
|
+
actions.push('retargeted_missing_fastmode_default_profile_target');
|
|
490
|
+
}
|
|
491
|
+
else if (!topLevel && misplaced === 'sks-fast-high') {
|
|
492
|
+
next = insertTopLevelTomlKey(next, `default_profile = ${JSON.stringify(misplaced)}`);
|
|
493
|
+
actions.push('restored_fastmode_top_level_default_profile');
|
|
494
|
+
}
|
|
495
|
+
const beforeUi = next;
|
|
496
|
+
next = upsertTomlTableKeyIfAbsentLocal(next, 'user.fast_mode', 'visible = true');
|
|
497
|
+
next = upsertTomlTableKeyIfAbsentLocal(next, 'user.fast_mode', 'enabled = true');
|
|
498
|
+
if (next !== beforeUi)
|
|
499
|
+
actions.push('ensured_fastmode_ui_visibility');
|
|
500
|
+
const beforeProfile = next;
|
|
501
|
+
next = upsertTomlTableKeyLocal(next, 'profiles.sks-fast-high', `model = "${REQUIRED_CODEX_MODEL}"`);
|
|
502
|
+
next = upsertTomlTableKeyLocal(next, 'profiles.sks-fast-high', 'service_tier = "fast"');
|
|
503
|
+
if (next !== beforeProfile)
|
|
504
|
+
actions.push('normalized_sks_fast_high_profile');
|
|
505
|
+
return { text: ensureTrailingNewline(next), actions, defaultProfile: misplaced || topLevel };
|
|
506
|
+
}
|
|
507
|
+
function tomlTableString(text, table, key) {
|
|
508
|
+
const block = tomlTableBlock(text, table);
|
|
509
|
+
const match = block?.match(new RegExp(`^\\s*${escapeRegExp(key)}\\s*=\\s*"([^"]*)"\\s*$`, 'm'));
|
|
510
|
+
return match?.[1] || null;
|
|
511
|
+
}
|
|
512
|
+
function topLevelTomlString(text, key) {
|
|
513
|
+
const top = String(text || '').slice(0, Math.max(0, String(text || '').search(/^\s*\[/m)));
|
|
514
|
+
const match = top.match(new RegExp(`^\\s*${escapeRegExp(key)}\\s*=\\s*"([^"]*)"\\s*$`, 'm'));
|
|
515
|
+
return match?.[1] || null;
|
|
516
|
+
}
|
|
517
|
+
function tomlTableBlock(text, table) {
|
|
518
|
+
const lines = String(text || '').split(/\r?\n/);
|
|
519
|
+
const start = lines.findIndex((line) => tableHeaderMatches(line, table));
|
|
520
|
+
if (start < 0)
|
|
521
|
+
return null;
|
|
522
|
+
let end = lines.length;
|
|
523
|
+
for (let index = start + 1; index < lines.length; index += 1) {
|
|
524
|
+
if (/^\s*\[[^\]]+\]\s*$/.test(lines[index] || '')) {
|
|
525
|
+
end = index;
|
|
526
|
+
break;
|
|
527
|
+
}
|
|
528
|
+
}
|
|
529
|
+
return lines.slice(start, end).join('\n');
|
|
530
|
+
}
|
|
531
|
+
function removeTomlTableKeyLocal(text, table, key) {
|
|
532
|
+
const lines = String(text || '').split(/\r?\n/);
|
|
533
|
+
let inTable = false;
|
|
534
|
+
const out = [];
|
|
535
|
+
for (const line of lines) {
|
|
536
|
+
if (/^\s*\[[^\]]+\]\s*$/.test(line))
|
|
537
|
+
inTable = tableHeaderMatches(line, table);
|
|
538
|
+
if (inTable && new RegExp(`^\\s*${escapeRegExp(key)}\\s*=`).test(line))
|
|
539
|
+
continue;
|
|
540
|
+
out.push(line);
|
|
541
|
+
}
|
|
542
|
+
return out.join('\n');
|
|
543
|
+
}
|
|
544
|
+
function upsertTomlTableKeyIfAbsentLocal(text, table, line) {
|
|
545
|
+
const key = tomlLineKey(line);
|
|
546
|
+
return tomlTableHasKey(text, table, key) ? text : upsertTomlTableKeyLocal(text, table, line);
|
|
547
|
+
}
|
|
548
|
+
function upsertTomlTableKeyLocal(text, table, line) {
|
|
549
|
+
const raw = String(text || '').trimEnd();
|
|
550
|
+
const key = tomlLineKey(line);
|
|
551
|
+
const lines = raw ? raw.split(/\r?\n/) : [];
|
|
552
|
+
const start = lines.findIndex((candidate) => tableHeaderMatches(candidate, table));
|
|
553
|
+
if (start < 0) {
|
|
554
|
+
return `${raw}${raw ? '\n\n' : ''}[${table}]\n${line}\n`;
|
|
555
|
+
}
|
|
556
|
+
let end = lines.length;
|
|
557
|
+
for (let index = start + 1; index < lines.length; index += 1) {
|
|
558
|
+
if (/^\s*\[[^\]]+\]\s*$/.test(lines[index] || '')) {
|
|
559
|
+
end = index;
|
|
560
|
+
break;
|
|
561
|
+
}
|
|
562
|
+
}
|
|
563
|
+
for (let index = start + 1; index < end; index += 1) {
|
|
564
|
+
if (new RegExp(`^\\s*${escapeRegExp(key)}\\s*=`).test(lines[index] || '')) {
|
|
565
|
+
if (lines[index] === line)
|
|
566
|
+
return `${lines.join('\n')}\n`;
|
|
567
|
+
lines[index] = line;
|
|
568
|
+
return `${lines.join('\n')}\n`;
|
|
569
|
+
}
|
|
570
|
+
}
|
|
571
|
+
lines.splice(end, 0, line);
|
|
572
|
+
return `${lines.join('\n')}\n`;
|
|
573
|
+
}
|
|
574
|
+
function upsertTopLevelTomlStringLocal(text, key, value) {
|
|
575
|
+
const raw = String(text || '').trimEnd();
|
|
576
|
+
const line = `${key} = ${JSON.stringify(value)}`;
|
|
577
|
+
const lines = raw ? raw.split(/\r?\n/) : [];
|
|
578
|
+
const firstTable = lines.findIndex((candidate) => /^\s*\[[^\]]+\]\s*$/.test(candidate || ''));
|
|
579
|
+
const end = firstTable < 0 ? lines.length : firstTable;
|
|
580
|
+
for (let index = 0; index < end; index += 1) {
|
|
581
|
+
if (new RegExp(`^\\s*${escapeRegExp(key)}\\s*=`).test(lines[index] || '')) {
|
|
582
|
+
lines[index] = line;
|
|
583
|
+
return `${lines.join('\n')}\n`;
|
|
584
|
+
}
|
|
585
|
+
}
|
|
586
|
+
return insertTopLevelTomlKey(raw, line);
|
|
587
|
+
}
|
|
588
|
+
function tomlTableHasKey(text, table, key) {
|
|
589
|
+
const block = tomlTableBlock(text, table);
|
|
590
|
+
return Boolean(block && new RegExp(`^\\s*${escapeRegExp(key)}\\s*=`, 'm').test(block));
|
|
591
|
+
}
|
|
592
|
+
function tableHeaderMatches(line, table) {
|
|
593
|
+
return new RegExp(`^\\s*\\[${escapeRegExp(table)}\\]\\s*$`).test(line || '');
|
|
594
|
+
}
|
|
595
|
+
function tomlLineKey(line) {
|
|
596
|
+
return String(line || '').split('=')[0]?.trim() || '';
|
|
597
|
+
}
|
|
598
|
+
function ensureTrailingNewline(text) {
|
|
599
|
+
return `${String(text || '').trim()}\n`;
|
|
600
|
+
}
|
|
601
|
+
function escapeRegExp(value) {
|
|
602
|
+
return String(value || '').replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
603
|
+
}
|
|
459
604
|
export async function ensureCurrentMigrationBeforeCommand(input) {
|
|
460
605
|
const env = input.env || process.env;
|
|
461
606
|
const command = input.command;
|
package/dist/core/version.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export const PACKAGE_VERSION = '5.
|
|
1
|
+
export const PACKAGE_VERSION = '5.7.0';
|
|
2
2
|
//# sourceMappingURL=version.js.map
|
|
@@ -5,6 +5,7 @@ import path from 'node:path';
|
|
|
5
5
|
import { codexFastModeDesktopStatus, codexLbConfigPath, configureCodexLb, ensureGlobalCodexFastModeDuringInstall, releaseCodexLbAuthHold, repairCodexLbAuth } from '../cli/install-helpers.js';
|
|
6
6
|
import { repairCodexConfigStructure, splitCodexProjectConfigPolicy } from '../core/codex/codex-project-config-policy.js';
|
|
7
7
|
import { parseCodexConfigToml, validateCodexConfigRoundTrip } from '../core/codex/codex-config-toml.js';
|
|
8
|
+
import { REQUIRED_CODEX_MODEL } from '../core/codex-model-guard.js';
|
|
8
9
|
const tmp = await fs.mkdtemp(path.join(os.tmpdir(), 'sks-codex-lb-gpt55-fast-'));
|
|
9
10
|
const home = path.join(tmp, 'home');
|
|
10
11
|
const root = path.join(tmp, 'project');
|
|
@@ -44,7 +45,7 @@ await fs.writeFile(projectConfig, [
|
|
|
44
45
|
'enabled = true',
|
|
45
46
|
'',
|
|
46
47
|
'[profiles.sks-fast-high]',
|
|
47
|
-
|
|
48
|
+
`model = "${REQUIRED_CODEX_MODEL}"`,
|
|
48
49
|
'service_tier = "fast"',
|
|
49
50
|
''
|
|
50
51
|
].join('\n'));
|
|
@@ -85,7 +86,7 @@ function assertFastProfile(text, label) {
|
|
|
85
86
|
...validation.blockers,
|
|
86
87
|
...(parsed.default_profile === 'sks-fast-high' ? [] : ['default_profile_not_sks_fast_high']),
|
|
87
88
|
...(parsed.user?.fast_mode?.default_profile === undefined ? [] : ['default_profile_inside_user_fast_mode']),
|
|
88
|
-
...(profile.model ===
|
|
89
|
+
...(profile.model === REQUIRED_CODEX_MODEL ? [] : ['sks_fast_high_model_not_required_codex_model']),
|
|
89
90
|
...(profile.service_tier === 'fast' ? [] : ['sks_fast_high_service_tier_not_fast']),
|
|
90
91
|
...(provider.requires_openai_auth === true ? [] : ['codex_lb_requires_openai_auth_not_true']),
|
|
91
92
|
...(provider.wire_api === 'responses' ? [] : ['codex_lb_wire_api_not_responses']),
|
|
@@ -12,8 +12,10 @@ const MAX_UNPACKED = Number(process.env.SKS_MAX_UNPACKED_BYTES || 10 * 1024 * 10
|
|
|
12
12
|
// (route-success-helpers.ts, seo-command.ts, ppt-command.ts, qa-loop-command.ts,
|
|
13
13
|
// research-command.ts, image-ux-review-command.ts, mad-sks-command.ts,
|
|
14
14
|
// sks-menubar.ts) with genuine new production logic, pushing the packed size
|
|
15
|
-
// to ~2306 KiB.
|
|
16
|
-
|
|
15
|
+
// to ~2306 KiB. 5.7.0 adds doctor/update migration repair coverage and publish
|
|
16
|
+
// contract checks, pushing the packed tarball to ~2345 KiB. Keep a narrow cap
|
|
17
|
+
// rather than giving the package a broad size budget.
|
|
18
|
+
const MAX_PACKED = Number(process.env.SKS_MAX_PACK_BYTES || 2350 * 1024);
|
|
17
19
|
function runNpmPack() {
|
|
18
20
|
const npmCli = process.env.npm_execpath; // set when invoked via `npm run`
|
|
19
21
|
const npmCache = process.env.SKS_RELEASE_NPM_CACHE || path.join(os.tmpdir(), 'sneakoscope-npm-cache');
|
|
@@ -393,7 +393,18 @@ for (const gate of allManifestGates)
|
|
|
393
393
|
assertGate(pkg.bin?.sks === 'dist/bin/sks.js', 'package runtime must use dist/bin/sks.js');
|
|
394
394
|
assertGate(pkg.bin?.sneakoscope === 'dist/bin/sks.js', 'sneakoscope runtime must use dist/bin/sks.js');
|
|
395
395
|
assertGate(!pkg.files?.includes('src'), 'package files must not include src runtime shadows');
|
|
396
|
-
|
|
396
|
+
const publishPrepIgnoreScripts = String(pkg.scripts?.['publish:prep-ignore-scripts'] || '');
|
|
397
|
+
assertGate(!/\bprepublishOnly\b/.test(publishPrepIgnoreScripts), 'publish:prep-ignore-scripts must not depend on npm lifecycle hooks that --ignore-scripts disables', { script: publishPrepIgnoreScripts || null });
|
|
398
|
+
for (const required of [
|
|
399
|
+
'build:incremental',
|
|
400
|
+
'release:version-truth',
|
|
401
|
+
'publish:packlist-performance',
|
|
402
|
+
'package-published-contract-check.js',
|
|
403
|
+
'release-registry-check.js --require-unpublished --require-publish-auth',
|
|
404
|
+
'publish-tag:check'
|
|
405
|
+
]) {
|
|
406
|
+
assertGate(publishPrepIgnoreScripts.includes(required), `publish:prep-ignore-scripts missing lifecycle-disabled publish preflight: ${required}`, { script: publishPrepIgnoreScripts || null });
|
|
407
|
+
}
|
|
397
408
|
assertGate(String(pkg.scripts?.['publish:ignore-scripts'] || '').includes('npm run publish:prep-ignore-scripts'), 'publish:ignore-scripts must run publish:prep-ignore-scripts before npm publish --ignore-scripts', { script: pkg.scripts?.['publish:ignore-scripts'] || null });
|
|
398
409
|
assertGate(String(pkg.scripts?.['publish:ignore-scripts'] || '').includes('--ignore-scripts'), 'publish:ignore-scripts must keep npm lifecycle scripts disabled for the final publish', { script: pkg.scripts?.['publish:ignore-scripts'] || null });
|
|
399
410
|
for (const file of requiredDocs) {
|
|
@@ -27,6 +27,46 @@ const secondResult = await installSksMenuBar({
|
|
|
27
27
|
sksEntry: localEntry,
|
|
28
28
|
env: launchGuardEnv
|
|
29
29
|
});
|
|
30
|
+
if (secondResult.action_script_path)
|
|
31
|
+
await fs.rm(secondResult.action_script_path, { force: true });
|
|
32
|
+
const restoredScriptResult = await installSksMenuBar({
|
|
33
|
+
apply: true,
|
|
34
|
+
launch: true,
|
|
35
|
+
home: temp,
|
|
36
|
+
root: fakeRoot,
|
|
37
|
+
sksEntry: localEntry,
|
|
38
|
+
env: launchGuardEnv
|
|
39
|
+
});
|
|
40
|
+
if (restoredScriptResult.action_script_path) {
|
|
41
|
+
await fs.writeFile(restoredScriptResult.action_script_path, '#!/bin/zsh\necho stale-sks-menubar-action\n', 'utf8');
|
|
42
|
+
}
|
|
43
|
+
const staleScriptMissingEntryResult = await installSksMenuBar({
|
|
44
|
+
apply: true,
|
|
45
|
+
launch: true,
|
|
46
|
+
home: temp,
|
|
47
|
+
root: fakeRoot,
|
|
48
|
+
sksEntry: path.join(fakeRoot, 'dist', 'bin', 'missing-sks.js'),
|
|
49
|
+
env: launchGuardEnv
|
|
50
|
+
});
|
|
51
|
+
const recoveredStaleScriptResult = await installSksMenuBar({
|
|
52
|
+
apply: true,
|
|
53
|
+
launch: true,
|
|
54
|
+
home: temp,
|
|
55
|
+
root: fakeRoot,
|
|
56
|
+
sksEntry: localEntry,
|
|
57
|
+
env: launchGuardEnv
|
|
58
|
+
});
|
|
59
|
+
if (recoveredStaleScriptResult.action_script_path) {
|
|
60
|
+
await fs.chmod(recoveredStaleScriptResult.action_script_path, 0o644);
|
|
61
|
+
}
|
|
62
|
+
const restoredExecutableBitResult = await installSksMenuBar({
|
|
63
|
+
apply: true,
|
|
64
|
+
launch: true,
|
|
65
|
+
home: temp,
|
|
66
|
+
root: fakeRoot,
|
|
67
|
+
sksEntry: localEntry,
|
|
68
|
+
env: launchGuardEnv
|
|
69
|
+
});
|
|
30
70
|
const envHomeResult = await installSksMenuBar({
|
|
31
71
|
apply: true,
|
|
32
72
|
launch: true,
|
|
@@ -55,6 +95,9 @@ const hasVisibleStatusSource = generatedSource.includes('NSStatusItem.variableLe
|
|
|
55
95
|
&& generatedSource.includes('SKS ⋯')
|
|
56
96
|
&& generatedSource.includes('Timer.scheduledTimer(withTimeInterval: 30.0');
|
|
57
97
|
const hasBackgroundReadonlyActions = generatedSource.includes('runSksBackground(["codex-lb", "fast-check"]')
|
|
98
|
+
&& generatedSource.includes('runSksBackground(["fast-mode", "on", "--json"]')
|
|
99
|
+
&& generatedSource.includes('runSksBackground(["fast-mode", "off", "--json"]')
|
|
100
|
+
&& generatedSource.includes('runSksSilent(["fast-mode", "status", "--json"]')
|
|
58
101
|
&& generatedSource.includes('runSksBackground(["update", "check"]')
|
|
59
102
|
&& generatedSource.includes('display notification')
|
|
60
103
|
&& !generatedSource.includes('runSksInTerminal')
|
|
@@ -89,6 +132,21 @@ const hasBuildStamp = buildStampExists
|
|
|
89
132
|
&& result.build_stamp?.codesign_identifier === 'com.sneakoscope.sks-menubar';
|
|
90
133
|
const isIdempotent = secondResult.actions.includes('menubar_up_to_date')
|
|
91
134
|
&& secondResult.build_stamp?.action_script_sha256 === result.build_stamp?.action_script_sha256;
|
|
135
|
+
const restoresMissingActionScript = restoredScriptResult.actions.includes(`wrote ${secondResult.action_script_path}`)
|
|
136
|
+
&& actionScriptExists
|
|
137
|
+
&& restoredScriptResult.build_stamp?.action_script_sha256 === result.build_stamp?.action_script_sha256;
|
|
138
|
+
const blocksStaleActionScriptReuse = staleScriptMissingEntryResult.ok === false
|
|
139
|
+
&& staleScriptMissingEntryResult.blockers.includes('sks_entry_unresolved')
|
|
140
|
+
&& staleScriptMissingEntryResult.warnings.includes('sks_entry_unresolved_stale_action_script_not_reused')
|
|
141
|
+
&& staleScriptMissingEntryResult.target_check?.used_previous_script === false;
|
|
142
|
+
const recoversStaleActionScriptWhenEntryExists = recoveredStaleScriptResult.ok === true
|
|
143
|
+
&& recoveredStaleScriptResult.actions.includes(`wrote ${restoredScriptResult.action_script_path}`)
|
|
144
|
+
&& recoveredStaleScriptResult.build_stamp?.action_script_sha256 === result.build_stamp?.action_script_sha256;
|
|
145
|
+
const restoresExecutableBit = restoredExecutableBitResult.ok === true
|
|
146
|
+
&& restoredExecutableBitResult.actions.includes('menubar_up_to_date')
|
|
147
|
+
&& restoredExecutableBitResult.actions.includes('restored action script executable bit')
|
|
148
|
+
&& actionScriptExists
|
|
149
|
+
&& await isExecutable(result.action_script_path);
|
|
92
150
|
const hasCommandRegistry = commandRegistry.includes('menubar:')
|
|
93
151
|
&& commandRegistry.includes('menubarCommand')
|
|
94
152
|
&& commandRegistry.includes('dist/core/commands/menubar-command.js');
|
|
@@ -102,6 +160,8 @@ const expectedMenuItems = [
|
|
|
102
160
|
'Use ChatGPT OAuth',
|
|
103
161
|
'Set codex-lb Domain and Key',
|
|
104
162
|
'Set OpenRouter Key and GLM Profiles',
|
|
163
|
+
'Fast Mode On',
|
|
164
|
+
'Fast Mode Off',
|
|
105
165
|
'Fast Check',
|
|
106
166
|
'SKS Version Check',
|
|
107
167
|
'Update SKS Now',
|
|
@@ -147,6 +207,10 @@ const darwinOk = cltMissing
|
|
|
147
207
|
&& hasBuildStamp
|
|
148
208
|
&& swiftParse.ok === true
|
|
149
209
|
&& isIdempotent
|
|
210
|
+
&& restoresMissingActionScript
|
|
211
|
+
&& blocksStaleActionScriptReuse
|
|
212
|
+
&& recoversStaleActionScriptWhenEntryExists
|
|
213
|
+
&& restoresExecutableBit
|
|
150
214
|
&& hasCommandRegistry
|
|
151
215
|
&& noLaunchctlSecretSetenv
|
|
152
216
|
&& hasLaunchctlUnsetenv
|
|
@@ -164,6 +228,10 @@ const report = {
|
|
|
164
228
|
env_home_temp: envHomeTemp,
|
|
165
229
|
result,
|
|
166
230
|
second_result: secondResult,
|
|
231
|
+
restored_script_result: restoredScriptResult,
|
|
232
|
+
stale_script_missing_entry_result: staleScriptMissingEntryResult,
|
|
233
|
+
recovered_stale_script_result: recoveredStaleScriptResult,
|
|
234
|
+
restored_executable_bit_result: restoredExecutableBitResult,
|
|
167
235
|
env_home_result: envHomeResult,
|
|
168
236
|
executable_exists: executableExists,
|
|
169
237
|
launch_agent_exists: launchAgentExists,
|
|
@@ -185,6 +253,10 @@ const report = {
|
|
|
185
253
|
has_build_stamp: hasBuildStamp,
|
|
186
254
|
swift_parse: swiftParse,
|
|
187
255
|
is_idempotent: isIdempotent,
|
|
256
|
+
restores_missing_action_script: restoresMissingActionScript,
|
|
257
|
+
blocks_stale_action_script_reuse: blocksStaleActionScriptReuse,
|
|
258
|
+
recovers_stale_action_script_when_entry_exists: recoversStaleActionScriptWhenEntryExists,
|
|
259
|
+
restores_executable_bit: restoresExecutableBit,
|
|
188
260
|
has_command_registry: hasCommandRegistry,
|
|
189
261
|
no_launchctl_secret_setenv: noLaunchctlSecretSetenv,
|
|
190
262
|
has_launchctl_unsetenv: hasLaunchctlUnsetenv,
|
|
@@ -209,6 +281,17 @@ async function exists(file) {
|
|
|
209
281
|
return false;
|
|
210
282
|
}
|
|
211
283
|
}
|
|
284
|
+
async function isExecutable(file) {
|
|
285
|
+
if (!file)
|
|
286
|
+
return false;
|
|
287
|
+
try {
|
|
288
|
+
await fs.access(file, fs.constants.X_OK);
|
|
289
|
+
return true;
|
|
290
|
+
}
|
|
291
|
+
catch {
|
|
292
|
+
return false;
|
|
293
|
+
}
|
|
294
|
+
}
|
|
212
295
|
async function swiftParseSmoke(sourcePath) {
|
|
213
296
|
if (process.platform !== 'darwin')
|
|
214
297
|
return { ok: true, status: 'skipped', reason: 'not_macos' };
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "sneakoscope",
|
|
3
3
|
"displayName": "ㅅㅋㅅ",
|
|
4
|
-
"version": "5.
|
|
4
|
+
"version": "5.7.0",
|
|
5
5
|
"description": "Sneakoscope Codex: fast proof-first Codex trust layer with image-based Voxel TriWiki.",
|
|
6
6
|
"type": "module",
|
|
7
7
|
"homepage": "https://github.com/mandarange/Sneakoscope-Codex#readme",
|
|
@@ -61,19 +61,23 @@
|
|
|
61
61
|
},
|
|
62
62
|
"scripts": {
|
|
63
63
|
"build": "npm run build:clean",
|
|
64
|
+
"prepack": "npm run build",
|
|
64
65
|
"build:clean": "node -e \"const fs=require('fs'); fs.rmSync('dist',{recursive:true,force:true}); fs.rmSync('.sneakoscope/cache/tsbuildinfo',{recursive:true,force:true})\" && tsc -p tsconfig.json && node ./dist/scripts/ensure-bin-executable.js && node ./dist/scripts/build-dist.js",
|
|
65
66
|
"build:incremental": "tsc -p tsconfig.json && node ./dist/scripts/ensure-bin-executable.js && node ./dist/scripts/build-dist.js",
|
|
66
67
|
"test": "node --test --test-concurrency=1 dist/core/__tests__/*.test.js dist/core/proof/__tests__/*.test.js dist/core/stop-gate/__tests__/*.test.js dist/core/commands/__tests__/*.test.js dist/core/dfix/__tests__/*.test.js dist/core/ppt/__tests__/*.test.js dist/core/mad-sks/__tests__/*.test.js dist/core/codex-app/__tests__/*.test.js dist/core/doctor/__tests__/*.test.js dist/cli/__tests__/*.test.js dist/core/triwiki/__tests__/*.test.js dist/core/naruto/__tests__/*.test.js dist/core/agent-bridge/__tests__/*.test.js",
|
|
67
68
|
"selftest:real": "node ./dist/bin/sks.js selftest --real --json",
|
|
68
|
-
"check": "npm run release:check:
|
|
69
|
+
"check": "npm run release:check:confidence",
|
|
69
70
|
"dev:sks": "npm run build:incremental --silent && node ./dist/bin/sks.js",
|
|
70
|
-
"prepublishOnly": "
|
|
71
|
+
"prepublishOnly": "node ./dist/scripts/prepublish-release-check-or-fast.js && node ./dist/scripts/release-check-stamp.js verify && node ./dist/scripts/package-published-contract-check.js && node ./dist/scripts/release-registry-check.js --require-unpublished --require-publish-auth",
|
|
71
72
|
"runtime:no-src-mjs": "node ./dist/scripts/runtime-no-src-mjs-check.js",
|
|
72
73
|
"runtime:ts-source-of-truth": "node ./dist/scripts/runtime-ts-source-of-truth-check.js",
|
|
73
74
|
"architecture:guard": "node ./dist/scripts/architecture-guard-check.js",
|
|
74
75
|
"runtime:dist-parity": "node ./dist/scripts/runtime-dist-parity-check.js",
|
|
75
|
-
"release:check": "npm run release:check:affected
|
|
76
|
+
"release:check": "npm run release:check:affected",
|
|
76
77
|
"release:metadata": "node ./dist/scripts/release-metadata-check.js",
|
|
78
|
+
"release:version-truth": "node ./dist/scripts/release-version-truth-check.js",
|
|
79
|
+
"release:dist-freshness": "node ./dist/scripts/release-dist-freshness-check.js",
|
|
80
|
+
"release:provenance": "node ./dist/scripts/release-provenance-check.js",
|
|
77
81
|
"release:gate-script-parity": "node ./dist/scripts/release-gate-script-parity-check.js",
|
|
78
82
|
"ppt:real-imagegen-wiring": "node ./dist/scripts/ppt-real-imagegen-wiring-check.js",
|
|
79
83
|
"ux-review:run-wires-imagegen": "node ./dist/scripts/ux-review-run-wires-imagegen-check.js",
|
|
@@ -111,6 +115,7 @@
|
|
|
111
115
|
"zellij:layout-valid": "node ./dist/scripts/zellij-layout-valid-check.js",
|
|
112
116
|
"zellij:doctor-readiness": "node ./dist/scripts/zellij-doctor-readiness-check.js",
|
|
113
117
|
"codex:project-config-policy-splitter": "node ./dist/scripts/codex-project-config-policy-splitter-check.js",
|
|
118
|
+
"legacy:upgrade-zero-break": "node ./dist/scripts/legacy-upgrade-matrix-check.js",
|
|
114
119
|
"packcheck": "for d in bin test; do [ -d \"$d\" ] && find \"$d\" -name '*.mjs' -print0; done | xargs -0 -n1 node --check && npm run runtime:no-src-mjs",
|
|
115
120
|
"changelog:check": "node ./dist/scripts/changelog-check.js",
|
|
116
121
|
"cli-entrypoint:check": "node ./dist/scripts/check-cli-entrypoint.js",
|
|
@@ -133,8 +138,12 @@
|
|
|
133
138
|
"release:check:fast": "npm run build:incremental --silent && node ./dist/scripts/release-gate-dag-runner.js --preset fast --changed-since auto --sla 5m && node ./dist/scripts/release-check-stamp.js write",
|
|
134
139
|
"release:check:confidence": "npm run build:incremental --silent && node ./dist/scripts/release-gate-dag-runner.js --preset confidence --changed-since auto --sla 5m && node ./dist/scripts/release-check-stamp.js write",
|
|
135
140
|
"release:check:full": "npm run build:clean --silent && node ./dist/scripts/release-gate-dag-runner.js --preset release --full && node ./dist/scripts/release-gate-dag-runner.js --preset bench --full && node ./dist/scripts/release-check-stamp.js write",
|
|
136
|
-
"publish:
|
|
141
|
+
"publish:packlist-performance": "node ./dist/scripts/packlist-performance-check.js",
|
|
142
|
+
"publish:dry": "npm run publish:prep-ignore-scripts && npm publish --dry-run --ignore-scripts --json",
|
|
143
|
+
"publish:prep-ignore-scripts": "npm run build:incremental --silent && npm run release:version-truth --silent && npm run publish:packlist-performance --silent && node ./dist/scripts/package-published-contract-check.js && node ./dist/scripts/release-registry-check.js --require-unpublished --require-publish-auth && npm run publish-tag:check --silent",
|
|
137
144
|
"publish:ignore-scripts": "npm run publish:prep-ignore-scripts && npm publish --ignore-scripts",
|
|
145
|
+
"publish:npm": "npm run publish:ignore-scripts",
|
|
146
|
+
"release:publish": "npm run publish:ignore-scripts",
|
|
138
147
|
"gates:run": "node ./dist/scripts/release-gate-dag-runner.js",
|
|
139
148
|
"policy:gate-audit": "node ./dist/scripts/gate-policy-audit-check.js"
|
|
140
149
|
},
|