sneakoscope 10.3.4 → 10.3.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 (83) hide show
  1. package/README.md +203 -3
  2. package/config/skills-hash-ledger.v1.json +17 -1
  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 +1 -2
  9. package/dist/commands/imagegen.js +154 -0
  10. package/dist/config/skills-manifest.json +35 -19
  11. package/dist/core/agents/native-worker-backend-router.js +13 -4
  12. package/dist/core/agents/official-subagent-helper-policy.js +1 -2
  13. package/dist/core/codex-app/menubar/constants.js +2 -0
  14. package/dist/core/codex-app.js +6 -6
  15. package/dist/core/codex-lb/desktop-bridge/imagegen-endpoint.js +95 -0
  16. package/dist/core/codex-lb/desktop-bridge/server.js +6 -1
  17. package/dist/core/codex-lb/desktop-bridge/types.js +1 -0
  18. package/dist/core/codex-native/core-skill-manifest.js +4 -5
  19. package/dist/core/codex-native/native-capability-repair-matrix.js +4 -5
  20. package/dist/core/commands/image-ux-review-command.js +6 -7
  21. package/dist/core/commands/ppt-command.js +3 -4
  22. package/dist/core/commands/qa-loop-command.js +28 -3
  23. package/dist/core/decisions/cli.js +1 -1
  24. package/dist/core/decisions/integration.js +51 -0
  25. package/dist/core/decisions/policy.js +27 -0
  26. package/dist/core/decisions/questions.js +44 -3
  27. package/dist/core/decisions/types.js +2 -0
  28. package/dist/core/doctor/doctor-readiness-matrix.js +1 -2
  29. package/dist/core/doctor/imagegen-repair.js +3 -4
  30. package/dist/core/feature-fixtures.js +1 -0
  31. package/dist/core/feature-registry.js +3 -3
  32. package/dist/core/hooks-runtime/hook-context.js +2 -2
  33. package/dist/core/hooks-runtime/hook-io.js +1 -2
  34. package/dist/core/hooks-runtime/jev-turn-plan.js +81 -0
  35. package/dist/core/hooks-runtime/managed-guidance-preflight.js +24 -4
  36. package/dist/core/hooks-runtime.js +29 -5
  37. package/dist/core/image-ux-review/imagegen-adapter.js +159 -316
  38. package/dist/core/image-ux-review.js +28 -20
  39. package/dist/core/imagegen/imagegen-auth-readiness.js +10 -8
  40. package/dist/core/imagegen/imagegen-capability.js +79 -14
  41. package/dist/core/imagegen/imagegen-config.js +45 -0
  42. package/dist/core/imagegen/imagegen-evidence.js +14 -2
  43. package/dist/core/imagegen/imagegen-generate.js +284 -0
  44. package/dist/core/imagegen/imagegen-jev.js +53 -0
  45. package/dist/core/imagegen/imagegen-model-policy.js +2 -5
  46. package/dist/core/imagegen/imagegen-request-validator.js +3 -3
  47. package/dist/core/imagegen/openrouter-images.js +288 -0
  48. package/dist/core/imagegen/require-imagegen.js +14 -7
  49. package/dist/core/init/skills.js +43 -14
  50. package/dist/core/lean-engineering-policy.js +2 -2
  51. package/dist/core/managed-assets/managed-assets-manifest.js +1 -2
  52. package/dist/core/pipeline-internals/runtime-core.js +4 -5
  53. package/dist/core/pipeline-internals/runtime-gates.js +5 -5
  54. package/dist/core/ppt-review/ppt-patch-handoff.js +1 -2
  55. package/dist/core/ppt-review/slide-imagegen-review.js +10 -11
  56. package/dist/core/ppt.js +50 -35
  57. package/dist/core/qa-loop/qa-loop-budget-policy.js +6 -2
  58. package/dist/core/qa-loop.js +8 -8
  59. package/dist/core/recallpulse.js +1 -2
  60. package/dist/core/research/research-synthesis-prompt.js +2 -3
  61. package/dist/core/routes/design-policy.js +1 -2
  62. package/dist/core/routes/dollar-manifest-lite.js +1 -2
  63. package/dist/core/routes/evidence.js +1 -1
  64. package/dist/core/routes/ppt-policy.js +1 -2
  65. package/dist/core/routes.js +16 -5
  66. package/dist/core/subagents/agent-catalog.js +1 -2
  67. package/dist/core/subagents/official-subagent-prompt.js +3 -3
  68. package/dist/core/triwiki-wrongness/wrongness-schema.js +3 -4
  69. package/dist/core/update/project-migration-fanout-runner.js +56 -0
  70. package/dist/core/update/sks-project-registry.js +223 -0
  71. package/dist/core/update/temporary-install-smoke.js +42 -13
  72. package/dist/core/update/update-migration-state.js +7 -9
  73. package/dist/core/update/update-operation.js +3 -0
  74. package/dist/core/update-check.js +2 -2
  75. package/dist/core/version.js +1 -1
  76. package/dist/native/sks-menubar/Sources/ControlCenterWindowController.swift +2 -0
  77. package/dist/native/sks-menubar/Sources/ImageGenerationModels.swift +341 -0
  78. package/dist/native/sks-menubar/Sources/ImageGenerationViewController.swift +330 -0
  79. package/dist/native/sks-menubar/Sources/SidebarItem.swift +2 -0
  80. package/dist/scripts/qa-loop-effort-escalation-check.js +4 -0
  81. package/package.json +1 -1
  82. package/dist/core/codex-app/openrouter-base-instructions.js +0 -1
  83. package/dist/core/research/research-prompt-contract.js +0 -23
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "schema": "sks.skills-manifest.v1",
3
- "package_version": "10.3.4",
3
+ "package_version": "10.3.6",
4
4
  "skills": [
5
5
  {
6
6
  "canonical_name": "sks",
@@ -17,8 +17,9 @@
17
17
  {
18
18
  "canonical_name": "sks-align",
19
19
  "type": "core",
20
- "content_sha256": "b9db40d6e1dd2fc6e4665a2b30738d370da955cd4d6e86c88bd85059c7faa08c",
20
+ "content_sha256": "9eef36214be7e07a963eb36bb1df2c025cd0578b7419ddf4fd307081a2b62093",
21
21
  "hash_history": [
22
+ "b9db40d6e1dd2fc6e4665a2b30738d370da955cd4d6e86c88bd85059c7faa08c",
22
23
  "c485f39d4873adb9793672f7dcf4e956595ffb9dcbb032b3ffb0515b5857d31d",
23
24
  "e98e1b67e228bec5c37d00c0206a2e01d2da698a83c80b527105bf04a19c136a"
24
25
  ],
@@ -69,8 +70,9 @@
69
70
  {
70
71
  "canonical_name": "sks-commit",
71
72
  "type": "official",
72
- "content_sha256": "aa2eeaa6be6d635170a8ecfc76353db95552f543cca107f239054c492409e3a9",
73
+ "content_sha256": "63cad87de9187f67e001949b0edcf39344626748f8f168bed257316dc1684d53",
73
74
  "hash_history": [
75
+ "aa2eeaa6be6d635170a8ecfc76353db95552f543cca107f239054c492409e3a9",
74
76
  "aea41328993b11e26e26ae94df6ed44312d1570ed39448531428b53ade9d7461",
75
77
  "943c6dcf822df086b320140e74404d4c7bcfd531264e25ada6624b5009f26207"
76
78
  ],
@@ -79,8 +81,9 @@
79
81
  {
80
82
  "canonical_name": "sks-commit-and-push",
81
83
  "type": "official",
82
- "content_sha256": "acd6c7845c58d72234776e4608e1440583c62c38b513625d1272e4a413a40fb6",
84
+ "content_sha256": "2307093e26513a26e71ac6cdfcf3fd1598979c6035525ee5d3de58820cb4adda",
83
85
  "hash_history": [
86
+ "acd6c7845c58d72234776e4608e1440583c62c38b513625d1272e4a413a40fb6",
84
87
  "8e4ff7a39440c82e6c67a67d5bb267c69f508cedb5d9d5a93261f4dcdf8e8a1a",
85
88
  "b005b4a7456b80b95768ad358fe5950bf517483c6de71aec14ee3d1c600cc074"
86
89
  ],
@@ -155,8 +158,9 @@
155
158
  {
156
159
  "canonical_name": "sks-design-artifact-expert",
157
160
  "type": "official",
158
- "content_sha256": "6db9a7088e5f8d21dec9c8eed00abe665e1e89f19dcbb6d8472d77e4551cb556",
161
+ "content_sha256": "6881c1acff42b3cc760f089165a6ea753c774882bf0ec989b71f14936e894690",
159
162
  "hash_history": [
163
+ "6db9a7088e5f8d21dec9c8eed00abe665e1e89f19dcbb6d8472d77e4551cb556",
160
164
  "a09daba0a2e479a68ed81ec6fba8d70e54c8398ed86f3d1879f874b98480b97c",
161
165
  "4a28d166eaf0bc4477b566b056034f972a7034165e36d8186daa9947bf92e3cf"
162
166
  ],
@@ -165,8 +169,9 @@
165
169
  {
166
170
  "canonical_name": "sks-design-system-builder",
167
171
  "type": "official",
168
- "content_sha256": "47654c9f74317abbd0a5a75f89cd2d563708e8234e8887cc7ab39bf49030abaa",
172
+ "content_sha256": "9075bc17039da34ddd7d798009fdbcdedb8d03358a29c9a925d194bd76e9dcc4",
169
173
  "hash_history": [
174
+ "47654c9f74317abbd0a5a75f89cd2d563708e8234e8887cc7ab39bf49030abaa",
170
175
  "0a41e6ace960abaaf6abf5e7b1e53fd39f414e1e00b59fa725f2db9e3eb05b58",
171
176
  "c4f0007cad5774510bdc55e2815ce0911c220afa8d5dd4efc327ba1231c8f3da"
172
177
  ],
@@ -175,8 +180,9 @@
175
180
  {
176
181
  "canonical_name": "sks-design-ui-editor",
177
182
  "type": "official",
178
- "content_sha256": "2f9087664d8abe938a6dfbeaef5301ef00531e34a15506508e1d6d6b7132b894",
183
+ "content_sha256": "c3bc8bbaac134f7d742cd5e4bed7dd61a99655c54a6bd42f669e6bdd033156fb",
179
184
  "hash_history": [
185
+ "2f9087664d8abe938a6dfbeaef5301ef00531e34a15506508e1d6d6b7132b894",
180
186
  "6c24e950a12dec52c625964069c7c21a0220a58e0f69f977d802f44fdb03a940",
181
187
  "83a806cc93a3c5342e0dccfc6a45983382d5bf74d1226c4e3288228db22b737a",
182
188
  "1b65f0028a6dcb2f7eeab0b0df411a75546bc3aefa8a76067e1818da000c2249"
@@ -248,8 +254,9 @@
248
254
  {
249
255
  "canonical_name": "sks-goal",
250
256
  "type": "official",
251
- "content_sha256": "36c12285a339f9505fd88d6d9ea5691e451449f0bf8f55c21f51f0d715623235",
257
+ "content_sha256": "942c5e8db400cc1cd2b5ca9527124135fb4b8d9e8289338632d8929691aa54ed",
252
258
  "hash_history": [
259
+ "36c12285a339f9505fd88d6d9ea5691e451449f0bf8f55c21f51f0d715623235",
253
260
  "5ab1ac18fc265c375bae92ff23ddbd80c378484d6629c378f0e9270e660ded11",
254
261
  "867544877ac04df6e0232d6d425797e7fab2cceff9a7176a3c9e61f8c4a416d7",
255
262
  "0db0c58e72c0d58b24163371efe7a647c67d5d232020b2b4ed2557f19fe648d7"
@@ -342,8 +349,9 @@
342
349
  {
343
350
  "canonical_name": "sks-image-ux-review",
344
351
  "type": "core",
345
- "content_sha256": "c7a5ea91adb0d45e652066cdb73f514cc7fcb47121cc13cce5e177f94630a42a",
352
+ "content_sha256": "643400c1682aaa4a84782e3740eb14efb0ddb905a84c086bd9a0f8afdabd5f02",
346
353
  "hash_history": [
354
+ "c7a5ea91adb0d45e652066cdb73f514cc7fcb47121cc13cce5e177f94630a42a",
347
355
  "54d4169dc7f362ac9fe2d090bd2612e41d30acbc3e883d6bd382929bdfb9459e",
348
356
  "9293346873b5fb25a9d93b630064a2c8ceede2bfdfa4c6ffe7fbb7f64da6595c"
349
357
  ],
@@ -352,8 +360,9 @@
352
360
  {
353
361
  "canonical_name": "sks-imagegen",
354
362
  "type": "official",
355
- "content_sha256": "ebad63dae59ff70a4404148d09bffaca69e6c43e88d6e9f6f3d0dc4d5a4c65f6",
363
+ "content_sha256": "0f3ba271f2977d1124b8236e25f5e05a3d03af234652e39601dc5054346e306c",
356
364
  "hash_history": [
365
+ "ebad63dae59ff70a4404148d09bffaca69e6c43e88d6e9f6f3d0dc4d5a4c65f6",
357
366
  "478e3d8f805eed55c3f3e6c2069142482a7dbd8fa5d9a59f03b136e0e1cb77d0",
358
367
  "a7f466ba1829a757f38432fbe8c3a672e22e91948537dafe8f8ce09561d2256e",
359
368
  "7a1f9372b03975886233a623031f41e06fd782b1e7a3409517bb428d9c6b76dd"
@@ -363,8 +372,9 @@
363
372
  {
364
373
  "canonical_name": "sks-imagegen-source-scout",
365
374
  "type": "official",
366
- "content_sha256": "b306134faf487b86e11a9736ea1ed60d2335eef858e58bedc80fd3dc4ff7137c",
375
+ "content_sha256": "84957463d326f0f7028fc47aabb3f1857c76f13534e3aed1c9fc1b075896dbd1",
367
376
  "hash_history": [
377
+ "b306134faf487b86e11a9736ea1ed60d2335eef858e58bedc80fd3dc4ff7137c",
368
378
  "440f361fb29afcbb6f6cdc88c6a7318953b4c8fd3181ef7c6d8187f091d18745",
369
379
  "95faf4358f1c6567ca6894bfb577629f14a23d623716be70325c0ff9a893d42e",
370
380
  "95e71d4431a4c1f6911f0f76eaa1c2b475c52fd22d35c0a6c241e21e090507ad",
@@ -394,15 +404,15 @@
394
404
  {
395
405
  "canonical_name": "sks-naruto",
396
406
  "type": "core",
397
- "content_sha256": "b2eb207b2773ab1995ee6e113ba6f3b64de43389e76aef4a0f06d4845ff86223",
407
+ "content_sha256": "c88999663811a50d096b7cbb696fbea5b8f72707bcbf4a232bb07fe3a10cb2a6",
398
408
  "hash_history": [
409
+ "b2eb207b2773ab1995ee6e113ba6f3b64de43389e76aef4a0f06d4845ff86223",
399
410
  "65e19a5d16f486b13541048c239e828f8039bfc6e38bafd7949d9c936fe4b5b2",
400
411
  "da43debf97f0b4a1583d8202a7306aca97ac97865accf9bca8f41d75c84a1cb9",
401
412
  "b981bea4183376c6c0204941ad6c2e78782e2cdea4f8d25cc85630c609faaf95",
402
413
  "5df9c9678eb68fd79ceb998ae7a52dd54dc92336ad5169e8a01acca89f76bd60",
403
414
  "a1219f6dbad9c8c185953125ef0b8dccf081aa01efb8e8acaa543c6214ac049c",
404
415
  "d0d5968e78ac25e1d3e588735de1ddbcf149cfb3165edebca5dec1ed7c7a5c46",
405
- "34222c72e4e1ead3584907f4d905444b7de820283ee7348018f110d5e6b04461",
406
416
  "49b5e3dcc1b537b49c2cf09e5b875cb16acb05c622b22798e265e64dacd8ac90"
407
417
  ],
408
418
  "deprecated_aliases": []
@@ -420,8 +430,9 @@
420
430
  {
421
431
  "canonical_name": "sks-pipeline-runner",
422
432
  "type": "official",
423
- "content_sha256": "6f38d3387e4ab020291afe7f74713b135543e52707f5bfbffa6b3584542f45a5",
433
+ "content_sha256": "15159b6f6edea91be29612fe3cee2047d8ec47f4f7c95a33601198a9bfec3eda",
424
434
  "hash_history": [
435
+ "6f38d3387e4ab020291afe7f74713b135543e52707f5bfbffa6b3584542f45a5",
425
436
  "7749638f1e8393f3beb1f7b0c37195dd0463abdb6fd7da5d31b3d816ee91fa37",
426
437
  "fd06dfb27be41e5ffec3e3ec8c5362289f5919cf2afa9da5ab6b97e7baa4a0ac",
427
438
  "66e105773b8e042eec5d5679b97b7cb305cad8d45671034907fbfa728fc4d68a",
@@ -433,8 +444,9 @@
433
444
  {
434
445
  "canonical_name": "sks-plan",
435
446
  "type": "official",
436
- "content_sha256": "7795867b38a5f169924125850f137c31995cf28000f74284839530a68ace156a",
447
+ "content_sha256": "81b49b026cd6761a1b63029d8d39b830e0801a7f3d2f9a8609127769173ddd4e",
437
448
  "hash_history": [
449
+ "7795867b38a5f169924125850f137c31995cf28000f74284839530a68ace156a",
438
450
  "b6f3b09230e9809acf4e13df2de6af3c75a8534e8890d6560664ebfc2e4072f8"
439
451
  ],
440
452
  "deprecated_aliases": []
@@ -442,8 +454,9 @@
442
454
  {
443
455
  "canonical_name": "sks-ppt",
444
456
  "type": "official",
445
- "content_sha256": "fba3f438b9f22dae0813cd12bf310539a7d2b71c8cd9322eb840514e24884eaf",
457
+ "content_sha256": "a25e537ff49b5bffdc093a5f772a8d218003ca1bb81e0aa304561684a9551b31",
446
458
  "hash_history": [
459
+ "fba3f438b9f22dae0813cd12bf310539a7d2b71c8cd9322eb840514e24884eaf",
447
460
  "c9a0d90e12560dd3f04959869051370e6baf46eda6eb63f708ea1661c5c9d041",
448
461
  "1d4de05afd42ee5739c0ed925af9e0ac4785fc746e659c60d3d908d465e6386c",
449
462
  "02e8a0758ec6d056ce9851a5a4505b1d32e302e730be3eb169a41392a5d6b2e2",
@@ -454,8 +467,9 @@
454
467
  {
455
468
  "canonical_name": "sks-prompt-pipeline",
456
469
  "type": "official",
457
- "content_sha256": "f82a103e7962e416961add515d7b3e65df89848dec1fbb9319bd49d7f1dac982",
470
+ "content_sha256": "5e423981384fc3825c74327c4ca0fe09905a0dc81a533676c7e76ebb385348fc",
458
471
  "hash_history": [
472
+ "f82a103e7962e416961add515d7b3e65df89848dec1fbb9319bd49d7f1dac982",
459
473
  "93fd938dccd65d9b4d1dd140b60e1baedc627e7fcc54f9afd95eb2e44efd1143",
460
474
  "033bb114ec1fac3f8c312f698b1861ed4c2ce6f65c06f4f1a872c4b101b74b92",
461
475
  "e7c8ef56d38fdc4879c983f7d6706f26fc1cf0a60c508836bd628e815700bcc3",
@@ -476,8 +490,9 @@
476
490
  {
477
491
  "canonical_name": "sks-reasoning-router",
478
492
  "type": "official",
479
- "content_sha256": "41e14e8d5b93d743096664869ee68c41c86e911b0bbc165bdcd10e4a45faa4b6",
493
+ "content_sha256": "b0f458caa1c3bd7bb7241a09b80fce5700aeb99b340e84c08a9b2b66bc875ba7",
480
494
  "hash_history": [
495
+ "41e14e8d5b93d743096664869ee68c41c86e911b0bbc165bdcd10e4a45faa4b6",
481
496
  "03d68436e568b3cee2bffc6ca58819019ca406f7b648ef4704e3465c7c83c114",
482
497
  "647f730520a1c7dc89c2642f5b8502624c65a861ae41aecf1fb137db40fd0611",
483
498
  "da0ddb58adc68ddeebdb9c45bf111c26eaa64d3e9dffe1dd39d7f30b943b8b88",
@@ -511,8 +526,9 @@
511
526
  {
512
527
  "canonical_name": "sks-research",
513
528
  "type": "core",
514
- "content_sha256": "d61163446ebc429974aad8467653ddb5948739978600e9c27bff385fc53968ba",
529
+ "content_sha256": "b7280ca8a5ccf4304d25e97522d57968d20af6ec9f03f7d55a251ebcf8666236",
515
530
  "hash_history": [
531
+ "d61163446ebc429974aad8467653ddb5948739978600e9c27bff385fc53968ba",
516
532
  "8903022e98fa470cd764f7c8d1b28d4f996d6daf146260f20548acbe1276c55a",
517
533
  "2e96f95315d99b645d4171ba4648d9f9218ec3e98dcd6d363b5de522d2e1bfe3"
518
534
  ],
@@ -12,6 +12,7 @@ import { categoryForWorkerRole, isNarutoGpt56Model, modelRouteReason, routeModel
12
12
  import { codexTimeoutClassForRoute } from '../codex-control/codex-reliability-shield.js';
13
13
  import { decideSubagentModel } from '../subagents/model-policy.js';
14
14
  import { latestTierModelSet } from '../subagents/model-tiers.js';
15
+ import { consultJevTurnModel } from '../decisions/integration.js';
15
16
  export const NATIVE_WORKER_BACKEND_ROUTER_SCHEMA = 'sks.native-worker-backend-router.v1';
16
17
  export async function runNativeWorkerBackendRouter(input) {
17
18
  const root = path.resolve(input.agentRoot);
@@ -254,7 +255,15 @@ export async function resolveWorkerModelRouting(input, deps = {}) {
254
255
  ? String(input.agent.routed_model || '').trim()
255
256
  : '';
256
257
  const jevEffort = jevModel ? normalizeModelReasoning(input.agent?.routed_model_reasoning_effort) : null;
257
- const selectedModel = explicitModel || jevModel || savedPreferenceModel;
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;
258
267
  const taskPolicy = decideSubagentModel({ title: taskKindText, description: riskText, role: input.agent?.role });
259
268
  const routed = narutoOnly
260
269
  ? await routeModel(category, {
@@ -262,14 +271,14 @@ export async function resolveWorkerModelRouting(input, deps = {}) {
262
271
  narutoOnly: true,
263
272
  taskText: taskKindText,
264
273
  riskText,
265
- reasoningEffort: jevEffort || savedAstraEffort,
274
+ reasoningEffort: jevEffort || savedAstraEffort || liveJevEffort,
266
275
  availableModels: lbCatalog?.models || [],
267
276
  availableModelEfforts: lbCatalog?.model_efforts || {},
268
277
  ...(selectedModel ? { model: selectedModel } : {})
269
278
  })
270
279
  : {
271
- model: (explicitModel && currentModels.has(explicitModel) ? explicitModel : '') || savedPreferenceModel || taskPolicy.model,
272
- reasoning: explicitReasoning || savedAstraEffort || taskPolicy.modelReasoningEffort,
280
+ model: (explicitModel && currentModels.has(explicitModel) ? explicitModel : '') || savedPreferenceModel || liveJevModel || taskPolicy.model,
281
+ reasoning: explicitReasoning || savedAstraEffort || liveJevEffort || taskPolicy.modelReasoningEffort,
273
282
  serviceTier: explicitTier || input.fastModePolicy.service_tier || 'fast'
274
283
  };
275
284
  const blockers = [
@@ -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}`)
@@ -0,0 +1,95 @@
1
+ import { readImagegenConfig, isOpenRouterModelId } from '../../imagegen/imagegen-config.js';
2
+ import { generateOpenRouterImages } from '../../imagegen/openrouter-images.js';
3
+ import { resolveOpenRouterApiKey } from '../../providers/openrouter/openrouter-secret-store.js';
4
+ export const DESKTOP_BRIDGE_IMAGEGEN_SCHEMA = 'sks.desktop-bridge-imagegen.v1';
5
+ const MAX_BODY_BYTES = 48 * 1024 * 1024;
6
+ const MAX_REFERENCES = 8;
7
+ class ImagegenEndpointError extends Error {
8
+ code;
9
+ status;
10
+ constructor(code, status) {
11
+ super(code);
12
+ this.code = code;
13
+ this.status = status;
14
+ }
15
+ }
16
+ async function readBody(req) {
17
+ const chunks = [];
18
+ let size = 0;
19
+ for await (const chunk of req) {
20
+ const buffer = Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk);
21
+ size += buffer.length;
22
+ if (size > MAX_BODY_BYTES)
23
+ throw new ImagegenEndpointError('imagegen_request_too_large', 413);
24
+ chunks.push(buffer);
25
+ }
26
+ return Buffer.concat(chunks).toString('utf8');
27
+ }
28
+ function references(value) {
29
+ if (value === undefined)
30
+ return [];
31
+ if (!Array.isArray(value) || value.length > MAX_REFERENCES)
32
+ throw new ImagegenEndpointError('imagegen_references_invalid', 400);
33
+ return value.map((row) => {
34
+ const mime = typeof row?.mime === 'string' ? row.mime.toLowerCase() : '';
35
+ const base64 = typeof row?.base64 === 'string' ? row.base64 : '';
36
+ if (!/^image\/[a-z0-9.+-]+$/.test(mime) || !/^[A-Za-z0-9+/=]+$/.test(base64))
37
+ throw new ImagegenEndpointError('imagegen_references_invalid', 400);
38
+ return { mime, base64 };
39
+ });
40
+ }
41
+ function send(res, status, payload) {
42
+ res.writeHead(status, { 'content-type': 'application/json', 'cache-control': 'no-store', connection: 'close' });
43
+ res.end(JSON.stringify({ schema: DESKTOP_BRIDGE_IMAGEGEN_SCHEMA, ...payload }));
44
+ }
45
+ export async function handleDesktopBridgeImagegen(req, res, deps = {}) {
46
+ const env = deps.env || process.env;
47
+ try {
48
+ if (req.method !== 'POST')
49
+ throw new ImagegenEndpointError('imagegen_method_not_allowed', 405);
50
+ let body;
51
+ try {
52
+ body = JSON.parse(await readBody(req));
53
+ }
54
+ catch (error) {
55
+ if (error instanceof ImagegenEndpointError)
56
+ throw error;
57
+ throw new ImagegenEndpointError('imagegen_request_invalid_json', 400);
58
+ }
59
+ const prompt = typeof body?.prompt === 'string' ? body.prompt.trim() : '';
60
+ if (!prompt)
61
+ throw new ImagegenEndpointError('imagegen_prompt_required', 400);
62
+ const config = await readImagegenConfig(env);
63
+ if (config.mode !== 'openrouter' || !config.openrouter_model)
64
+ throw new ImagegenEndpointError('imagegen_custom_mode_off', 409);
65
+ const requested = body?.model === undefined ? config.openrouter_model : body.model;
66
+ if (!isOpenRouterModelId(requested) || requested !== config.openrouter_model)
67
+ throw new ImagegenEndpointError('imagegen_model_not_selected', 409);
68
+ const key = await resolveOpenRouterApiKey({ env });
69
+ if (!key.key)
70
+ throw new ImagegenEndpointError('openrouter_key_missing', 424);
71
+ const result = await (deps.generate || generateOpenRouterImages)({
72
+ apiKey: key.key,
73
+ model: requested,
74
+ prompt,
75
+ references: references(body?.references),
76
+ aspectRatio: typeof body?.aspect_ratio === 'string' ? body.aspect_ratio : null,
77
+ quality: typeof body?.quality === 'string' ? body.quality : null,
78
+ outputFormat: typeof body?.output_format === 'string' ? body.output_format : null,
79
+ env
80
+ });
81
+ if (!result.ok) {
82
+ send(res, result.status && result.status >= 400 && result.status < 600 ? result.status : 502, { ok: false, error: result.error, model: requested });
83
+ return;
84
+ }
85
+ send(res, 200, { ok: true, model: result.model, requested_model: requested, images: result.images, text: result.text, usage: result.usage, warnings: result.warnings });
86
+ }
87
+ catch (error) {
88
+ const code = error instanceof ImagegenEndpointError ? error.code : 'imagegen_bridge_failed';
89
+ const status = error instanceof ImagegenEndpointError ? error.status : 500;
90
+ if (!res.headersSent)
91
+ send(res, status, { ok: false, error: code });
92
+ else
93
+ res.destroy();
94
+ }
95
+ }
@@ -7,7 +7,8 @@ import { assertAllowedOrigin, assertAllowedPath, assertLoopbackPeer, assertLoopb
7
7
  import { createDesktopBridgePublicState, desktopBridgeListenOrigin, desktopBridgeStatePath, refreshDesktopBridgeState, removeDesktopBridgeStateIfOwned, writeDesktopBridgeState, } from './state.js';
8
8
  import { DesktopBridgeError, DesktopBridgeRequestBodyTooLargeError } from './types.js';
9
9
  import { PACKAGE_VERSION } from '../../version.js';
10
- import { DESKTOP_BRIDGE_CLIENT_PATH_PREFIX, DESKTOP_BRIDGE_DIAGNOSTIC_HEALTH_PATH, DESKTOP_BRIDGE_DIAGNOSTIC_PATH, DESKTOP_BRIDGE_DIAGNOSTIC_PROTOCOL } from './types.js';
10
+ import { DESKTOP_BRIDGE_CLIENT_PATH_PREFIX, DESKTOP_BRIDGE_DIAGNOSTIC_HEALTH_PATH, DESKTOP_BRIDGE_DIAGNOSTIC_PATH, DESKTOP_BRIDGE_DIAGNOSTIC_PROTOCOL, DESKTOP_BRIDGE_IMAGEGEN_PATH } from './types.js';
11
+ import { handleDesktopBridgeImagegen } from './imagegen-endpoint.js';
11
12
  import { forwardWebSocket, safeEndUpgradeSocket } from './websocket-forward.js';
12
13
  function authenticateDesktopBridgeClient(req, input) {
13
14
  const raw = String(req.url || '/');
@@ -251,6 +252,10 @@ export async function startPreparedDesktopBridge(input, options = {}) {
251
252
  writeDiagnosticHealth(req, res, input);
252
253
  return;
253
254
  }
255
+ if (authenticated.pathname === DESKTOP_BRIDGE_IMAGEGEN_PATH) {
256
+ await handleDesktopBridgeImagegen(req, res);
257
+ return;
258
+ }
254
259
  assertAllowedPath(authenticated.pathname, input.allowedPathPrefixes);
255
260
  const prepared = await prepareDesktopBridgeRequest(req, input);
256
261
  await forwardHttp(req, res, input, prepared, `${desktopBridgeListenOrigin(input)}${authenticated.clientBasePath}`);
@@ -4,6 +4,7 @@ export const DESKTOP_BRIDGE_DIAGNOSTIC_HEALTH_PATH = '/__sks/diagnostics/health'
4
4
  export const DESKTOP_BRIDGE_DIAGNOSTIC_PATH = '/__sks/diagnostics/websocket';
5
5
  export const DESKTOP_BRIDGE_DIAGNOSTIC_PROTOCOL = 'sks.desktop-bridge.probe.v2';
6
6
  export const DESKTOP_BRIDGE_CLIENT_PATH_PREFIX = '/__sks/client';
7
+ export const DESKTOP_BRIDGE_IMAGEGEN_PATH = '/__sks/imagegen/generations';
7
8
  export const DESKTOP_BRIDGE_ALLOWED_PATH_PREFIXES = [
8
9
  '/backend-api/codex/',
9
10
  '/backend-api/files',
@@ -1,4 +1,3 @@
1
- import { IMAGEGEN_MODEL } from '../imagegen/imagegen-model-policy.js';
2
1
  import { PACKAGE_VERSION, nowIso, sha256 } from '../fsx.js';
3
2
  import { coreEngineeringDirectiveReference } from '../lean-engineering-policy.js';
4
3
  import { normalizeDollarSkillName, prefixKnownSksDollarReferences, sksPrefixedDollarCommand, sksPrefixedSkillName } from '../routes/dollar-prefix.js';
@@ -17,7 +16,7 @@ const CORE_SKILL_DEFINITIONS = [
17
16
  discovery: 'Run $sks-naruto to delegate implementation to child subagents.',
18
17
  when: 'Use when the user invokes $sks-naruto or $sks-work, or the selected route is Naruto: ordinary implementation work, where the parent orchestrates and children implement.',
19
18
  workflow: 'Run sks naruto run "<task>" [--agents N] [--max-threads N] [--json] with Codex official subagent threads only. The parent orchestrates only: decompose, assign disjoint slices, spawn, integrate, and verify. Do not implement slice work in the parent thread; the SKS PreToolUse gate denies parent-thread source edits until the first child thread starts and while children are still running, and .sneakoscope artifacts stay parent-writable. The parent owns decomposition, per-wave capacity, later root-owned waves, integration, and final verification. Automatic targets begin at 4/6/8/16 by task size: bounded, explicit parallel, large-scale, then mass mechanical or exploration fan-out. After decomposition both lanes may expand to the SKS-owned 256-child ceiling when independent useful slices and real host capacity remain positive; max_threads defaults to a 256-child frame budget cap, never a target. A measured lower Codex host cap or explicit provider/API budget remains authoritative, and multi-wave scheduling reuses returned capacity. Every child runs the newest model of the tier its work needs (fast, balanced, context, or deep); no model family is pinned. When Jev mode is on, Jev picks the tier for each new spawn and SKS seals it. A user role preference stays authoritative. Do not choose child models yourself. Keep the four task-class profiles and compatibility IDs; max_depth=1 blocks nested delegation. Wait for every planned thread before final. In an active Codex App Naruto mission, commit the strict parent evidence with sks naruto parent-summary --mission <id> --stdin, then return localized Markdown without exposing the JSON.',
20
- safety: 'Preserve user-authored content, inherit the parent permission mode, do not spawn nested subagents, do not inject the full pack or the full TriWiki context into every child, and do not fall back to another model, process runtime, custom scheduler, or worker pool. The historical Naruto process runtime is removed; stop with explicit blocker evidence when the official path is unavailable.',
19
+ safety: 'Preserve user-authored content, inherit the parent permission mode, do not spawn nested subagents, do not inject the full pack or the full TriWiki context into every child, and do not fall back to another model, process runtime, custom scheduler, or worker pool. Official Codex subagent threads are the only worker runtime; stop with explicit blocker evidence when the official path is unavailable.',
21
20
  cli: 'sks naruto run "<task>" [--agents N] [--max-threads N] [--json]; sks naruto status|subagents|proof [--mission <id>] [--json]; sks naruto parent-summary --mission <id> --stdin [--json]',
22
21
  evidence: 'subagent-plan.json, subagent-events.jsonl, subagent-parent-summary.json, subagent-evidence.json, naruto-summary.json, and naruto-gate.json.',
23
22
  fallback: 'When official subagents are unavailable, report the explicit availability blocker; the orchestration gate releases parent edits only after its bounded denials, and that release is recorded. Never fabricate process, PID, or subagent evidence.'
@@ -42,7 +41,7 @@ const CORE_SKILL_DEFINITIONS = [
42
41
  purpose: 'run evidence-bound discovery, source ledgers, and synthesis cycles.',
43
42
  discovery: 'Run $sks-research for evidence-bound discovery, not code edits.',
44
43
  when: 'Use when the user invokes $Research or asks for evidence-bound discovery, hypotheses, or falsification.',
45
- workflow: 'Frame the research criteria and map assumptions before retrieval. Run layered Super Search first and accept only source rows correlated to verified proof, source-ledger, and hydrated-content artifacts. Then run three independent official research_reviewer threads covering evidence integrity, method validity, and falsification or replication. Each reviewer must return source ids, falsifiers, and cheap probes. Critical, major, or required revisions trigger a mission-local research_synthesizer revision and a fresh bounded review cycle; minor concerns remain advisory. agent-ledger.json and debate-ledger.json are compatibility projections only; do not launch a removed legacy scheduler or a custom debate pool.',
44
+ workflow: 'Frame the research criteria and map assumptions before retrieval. Run layered Super Search first and accept only source rows correlated to verified proof, source-ledger, and hydrated-content artifacts. Then run three independent official research_reviewer threads covering evidence integrity, method validity, and falsification or replication. Each reviewer must return source ids, falsifiers, and cheap probes. Critical, major, or required revisions trigger a mission-local research_synthesizer revision and a fresh bounded review cycle; minor concerns remain advisory. The reviewer and synthesizer threads are the only research workers; agent-ledger.json and debate-ledger.json are compatibility projections of them.',
46
45
  safety: 'Preserve user-authored content, keep research route state bounded, and do not edit repository source. Do not overclaim novelty, breakthrough, publication acceptance, or experimental support beyond recorded evidence.',
47
46
  evidence: 'research plan, source ledger, cycle record, synthesis, and final review.',
48
47
  fallback: 'State source/tool unavailability and avoid unsupported live-accuracy claims.'
@@ -66,7 +65,7 @@ const CORE_SKILL_DEFINITIONS = [
66
65
  purpose: 'run one screenshot-to-generated-annotation-to-UX-report pipeline without duplicate picker skills.',
67
66
  discovery: 'Run $sks-image-ux-review for screenshot-to-UX annotation.',
68
67
  when: 'Use for $Image-UX-Review, $UX-Review, $Visual-Review, or $UI-UX-Review requests; all aliases resolve to this one canonical skill.',
69
- workflow: ("Capture or attach the real source screenshot first; web/browser/webapp capture must pass the Codex Chrome Extension readiness gate first, while Computer Use is reserved for native Mac/non-web surfaces. Send the source image as the I2I reference to the selected Codex imagegen provider with " + IMAGEGEN_MODEL + " and a senior Toss UI/UX designer prompt that visibly adds numbered P0/P1/P2/P3 callouts, hierarchy, contrast, alignment, density, affordance, eye-flow arrows, and a corrected mini-comp. Then analyze the generated annotated image pixels with vision/OCR, not the source screenshot, and write the issue ledger, extraction report, and UX/UI change report with the generated image path and sha256."),
68
+ workflow: ("Capture or attach the real source screenshot first; web/browser/webapp capture must pass the Codex Chrome Extension readiness gate first, while Computer Use is reserved for native Mac/non-web surfaces. Send the source image as the I2I reference with `sks imagegen generate --reference` (the active SKS image mode) and a senior Toss UI/UX designer prompt that visibly adds numbered P0/P1/P2/P3 callouts, hierarchy, contrast, alignment, density, affordance, eye-flow arrows, and a corrected mini-comp. Then analyze the generated annotated image pixels with vision/OCR, not the source screenshot, and write the issue ledger, extraction report, and UX/UI change report with the generated image path and sha256."),
70
69
  safety: 'Do not substitute text-only critique, a source-screenshot-only report, placeholders, partial image frames, mock evidence, or an unrelated API provider for the selected real imagegen path. Apply fixes only when requested and recheck changed screens.',
71
70
  cli: 'sks ux-review run --image <path> [--fix] --json; legacy $sks-ux-review, $sks-visual-review, and $sks-ui-ux-review inputs route here internally.',
72
71
  evidence: 'image-ux-screen-inventory.json, image-ux-imagegen-request.json, image-ux-imagegen-response.json, image-ux-generated-review-ledger.json, image-ux-issue-ledger.json, image-ux-callout-extraction-report.json, image-ux-iteration-report.json, and image-ux-review-gate.json.',
@@ -144,7 +143,7 @@ const CORE_SKILL_DEFINITIONS = [
144
143
  purpose: 'create or replace TriWiki with an exhaustive repository code-navigation index so an LLM can find the purpose, file, symbol, exact coordinate, and supported directed relationships of current code quickly.',
145
144
  discovery: 'Run $sks-align to rebuild TriWiki from current repository code.',
146
145
  when: 'Use when the user invokes $Align or asks to reread the current codebase and rebuild or repair TriWiki strictly from current code. Cleanup is optional and independent.',
147
- workflow: 'Run sks align run directly against either an absent or existing TriWiki. Align ignores all prior TriWiki state as index input, walks every accepted current source file without incremental or fragment cache reuse, derives purpose only from source comments/docstrings, records exact file and symbol coordinates plus extractor-supported source relations, rechecks the full source inventory digest, validates graph/meta/manifest/code-pack/context-pack in temporary staging, transactionally replaces the active generation, then deletes the temporary prior-state handle. context-graph.json is the exhaustive authority; context-pack.json and managed AGENTS.md blocks are bounded fast-lookup projections. Keep align-ledger.json and align-gate.json truthful, then finish reflection and Honest Mode.',
146
+ workflow: 'Run sks align run directly against either an absent or existing TriWiki. Align ignores all prior TriWiki state as index input, walks every accepted current source file without incremental or fragment cache reuse, derives purpose only from source comments/docstrings, records exact file and symbol coordinates plus extractor-supported source relations, rechecks the full source inventory digest, validates graph/meta/manifest/code-pack/context-pack in temporary staging, transactionally replaces the active generation, then deletes the temporary prior-state handle. context-graph.json is the exhaustive authority; context-pack.json and managed AGENTS.md blocks are bounded fast-lookup projections. Keep align-ledger.json and align-gate.json truthful, then state what was verified and what remains.',
148
147
  safety: 'Never read prior TriWiki memory, wrongness, mission prompts, ordinary docs, external docs, proof cards, or LLM inference as index input. Refuse caps, extraction-limit violations, unreadable/oversized/binary supported-source files, symlink escapes, source drift during the scan, partial staging, non-code extractors, or incomplete file coverage. Do not retain a previous generation.',
149
148
  cli: 'sks align prepare|run|status|proof [mission|"scope"] [--json]',
150
149
  evidence: 'work-order-ledger.json, align-plan.json, align-ledger.json, align-gate.json, .sneakoscope/wiki/context-graph.json, context-graph.meta.json, code-navigation-manifest.json, code-pack.json, context-pack.json, managed AGENTS.md projections, completion-proof.json, trust-report.json, and Honest Mode.',
@@ -1,4 +1,3 @@
1
- import { IMAGEGEN_MODEL } from '../imagegen/imagegen-model-policy.js';
2
1
  import fs from 'node:fs/promises';
3
2
  import path from 'node:path';
4
3
  import { ensureDir, nowIso, writeJsonAtomic } from '../fsx.js';
@@ -80,16 +79,16 @@ async function stateForCapability(root, id, imageCapability, nativeFeatureMatrix
80
79
  repair_actions: verified
81
80
  ? ['postcheck-imagegen-path-contract']
82
81
  : builtInConfigured
83
- ? [("Use the selected model-capable image provider with " + IMAGEGEN_MODEL + " in a fresh task and record the selected raster output path before retrying the image route.")]
84
- : [("Select a provider supporting " + IMAGEGEN_MODEL + " surface, then verify it with a real generated raster output before retrying the image route.")],
82
+ ? ['Run `sks imagegen generate --prompt <text> --out <file>` (it follows the active SKS image mode) and record the raster output path before retrying the image route.']
83
+ : ['Check `sks imagegen status --json`, then verify the active image mode with one real generated raster before retrying the image route.'],
85
84
  after: null,
86
85
  artifact_path: path.join(reports, 'native-capability-repair-matrix.json'),
87
86
  core_blockers: [],
88
87
  route_blockers: verified ? {} : { 'route-image': [routeBlocker] },
89
88
  manual_actions: verified ? [] : [
90
89
  builtInConfigured
91
- ? ("Generate one real raster with the selected model-capable provider: " + IMAGEGEN_MODEL + " and bind its output path to the route evidence.")
92
- : ("Select a provider supporting " + IMAGEGEN_MODEL + " surface before image routes.")
90
+ ? 'Generate one real raster with `sks imagegen generate` and bind its output path to the route evidence.'
91
+ : 'Check `sks imagegen status --json` before image routes.'
93
92
  ],
94
93
  blockers: [],
95
94
  warnings: verified ? [] : [
@@ -1,4 +1,4 @@
1
- import { IMAGEGEN_MODEL, CODEX_BUILTIN_IMAGEGEN_MODEL } from '../imagegen/imagegen-model-policy.js';
1
+ import { CODEX_DEFAULT_IMAGEGEN_LABEL } from '../imagegen/imagegen-config.js';
2
2
  import path from 'node:path';
3
3
  import fsp from 'node:fs/promises';
4
4
  import { registerPathImageReference, upsertImageReferenceRegistry } from '../image/reference-evidence/reference-registry.js';
@@ -122,7 +122,7 @@ async function runImageUxReview(root, command, args = []) {
122
122
  process.exitCode = 1;
123
123
  if (flag(args, '--json'))
124
124
  return printJson(result);
125
- console.error(("UX Review blocked: no selected Codex imagegen/" + IMAGEGEN_MODEL + " provider is ready."));
125
+ console.error('UX Review blocked: the active SKS image mode could not generate an image (see `sks imagegen status --json`).');
126
126
  for (const action of imagegenRequired.blocker?.next_actions || [])
127
127
  console.error(`- ${action}`);
128
128
  return result;
@@ -156,6 +156,7 @@ async function runImageUxReview(root, command, args = []) {
156
156
  }
157
157
  if (!generatedImage && shouldGenerateCallouts) {
158
158
  const outputDir = path.join(dir, 'generated-callouts');
159
+ const responsesModel = readOption(args, '--responses-model', null);
159
160
  const result = await generateImagegenCalloutReview({
160
161
  mission_id: id,
161
162
  source_screen_id: 'screen-1',
@@ -166,9 +167,7 @@ async function runImageUxReview(root, command, args = []) {
166
167
  }),
167
168
  requested_fidelity: 'original',
168
169
  privacy: 'local-only'
169
- }, {
170
- openai: { responsesModel: readOption(args, '--responses-model', null) }
171
- });
170
+ }, responsesModel ? { env: { ...process.env, SKS_IMAGEGEN_RESPONSES_MODEL: responsesModel } } : {});
172
171
  if (result.request_artifact)
173
172
  await fsp.copyFile(result.request_artifact, path.join(dir, IMAGE_UX_REVIEW_IMAGEGEN_REQUEST_ARTIFACT));
174
173
  if (result.response_artifact)
@@ -640,7 +639,7 @@ async function attachGeneratedReviewImage(root, dir, contract, imagePath, opts =
640
639
  id: opts.mock ? 'generated-review-fixture-1' : undefined,
641
640
  source_screen_id: sourceScreen.id || 'screen-1',
642
641
  provider_surface: opts.providerSurface || 'Codex App $imagegen',
643
- provider_model: response?.model || (opts.mock ? IMAGEGEN_MODEL : CODEX_BUILTIN_IMAGEGEN_MODEL),
642
+ provider_model: response?.model || (opts.mock ? 'mock-imagegen' : CODEX_DEFAULT_IMAGEGEN_LABEL),
644
643
  evidence_class: evidenceClass,
645
644
  output_source: outputSource,
646
645
  output_sha256: outputSha256 || undefined,
@@ -947,7 +946,7 @@ export async function stageImageReference(root, dir, imagePath, subdir, preferre
947
946
  }
948
947
  function promptForRun(command, args) {
949
948
  const source = readOption(args, '--image', null) || readOption(args, '--screenshot', null) || readOption(args, '--mission', null) || 'latest Codex Chrome Extension or native Computer Use screenshot';
950
- return `$${routeForCommand(command).replace(/^\$/, '')} ${source} with ${IMAGEGEN_MODEL} callouts${flag(args, '--fix') ? ', then fix the issues' : ''}`;
949
+ return `$${routeForCommand(command).replace(/^\$/, '')} ${source} with generated image callouts${flag(args, '--fix') ? ', then fix the issues' : ''}`;
951
950
  }
952
951
  function sourceImageFromContract(contract) {
953
952
  const sources = contract?.answers?.IMAGE_UX_REVIEW_SOURCE_IMAGES;
@@ -1,4 +1,3 @@
1
- import { IMAGEGEN_MODEL } from '../imagegen/imagegen-model-policy.js';
2
1
  import path from 'node:path';
3
2
  import { exists, projectRoot, readJson, writeJsonAtomic } from '../fsx.js';
4
3
  import { createMission, findLatestMission, loadMission } from '../mission.js';
@@ -48,7 +47,7 @@ export async function pptCommand(command, args = []) {
48
47
  process.exitCode = 1;
49
48
  if (flag(args, '--json'))
50
49
  return printJson(result);
51
- console.error(("PPT build blocked: no selected Codex imagegen/" + IMAGEGEN_MODEL + " provider is ready."));
50
+ console.error('PPT build blocked: the active SKS image mode could not generate an image (see `sks imagegen status --json`).');
52
51
  for (const action of imagegenRequired.blocker?.next_actions || [])
53
52
  console.error(`- ${action}`);
54
53
  return result;
@@ -160,7 +159,7 @@ async function pptImagegenReview(root, command, action, args = []) {
160
159
  process.exitCode = 1;
161
160
  if (flag(args, '--json'))
162
161
  return printJson(result);
163
- console.error(("PPT imagegen review blocked: no selected Codex imagegen/" + IMAGEGEN_MODEL + " provider is ready."));
162
+ console.error('PPT imagegen review blocked: the active SKS image mode could not generate an image (see `sks imagegen status --json`).');
164
163
  for (const action of imagegenRequired.blocker?.next_actions || [])
165
164
  console.error(`- ${action}`);
166
165
  return result;
@@ -263,7 +262,7 @@ function nextActionForPptGate(gate = {}) {
263
262
  if (blockers.includes('slide_export_unavailable'))
264
263
  return 'Attach exported slide images with --manual-slide-images, then rerun the PPT review.';
265
264
  if (blockers.includes('ppt_imagegen_callouts_missing'))
266
- return ("Generate slide callout review images with the selected model-capable provider: " + IMAGEGEN_MODEL + " and rerun extraction.");
265
+ return 'Generate slide callout review images with `sks imagegen generate --reference <slide image>` and rerun extraction.';
267
266
  if (blockers.includes('ppt_slide_issue_extraction_missing'))
268
267
  return 'Run `sks ppt extract-issues --generated-slide <path> --session <id> --json`, or configure Structured Outputs fallback.';
269
268
  if (blockers.includes('ppt_slide_recheck_missing'))