sneakoscope 7.1.0 → 7.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +7 -1
- package/crates/sks-core/Cargo.lock +1 -1
- package/crates/sks-core/Cargo.toml +1 -1
- package/dist/cli/command-manifest-lite.js +1 -1
- package/dist/cli/command-registry.js +1 -1
- package/dist/commands/codex-app.js +28 -1
- package/dist/commands/doctor-profile.js +78 -0
- package/dist/commands/doctor.js +20 -68
- package/dist/config/skills-manifest.json +52 -52
- package/dist/core/agent-bridge/host-capability-runtime.js +34 -23
- package/dist/core/codex-app/codex-model-catalog.js +371 -0
- package/dist/core/codex-app/menubar/constants.js +1 -0
- package/dist/core/codex-app/menubar/installer.js +11 -1
- package/dist/core/codex-app/multi-provider-router-support.js +206 -0
- package/dist/core/codex-app/multi-provider-router.js +317 -0
- package/dist/core/codex-control/codex-app-server-v2-client.js +39 -2
- package/dist/core/codex-runtime/codex-desktop-config-policy.js +2 -0
- package/dist/core/commands/telegram-command.js +224 -108
- package/dist/core/managed-assets/managed-assets-manifest.js +1 -1
- package/dist/core/release/macos-menubar-proof.js +58 -1
- package/dist/core/release/main-push-guard.js +287 -10
- package/dist/core/release/main-push-receipt.js +8 -1
- package/dist/core/release/package-size-budget.js +1 -1
- package/dist/core/release/runtime-script-pack-closure.js +67 -3
- package/dist/core/remote/index.js +2 -0
- package/dist/core/remote/local-worker-client.js +35 -0
- package/dist/core/remote/machine-registry.js +17 -10
- package/dist/core/remote/session-binding.js +153 -0
- package/dist/core/remote/types.js +1 -0
- package/dist/core/remote/worker.js +230 -14
- package/dist/core/routes.js +1 -1
- package/dist/core/subagents/official-subagent-preparation.js +37 -1
- package/dist/core/subagents/official-subagent-prompt.js +4 -2
- package/dist/core/subagents/official-subagent-runner.js +5 -0
- package/dist/core/subagents/role-model-preferences.js +176 -40
- package/dist/core/telegram/config.js +28 -9
- package/dist/core/telegram/hub.js +8 -2
- package/dist/core/telegram/index.js +2 -0
- package/dist/core/telegram/messages.js +8 -2
- package/dist/core/telegram/runtime-projection.js +6 -2
- package/dist/core/telegram/runtime.js +19 -9
- package/dist/core/telegram/service.js +181 -0
- package/dist/core/telegram/setup.js +220 -0
- package/dist/core/update-check.js +13 -5
- package/dist/core/version.js +1 -1
- package/dist/native/sks-menubar/Sources/ControlCenterWindowController.swift +1 -1
- package/dist/native/sks-menubar/Sources/ProcessClient.swift +1 -1
- package/dist/native/sks-menubar/Sources/ProvidersMultiProvider.swift +271 -0
- package/dist/native/sks-menubar/Sources/ProvidersOpenRouter.swift +14 -3
- package/dist/native/sks-menubar/Sources/ProvidersViewController.swift +4 -1
- package/dist/native/sks-menubar/Sources/RemoteTelegramViewController.swift +157 -50
- package/dist/native/sks-menubar/Sources/UpdatesViewController.swift +4 -1
- package/dist/scripts/postinstall-global-doctor-blackbox.js +10 -0
- package/dist/scripts/release-macos-menubar-proof.js +38 -3
- package/dist/scripts/release-provenance-check.js +3 -1
- package/package.json +3 -1
- package/runtime-required-scripts.json +9 -0
package/README.md
CHANGED
|
@@ -22,7 +22,7 @@ Proof-first orchestration for Codex CLI, ChatGPT Desktop, AI coding agents, mult
|
|
|
22
22
|
Sneakoscope Codex (`sks`) is an open-source trust layer for Codex CLI and ChatGPT Desktop. It coordinates bounded AI coding agents, records machine-verifiable evidence, preserves project memory, and blocks release claims that are not supported by current tests or artifacts. Search visibility outcomes are measured separately; SKS does not promise rankings or traffic.
|
|
23
23
|
<!-- END SKS SEARCH VISIBILITY MARKETING -->
|
|
24
24
|
|
|
25
|
-
Current release: **SKS 7.1.
|
|
25
|
+
Current release: **SKS 7.1.1**, with the package preferred Codex channel at **CLI 0.145.0**. SKS stays version-agnostic: older hosts keep working where capabilities allow, while Menu Bar / Center induce updates to the preferred latest. It resolves managed SKS skills from the authoritative global install, preserves a runnable Naruto child slot when `max_threads=2`, and keeps current-version Menu Bar repair transactional so stamped generations remain verifiable. Naruto uses stable opt-in multi-agent V2 when the host exposes it. See [CHANGELOG.md](CHANGELOG.md).
|
|
26
26
|
|
|
27
27
|
## What 7.0.0 Ships
|
|
28
28
|
|
|
@@ -54,6 +54,12 @@ The SKS menu bar shows the installed Codex CLI version and latest known version.
|
|
|
54
54
|
|
|
55
55
|
**Manage MCP Servers…** opens a native macOS manager for the global `~/.codex/config.toml`. It can add remote URL or local stdio servers, enable/disable existing entries, remove entries after confirmation, and refresh the current state. Mutations are lock-protected, backed up, TOML-validated, and written with mode `0600`; configured environment values and command arguments are never rendered in the list. Changes apply to new Codex sessions. The same plumbing is available through the canonical `sks mcp config list|get|add|edit|duplicate|enable|disable|remove|test|login|logout|backups|restore` surface for diagnostics and automation.
|
|
56
56
|
|
|
57
|
+
### Telegram remote coding on this Mac
|
|
58
|
+
|
|
59
|
+
Open **SKS Center → Remote & Telegram**, create a private bot with BotFather, send `/start` to that bot from the Telegram account you want to pair, then choose **Connect Bot & Register Coding Session…** and paste the token. SKS verifies the bot, stores the token only in macOS Keychain, pairs only that private chat/user, and registers one dedicated session bound to the current project. Choose **Start Hub**, then send ordinary text to the bot. On the first real message, the Hub creates the Codex thread and starts its first turn in the same App Server connection so the thread is durably resumable; later messages resume that exact thread and return the final response to Telegram.
|
|
60
|
+
|
|
61
|
+
The Hub runs as a user LaunchAgent and uses `caffeinate -i` while the logged-in Mac is available. The Mac still needs to remain powered on, logged in, awake, and network-connected; closing the lid or logging out can stop access. Telegram input has no arbitrary shell path, runs with approvals disabled and network access disabled inside the Codex workspace sandbox, and cannot target an unpaired chat or another project.
|
|
62
|
+
|
|
57
63
|
## The Front Door
|
|
58
64
|
|
|
59
65
|
| Command | What it does |
|
|
@@ -36,7 +36,7 @@ export const COMMAND_MANIFEST_LITE = [
|
|
|
36
36
|
{ name: 'codex-lb', summary: 'Inspect codex-lb status and circuit health', maturity: 'beta' },
|
|
37
37
|
{ name: 'menubar', summary: 'Inspect/install/restart/uninstall SKS menu bar', maturity: 'beta', skipMigrationGate: true, allowedDuringActiveRoute: true, diagnostic: true },
|
|
38
38
|
{ name: 'remote', summary: 'Inspect official Remote readiness and run the proof-aware SSH stdio worker', maturity: 'beta' },
|
|
39
|
-
{ name: 'telegram', summary: '
|
|
39
|
+
{ name: 'telegram', summary: 'Pair and run the private local Codex Telegram Hub', maturity: 'beta' },
|
|
40
40
|
{ name: 'hooks', summary: 'Explain and inspect Codex hooks', maturity: 'beta', skipMigrationGate: true },
|
|
41
41
|
{ name: 'zellij-lane', summary: 'Render a Zellij lane frame for SKS sessions', maturity: 'beta' },
|
|
42
42
|
{ name: 'zellij-slot-pane', summary: 'Render a compact Zellij worker slot pane', maturity: 'beta' },
|
|
@@ -155,7 +155,7 @@ const COMMAND_DEFINITIONS = {
|
|
|
155
155
|
'codex-lb': entry('beta', 'Inspect codex-lb status and circuit health', 'dist/commands/codex-lb.js', directCommand(() => import('../commands/codex-lb.js'), 'dist/commands/codex-lb.js')),
|
|
156
156
|
menubar: activeRouteDiagnostic(entry('beta', 'Inspect/install/restart/uninstall SKS menu bar', 'dist/core/commands/menubar-command.js', subcommand(() => import('../core/commands/menubar-command.js'), 'menubarCommand', 'dist/core/commands/menubar-command.js', 'status'))),
|
|
157
157
|
remote: entry('beta', 'Inspect official Remote readiness and run the proof-aware SSH stdio worker', 'dist/core/commands/remote-command.js', argsCommand(() => import('../core/commands/remote-command.js'), 'remoteCommand', 'dist/core/commands/remote-command.js')),
|
|
158
|
-
telegram: entry('beta', '
|
|
158
|
+
telegram: entry('beta', 'Pair and run the private local Codex Telegram Hub', 'dist/core/commands/telegram-command.js', argsCommand(() => import('../core/commands/telegram-command.js'), 'telegramCommand', 'dist/core/commands/telegram-command.js')),
|
|
159
159
|
hooks: skipMigrationGate(entry('beta', 'Explain and inspect Codex hooks', 'dist/commands/hooks.js', directCommand(() => import('../commands/hooks.js'), 'dist/commands/hooks.js'))),
|
|
160
160
|
'zellij-lane': entry('beta', 'Render a Zellij lane frame for SKS sessions', 'dist/commands/zellij-lane.js', directCommand(() => import('../commands/zellij-lane.js'), 'dist/commands/zellij-lane.js')),
|
|
161
161
|
'zellij-slot-pane': entry('beta', 'Render a compact Zellij worker slot pane', 'dist/commands/zellij-slot-pane.js', directCommand(() => import('../commands/zellij-slot-pane.js'), 'dist/commands/zellij-slot-pane.js')),
|
|
@@ -16,6 +16,7 @@ import { OPENROUTER_DEFAULT_MODEL } from '../core/codex-app/openrouter-provider.
|
|
|
16
16
|
import { promptForOpenRouterKeyHidden, writeStoredOpenRouterKey } from '../core/providers/openrouter/openrouter-secret-store.js';
|
|
17
17
|
import { compactOpenRouterModelsResult, listOpenRouterModels, testOpenRouterConnection } from '../core/providers/openrouter/openrouter-account.js';
|
|
18
18
|
import { restartCodexApp } from '../core/codex-app/codex-app-restart.js';
|
|
19
|
+
import { MULTI_PROVIDER_ROUTER_DEFAULT_BASE_URL, multiProviderRouterStatus, testMultiProviderRouter, useMultiProviderRouter } from '../core/codex-app/multi-provider-router.js';
|
|
19
20
|
import { resetRoleModelPreference, roleModelPreferencesStatus, setRoleModelPreference } from '../core/subagents/role-model-preferences.js';
|
|
20
21
|
export async function run(_command, args = []) {
|
|
21
22
|
const action = args[0] || 'check';
|
|
@@ -93,12 +94,38 @@ export async function run(_command, args = []) {
|
|
|
93
94
|
const result = await testOpenRouterConnection({ model: readOption(args, '--model', '') });
|
|
94
95
|
return printCodexAppResult(args, result);
|
|
95
96
|
}
|
|
97
|
+
if (action === 'router-status' || action === 'multi-provider-status' || action === 'opencodex-status') {
|
|
98
|
+
const result = await multiProviderRouterStatus({
|
|
99
|
+
baseUrl: readOption(args, '--base-url', ''),
|
|
100
|
+
catalogPath: readOption(args, '--catalog', '')
|
|
101
|
+
});
|
|
102
|
+
return printCodexAppResult(args, result);
|
|
103
|
+
}
|
|
104
|
+
if (action === 'router-test' || action === 'multi-provider-test' || action === 'opencodex-test') {
|
|
105
|
+
const result = await testMultiProviderRouter({
|
|
106
|
+
baseUrl: readOption(args, '--base-url', MULTI_PROVIDER_ROUTER_DEFAULT_BASE_URL),
|
|
107
|
+
catalogPath: readOption(args, '--catalog', ''),
|
|
108
|
+
model: readOption(args, '--model', '')
|
|
109
|
+
});
|
|
110
|
+
return printCodexAppResult(args, result);
|
|
111
|
+
}
|
|
112
|
+
if (action === 'use-router' || action === 'use-multi-provider' || action === 'use-opencodex') {
|
|
113
|
+
const result = await useMultiProviderRouter({
|
|
114
|
+
model: readOption(args, '--model', ''),
|
|
115
|
+
baseUrl: readOption(args, '--base-url', MULTI_PROVIDER_ROUTER_DEFAULT_BASE_URL),
|
|
116
|
+
catalogPath: readOption(args, '--catalog', ''),
|
|
117
|
+
replaceCatalog: flag(args, '--replace-catalog'),
|
|
118
|
+
restartApp: flag(args, '--restart-app') || flag(args, '--restart') || !flag(args, '--no-restart-app')
|
|
119
|
+
});
|
|
120
|
+
return printCodexAppResult(args, result);
|
|
121
|
+
}
|
|
96
122
|
if (action === 'role-models') {
|
|
97
123
|
return printCodexAppResult(args, await roleModelPreferencesStatus());
|
|
98
124
|
}
|
|
99
125
|
if (action === 'set-role-model') {
|
|
100
126
|
const result = await setRoleModelPreference({
|
|
101
127
|
role: readOption(args, '--role', ''),
|
|
128
|
+
provider: readOption(args, '--provider', ''),
|
|
102
129
|
model: readOption(args, '--model', ''),
|
|
103
130
|
reasoning: readOption(args, '--reasoning', '')
|
|
104
131
|
});
|
|
@@ -168,7 +195,7 @@ export async function run(_command, args = []) {
|
|
|
168
195
|
process.exitCode = 1;
|
|
169
196
|
return;
|
|
170
197
|
}
|
|
171
|
-
console.error('Usage: sks codex-app check|status|harness-matrix|skill-sync|agent-role-sync|init-deep|hook-lifecycle|execution-profile|set-openrouter-key [--api-key-stdin]|use-openrouter --model <id>|openrouter-status|openrouter-models [--ids-only]|openrouter-test [--model <id>]|role-models|set-role-model --role <name> --
|
|
198
|
+
console.error('Usage: sks codex-app check|status|harness-matrix|skill-sync|agent-role-sync|init-deep|hook-lifecycle|execution-profile|set-openrouter-key [--api-key-stdin]|use-openrouter --model <id>|openrouter-status|openrouter-models [--ids-only]|openrouter-test [--model <id>]|router-status [--base-url <loopback-url>] [--catalog <path>]|router-test --model <provider/model> [--base-url <loopback-url>] [--catalog <path>]|use-router --model <provider/model> [--base-url <loopback-url>] [--catalog <path>] [--replace-catalog]|role-models|set-role-model --role <name> [--provider <id>] --model <catalog-slug> --reasoning <effort>|reset-role-model --role <name>|product-design [--check-only]|ensure-product-design|chrome-extension|pat status|remote-control [--json]');
|
|
172
199
|
console.error('Note: glm-profile is retired (strips leftover Desktop GLM profiles); use set-openrouter-key / use-openrouter.');
|
|
173
200
|
process.exitCode = 1;
|
|
174
201
|
}
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import { flag } from '../cli/args.js';
|
|
2
|
+
import { sksMenuBarRestartDeferred } from '../core/codex-app/sks-menubar.js';
|
|
3
|
+
export function doctorProfileFromArgs(args = [], doctorFix = false) {
|
|
4
|
+
const explicit = readOption(args, '--profile');
|
|
5
|
+
if (isDoctorProfile(explicit))
|
|
6
|
+
return explicit;
|
|
7
|
+
if (flag(args, '--full'))
|
|
8
|
+
return 'full';
|
|
9
|
+
if (flag(args, '--capabilities'))
|
|
10
|
+
return 'capabilities';
|
|
11
|
+
return doctorFix ? 'fix' : 'fast';
|
|
12
|
+
}
|
|
13
|
+
export function doctorArgWarnings(args = []) {
|
|
14
|
+
const warnings = [];
|
|
15
|
+
const explicit = readOption(args, '--profile');
|
|
16
|
+
if (explicit && !isDoctorProfile(explicit)) {
|
|
17
|
+
warnings.push(`unknown_profile:${explicit}; supported profiles: migration, full, capabilities, fast, fix`);
|
|
18
|
+
}
|
|
19
|
+
for (const value of unknownDoctorFlags(args))
|
|
20
|
+
warnings.push(`unknown_flag:${value}`);
|
|
21
|
+
return warnings;
|
|
22
|
+
}
|
|
23
|
+
export function doctorMenuBarInstallPolicy(args = [], doctorFix = false, env = process.env) {
|
|
24
|
+
const profile = doctorProfileFromArgs(args, doctorFix);
|
|
25
|
+
const phaseEnabled = doctorPhaseIdsForProfile(profile).includes('sks_menubar');
|
|
26
|
+
const apply = doctorFix && phaseEnabled;
|
|
27
|
+
return {
|
|
28
|
+
profile,
|
|
29
|
+
phase_enabled: phaseEnabled,
|
|
30
|
+
apply,
|
|
31
|
+
launch: apply && !sksMenuBarRestartDeferred(env)
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
export function doctorPhaseIdsForProfile(profile) {
|
|
35
|
+
const required = [
|
|
36
|
+
'codex_startup_repair',
|
|
37
|
+
'startup_config_repair',
|
|
38
|
+
'context7_repair',
|
|
39
|
+
'context7_mcp_repair',
|
|
40
|
+
'hook_trust_repair',
|
|
41
|
+
'command_alias_cleanup'
|
|
42
|
+
];
|
|
43
|
+
if (profile === 'migration')
|
|
44
|
+
return required;
|
|
45
|
+
const optional = ['supabase_mcp_repair', 'native_capability_repair', 'sks_menubar'];
|
|
46
|
+
if (profile === 'full' || profile === 'capabilities')
|
|
47
|
+
return ['setup', ...required, ...optional];
|
|
48
|
+
return [...required, ...optional];
|
|
49
|
+
}
|
|
50
|
+
function unknownDoctorFlags(args) {
|
|
51
|
+
const knownBoolean = new Set([
|
|
52
|
+
'--fix', '--yes', '-y', '--machine-only', '--actual-codex', '--require-actual-codex',
|
|
53
|
+
'--full', '--capabilities', '--repair-codex-app-ui', '--repair-zellij', '--install-homebrew',
|
|
54
|
+
'--repair-native-capabilities', '--repair-codex-native', '--local-only', '--global-only', '--project', '--global',
|
|
55
|
+
'--dry-run', '--json'
|
|
56
|
+
]);
|
|
57
|
+
const knownValue = new Set(['--profile', '--report-file', '--codex-bin', '--install-scope']);
|
|
58
|
+
const unknown = [];
|
|
59
|
+
for (let index = 0; index < args.length; index += 1) {
|
|
60
|
+
const arg = String(args[index] || '');
|
|
61
|
+
if (!arg.startsWith('-'))
|
|
62
|
+
continue;
|
|
63
|
+
if (knownValue.has(arg)) {
|
|
64
|
+
index += 1;
|
|
65
|
+
continue;
|
|
66
|
+
}
|
|
67
|
+
if (!knownBoolean.has(arg))
|
|
68
|
+
unknown.push(arg);
|
|
69
|
+
}
|
|
70
|
+
return unknown;
|
|
71
|
+
}
|
|
72
|
+
function isDoctorProfile(value) {
|
|
73
|
+
return ['migration', 'full', 'capabilities', 'fast', 'fix'].includes(String(value || ''));
|
|
74
|
+
}
|
|
75
|
+
function readOption(args, name) {
|
|
76
|
+
const index = args.indexOf(name);
|
|
77
|
+
return index >= 0 && args[index + 1] ? String(args[index + 1]) : null;
|
|
78
|
+
}
|
package/dist/commands/doctor.js
CHANGED
|
@@ -25,11 +25,13 @@ import { buildCodexNativeFeatureMatrix } from '../core/codex-native/codex-native
|
|
|
25
25
|
import { withSecretPreservationGuard } from '../core/config/config-migration-journal.js';
|
|
26
26
|
import { reconcileDoctorSkills } from '../core/doctor/doctor-skill-reconcile.js';
|
|
27
27
|
import { isUpdateMigrationReceiptCurrent, projectUpdateMigrationReceiptPath, writeProjectUpdateMigrationReceipt } from '../core/update/update-migration-state.js';
|
|
28
|
-
import { inspectSksMenuBarStatus, installSksMenuBar } from '../core/codex-app/sks-menubar.js';
|
|
28
|
+
import { inspectSksMenuBarStatus, installSksMenuBar, sksMenuBarRestartDeferred } from '../core/codex-app/sks-menubar.js';
|
|
29
29
|
import { sweepSksTempDirs } from '../core/retention.js';
|
|
30
30
|
import { detectImagegenCapability } from '../core/imagegen/imagegen-capability.js';
|
|
31
31
|
import { CURRENT_CODEX_RELEASE_MANIFEST } from '../core/codex-compat/codex-release-manifest.js';
|
|
32
32
|
import { formatHarnessConflictReport, scanHarnessConflicts } from '../core/harness-conflicts.js';
|
|
33
|
+
import { doctorArgWarnings, doctorMenuBarInstallPolicy, doctorPhaseIdsForProfile, doctorProfileFromArgs } from './doctor-profile.js';
|
|
34
|
+
export { doctorArgWarnings, doctorMenuBarInstallPolicy, doctorProfileFromArgs } from './doctor-profile.js';
|
|
33
35
|
export async function run(_command, args = [], deps = {}) {
|
|
34
36
|
const root = await projectRoot();
|
|
35
37
|
const doctorFix = flag(args, '--fix');
|
|
@@ -88,6 +90,9 @@ export async function executeDoctorGlobalOnlyFix(args = [], root, deps = {}) {
|
|
|
88
90
|
|| (await import('../cli/install-helpers.js')).ensureStoredOpenRouterProviderDuringInstall;
|
|
89
91
|
const installMenuBarImpl = deps.installSksMenuBarImpl || installSksMenuBar;
|
|
90
92
|
const codexLbStatusImpl = deps.codexLbStatusImpl || codexLbStatus;
|
|
93
|
+
const doctorEnv = deps.env || (deps.home
|
|
94
|
+
? { ...process.env, HOME: home }
|
|
95
|
+
: process.env);
|
|
91
96
|
const providerStatus = await codexLbStatusImpl({
|
|
92
97
|
probeToolOutputRecovery: true,
|
|
93
98
|
allowUnverifiedToolOutputRecovery: codexLbToolOutputRecoveryOverrideAcknowledged({ args })
|
|
@@ -128,9 +133,11 @@ export async function executeDoctorGlobalOnlyFix(args = [], root, deps = {}) {
|
|
|
128
133
|
status: 'failed',
|
|
129
134
|
error: err?.message || String(err)
|
|
130
135
|
}));
|
|
131
|
-
const openRouterEnv =
|
|
132
|
-
|
|
133
|
-
|
|
136
|
+
const openRouterEnv = {
|
|
137
|
+
...doctorEnv,
|
|
138
|
+
HOME: home,
|
|
139
|
+
SKS_HOME: path.join(home, '.sneakoscope')
|
|
140
|
+
};
|
|
134
141
|
const openRouterProvider = await ensureStoredOpenRouterProviderImpl({ home, env: openRouterEnv }).catch((err) => ({
|
|
135
142
|
schema: 'sks.openrouter-provider-upgrade-repair.v1',
|
|
136
143
|
ok: false,
|
|
@@ -142,7 +149,8 @@ export async function executeDoctorGlobalOnlyFix(args = [], root, deps = {}) {
|
|
|
142
149
|
home,
|
|
143
150
|
root: home,
|
|
144
151
|
apply: true,
|
|
145
|
-
launch:
|
|
152
|
+
launch: !sksMenuBarRestartDeferred(doctorEnv),
|
|
153
|
+
env: doctorEnv,
|
|
146
154
|
quiet: flag(args, '--json') || flag(args, '--machine-only')
|
|
147
155
|
}).catch((err) => ({
|
|
148
156
|
schema: 'sks.codex-app-sks-menubar.v1',
|
|
@@ -674,15 +682,18 @@ async function runDoctor(args = [], root, doctorFix) {
|
|
|
674
682
|
blockers: [err?.message || String(err)]
|
|
675
683
|
}))
|
|
676
684
|
: codexAppUiPlan;
|
|
685
|
+
const menuBarPolicy = doctorMenuBarInstallPolicy(args, doctorFix, process.env);
|
|
686
|
+
const menuBarLaunchRequested = menuBarPolicy.launch;
|
|
677
687
|
const sksMenuBar = await installSksMenuBar({
|
|
678
688
|
root,
|
|
679
|
-
apply:
|
|
680
|
-
launch:
|
|
689
|
+
apply: menuBarPolicy.apply,
|
|
690
|
+
launch: menuBarLaunchRequested,
|
|
691
|
+
env: process.env,
|
|
681
692
|
quiet: machineOnly || flag(args, '--json')
|
|
682
693
|
}).catch((err) => ({
|
|
683
694
|
schema: 'sks.codex-app-sks-menubar.v1',
|
|
684
695
|
ok: false,
|
|
685
|
-
apply:
|
|
696
|
+
apply: menuBarPolicy.apply,
|
|
686
697
|
status: 'blocked',
|
|
687
698
|
platform: process.platform,
|
|
688
699
|
app_path: null,
|
|
@@ -693,7 +704,7 @@ async function runDoctor(args = [], root, doctorFix) {
|
|
|
693
704
|
report_path: `${root}/.sneakoscope/reports/sks-menubar.json`,
|
|
694
705
|
menu_items: [],
|
|
695
706
|
actions: [],
|
|
696
|
-
launch: { requested:
|
|
707
|
+
launch: { requested: menuBarLaunchRequested, method: 'none', ok: false, error: err?.message || String(err) },
|
|
697
708
|
tcc_automation_status: 'unknown',
|
|
698
709
|
next_actions: [
|
|
699
710
|
'Run: sks menubar status',
|
|
@@ -1708,65 +1719,6 @@ function fallbackCodexNativeFeatureMatrix(codex, blockers = [], warnings = []) {
|
|
|
1708
1719
|
warnings
|
|
1709
1720
|
};
|
|
1710
1721
|
}
|
|
1711
|
-
export function doctorProfileFromArgs(args = [], doctorFix = false) {
|
|
1712
|
-
const explicit = readOption(args, '--profile', null);
|
|
1713
|
-
if (explicit === 'migration' || explicit === 'full' || explicit === 'capabilities' || explicit === 'fast' || explicit === 'fix')
|
|
1714
|
-
return explicit;
|
|
1715
|
-
if (flag(args, '--full'))
|
|
1716
|
-
return 'full';
|
|
1717
|
-
if (flag(args, '--capabilities'))
|
|
1718
|
-
return 'capabilities';
|
|
1719
|
-
return doctorFix ? 'fix' : 'fast';
|
|
1720
|
-
}
|
|
1721
|
-
export function doctorArgWarnings(args = []) {
|
|
1722
|
-
const warnings = [];
|
|
1723
|
-
const explicit = readOption(args, '--profile', null);
|
|
1724
|
-
if (explicit && !['migration', 'full', 'capabilities', 'fast', 'fix'].includes(String(explicit))) {
|
|
1725
|
-
warnings.push(`unknown_profile:${explicit}; supported profiles: migration, full, capabilities, fast, fix`);
|
|
1726
|
-
}
|
|
1727
|
-
for (const flag of unknownDoctorFlags(args))
|
|
1728
|
-
warnings.push(`unknown_flag:${flag}`);
|
|
1729
|
-
return warnings;
|
|
1730
|
-
}
|
|
1731
|
-
function unknownDoctorFlags(args = []) {
|
|
1732
|
-
const knownBoolean = new Set([
|
|
1733
|
-
'--fix', '--yes', '-y', '--machine-only', '--actual-codex', '--require-actual-codex',
|
|
1734
|
-
'--full', '--capabilities', '--repair-codex-app-ui', '--repair-zellij', '--install-homebrew',
|
|
1735
|
-
'--repair-native-capabilities', '--repair-codex-native', '--local-only', '--global-only', '--project', '--global',
|
|
1736
|
-
'--dry-run', '--json'
|
|
1737
|
-
]);
|
|
1738
|
-
const knownValue = new Set(['--profile', '--report-file', '--codex-bin', '--install-scope']);
|
|
1739
|
-
const unknown = [];
|
|
1740
|
-
for (let index = 0; index < args.length; index += 1) {
|
|
1741
|
-
const arg = String(args[index] || '');
|
|
1742
|
-
if (!arg.startsWith('-'))
|
|
1743
|
-
continue;
|
|
1744
|
-
if (knownValue.has(arg)) {
|
|
1745
|
-
index += 1;
|
|
1746
|
-
continue;
|
|
1747
|
-
}
|
|
1748
|
-
if (knownBoolean.has(arg))
|
|
1749
|
-
continue;
|
|
1750
|
-
unknown.push(arg);
|
|
1751
|
-
}
|
|
1752
|
-
return unknown;
|
|
1753
|
-
}
|
|
1754
|
-
function doctorPhaseIdsForProfile(profile) {
|
|
1755
|
-
const required = [
|
|
1756
|
-
'codex_startup_repair',
|
|
1757
|
-
'startup_config_repair',
|
|
1758
|
-
'context7_repair',
|
|
1759
|
-
'context7_mcp_repair',
|
|
1760
|
-
'hook_trust_repair',
|
|
1761
|
-
'command_alias_cleanup'
|
|
1762
|
-
];
|
|
1763
|
-
if (profile === 'migration')
|
|
1764
|
-
return required;
|
|
1765
|
-
const optional = ['supabase_mcp_repair', 'native_capability_repair', 'sks_menubar'];
|
|
1766
|
-
if (profile === 'full' || profile === 'capabilities')
|
|
1767
|
-
return ['setup', ...required, ...optional];
|
|
1768
|
-
return [...required, ...optional];
|
|
1769
|
-
}
|
|
1770
1722
|
async function writeJsonReportFile(file, value) {
|
|
1771
1723
|
const fsp = await import('node:fs/promises');
|
|
1772
1724
|
const path = await import('node:path');
|