sneakoscope 2.0.4 → 2.0.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (120) hide show
  1. package/README.md +18 -11
  2. package/crates/sks-core/Cargo.lock +1 -1
  3. package/crates/sks-core/Cargo.toml +1 -1
  4. package/crates/sks-core/src/main.rs +1 -1
  5. package/dist/.sks-build-stamp.json +4 -4
  6. package/dist/bin/sks.js +1 -1
  7. package/dist/build-manifest.json +78 -8
  8. package/dist/cli/install-helpers.js +23 -0
  9. package/dist/commands/codex-app.js +25 -3
  10. package/dist/commands/doctor.js +33 -4
  11. package/dist/commands/mad-sks.js +2 -2
  12. package/dist/core/agents/agent-orchestrator.js +22 -3
  13. package/dist/core/agents/agent-proof-evidence.js +59 -2
  14. package/dist/core/agents/agent-roster.js +35 -6
  15. package/dist/core/agents/agent-schema.js +1 -1
  16. package/dist/core/agents/agent-worker-pipeline.js +9 -1
  17. package/dist/core/agents/native-worker-backend-router.js +50 -10
  18. package/dist/core/agents/ollama-worker-config.js +164 -15
  19. package/dist/core/codex/codex-0-137-compat.js +119 -0
  20. package/dist/core/codex-app.js +124 -2
  21. package/dist/core/codex-control/codex-control-proof.js +4 -1
  22. package/dist/core/codex-control/codex-sdk-capability.js +1 -1
  23. package/dist/core/codex-control/codex-task-runner.js +329 -5
  24. package/dist/core/codex-control/python-codex-sdk-adapter.js +197 -0
  25. package/dist/core/codex-control/python-codex-sdk-event-translator.js +14 -0
  26. package/dist/core/commands/local-model-command.js +65 -19
  27. package/dist/core/commands/naruto-command.js +124 -8
  28. package/dist/core/commands/run-command.js +1 -1
  29. package/dist/core/doctor/doctor-readiness-matrix.js +21 -2
  30. package/dist/core/fsx.js +1 -1
  31. package/dist/core/hooks-runtime.js +2 -233
  32. package/dist/core/init.js +8 -8
  33. package/dist/core/local-llm/local-llm-backpressure.js +20 -0
  34. package/dist/core/local-llm/local-llm-capability.js +29 -0
  35. package/dist/core/local-llm/local-llm-client.js +100 -0
  36. package/dist/core/local-llm/local-llm-config.js +6 -1
  37. package/dist/core/local-llm/local-llm-context-cache.js +21 -0
  38. package/dist/core/local-llm/local-llm-control-adapter.js +101 -0
  39. package/dist/core/local-llm/local-llm-json-repair.js +52 -0
  40. package/dist/core/local-llm/local-llm-metrics.js +42 -0
  41. package/dist/core/local-llm/local-llm-ollama-client.js +67 -0
  42. package/dist/core/local-llm/local-llm-openai-compatible-client.js +30 -0
  43. package/dist/core/local-llm/local-llm-prompt-cache.js +12 -0
  44. package/dist/core/local-llm/local-llm-scheduler.js +29 -0
  45. package/dist/core/local-llm/local-llm-schema-enforcer.js +15 -0
  46. package/dist/core/local-llm/local-llm-smoke.js +83 -0
  47. package/dist/core/local-llm/local-llm-warmup.js +20 -0
  48. package/dist/core/local-llm/local-worker-eligibility.js +27 -0
  49. package/dist/core/naruto/hardware-capacity-probe.js +36 -0
  50. package/dist/core/naruto/naruto-active-pool.js +134 -0
  51. package/dist/core/naruto/naruto-backpressure.js +13 -0
  52. package/dist/core/naruto/naruto-concurrency-governor.js +65 -0
  53. package/dist/core/naruto/naruto-finalizer.js +18 -0
  54. package/dist/core/naruto/naruto-generation-scheduler.js +18 -0
  55. package/dist/core/naruto/naruto-gpt-final-pack.js +49 -0
  56. package/dist/core/naruto/naruto-parallel-patch-apply.js +95 -0
  57. package/dist/core/naruto/naruto-patch-transaction-batch.js +42 -0
  58. package/dist/core/naruto/naruto-role-policy.js +107 -0
  59. package/dist/core/naruto/naruto-verification-dag.js +42 -0
  60. package/dist/core/naruto/naruto-verification-pool.js +18 -0
  61. package/dist/core/naruto/naruto-work-graph.js +198 -0
  62. package/dist/core/naruto/naruto-work-item.js +40 -0
  63. package/dist/core/naruto/naruto-work-stealing.js +11 -0
  64. package/dist/core/naruto/resource-pressure-monitor.js +32 -0
  65. package/dist/core/pipeline/finalize-pipeline-result.js +58 -0
  66. package/dist/core/pipeline/gpt-final-required.js +12 -0
  67. package/dist/core/pipeline-internals/runtime-core.js +1 -1
  68. package/dist/core/ppt.js +31 -8
  69. package/dist/core/product-design-app-server.js +410 -0
  70. package/dist/core/product-design-plugin.js +139 -0
  71. package/dist/core/prompt/prompt-placeholder-guard.js +30 -0
  72. package/dist/core/router/capability-card.js +13 -0
  73. package/dist/core/router/route-cache.js +3 -0
  74. package/dist/core/router/ultra-router.js +2 -1
  75. package/dist/core/routes.js +12 -12
  76. package/dist/core/version.js +1 -1
  77. package/dist/core/zellij/zellij-lane-runtime.js +2 -2
  78. package/dist/core/zellij/zellij-naruto-dashboard.js +36 -0
  79. package/dist/core/zellij/zellij-worker-pane-manager.js +4 -4
  80. package/dist/scripts/blackbox-command-import-smoke.js +10 -1
  81. package/dist/scripts/check-package-boundary.js +12 -3
  82. package/dist/scripts/codex-0-137-compat-check.js +27 -0
  83. package/dist/scripts/codex-environment-scoped-approvals-check.js +10 -0
  84. package/dist/scripts/codex-plugin-list-json-check.js +8 -0
  85. package/dist/scripts/codex-thread-runtime-choice-check.js +10 -0
  86. package/dist/scripts/local-collab-all-pipelines-final-gpt-check.js +21 -0
  87. package/dist/scripts/local-llm-all-pipelines-check.js +11 -0
  88. package/dist/scripts/local-llm-cache-performance-check.js +10 -0
  89. package/dist/scripts/local-llm-capability-check.js +14 -0
  90. package/dist/scripts/local-llm-smoke-check.js +23 -0
  91. package/dist/scripts/local-llm-structured-output-check.js +11 -0
  92. package/dist/scripts/local-llm-throughput-check.js +10 -0
  93. package/dist/scripts/local-llm-tool-call-repair-check.js +10 -0
  94. package/dist/scripts/local-llm-warmup-check.js +11 -0
  95. package/dist/scripts/naruto-active-pool-check.js +39 -0
  96. package/dist/scripts/naruto-concurrency-governor-check.js +52 -0
  97. package/dist/scripts/naruto-gpt-final-pack-check.js +34 -0
  98. package/dist/scripts/naruto-parallel-patch-apply-check.js +41 -0
  99. package/dist/scripts/naruto-readonly-routing-check.js +116 -0
  100. package/dist/scripts/naruto-real-local-gpt-final-smoke.js +16 -0
  101. package/dist/scripts/naruto-role-distribution-check.js +23 -0
  102. package/dist/scripts/naruto-shadow-clone-swarm-check.js +13 -0
  103. package/dist/scripts/naruto-verification-pool-check.js +36 -0
  104. package/dist/scripts/naruto-work-graph-check.js +24 -0
  105. package/dist/scripts/naruto-zellij-massive-ui-check.js +23 -0
  106. package/dist/scripts/product-design-auto-install-check.js +119 -0
  107. package/dist/scripts/product-design-plugin-routing-check.js +101 -0
  108. package/dist/scripts/prompt-placeholder-guard-check.js +33 -0
  109. package/dist/scripts/python-codex-sdk-all-pipelines-check.js +47 -0
  110. package/dist/scripts/python-codex-sdk-capability-check.js +75 -0
  111. package/dist/scripts/python-codex-sdk-sandbox-policy-check.js +10 -0
  112. package/dist/scripts/python-codex-sdk-stream-bridge-check.js +12 -0
  113. package/dist/scripts/release-parallel-check.js +16 -2
  114. package/dist/scripts/release-provenance-check.js +21 -0
  115. package/dist/scripts/release-real-check.js +5 -0
  116. package/dist/scripts/zellij-worker-pane-manager-check.js +1 -1
  117. package/package.json +36 -4
  118. package/schemas/local-llm/local-model-config.schema.json +74 -0
  119. package/schemas/naruto/naruto-concurrency-governor.schema.json +21 -0
  120. package/schemas/naruto/naruto-work-graph.schema.json +22 -0
