sneakoscope 10.3.3 → 10.3.5

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 (125) hide show
  1. package/README.md +221 -11
  2. package/config/skills-hash-ledger.v1.json +21 -2
  3. package/crates/sks-core/Cargo.lock +1 -1
  4. package/crates/sks-core/Cargo.toml +1 -1
  5. package/dist/cli/command-manifest-lite.js +3 -1
  6. package/dist/cli/command-registry.js +8 -0
  7. package/dist/cli/install-helpers.js +1 -2
  8. package/dist/commands/doctor.js +3 -4
  9. package/dist/commands/imagegen.js +154 -0
  10. package/dist/config/skills-manifest.json +40 -21
  11. package/dist/core/agents/agent-effort-policy.js +15 -13
  12. package/dist/core/agents/native-worker-backend-router.js +24 -10
  13. package/dist/core/agents/official-subagent-helper-policy.js +1 -2
  14. package/dist/core/codex-app/menubar/constants.js +2 -0
  15. package/dist/core/codex-app.js +6 -6
  16. package/dist/core/codex-lb/desktop-bridge/imagegen-endpoint.js +95 -0
  17. package/dist/core/codex-lb/desktop-bridge/server.js +6 -1
  18. package/dist/core/codex-lb/desktop-bridge/types.js +1 -0
  19. package/dist/core/codex-lb/desktop-bridge-migration/retired-runtime-cleanup.js +1 -0
  20. package/dist/core/codex-native/core-skill-manifest.js +8 -9
  21. package/dist/core/codex-native/native-capability-repair-matrix.js +4 -5
  22. package/dist/core/commands/image-ux-review-command.js +6 -7
  23. package/dist/core/commands/ppt-command.js +3 -4
  24. package/dist/core/commands/qa-loop-command.js +28 -3
  25. package/dist/core/decisions/cli.js +9 -2
  26. package/dist/core/decisions/config.js +7 -0
  27. package/dist/core/decisions/integration.js +105 -12
  28. package/dist/core/decisions/policy.js +54 -4
  29. package/dist/core/decisions/questions.js +81 -10
  30. package/dist/core/decisions/routing.js +15 -10
  31. package/dist/core/decisions/types.js +13 -25
  32. package/dist/core/doctor/current-project-guidance.js +38 -1
  33. package/dist/core/doctor/doctor-readiness-matrix.js +1 -2
  34. package/dist/core/doctor/imagegen-repair.js +3 -4
  35. package/dist/core/doctor/skill-legacy-surface.js +2 -1
  36. package/dist/core/feature-fixtures.js +1 -0
  37. package/dist/core/feature-registry.js +3 -3
  38. package/dist/core/hooks-runtime/hook-context.js +2 -2
  39. package/dist/core/hooks-runtime/hook-io.js +1 -2
  40. package/dist/core/hooks-runtime/jev-spawn-routing.js +21 -2
  41. package/dist/core/hooks-runtime/jev-turn-plan.js +81 -0
  42. package/dist/core/hooks-runtime/managed-guidance-preflight.js +50 -0
  43. package/dist/core/hooks-runtime/official-subagent-lifecycle.js +3 -3
  44. package/dist/core/hooks-runtime/parent-orchestration-gate.js +372 -0
  45. package/dist/core/hooks-runtime/subagent-context.js +13 -3
  46. package/dist/core/hooks-runtime/subagent-spawn-policy.js +5 -10
  47. package/dist/core/hooks-runtime.js +73 -11
  48. package/dist/core/image-ux-review/imagegen-adapter.js +159 -316
  49. package/dist/core/image-ux-review.js +28 -20
  50. package/dist/core/imagegen/imagegen-auth-readiness.js +10 -8
  51. package/dist/core/imagegen/imagegen-capability.js +79 -14
  52. package/dist/core/imagegen/imagegen-config.js +45 -0
  53. package/dist/core/imagegen/imagegen-evidence.js +14 -2
  54. package/dist/core/imagegen/imagegen-generate.js +284 -0
  55. package/dist/core/imagegen/imagegen-jev.js +53 -0
  56. package/dist/core/imagegen/imagegen-model-policy.js +2 -5
  57. package/dist/core/imagegen/imagegen-request-validator.js +3 -3
  58. package/dist/core/imagegen/openrouter-images.js +288 -0
  59. package/dist/core/imagegen/require-imagegen.js +14 -7
  60. package/dist/core/init/skills/inventory.js +5 -1
  61. package/dist/core/init/skills.js +12 -13
  62. package/dist/core/init.js +36 -4
  63. package/dist/core/lean-engineering-policy.js +2 -2
  64. package/dist/core/managed-assets/managed-assets-manifest.js +18 -19
  65. package/dist/core/pipeline-internals/runtime-core.js +6 -7
  66. package/dist/core/pipeline-internals/runtime-gates.js +5 -5
  67. package/dist/core/ppt-review/ppt-patch-handoff.js +1 -2
  68. package/dist/core/ppt-review/slide-imagegen-review.js +10 -11
  69. package/dist/core/ppt.js +50 -35
  70. package/dist/core/provider/model-router.js +8 -5
  71. package/dist/core/qa-loop/qa-loop-budget-policy.js +6 -2
  72. package/dist/core/qa-loop.js +8 -8
  73. package/dist/core/recallpulse/policy.js +2 -2
  74. package/dist/core/recallpulse.js +4 -5
  75. package/dist/core/release/gate-affected-globs.js +0 -1
  76. package/dist/core/research/mock-result.js +2 -2
  77. package/dist/core/research/research-adversarial-review.js +7 -7
  78. package/dist/core/research/research-claim-synthesizer.js +3 -3
  79. package/dist/core/research/research-falsification-runner.js +3 -3
  80. package/dist/core/research/research-super-search.js +5 -2
  81. package/dist/core/research/research-synthesis-prompt.js +2 -3
  82. package/dist/core/research/research-synthesis-writer.js +2 -2
  83. package/dist/core/research.js +5 -5
  84. package/dist/core/routes/design-policy.js +1 -2
  85. package/dist/core/routes/dollar-manifest-lite.js +2 -3
  86. package/dist/core/routes/evidence.js +1 -1
  87. package/dist/core/routes/ppt-policy.js +1 -2
  88. package/dist/core/routes.js +26 -15
  89. package/dist/core/runtime/task-profile.js +9 -5
  90. package/dist/core/subagents/agent-catalog.js +1 -2
  91. package/dist/core/subagents/model-policy.js +27 -45
  92. package/dist/core/subagents/model-tiers.js +153 -0
  93. package/dist/core/subagents/naruto-command-args.js +3 -3
  94. package/dist/core/subagents/naruto-help-contract.js +18 -13
  95. package/dist/core/subagents/naruto-host-credentials.js +8 -13
  96. package/dist/core/subagents/official-subagent-config.js +11 -7
  97. package/dist/core/subagents/official-subagent-preparation.js +12 -8
  98. package/dist/core/subagents/official-subagent-prompt.js +36 -36
  99. package/dist/core/subagents/official-subagent-runner.js +3 -3
  100. package/dist/core/subagents/role-model-preferences.js +26 -21
  101. package/dist/core/triwiki-wrongness/wrongness-schema.js +3 -4
  102. package/dist/core/update/managed-permission-repair.js +462 -0
  103. package/dist/core/update/project-migration-fanout-runner.js +56 -0
  104. package/dist/core/update/sks-project-registry.js +223 -0
  105. package/dist/core/update/update-migration-state/retired-local-decision.js +32 -2
  106. package/dist/core/update/update-migration-state/simple-stages.js +25 -1
  107. package/dist/core/update/update-migration-state.js +69 -9
  108. package/dist/core/update/update-operation.js +3 -0
  109. package/dist/core/update-check.js +35 -8
  110. package/dist/core/version.js +1 -1
  111. package/dist/native/sks-menubar/Sources/ControlCenterWindowController.swift +2 -0
  112. package/dist/native/sks-menubar/Sources/ImageGenerationModels.swift +341 -0
  113. package/dist/native/sks-menubar/Sources/ImageGenerationViewController.swift +330 -0
  114. package/dist/native/sks-menubar/Sources/SidebarItem.swift +2 -0
  115. package/dist/scripts/codex-native-agent-role-content-check.js +10 -5
  116. package/dist/scripts/codex-native-gate-lib.js +3 -1
  117. package/dist/scripts/current-surface-update-e2e-check.js +1 -0
  118. package/dist/scripts/mutation-callsite-coverage-check.js +2 -2
  119. package/dist/scripts/qa-loop-effort-escalation-check.js +4 -0
  120. package/dist/scripts/release-affected-selector-check.js +1 -2
  121. package/dist/scripts/typed-routing-gate-lib.js +3 -1
  122. package/package.json +1 -1
  123. package/release-gates.v2.json +2 -6
  124. package/dist/core/codex-app/openrouter-base-instructions.js +0 -1
  125. package/dist/core/research/research-prompt-contract.js +0 -23