@@ -0,0 +1,119 @@
1
+ import { runProcess, which } from '../fsx.js';
2
+ import { compareSemverLike, parseCodexVersionText } from '../codex-compat/codex-version-policy.js';
3
+ import { createHash } from 'node:crypto';
4
+ export const CODEX_0_137_BASELINE_TAG = 'rust-v0.137.0';
5
+ export const CODEX_0_137_VERSION = '0.137.0';
6
+ export const CODEX_0_137_SCHEMA = 'sks.codex-0.137-compat.v1';
7
+ export function codex0137Matrix(input = {}) {
8
+ const version = parseCodexVersionText(input.version) || input.version || null;
9
+ const available = input.available !== false && Boolean(version);
10
+ const meets = available && compareSemverLike(version, CODEX_0_137_VERSION) >= 0;
11
+ const pluginJsonDetected = looksLikeJson(input.pluginListText || '');
12
+ const runtimeDetected = /runtime|model|provider|thread/i.test(input.debugModelsText || '');
13
+ const approvalsDetected = /approval|environment|sandbox|profile|permission/i.test(input.doctorText || '');
14
+ const localOrBaseline = (detected) => detected ? 'detected' : meets ? 'release_baseline' : available ? 'blocked' : 'unavailable';
15
+ const capabilities = [
16
+ capability('plugin_list_json', 'P0', localOrBaseline(pluginJsonDetected), '`codex plugin list --json` parses as JSON or 0.137 baseline records it.'),
17
+ capability('thread_runtime_choice', 'P0', localOrBaseline(runtimeDetected), 'Thread/runtime choice is tracked by SKS per-thread proof and Codex runtime evidence.'),
18
+ capability('environment_scoped_approvals', 'P0', localOrBaseline(approvalsDetected), 'Approval proof carries environment identity and sandbox scope.'),
19
+ capability('managed_proxy_ca_bundle_child_commands', 'P1', meets ? 'release_baseline' : available ? 'blocked' : 'unavailable', 'Managed proxy CA bundle propagation is release-baseline plus SKS env proof.'),
20
+ capability('python_sdk_app_server_json_rpc', 'P0', meets ? 'release_baseline' : available ? 'blocked' : 'unavailable', 'Python SDK controls local app-server over JSON-RPC per current Codex manual.')
21
+ ];
22
+ const below = available && version ? compareSemverLike(version, CODEX_0_137_VERSION) < 0 : false;
23
+ const blockers = [
24
+ ...(input.requireReal && (!version || below) ? ['codex_0_137_required_but_not_detected'] : []),
25
+ ...capabilities
26
+ .filter((row) => input.requireReal && row.priority === 'P0' && (row.status === 'blocked' || row.status === 'unavailable'))
27
+ .map((row) => `codex_0_137_capability_unavailable:${row.id}`)
28
+ ];
29
+ return {
30
+ schema: CODEX_0_137_SCHEMA,
31
+ baseline: CODEX_0_137_BASELINE_TAG,
32
+ required_version: CODEX_0_137_VERSION,
33
+ release_evidence: {
34
+ upstream: 'openai/codex',
35
+ npm_package: '@openai/codex-sdk',
36
+ npm_version: '0.137.0',
37
+ manual_source: 'https://developers.openai.com/codex/codex-manual.md',
38
+ checked_topics: ['Codex SDK TypeScript', 'Codex SDK Python', 'CLI plugin/json/runtime/approval surfaces']
39
+ },
40
+ inherited_baselines: ['rust-v0.136.0', 'rust-v0.135.0', 'rust-v0.134.0'],
41
+ detected_version: version,
42
+ available,
43
+ require_real: input.requireReal === true,
44
+ capabilities,
45
+ plugin_list_json_supported: supported(capabilities, 'plugin_list_json'),
46
+ thread_runtime_choice_supported: supported(capabilities, 'thread_runtime_choice'),
47
+ environment_scoped_approvals_supported: supported(capabilities, 'environment_scoped_approvals'),
48
+ ok: blockers.length === 0,
49
+ warnings: !input.requireReal && (!version || below) ? [`Codex ${CODEX_0_137_BASELINE_TAG} not detected; release:check treats this as warning-only.`] : [],
50
+ blockers
51
+ };
52
+ }
53
+ export async function collectCodex0137LocalEvidence(opts = {}) {
54
+ const bin = opts.codexBin || await which('codex');
55
+ if (!bin) {
56
+ return {
57
+ available: false,
58
+ versionText: '',
59
+ pluginListText: '',
60
+ debugModelsText: '',
61
+ doctorText: '',
62
+ warnings: ['codex_binary_missing']
63
+ };
64
+ }
65
+ const run = async (args) => runProcess(bin, args, { timeoutMs: 10000, maxOutputBytes: 64 * 1024 }).catch((err) => ({
66
+ code: 1,
67
+ stdout: '',
68
+ stderr: err.message || String(err)
69
+ }));
70
+ const [version, pluginList, debugModels, doctor] = await Promise.all([
71
+ run(['--version']),
72
+ run(['plugin', 'list', '--json']),
73
+ run(['debug', 'models', '--bundled']),
74
+ run(['doctor', '--json'])
75
+ ]);
76
+ return {
77
+ available: version.code === 0,
78
+ versionText: `${version.stdout || ''}${version.stderr || ''}`.trim(),
79
+ pluginListText: `${pluginList.stdout || ''}${pluginList.stderr || ''}`,
80
+ debugModelsText: summarizeCodexCommandOutput(`${debugModels.stdout || ''}${debugModels.stderr || ''}`, ['runtime', 'model', 'provider', 'thread']),
81
+ doctorText: summarizeCodexCommandOutput(`${doctor.stdout || ''}${doctor.stderr || ''}`, ['approval', 'environment', 'sandbox', 'profile', 'permission']),
82
+ warnings: [
83
+ ...(pluginList.code === 0 ? [] : ['codex_plugin_list_json_unavailable']),
84
+ ...(debugModels.code === 0 ? [] : ['codex_debug_models_unavailable']),
85
+ ...(doctor.code === 0 ? [] : ['codex_doctor_json_unavailable'])
86
+ ]
87
+ };
88
+ }
89
+ function capability(id, priority, status, detector) {
90
+ return { id, priority, status, detector, notes: [] };
91
+ }
92
+ function supported(capabilities, id) {
93
+ const status = capabilities.find((capability) => capability.id === id)?.status;
94
+ return status === 'detected' || status === 'release_baseline';
95
+ }
96
+ function looksLikeJson(value) {
97
+ const text = String(value || '').trim();
98
+ if (!text)
99
+ return false;
100
+ try {
101
+ JSON.parse(text);
102
+ return true;
103
+ }
104
+ catch {
105
+ return false;
106
+ }
107
+ }
108
+ function summarizeCodexCommandOutput(value, keywords) {
109
+ const text = String(value || '');
110
+ const lower = text.toLowerCase();
111
+ const matched = keywords.filter((keyword) => lower.includes(keyword.toLowerCase()));
112
+ return [
113
+ `raw_output_redacted=true`,
114
+ `bytes=${Buffer.byteLength(text, 'utf8')}`,
115
+ `sha256=${createHash('sha256').update(text).digest('hex')}`,
116
+ `matched_keywords=${matched.join(',') || 'none'}`
117
+ ].join(' ');
118
+ }
119
+ //# sourceMappingURL=codex-0-137-compat.js.map
@@ -4,6 +4,8 @@ import fsp from 'node:fs/promises';
4
4
  import { exists, runProcess } from './fsx.js';