@@ -0,0 +1,154 @@
1
+ import path from 'node:path';
2
+ import { flag, readOption } from '../cli/args.js';
3
+ import { printJson } from '../cli/output.js';
4
+ import { readDecisionConfig, jevEnabled } from '../core/decisions/config.js';
5
+ import { imagegenConfigPath, imagegenSelection, readImagegenConfig, writeImagegenConfig, isOpenRouterModelId } from '../core/imagegen/imagegen-config.js';
6
+ import { generateSksImage } from '../core/imagegen/imagegen-generate.js';
7
+ import { listOpenRouterImageModels } from '../core/imagegen/openrouter-images.js';
8
+ import { decideImagegenParameters } from '../core/imagegen/imagegen-jev.js';
9
+ import { resolveOpenRouterApiKey } from '../core/providers/openrouter/openrouter-secret-store.js';
10
+ export const IMAGEGEN_STATUS_SCHEMA = 'sks.imagegen-status.v1';
11
+ const USAGE = [
12
+ 'Usage: sks imagegen status|models|enable|disable|generate [options] [--json]',
13
+ ' status Show the active image mode (Codex default or custom OpenRouter model).',
14
+ ' models [--refresh] List OpenRouter models that output images.',
15
+ ' enable --model <id> Use this OpenRouter image model through the SKS Desktop Bridge.',
16
+ ' disable Go back to Codex default image generation.',
17
+ ' generate --prompt <text> --out <file> [--reference <file>]... [--aspect <ratio>] [--quality <q>]',
18
+ ' Make an image with the active mode and write evidence next to it.'
19
+ ].join('\n');
20
+ async function statusPayload(config, env, extra = {}) {
21
+ const selection = imagegenSelection(config);
22
+ const key = await resolveOpenRouterApiKey({ env }).catch(() => ({ key: null }));
23
+ const jev = await readDecisionConfig(env).then(jevEnabled).catch(() => false);
24
+ const warnings = [];
25
+ if (config.mode === 'openrouter' && !key.key)
26
+ warnings.push('openrouter_key_missing');
27
+ return {
28
+ schema: IMAGEGEN_STATUS_SCHEMA,
29
+ ok: true,
30
+ mode: config.mode,
31
+ custom_model_enabled: config.mode === 'openrouter',
32
+ openrouter_model: config.openrouter_model,
33
+ openrouter_key_present: Boolean(key.key),
34
+ effective: { provider: selection.mode, model: selection.model, label: selection.label },
35
+ jev_enabled: jev,
36
+ blockers: [],
37
+ warnings,
38
+ config_path: imagegenConfigPath(env),
39
+ ...extra
40
+ };
41
+ }
42
+ function print(payload, json) {
43
+ if (json) {
44
+ printJson(payload);
45
+ return;
46
+ }
47
+ if (payload.schema === IMAGEGEN_STATUS_SCHEMA) {
48
+ console.log(`Image generation: ${payload.effective?.label}`);
49
+ if (payload.custom_model_enabled && !payload.openrouter_key_present)
50
+ console.log('Warning: no OpenRouter key; add it in SKS Control Center (Connections, OpenRouter) or with `sks bridge provider configure openrouter --api-key-stdin`.');
51
+ for (const warning of payload.warnings || [])
52
+ if (warning !== 'openrouter_key_missing')
53
+ console.log(`Warning: ${warning}`);
54
+ for (const blocker of payload.blockers || [])
55
+ console.log(`Blocked: ${blocker}`);
56
+ return;
57
+ }
58
+ console.log(JSON.stringify(payload, null, 2));
59
+ }
60
+ function readAll(args, name) {
61
+ const out = [];
62
+ for (let i = 0; i < args.length; i++)
63
+ if (args[i] === name && args[i + 1])
64
+ out.push(args[i + 1]);
65
+ return out;
66
+ }
67
+ export async function run(_command, args = []) {
68
+ const env = process.env;
69
+ const json = flag(args, '--json');
70
+ const action = args.find((arg) => !arg.startsWith('-')) || 'status';
71
+ if (flag(args, '--help') || flag(args, '-h')) {
72
+ if (json)
73
+ printJson({ ok: true, command: 'imagegen', usage: USAGE, mutated: false });
74
+ else
75
+ console.log(USAGE);
76
+ return;
77
+ }
78
+ if (action === 'status') {
79
+ print(await statusPayload(await readImagegenConfig(env), env), json);
80
+ return;
81
+ }
82
+ if (action === 'models') {
83
+ const list = await listOpenRouterImageModels({ env, refresh: flag(args, '--refresh') });
84
+ const config = await readImagegenConfig(env);
85
+ const payload = { ...list, models: list.models.map((model) => ({ ...model, selected: model.id === config.openrouter_model })) };
86
+ if (json)
87
+ printJson(payload);
88
+ else
89
+ for (const model of payload.models)
90
+ console.log(`${model.selected ? '*' : ' '} ${model.id} ${model.name}`);
91
+ if (!list.ok)
92
+ process.exitCode = 1;
93
+ return;
94
+ }
95
+ if (action === 'enable') {
96
+ const model = String(readOption(args, '--model', '') || '').trim();
97
+ const before = await readImagegenConfig(env);
98
+ const fail = async (blocker) => {
99
+ print({ ...(await statusPayload(before, env)), ok: false, blockers: [blocker], changed: false }, json);
100
+ process.exitCode = 1;
101
+ };
102
+ if (!model)
103
+ return fail('imagegen_model_required');
104
+ if (!isOpenRouterModelId(model))
105
+ return fail('imagegen_model_not_image_capable');
106
+ const list = await listOpenRouterImageModels({ env });
107
+ if (!list.ok)
108
+ return fail(list.blockers[0] || 'openrouter_models_unavailable');
109
+ const row = list.models.find((candidate) => candidate.id === model);
110
+ if (!row)
111
+ return fail('imagegen_model_not_image_capable');
112
+ const next = await writeImagegenConfig({ mode: 'openrouter', openrouterModel: model }, env);
113
+ const payload = await statusPayload(next, env, { changed: before.mode !== next.mode || before.openrouter_model !== next.openrouter_model });
114
+ if (row.max_references === 0)
115
+ payload.warnings.push('imagegen_model_takes_no_reference_images');
116
+ print(payload, json);
117
+ return;
118
+ }
119
+ if (action === 'disable') {
120
+ const before = await readImagegenConfig(env);
121
+ const next = await writeImagegenConfig({ mode: 'codex' }, env);
122
+ print(await statusPayload(next, env, { changed: before.mode !== 'codex' }), json);
123
+ return;
124
+ }
125
+ if (action === 'generate') {
126
+ const prompt = String(readOption(args, '--prompt', '') || '').trim();
127
+ const out = String(readOption(args, '--out', '') || '').trim();
128
+ if (!prompt || !out) {
129
+ print({ schema: 'sks.imagegen-generate.v1', ok: false, blockers: [!prompt ? 'imagegen_prompt_required' : 'imagegen_out_required'], usage: USAGE }, json);
130
+ process.exitCode = 1;
131
+ return;
132
+ }
133
+ const references = readAll(args, '--reference').map((file) => path.resolve(file));
134
+ const explicitAspect = readOption(args, '--aspect', null);
135
+ const explicitQuality = readOption(args, '--quality', null);
136
+ const jev = explicitAspect && explicitQuality
137
+ ? null
138
+ : await decideImagegenParameters({ root: process.cwd(), prompt, hasReference: references.length > 0, ask: { aspect: !explicitAspect, quality: !explicitQuality }, env }).catch(() => null);
139
+ const result = await generateSksImage({
140
+ prompt,
141
+ outPath: path.resolve(out),
142
+ references,
143
+ aspectRatio: explicitAspect || jev?.aspectRatio || null,
144
+ quality: explicitQuality || jev?.quality || null,
145
+ env
146
+ });
147
+ print({ ...result, jev }, json);
148
+ if (!result.ok)
149
+ process.exitCode = 1;
150
+ return;
151
+ }
152
+ print({ ok: false, blockers: [`imagegen_unknown_action:${action}`], usage: USAGE }, json);
153
+ process.exitCode = 1;
154
+ }
@@ -1,12 +1,13 @@
1
1
  {
2
2
  "schema": "sks.skills-manifest.v1",
3
- "package_version": "10.3.3",
3
+ "package_version": "10.3.5",
4
4
  "skills": [
5
5
  {
6
6
  "canonical_name": "sks",
7
7
  "type": "official",
8
- "content_sha256": "d0288d27c8bc1c89decb258c6805ed4286cd0d65371ef0eec453be233b39a2a1",
8
+ "content_sha256": "8aa34586ba331f0447668c2ce863fe6c9ec4f881828ebed26ca5ecc754d66840",
9
9
  "hash_history": [
10
+ "d0288d27c8bc1c89decb258c6805ed4286cd0d65371ef0eec453be233b39a2a1",
10
11
  "905fc5472d36f0780b56f0e09404f42ea20293b1a4615d2050b7db3043231dbd",
11
12
  "6d90142f3617a8ae92d9af8cb2fc18ab58a7d0070868504e1fe89e0effc305a5",
12
13
  "5b17aeb1484e9e2b3791bff6dcb175f30857f47e71b36eb0340e575385e8e82b"
@@ -16,8 +17,9 @@
16
17
  {
17
18
  "canonical_name": "sks-align",
18
19
  "type": "core",
19
- "content_sha256": "b9db40d6e1dd2fc6e4665a2b30738d370da955cd4d6e86c88bd85059c7faa08c",
20
+ "content_sha256": "9eef36214be7e07a963eb36bb1df2c025cd0578b7419ddf4fd307081a2b62093",
20
21
  "hash_history": [
22
+ "b9db40d6e1dd2fc6e4665a2b30738d370da955cd4d6e86c88bd85059c7faa08c",
21
23
  "c485f39d4873adb9793672f7dcf4e956595ffb9dcbb032b3ffb0515b5857d31d",
22
24
  "e98e1b67e228bec5c37d00c0206a2e01d2da698a83c80b527105bf04a19c136a"
23
25
  ],
@@ -68,8 +70,9 @@
68
70
  {
69
71
  "canonical_name": "sks-commit",
70
72
  "type": "official",
71
- "content_sha256": "aa2eeaa6be6d635170a8ecfc76353db95552f543cca107f239054c492409e3a9",
73
+ "content_sha256": "63cad87de9187f67e001949b0edcf39344626748f8f168bed257316dc1684d53",
72
74
  "hash_history": [
75
+ "aa2eeaa6be6d635170a8ecfc76353db95552f543cca107f239054c492409e3a9",
73
76
  "aea41328993b11e26e26ae94df6ed44312d1570ed39448531428b53ade9d7461",
74
77
  "943c6dcf822df086b320140e74404d4c7bcfd531264e25ada6624b5009f26207"
75
78
  ],
@@ -78,8 +81,9 @@
78
81
  {
79
82
  "canonical_name": "sks-commit-and-push",
80
83
  "type": "official",
81
- "content_sha256": "acd6c7845c58d72234776e4608e1440583c62c38b513625d1272e4a413a40fb6",
84
+ "content_sha256": "2307093e26513a26e71ac6cdfcf3fd1598979c6035525ee5d3de58820cb4adda",
82
85
  "hash_history": [
86
+ "acd6c7845c58d72234776e4608e1440583c62c38b513625d1272e4a413a40fb6",
83
87
  "8e4ff7a39440c82e6c67a67d5bb267c69f508cedb5d9d5a93261f4dcdf8e8a1a",
84
88
  "b005b4a7456b80b95768ad358fe5950bf517483c6de71aec14ee3d1c600cc074"
85
89
  ],
@@ -154,8 +158,9 @@
154
158
  {
155
159
  "canonical_name": "sks-design-artifact-expert",
156
160
  "type": "official",
157
- "content_sha256": "6db9a7088e5f8d21dec9c8eed00abe665e1e89f19dcbb6d8472d77e4551cb556",
161
+ "content_sha256": "6881c1acff42b3cc760f089165a6ea753c774882bf0ec989b71f14936e894690",
158
162
  "hash_history": [
163
+ "6db9a7088e5f8d21dec9c8eed00abe665e1e89f19dcbb6d8472d77e4551cb556",
159
164
  "a09daba0a2e479a68ed81ec6fba8d70e54c8398ed86f3d1879f874b98480b97c",
160
165
  "4a28d166eaf0bc4477b566b056034f972a7034165e36d8186daa9947bf92e3cf"
161
166
  ],
@@ -164,8 +169,9 @@
164
169
  {
165
170
  "canonical_name": "sks-design-system-builder",
166
171
  "type": "official",
167
- "content_sha256": "47654c9f74317abbd0a5a75f89cd2d563708e8234e8887cc7ab39bf49030abaa",
172
+ "content_sha256": "9075bc17039da34ddd7d798009fdbcdedb8d03358a29c9a925d194bd76e9dcc4",
168
173
  "hash_history": [
174
+ "47654c9f74317abbd0a5a75f89cd2d563708e8234e8887cc7ab39bf49030abaa",
169
175
  "0a41e6ace960abaaf6abf5e7b1e53fd39f414e1e00b59fa725f2db9e3eb05b58",
170
176
  "c4f0007cad5774510bdc55e2815ce0911c220afa8d5dd4efc327ba1231c8f3da"
171
177
  ],
@@ -174,8 +180,9 @@
174
180
  {
175
181
  "canonical_name": "sks-design-ui-editor",
176
182
  "type": "official",
177
- "content_sha256": "2f9087664d8abe938a6dfbeaef5301ef00531e34a15506508e1d6d6b7132b894",
183
+ "content_sha256": "c3bc8bbaac134f7d742cd5e4bed7dd61a99655c54a6bd42f669e6bdd033156fb",
178
184
  "hash_history": [
185
+ "2f9087664d8abe938a6dfbeaef5301ef00531e34a15506508e1d6d6b7132b894",
179
186
  "6c24e950a12dec52c625964069c7c21a0220a58e0f69f977d802f44fdb03a940",
180
187
  "83a806cc93a3c5342e0dccfc6a45983382d5bf74d1226c4e3288228db22b737a",
181
188
  "1b65f0028a6dcb2f7eeab0b0df411a75546bc3aefa8a76067e1818da000c2249"
@@ -247,8 +254,9 @@
247
254
  {
248
255
  "canonical_name": "sks-goal",
249
256
  "type": "official",
250
- "content_sha256": "36c12285a339f9505fd88d6d9ea5691e451449f0bf8f55c21f51f0d715623235",
257
+ "content_sha256": "942c5e8db400cc1cd2b5ca9527124135fb4b8d9e8289338632d8929691aa54ed",
251
258
  "hash_history": [
259
+ "36c12285a339f9505fd88d6d9ea5691e451449f0bf8f55c21f51f0d715623235",
252
260
  "5ab1ac18fc265c375bae92ff23ddbd80c378484d6629c378f0e9270e660ded11",
253
261
  "867544877ac04df6e0232d6d425797e7fab2cceff9a7176a3c9e61f8c4a416d7",
254
262
  "0db0c58e72c0d58b24163371efe7a647c67d5d232020b2b4ed2557f19fe648d7"
@@ -341,8 +349,9 @@
341
349
  {
342
350
  "canonical_name": "sks-image-ux-review",
343
351
  "type": "core",
344
- "content_sha256": "c7a5ea91adb0d45e652066cdb73f514cc7fcb47121cc13cce5e177f94630a42a",
352
+ "content_sha256": "643400c1682aaa4a84782e3740eb14efb0ddb905a84c086bd9a0f8afdabd5f02",
345
353
  "hash_history": [
354
+ "c7a5ea91adb0d45e652066cdb73f514cc7fcb47121cc13cce5e177f94630a42a",
346
355
  "54d4169dc7f362ac9fe2d090bd2612e41d30acbc3e883d6bd382929bdfb9459e",
347
356
  "9293346873b5fb25a9d93b630064a2c8ceede2bfdfa4c6ffe7fbb7f64da6595c"
348
357
  ],
@@ -351,8 +360,9 @@
351
360
  {
352
361
  "canonical_name": "sks-imagegen",
353
362
  "type": "official",
354
- "content_sha256": "ebad63dae59ff70a4404148d09bffaca69e6c43e88d6e9f6f3d0dc4d5a4c65f6",
363
+ "content_sha256": "0f3ba271f2977d1124b8236e25f5e05a3d03af234652e39601dc5054346e306c",
355
364
  "hash_history": [
365
+ "ebad63dae59ff70a4404148d09bffaca69e6c43e88d6e9f6f3d0dc4d5a4c65f6",
356
366
  "478e3d8f805eed55c3f3e6c2069142482a7dbd8fa5d9a59f03b136e0e1cb77d0",
357
367
  "a7f466ba1829a757f38432fbe8c3a672e22e91948537dafe8f8ce09561d2256e",
358
368
  "7a1f9372b03975886233a623031f41e06fd782b1e7a3409517bb428d9c6b76dd"
@@ -362,8 +372,9 @@
362
372
  {
363
373
  "canonical_name": "sks-imagegen-source-scout",
364
374
  "type": "official",
365
- "content_sha256": "b306134faf487b86e11a9736ea1ed60d2335eef858e58bedc80fd3dc4ff7137c",
375
+ "content_sha256": "84957463d326f0f7028fc47aabb3f1857c76f13534e3aed1c9fc1b075896dbd1",
366
376
  "hash_history": [
377
+ "b306134faf487b86e11a9736ea1ed60d2335eef858e58bedc80fd3dc4ff7137c",
367
378
  "440f361fb29afcbb6f6cdc88c6a7318953b4c8fd3181ef7c6d8187f091d18745",
368
379
  "95faf4358f1c6567ca6894bfb577629f14a23d623716be70325c0ff9a893d42e",
369
380
  "95e71d4431a4c1f6911f0f76eaa1c2b475c52fd22d35c0a6c241e21e090507ad",
@@ -393,15 +404,15 @@
393
404
  {
394
405
  "canonical_name": "sks-naruto",
395
406
  "type": "core",
396
- "content_sha256": "65e19a5d16f486b13541048c239e828f8039bfc6e38bafd7949d9c936fe4b5b2",
407
+ "content_sha256": "c88999663811a50d096b7cbb696fbea5b8f72707bcbf4a232bb07fe3a10cb2a6",
397
408
  "hash_history": [
409
+ "b2eb207b2773ab1995ee6e113ba6f3b64de43389e76aef4a0f06d4845ff86223",
410
+ "65e19a5d16f486b13541048c239e828f8039bfc6e38bafd7949d9c936fe4b5b2",
398
411
  "da43debf97f0b4a1583d8202a7306aca97ac97865accf9bca8f41d75c84a1cb9",
399
412
  "b981bea4183376c6c0204941ad6c2e78782e2cdea4f8d25cc85630c609faaf95",
400
413
  "5df9c9678eb68fd79ceb998ae7a52dd54dc92336ad5169e8a01acca89f76bd60",
401
414
  "a1219f6dbad9c8c185953125ef0b8dccf081aa01efb8e8acaa543c6214ac049c",
402
415
  "d0d5968e78ac25e1d3e588735de1ddbcf149cfb3165edebca5dec1ed7c7a5c46",
403
- "34222c72e4e1ead3584907f4d905444b7de820283ee7348018f110d5e6b04461",
404
- "f8e808622e222b4ad7dcb2907e5f06a890db83139ae443ec6c8c33781dfa3e37",
405
416
  "49b5e3dcc1b537b49c2cf09e5b875cb16acb05c622b22798e265e64dacd8ac90"
406
417
  ],
407
418
  "deprecated_aliases": []
@@ -419,8 +430,10 @@
419
430
  {
420
431
  "canonical_name": "sks-pipeline-runner",
421
432
  "type": "official",
422
- "content_sha256": "7749638f1e8393f3beb1f7b0c37195dd0463abdb6fd7da5d31b3d816ee91fa37",
433
+ "content_sha256": "15159b6f6edea91be29612fe3cee2047d8ec47f4f7c95a33601198a9bfec3eda",
423
434
  "hash_history": [
435
+ "6f38d3387e4ab020291afe7f74713b135543e52707f5bfbffa6b3584542f45a5",
436
+ "7749638f1e8393f3beb1f7b0c37195dd0463abdb6fd7da5d31b3d816ee91fa37",
424
437
  "fd06dfb27be41e5ffec3e3ec8c5362289f5919cf2afa9da5ab6b97e7baa4a0ac",
425
438
  "66e105773b8e042eec5d5679b97b7cb305cad8d45671034907fbfa728fc4d68a",
426
439
  "020ba4da2f96bcda23cee4596b1e790816780178f1917dee748ff4b289cba0e5",
@@ -431,8 +444,9 @@
431
444
  {
432
445
  "canonical_name": "sks-plan",
433
446
  "type": "official",
434
- "content_sha256": "7795867b38a5f169924125850f137c31995cf28000f74284839530a68ace156a",
447
+ "content_sha256": "81b49b026cd6761a1b63029d8d39b830e0801a7f3d2f9a8609127769173ddd4e",
435
448
  "hash_history": [
449
+ "7795867b38a5f169924125850f137c31995cf28000f74284839530a68ace156a",
436
450
  "b6f3b09230e9809acf4e13df2de6af3c75a8534e8890d6560664ebfc2e4072f8"
437
451
  ],
438
452
  "deprecated_aliases": []
@@ -440,8 +454,9 @@
440
454
  {
441
455
  "canonical_name": "sks-ppt",
442
456
  "type": "official",
443
- "content_sha256": "fba3f438b9f22dae0813cd12bf310539a7d2b71c8cd9322eb840514e24884eaf",
457
+ "content_sha256": "a25e537ff49b5bffdc093a5f772a8d218003ca1bb81e0aa304561684a9551b31",
444
458
  "hash_history": [
459
+ "fba3f438b9f22dae0813cd12bf310539a7d2b71c8cd9322eb840514e24884eaf",
445
460
  "c9a0d90e12560dd3f04959869051370e6baf46eda6eb63f708ea1661c5c9d041",
446
461
  "1d4de05afd42ee5739c0ed925af9e0ac4785fc746e659c60d3d908d465e6386c",
447
462
  "02e8a0758ec6d056ce9851a5a4505b1d32e302e730be3eb169a41392a5d6b2e2",
@@ -452,8 +467,10 @@
452
467
  {
453
468
  "canonical_name": "sks-prompt-pipeline",
454
469
  "type": "official",
455
- "content_sha256": "93fd938dccd65d9b4d1dd140b60e1baedc627e7fcc54f9afd95eb2e44efd1143",
470
+ "content_sha256": "5e423981384fc3825c74327c4ca0fe09905a0dc81a533676c7e76ebb385348fc",
456
471
  "hash_history": [
472
+ "f82a103e7962e416961add515d7b3e65df89848dec1fbb9319bd49d7f1dac982",
473
+ "93fd938dccd65d9b4d1dd140b60e1baedc627e7fcc54f9afd95eb2e44efd1143",
457
474
  "033bb114ec1fac3f8c312f698b1861ed4c2ce6f65c06f4f1a872c4b101b74b92",
458
475
  "e7c8ef56d38fdc4879c983f7d6706f26fc1cf0a60c508836bd628e815700bcc3",
459
476
  "480c8afffafa9d52c483a963b4b8fafdffc0a47cd6d2efd3fb6d7924c11832c5",
@@ -473,8 +490,9 @@
473
490
  {
474
491
  "canonical_name": "sks-reasoning-router",
475
492
  "type": "official",
476
- "content_sha256": "41e14e8d5b93d743096664869ee68c41c86e911b0bbc165bdcd10e4a45faa4b6",
493
+ "content_sha256": "b0f458caa1c3bd7bb7241a09b80fce5700aeb99b340e84c08a9b2b66bc875ba7",
477
494
  "hash_history": [
495
+ "41e14e8d5b93d743096664869ee68c41c86e911b0bbc165bdcd10e4a45faa4b6",
478
496
  "03d68436e568b3cee2bffc6ca58819019ca406f7b648ef4704e3465c7c83c114",
479
497
  "647f730520a1c7dc89c2642f5b8502624c65a861ae41aecf1fb137db40fd0611",
480
498
  "da0ddb58adc68ddeebdb9c45bf111c26eaa64d3e9dffe1dd39d7f30b943b8b88",
@@ -508,8 +526,9 @@
508
526
  {
509
527
  "canonical_name": "sks-research",
510
528
  "type": "core",
511
- "content_sha256": "d61163446ebc429974aad8467653ddb5948739978600e9c27bff385fc53968ba",
529
+ "content_sha256": "b7280ca8a5ccf4304d25e97522d57968d20af6ec9f03f7d55a251ebcf8666236",
512
530
  "hash_history": [
531
+ "d61163446ebc429974aad8467653ddb5948739978600e9c27bff385fc53968ba",
513
532
  "8903022e98fa470cd764f7c8d1b28d4f996d6daf146260f20548acbe1276c55a",
514
533
  "2e96f95315d99b645d4171ba4648d9f9218ec3e98dcd6d363b5de522d2e1bfe3"
515
534
  ],
@@ -1,6 +1,7 @@
1
1
  import { codexModelEffortCapability } from '../codex-control/codex-model-capabilities.js';
2
2
  import { managedOfficialSubagentRoleByName } from '../managed-assets/managed-assets-manifest.js';
3
- import { ASTRA_SUBAGENT_MODEL, decideSubagentModel, subagentModelProfile } from '../subagents/model-policy.js';
3
+ import { decideSubagentModel, subagentModelProfile } from '../subagents/model-policy.js';
4
+ import { MODEL_TIERS, resolveLatestModelTiers } from '../subagents/model-tiers.js';
4
5
  export function decideAgentEffort(input = {}) {
5
6
  return decideOfficialSubagentModel(input);
6
7
  }
@@ -38,14 +39,14 @@ export function decideOfficialSubagentModel(input = {}) {
38
39
  reason: `managed_role:${managedRole.codex_name}:${profile.policy}`,
39
40
  dynamic: true,
40
41
  escalation_triggers: [
41
- 'focused review, debugging, planning, integration, security, database, research, release, or unresolved ambiguity selects Astra Max',
42
+ 'focused review, debugging, planning, integration, security, database, research, release, or unresolved ambiguity selects the deep tier',
42
43
  'incidental judgment vocabulary does not override a clearly classified implementation or context/tools slice',
43
44
  'requested model/effort profile unavailable blocks instead of silently falling back'
44
45
  ],
45
46
  downshift_triggers: [
46
- 'instructed UI, logic, backend, or native implementation selects Astra Low',
47
- 'long-context, Browser/Chrome, Computer Use, image-generation, or large search selects Astra Medium',
48
- 'tiny short-context mechanical search/typing/rename work selects Astra Low'
47
+ 'instructed UI, logic, backend, or native implementation selects the balanced tier',
48
+ 'long-context, Browser/Chrome, Computer Use, image-generation, or large search selects the context tier',
49
+ 'tiny short-context mechanical search/typing/rename work selects the balanced tier'
49
50
  ]
50
51
  };
51
52
  }
@@ -92,14 +93,14 @@ export function decideOfficialSubagentModel(input = {}) {
92
93
  reason: routed.reason,
93
94
  dynamic: true,
94
95
  escalation_triggers: [
95
- 'focused review, debugging, planning, integration, security, database, research, release, or unresolved ambiguity selects Astra Max',
96
+ 'focused review, debugging, planning, integration, security, database, research, release, or unresolved ambiguity selects the deep tier',
96
97
  'incidental judgment vocabulary does not override a clearly classified implementation or context/tools slice',
97
98
  'requested model/effort profile unavailable blocks instead of silently falling back'
98
99
  ],
99
100
  downshift_triggers: [
100
- 'instructed UI, logic, backend, or native implementation selects Astra Low',
101
- 'long-context, Browser/Chrome, Computer Use, or image-generation execution selects Astra Medium',
102
- 'tiny short-context mechanical work selects Astra Low'
101
+ 'instructed UI, logic, backend, or native implementation selects the balanced tier',
102
+ 'long-context, Browser/Chrome, Computer Use, or image-generation execution selects the context tier',
103
+ 'tiny short-context mechanical work selects the balanced tier'
103
104
  ]
104
105
  };
105
106
  }
@@ -118,21 +119,22 @@ export function buildAgentEffortPolicy(roster = {}) {
118
119
  reason: agent.reasoning_reason,
119
120
  dynamic: true
120
121
  })) : [];
122
+ const latest = resolveLatestModelTiers();
121
123
  return {
122
124
  schema: 'sks.agent-effort-policy.v1',
123
125
  policy_version: 1,
124
126
  dynamic: true,
125
127
  service_tier: 'fast',
126
128
  model_catalog_policy: 'official_subagent_four_profile_matrix',
127
- model_constraint: [ASTRA_SUBAGENT_MODEL],
128
- model_tiers: ['low', 'medium', 'high', 'max'].map((effort) => `${ASTRA_SUBAGENT_MODEL}-${effort}`),
129
+ model_constraint: [...new Set(MODEL_TIERS.map((tier) => latest.models[tier]))],
130
+ model_tiers: MODEL_TIERS.map((tier) => `${tier}:${latest.models[tier]}-${latest.efforts[tier]}`),
129
131
  allowed_efforts: ['low', 'medium', 'high', 'max'],
130
- model_effort_capability: codexModelEffortCapability({ model: ASTRA_SUBAGENT_MODEL }),
132
+ model_effort_capability: codexModelEffortCapability({ model: latest.models.deep }),
131
133
  max_agents: roster.max_agents || 20,
132
134
  agent_count: roster.agent_count || decisions.length,
133
135
  concurrency: roster.concurrency || decisions.length,
134
136
  decisions,
135
- rule: 'All child agents use GPT-6 Astra: Low for tiny short-context mechanical work and instructed implementation, Medium for reads and tool execution, and Max for focused judgment. The parent keeps its user-selected model, reasoning effort, and service tier; explicit Astra effort preferences may override role defaults.'
137
+ rule: 'Every child uses the newest model of the tier its work needs: fast for tiny mechanical work, balanced for instructed implementation, context for reads and tool execution, and deep for focused judgment. With Jev mode on, Jev picks the tier for each spawn. The parent keeps its user-selected model, reasoning effort, and service tier; stored role preferences may override role defaults.'
136
138
  };
137
139
  }
138
140
  export function reasoningProfileName(effort) {
@@ -10,7 +10,9 @@ import { leanEngineeringCompactText, leanPolicyReference } from '../lean-enginee
10
10
  import { readCodexLbModelCatalog, readLbHealth } from '../codex-lb/codex-lb-env.js';
11
11
  import { categoryForWorkerRole, isNarutoGpt56Model, modelRouteReason, routeModel } from '../provider/model-router.js';
12
12
  import { codexTimeoutClassForRoute } from '../codex-control/codex-reliability-shield.js';
13
- import { ASTRA_SUBAGENT_MODEL, decideSubagentModel } from '../subagents/model-policy.js';
13
+ import { decideSubagentModel } from '../subagents/model-policy.js';
14
+ import { latestTierModelSet } from '../subagents/model-tiers.js';
15
+ import { consultJevTurnModel } from '../decisions/integration.js';
14
16
  export const NATIVE_WORKER_BACKEND_ROUTER_SCHEMA = 'sks.native-worker-backend-router.v1';
15
17
  export async function runNativeWorkerBackendRouter(input) {
16
18
  const root = path.resolve(input.agentRoot);
@@ -241,15 +243,27 @@ export async function resolveWorkerModelRouting(input, deps = {}) {
241
243
  const explicitNarutoModelInvalid = narutoOnly && Boolean(explicitModel) && !isNarutoGpt56Model(explicitModel);
242
244
  const explicitNarutoReasoningInvalid = narutoOnly && Boolean(explicitReasoningRaw) && !explicitReasoning;
243
245
  const explicitNarutoTierInvalid = narutoOnly && Boolean(explicitTierRaw) && !explicitTier;
244
- const savedAstraEffort = input.agent?.routed_model_policy === 'user_role_model_preference'
245
- && input.agent?.routed_model === ASTRA_SUBAGENT_MODEL
246
+ const currentModels = latestTierModelSet();
247
+ const savedPreferenceModel = input.agent?.routed_model_policy === 'user_role_model_preference'
248
+ && currentModels.has(String(input.agent?.routed_model || ''))
249
+ ? String(input.agent?.routed_model)
250
+ : '';
251
+ const savedAstraEffort = savedPreferenceModel
246
252
  ? normalizeModelReasoning(input.agent?.routed_model_reasoning_effort)
247
253
  : null;
248
254
  const jevModel = !explicitModel && input.agent?.routed_model_policy === 'jev_sealed_routing'
249
255
  ? String(input.agent.routed_model || '').trim()
250
256
  : '';
251
257
  const jevEffort = jevModel ? normalizeModelReasoning(input.agent?.routed_model_reasoning_effort) : null;
252
- const selectedModel = explicitModel || jevModel;
258
+ const consult = deps.consultJev === false ? null : deps.consultJev || consultJevTurnModel;
259
+ const liveJev = consult && !explicitModel && !jevModel && !savedPreferenceModel
260
+ ? await consult({ root: deps.root || process.cwd(), prompt: `${taskKindText}\n${riskText}`.trim().slice(0, 1200), roleId: 'spawn', env }).catch(() => null)
261
+ : null;
262
+ const liveJevServed = Boolean(liveJev?.model && currentModels.has(liveJev.model)
263
+ && (!narutoOnly || (Array.isArray(lbCatalog?.models) && lbCatalog.models.includes(liveJev.model))));
264
+ const liveJevModel = liveJevServed ? String(liveJev.model) : '';
265
+ const liveJevEffort = liveJevModel ? normalizeModelReasoning(liveJev?.effort) : null;
266
+ const selectedModel = explicitModel || jevModel || savedPreferenceModel || liveJevModel;
253
267
  const taskPolicy = decideSubagentModel({ title: taskKindText, description: riskText, role: input.agent?.role });
254
268
  const routed = narutoOnly
255
269
  ? await routeModel(category, {
@@ -257,20 +271,20 @@ export async function resolveWorkerModelRouting(input, deps = {}) {
257
271
  narutoOnly: true,
258
272
  taskText: taskKindText,
259
273
  riskText,
260
- reasoningEffort: jevEffort || savedAstraEffort,
274
+ reasoningEffort: jevEffort || savedAstraEffort || liveJevEffort,
261
275
  availableModels: lbCatalog?.models || [],
262
276
  availableModelEfforts: lbCatalog?.model_efforts || {},
263
277
  ...(selectedModel ? { model: selectedModel } : {})
264
278
  })
265
279
  : {
266
- model: ASTRA_SUBAGENT_MODEL,
267
- reasoning: explicitReasoning || savedAstraEffort || taskPolicy.modelReasoningEffort,
280
+ model: (explicitModel && currentModels.has(explicitModel) ? explicitModel : '') || savedPreferenceModel || liveJevModel || taskPolicy.model,
281
+ reasoning: explicitReasoning || savedAstraEffort || liveJevEffort || taskPolicy.modelReasoningEffort,
268
282
  serviceTier: explicitTier || input.fastModePolicy.service_tier || 'fast'
269
283
  };
270
284
  const blockers = [
271
285
  ...(narutoOnly && !lbCatalog?.ok ? (lbCatalog?.blockers || ['codex_lb_model_catalog_unavailable']) : []),
272
- ...(explicitNarutoModelInvalid ? ['naruto_worker_model_outside_gpt_5_6_family'] : []),
273
- ...(!narutoOnly && explicitModel && explicitModel !== ASTRA_SUBAGENT_MODEL ? ['subagent_model_must_be_astra'] : []),
286
+ ...(explicitNarutoModelInvalid ? ['naruto_worker_model_not_current'] : []),
287
+ ...(!narutoOnly && explicitModel && !currentModels.has(explicitModel) ? ['subagent_model_must_be_current'] : []),
274
288
  ...(explicitNarutoReasoningInvalid ? ['naruto_reasoning_override_invalid'] : []),
275
289
  ...(explicitNarutoTierInvalid ? ['naruto_service_tier_override_invalid'] : []),
276
290
  ...(narutoOnly && explicitReasoning && explicitReasoning !== routed.reasoning ? ['naruto_reasoning_override_conflicts_with_policy'] : []),
@@ -306,7 +320,7 @@ export function narutoWorkerBackendBlocker(backend, narutoRequest = true) {
306
320
  if (!narutoRequest)
307
321
  return null;
308
322
  if (backend === 'process')
309
- return 'naruto_gpt_5_6_family_only_process_backend_forbidden';
323
+ return 'naruto_process_backend_forbidden';
310
324
  return null;
311
325
  }
312
326
  function normalizeBackend(value) {
@@ -1,4 +1,3 @@
1
- import { IMAGEGEN_MODEL } from '../imagegen/imagegen-model-policy.js';
2
1
  import path from 'node:path';
3
2
  import { nowIso, readJson, readText, writeJsonAtomic } from '../fsx.js';
4
3
  export const OFFICIAL_SUBAGENT_HELPER_POLICY_SCHEMA = 'sks.official-subagent-helper-policy.v1';
@@ -43,7 +42,7 @@ export async function writeOfficialSubagentHelperPolicy(root, input = {}) {
43
42
  built_in_agents_allowed: builtInAgentsAllowed,
44
43
  codex_app_capabilities_allowed: codexAppCapabilitiesAllowed,
45
44
  codex_builtin_imagegen_helper_allowed: true,
46
- preferred_image_generation_surface: ("Selected image provider: " + IMAGEGEN_MODEL + ""),
45
+ preferred_image_generation_surface: 'Active SKS image mode via sks imagegen generate',
47
46
  codex_app_builtin_evidence_class: 'codex_app_builtin',
48
47
  api_fallback_evidence_class: 'api_fallback',
49
48
  provider_surface_evidence_required: true,
@@ -34,6 +34,8 @@ export const NATIVE_SOURCE_FILES = [
34
34
  'SettingsViewController.swift',
35
35
  'LocalDecisionModels.swift',
36
36
  'LocalDecisionViewController.swift',
37
+ 'ImageGenerationModels.swift',
38
+ 'ImageGenerationViewController.swift',
37
39
  'OperationModels.swift',
38
40
  'ProviderRouteExplanation.swift',
39
41
  'OperationCoordinator.swift',
@@ -1,4 +1,4 @@
1
- import { IMAGEGEN_MODEL, CODEX_BUILTIN_IMAGEGEN_MODEL } from './imagegen/imagegen-model-policy.js';
1
+ import { CODEX_BUILTIN_IMAGEGEN_MODEL } from './imagegen/imagegen-model-policy.js';
2
2
  import path from 'node:path';
3
3
  import os from 'node:os';
4
4
  import fsp from 'node:fs/promises';
@@ -484,7 +484,7 @@ function codexNativeSksMenuStatus() {
484
484
  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: [] }, providerModelUi = null, nativeSksMenu = null, gitActions = { ok: true, blockers: [] }, imageGenerationReady, inAppBrowserReady, browserUseFeatureReady, computerUseReady, browserUseReady, browserToolReady, computerUseMcpListed, browserUseMcpListed, chromeExtension, remoteControl }) {
485
485
  const lines = [];
486
486
  if (!appInstalled) {
487
- lines.push(("Install and open Codex App for first-party MCP/plugin tools. Base Codex CLI flows remain available, but Codex Computer Use requires the App; imagegen/" + IMAGEGEN_MODEL + " evidence will be unavailable until Codex App is ready."));
487
+ lines.push(("Install and open Codex App for first-party MCP/plugin tools. Base Codex CLI flows remain available, but Codex Computer Use requires the App; imagegen evidence from Codex App will be unavailable until Codex App is ready; `sks imagegen generate` still works through the SKS Desktop Bridge."));
488
488
  lines.push(`Docs: ${CODEX_APP_DOCS_URL}`);
489
489
  }
490
490
  if (!codex?.bin)
@@ -572,10 +572,10 @@ export function codexAppGuidance({ appInstalled, codex, mcpList, featureList, re
572
572
  lines.push('Codex Chrome Extension is ready; SKS web/browser/webapp QA and UX review should use it before any other web surface.');
573
573
  }
574
574
  if (imageGenerationReady) {
575
- lines.push(("The built-in image tool is enabled. Current-model image work requires a provider that explicitly selects " + IMAGEGEN_MODEL + " and record real output."));
575
+ lines.push("The built-in image tool is enabled. SKS image work follows the active SKS image mode (`sks imagegen status`) and records real output.");
576
576
  }
577
577
  else if (appInstalled || codex?.bin) {
578
- lines.push(("Codex image_generation was not visible from `codex features list`. Required imagegen/" + IMAGEGEN_MODEL + " evidence must stay blocked or unverified until $imagegen is available in Codex App."));
578
+ lines.push(("Codex image_generation was not visible from `codex features list`. Codex-default image evidence stays unverified until $imagegen is available in Codex App; `sks imagegen generate` can still produce it through the SKS Desktop Bridge, and the custom OpenRouter image mode does not need it."));
579
579
  lines.push('Run: sks doctor --fix to attempt Codex CLI/App image_generation repair, then rerun the blocked visual route.');
580
580
  }
581
581
  if (computerUseReady && !computerUseMcpListed) {
@@ -589,7 +589,7 @@ export function codexAppGuidance({ appInstalled, codex, mcpList, featureList, re
589
589
  lines.push('Browser Use plugin files are installed, but `codex mcp list` does not list a browser-use MCP server. Treat Browser Use as plugin-scoped, not as SKS browser verification evidence.');
590
590
  }
591
591
  if (!lines.length)
592
- lines.push(("Codex App, Codex CLI, Chrome Extension, native Computer Use, Browser tooling, and built-in image feature checks look configured. Web UI E2E uses the Chrome Extension path; native non-web visual evidence uses Computer Use; generated image evidence still requires $imagegen/" + IMAGEGEN_MODEL + " output."));
592
+ lines.push(("Codex App, Codex CLI, Chrome Extension, native Computer Use, Browser tooling, and built-in image feature checks look configured. Web UI E2E uses the Chrome Extension path; native non-web visual evidence uses Computer Use; generated image evidence still requires real output from the active SKS image mode."));
593
593
  return lines;
594
594
  }
595
595
  export function formatCodexAppStatus(status, { includeRaw = false } = {}) {
@@ -610,7 +610,7 @@ export function formatCodexAppStatus(status, { includeRaw = false } = {}) {
610
610
  `Chrome Ext: ${status.chrome_extension?.ok ? 'ok' : `setup ${(status.chrome_extension?.blockers || []).join(', ') || 'required'}`}`,
611
611
  `Computer Use:${status.mcp.has_computer_use ? status.mcp.computer_use_source === 'plugin_cache' ? ' installed (verify @Computer in thread)' : ' ok' : ' missing'}`,
612
612
  `Browser: ${status.features?.browser_tool_ready ? `ok (${status.features.browser_tool_source})` : status.mcp.has_browser_use ? status.mcp.browser_use_source === 'plugin_cache' ? 'installed (plugin scoped)' : 'ok' : 'missing'}`,
613
- `Image Gen: ${status.features?.image_generation ? (`enabled (${CODEX_BUILTIN_IMAGEGEN_MODEL}; ${IMAGEGEN_MODEL} provider unverified)`) : status.features?.checked ? 'missing' : 'not checked'}`,
613
+ `Image Gen: ${status.features?.image_generation ? (`enabled (Codex built-in, documented engine ${CODEX_BUILTIN_IMAGEGEN_MODEL}; SKS image mode: sks imagegen status)`) : status.features?.checked ? 'missing' : 'not checked'}`,
614
614
  `Ready: ${status.ok ? 'yes' : 'no'}`,
615
615
  '',
616
616
  ...status.guidance.map((line) => `- ${line}`)