5
5
  import { EMPTY_CODEX_INFO, getCodexInfo } from './codex-adapter.js';
6
6
  import { CODEX_CHROME_EXTENSION_DOC_URL, DEFAULT_CODEX_APP_PLUGINS as DEFAULT_CODEX_APP_PLUGIN_TUPLES, RESERVED_CODEX_PLUGIN_SKILL_NAMES } from './routes.js';
7
+ import { PRODUCT_DESIGN_PLUGIN, normalizeProductDesignPluginEvidence } from './product-design-plugin.js';
8
+ import { PRODUCT_DESIGN_AUTO_INSTALL_ENV, ensureProductDesignPluginInstalled, productDesignAutoInstallRequested } from './product-design-app-server.js';
7
9
  export const CODEX_APP_DOCS_URL = 'https://developers.openai.com/codex/app/features';
8
10
  export const CODEX_CHANGELOG_URL = 'https://developers.openai.com/codex/changelog';
9
11
  export const CODEX_ACCESS_TOKENS_DOCS_URL = 'https://developers.openai.com/codex/enterprise/access-tokens';
@@ -128,6 +130,7 @@ export async function codexAppIntegrationStatus(opts = {}) {
128
130
  const chromePath = await findPluginCache('chrome', opts);
129
131
  const computerUsePath = await findPluginCache('computer-use', opts);
130
132
  const defaultPlugins = await codexDefaultPluginStatus(opts);
133
+ const productDesignPlugin = await codexProductDesignPluginStatus(opts);
131
134
  const pluginSkillShadows = await codexPluginSkillShadowStatus(opts);
132
135
  const fastModeConfig = await codexFastModeConfigStatus(opts);
133
136
  const computerUseMcpListed = /computer[-_ ]?use/i.test(mcpText);
@@ -209,6 +212,7 @@ export async function codexAppIntegrationStatus(opts = {}) {
209
212
  browser_use_cache: browserUsePath,
210
213
  chrome_cache: chromePath,
211
214
  default_plugins: defaultPlugins,
215
+ design_product: productDesignPlugin,
212
216
  skill_shadows: pluginSkillShadows,
213
217
  picker: {
214
218
  ok: pluginPickerReady,
@@ -219,7 +223,7 @@ export async function codexAppIntegrationStatus(opts = {}) {
219
223
  }
220
224
  },
221
225
  chrome_extension: chromeExtension,
222
- guidance: codexAppGuidance({ appInstalled, codex, mcpList, featureList, requiredFeatureFlags, requiredFeatureFlagsOk, defaultPlugins, pluginSkillShadows, fastModeConfig, gitActions, imageGenerationReady, inAppBrowserReady, browserUseFeatureReady, computerUseReady, browserUseReady, browserToolReady, computerUseMcpListed, browserUseMcpListed, chromeExtension, remoteControl })
226
+ guidance: codexAppGuidance({ appInstalled, codex, mcpList, featureList, requiredFeatureFlags, requiredFeatureFlagsOk, defaultPlugins, productDesignPlugin, pluginSkillShadows, fastModeConfig, gitActions, imageGenerationReady, inAppBrowserReady, browserUseFeatureReady, computerUseReady, browserUseReady, browserToolReady, computerUseMcpListed, browserUseMcpListed, chromeExtension, remoteControl })
223
227
  };
224
228
  }
225
229
  export async function codexChromeExtensionStatus(opts = {}) {
@@ -438,7 +442,7 @@ export function codexAccessTokenStatus(env = process.env) {
438
442
  : ['No CODEX_ACCESS_TOKEN detected in the current process environment. This is fine for interactive ChatGPT login or API-key auth.']
439
443
  };
440
444
  }
441
- export function codexAppGuidance({ appInstalled, codex, mcpList, featureList, requiredFeatureFlags = {}, requiredFeatureFlagsOk = true, defaultPlugins = { ok: true, missing_enabled: [] }, pluginSkillShadows = { ok: true, blocking: [] }, fastModeConfig = { ok: true, blockers: [] }, gitActions = { ok: true, blockers: [] }, imageGenerationReady, inAppBrowserReady, browserUseFeatureReady, computerUseReady, browserUseReady, browserToolReady, computerUseMcpListed, browserUseMcpListed, chromeExtension, remoteControl }) {
445
+ export function codexAppGuidance({ appInstalled, codex, mcpList, featureList, requiredFeatureFlags = {}, requiredFeatureFlagsOk = true, defaultPlugins = { ok: true, missing_enabled: [] }, productDesignPlugin = null, pluginSkillShadows = { ok: true, blocking: [] }, fastModeConfig = { ok: true, blockers: [] }, gitActions = { ok: true, blockers: [] }, imageGenerationReady, inAppBrowserReady, browserUseFeatureReady, computerUseReady, browserUseReady, browserToolReady, computerUseMcpListed, browserUseMcpListed, chromeExtension, remoteControl }) {
442
446
  const lines = [];
443
447
  if (!appInstalled) {
444
448
  lines.push('Install and open Codex App for first-party MCP/plugin tools. SKS Zellij launch can still run with Codex CLI alone, but Codex Computer Use and imagegen/gpt-image-2 evidence will be unavailable until Codex App is ready.');
@@ -474,6 +478,18 @@ export function codexAppGuidance({ appInstalled, codex, mcpList, featureList, re
474
478
  lines.push(`Codex default plugin source(s) missing: ${defaultPlugins.missing_installed.join(', ')}. The @ plugin picker can hide built-in surfaces when plugin files are absent even if config says enabled.`);
475
479
  lines.push('Run: sks doctor --fix, then restart Codex App if the plugin cache was just restored.');
476
480
  }
481
+ if (productDesignPlugin?.ok) {
482
+ lines.push(`Product Design plugin is ready for design routes via ${productDesignPlugin.source || 'verified evidence'} (${productDesignPlugin.id}).`);
483
+ }
484
+ else if (productDesignPlugin?.auto_install?.attempted) {
485
+ lines.push(`Product Design auto-install was attempted but did not produce ready evidence: ${(productDesignPlugin.blockers || []).join(', ') || 'unverified'}. Recheck with: ${productDesignPlugin.auto_install.command}`);
486
+ }
487
+ else if (productDesignPlugin?.app_server?.checked && !productDesignPlugin.app_server.ok) {
488
+ lines.push(`Product Design app-server lookup ran but is not ready: ${(productDesignPlugin.blockers || []).join(', ') || 'unverified'}. Run: ${productDesignPlugin.auto_install?.command || 'sks codex-app product-design --json'}`);
489
+ }
490
+ else if (productDesignPlugin?.remote_lookup_required) {
491
+ lines.push(`Product Design is a remote vertical marketplace plugin and may not appear in \`codex plugin list\`; design routes should run ${productDesignPlugin.auto_install?.command || 'sks codex-app product-design --json'} or set ${PRODUCT_DESIGN_AUTO_INSTALL_ENV}=1 before falling back to legacy design.md skills.`);
492
+ }
477
493
  if (pluginSkillShadows?.generated?.length) {
478
494
  const names = pluginSkillShadows.generated.map((entry) => `${entry.name}:${entry.scope}`).join(', ');
479
495
  lines.push(`Codex plugin picker generated skill shadow(s) detected: ${names}. Generated SKS skills with first-party plugin names can hide @ plugin entries after upgrades.`);
@@ -536,6 +552,7 @@ export function formatCodexAppStatus(status, { includeRaw = false } = {}) {
536
552
  `App Flags: ${status.features?.required_flags_ok ? 'ok' : `missing ${missingRequiredFeatureFlags(status.features?.required_flags).join(', ') || 'required flags'}`}`,
537
553
  `Fast UI: ${status.features?.fast_mode_config?.ok ? 'ok' : `locked ${(status.features?.fast_mode_config?.blockers || []).join(', ') || 'config'}`}`,
538
554
  `Default Plugins:${status.plugins?.default_plugins?.ok ? ' ok' : ` missing ${defaultPluginMissingSummary(status.plugins?.default_plugins) || 'plugin install/config'}`}`,
555
+ `Product Design:${productDesignStatusSummary(status.plugins?.design_product)}`,
539
556
  `Plugin Picker:${status.plugins?.picker?.ok ? ' ok' : ` blocked ${pluginPickerBlockers(status).join(', ') || 'config'}`}`,
540
557
  `Git Actions:${status.features?.git_actions?.ok ? ' ok' : ` blocked ${(status.features?.git_actions?.blockers || []).join(', ') || 'config'}`}`,
541
558
  `Chrome Ext: ${status.chrome_extension?.ok ? 'ok' : `setup ${(status.chrome_extension?.blockers || []).join(', ') || 'required'}`}`,
@@ -552,6 +569,30 @@ export function formatCodexAppStatus(status, { includeRaw = false } = {}) {
552
569
  lines.push('', status.features.stdout.trim());
553
570
  return lines.join('\n');
554
571
  }
572
+ export function formatCodexProductDesignPluginStatus(status) {
573
+ const lines = [
574
+ 'Codex App Product Design Plugin',
575
+ '',
576
+ `Ready: ${status.ok ? 'yes' : 'no'}`,
577
+ `Installed: ${status.installed ? 'yes' : 'no'}`,
578
+ `Enabled: ${status.enabled === true ? 'yes' : status.enabled === false ? 'no' : 'unknown'}`,
579
+ `Source: ${status.source || 'unverified'}`,
580
+ `Marketplace: ${status.marketplace}`,
581
+ `Remote ID: ${status.remote_plugin_id}`,
582
+ `Auto Install: ${status.auto_install?.requested ? 'requested' : 'not requested'}${status.auto_install?.attempted ? ' (attempted)' : ''}`,
583
+ `Command: ${status.auto_install?.command || 'sks codex-app product-design --json'}`,
584
+ '',
585
+ ...(status.blockers || []).map((blocker) => `- ${blocker}`)
586
+ ];
587
+ if (status.remote_evidence?.missing_skills?.length) {
588
+ lines.push(`- missing skills: ${status.remote_evidence.missing_skills.join(', ')}`);
589
+ }
590
+ if (status.ok)
591
+ lines.push('- Product Design is ready for design routes.');
592
+ else if (!status.auto_install?.requested)
593
+ lines.push('- Run `sks codex-app product-design --json`, or set SKS_PRODUCT_DESIGN_AUTO_INSTALL=1 for design-route auto-ensure.');
594
+ return lines.join('\n');
595
+ }
555
596
  function summarizeCodexMcpError(text) {
556
597
  const cleanLines = String(text || '')
557
598
  .split(/\r?\n/)
@@ -629,6 +670,76 @@ async function codexDefaultPluginStatus(opts = {}) {
629
670
  missing_enabled: missingEnabled
630
671
  };
631
672
  }
673
+ export async function codexProductDesignPluginStatus(opts = {}) {
674
+ const home = opts.home || os.homedir();
675
+ const cwd = opts.cwd || process.cwd();
676
+ const globalConfigPath = path.join(home || '', '.codex', 'config.toml');
677
+ const projectConfigPath = path.join(cwd || '', '.codex', 'config.toml');
678
+ const globalConfig = await readTextIfExists(globalConfigPath);
679
+ const projectConfig = path.resolve(projectConfigPath) === path.resolve(globalConfigPath)
680
+ ? ''
681
+ : await readTextIfExists(projectConfigPath);
682
+ const configText = `${globalConfig}\n${projectConfig}`;
683
+ const plugin = { name: PRODUCT_DESIGN_PLUGIN.name, marketplace: PRODUCT_DESIGN_PLUGIN.marketplace };
684
+ const autoInstallProductDesign = productDesignAutoInstallRequested(opts);
685
+ const appServerStatus = opts.productDesignAppServerStatus || (autoInstallProductDesign
686
+ ? await ensureProductDesignPluginInstalled({
687
+ ...opts,
688
+ autoInstallProductDesign
689
+ })
690
+ : null);
691
+ const injectedRemoteEvidence = opts.productDesignPluginReadResponse
692
+ ? normalizeProductDesignPluginEvidence(opts.productDesignPluginReadResponse)
693
+ : null;
694
+ const appServerEvidence = appServerStatus?.remote_evidence?.schema === 'sks.product-design-plugin-evidence.v1'
695
+ ? appServerStatus.remote_evidence
696
+ : null;
697
+ const remoteEvidence = appServerEvidence || injectedRemoteEvidence;
698
+ const localSource = await findDefaultPluginSource(plugin, { home, configText });
699
+ const configEnabled = codexPluginEnabled(configText, plugin);
700
+ const enabled = remoteEvidence?.enabled === true ? true : configEnabled ? true : null;
701
+ const installed = Boolean(localSource) || remoteEvidence?.installed === true;
702
+ const ok = Boolean(remoteEvidence?.ok || (installed && enabled === true));
703
+ const remoteLookupRequired = !remoteEvidence?.ok && (!localSource || enabled !== true) && !appServerStatus?.checked;
704
+ const blockers = ok ? [] : Array.from(new Set([
705
+ ...(!installed ? ['product_design_plugin_not_installed_or_not_locally_visible'] : []),
706
+ ...(enabled !== true ? ['product_design_plugin_enabled_state_requires_remote_evidence'] : []),
707
+ ...(remoteLookupRequired ? ['product_design_remote_vertical_lookup_required'] : []),
708
+ ...(autoInstallProductDesign && appServerStatus && !appServerStatus.ok ? ['product_design_app_server_install_failed'] : []),
709
+ ...(appServerStatus?.blockers || [])
710
+ ]));
711
+ return {
712
+ schema: 'sks.codex-product-design-plugin-status.v1',
713
+ ok,
714
+ checked: true,
715
+ route_required_only: true,
716
+ id: PRODUCT_DESIGN_PLUGIN.id,
717
+ name: PRODUCT_DESIGN_PLUGIN.name,
718
+ display_name: PRODUCT_DESIGN_PLUGIN.display_name,
719
+ marketplace: PRODUCT_DESIGN_PLUGIN.marketplace,
720
+ marketplace_kind: PRODUCT_DESIGN_PLUGIN.marketplace_kind,
721
+ remote_plugin_id: PRODUCT_DESIGN_PLUGIN.remote_plugin_id,
722
+ installed,
723
+ enabled,
724
+ source: remoteEvidence?.ok
725
+ ? appServerStatus?.install_attempted ? 'app_server_plugin_install' : 'app_server_plugin_read'
726
+ : localSource ? 'local_plugin_cache_or_marketplace_source' : null,
727
+ local_source: localSource,
728
+ remote_evidence: remoteEvidence,
729
+ app_server: appServerStatus,
730
+ auto_install: {
731
+ requested: autoInstallProductDesign,
732
+ attempted: Boolean(appServerStatus?.install_attempted),
733
+ command: 'sks codex-app product-design --json',
734
+ env: PRODUCT_DESIGN_AUTO_INSTALL_ENV
735
+ },
736
+ remote_lookup_required: remoteLookupRequired,
737
+ app_server_read_params: PRODUCT_DESIGN_PLUGIN.app_server.read_params,
738
+ app_server_install_params: PRODUCT_DESIGN_PLUGIN.app_server.install_params,
739
+ app_server_list_params: PRODUCT_DESIGN_PLUGIN.app_server.list_params,
740
+ blockers
741
+ };
742
+ }
632
743
  async function codexPluginSkillShadowStatus(opts = {}) {
633
744
  const home = opts.home || os.homedir();
634
745
  const cwd = opts.cwd || process.cwd();
@@ -754,6 +865,17 @@ function pluginPickerBlockers(status = {}) {
754
865
  out.push('fast_mode_config');
755
866
  return out;
756
867
  }
868
+ function productDesignStatusSummary(status = {}) {
869
+ if (status.ok)
870
+ return ' ok';
871
+ if (status.auto_install?.attempted)
872
+ return ' install unverified';
873
+ if (status.remote_lookup_required)
874
+ return ' remote lookup required';
875
+ if (status.app_server?.checked)
876
+ return ' app-server unverified';
877
+ return ' not checked';
878
+ }
757
879
  function defaultPluginMissingSummary(defaultPlugins = {}) {
758
880
  return [
759
881
  ...(defaultPlugins?.missing_installed || []),
@@ -7,7 +7,8 @@ export async function writeCodexControlProof(root, input) {
7
7
  schema: CODEX_CONTROL_PROOF_SCHEMA,
8
8
  generated_at: nowIso(),
9
9
  ok: input.result.ok === true,
10
- backend: 'codex-sdk',
10
+ backend: input.result.backend,
11
+ backend_family: input.result.backend_family,
11
12
  route: input.task.route,
12
13
  mission_id: input.task.missionId,
13
14
  work_item_id: input.task.workItemId || null,
@@ -22,6 +23,8 @@ export async function writeCodexControlProof(root, input) {
22
23
  output_schema_id: input.task.outputSchemaId,
23
24
  worker_result_path: input.result.workerResultPath,
24
25
  patch_envelope_path: input.result.patchEnvelopePath || null,
26
+ local_llm_proof_path: input.result.localLlmProofPath || null,
27
+ python_sdk_proof_path: input.result.pythonSdkProofPath || null,
25
28
  sandbox: input.sandbox || null,
26
29
  env: input.envProof || null,
27
30
  config: input.config ? redactCodexSdkConfig(input.config) : null,
@@ -37,7 +37,7 @@ export async function detectCodexSdkCapability(input = {}) {
37
37
  node_compatible: nodeCompatible,
38
38
  dynamic_import_ok: dynamicImportOk,
39
39
  structured_output_fake_smoke: structuredFake,
40
- setup_action: blockers.includes('codex_sdk_unavailable') ? 'npm install @openai/codex-sdk@0.136.0' : null,
40
+ setup_action: blockers.includes('codex_sdk_unavailable') ? 'npm install @openai/codex-sdk@0.137.0' : null,
41
41
  blockers
42
42
  };
43
43
  }