sneakoscope 10.1.4 → 10.1.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.
- package/README.md +1 -1
- package/config/skills-hash-ledger.v1.json +7 -0
- package/crates/sks-core/Cargo.lock +1 -1
- package/crates/sks-core/Cargo.toml +1 -1
- package/dist/cli/install-helpers.js +2 -1
- package/dist/commands/doctor.js +2 -1
- package/dist/config/skills-manifest.json +17 -9
- package/dist/core/agents/official-subagent-helper-policy.js +2 -1
- package/dist/core/bench.js +1 -1
- package/dist/core/codex-app.js +6 -5
- package/dist/core/codex-lb/desktop-bridge/http-forward.js +11 -6
- package/dist/core/codex-lb/desktop-bridge/rejection-log.js +3 -0
- package/dist/core/codex-lb/desktop-bridge/responses-websocket.js +2 -2
- package/dist/core/codex-lb/desktop-bridge/security.js +4 -0
- package/dist/core/codex-lb/desktop-bridge/server.js +10 -1
- package/dist/core/codex-lb/desktop-bridge/types.js +12 -0
- package/dist/core/codex-native/core-skill-manifest.js +3 -2
- package/dist/core/codex-native/native-capability-repair-matrix.js +5 -4
- package/dist/core/commands/image-ux-review-command.js +23 -27
- package/dist/core/commands/ppt-command.js +4 -3
- package/dist/core/commands/qa-loop-command.js +8 -8
- package/dist/core/doctor/doctor-readiness-matrix.js +2 -1
- package/dist/core/doctor/imagegen-repair.js +4 -3
- package/dist/core/evidence/evidence-router.js +3 -3
- package/dist/core/evidence/evidence-schema.js +1 -1
- package/dist/core/feature-fixtures.js +2 -2
- package/dist/core/feature-registry.js +3 -2
- package/dist/core/hooks-runtime/hook-io.js +2 -1
- package/dist/core/image-ux-review/callout-extraction.js +1 -1
- package/dist/core/image-ux-review/imagegen-adapter.js +63 -185
- package/dist/core/image-ux-review/recapture.js +1 -1
- package/dist/core/image-ux-review.js +46 -46
- package/dist/core/imagegen/imagegen-auth-readiness.js +6 -13
- package/dist/core/imagegen/imagegen-capability.js +22 -15
- package/dist/core/imagegen/imagegen-model-policy.js +22 -0
- package/dist/core/imagegen/{gpt-image-2-request-validator.js → imagegen-request-validator.js} +13 -12
- package/dist/core/imagegen/require-imagegen.js +4 -2
- package/dist/core/init/skills.js +6 -5
- package/dist/core/managed-assets/managed-assets-manifest.js +2 -1
- package/dist/core/performance-budgets.json +1 -1
- package/dist/core/pipeline-internals/runtime-core.js +3 -2
- package/dist/core/pipeline-internals/runtime-gates.js +9 -8
- package/dist/core/ppt-review/index.js +1 -1
- package/dist/core/ppt-review/ppt-patch-handoff.js +2 -1
- package/dist/core/ppt-review/slide-imagegen-review.js +14 -9
- package/dist/core/ppt-review/slide-issue-extraction.js +2 -2
- package/dist/core/ppt.js +25 -22
- package/dist/core/qa-loop/qa-contract.js +5 -5
- package/dist/core/qa-loop.js +55 -54
- package/dist/core/recallpulse.js +2 -1
- package/dist/core/routes/design-policy.js +2 -1
- package/dist/core/routes/dollar-manifest-lite.js +2 -1
- package/dist/core/routes/evidence.js +5 -4
- package/dist/core/routes/ppt-policy.js +2 -1
- package/dist/core/routes.js +6 -5
- package/dist/core/stop-gate/gate-evaluator.js +3 -3
- package/dist/core/subagents/agent-catalog.js +2 -1
- package/dist/core/triwiki-wrongness/wrongness-schema.js +7 -6
- package/dist/core/trust-kernel/trust-report.js +6 -6
- package/dist/core/version.js +1 -1
- package/dist/core/wiki-image/callout-parser.js +1 -1
- package/dist/core/wiki-image/validation.js +2 -2
- package/dist/scripts/imagegen-real-smoke-check.js +4 -5
- package/dist/scripts/ppt-real-imagegen-smoke-check.js +1 -1
- package/dist/scripts/ppt-real-imagegen-wiring-check.js +2 -2
- package/dist/scripts/search-visibility-gate-lib.js +0 -1
- package/dist/scripts/ux-review-imagegen-blackbox-check.js +3 -3
- package/dist/scripts/ux-review-real-imagegen-smoke-check.js +1 -1
- package/dist/scripts/ux-review-run-wires-imagegen-check.js +2 -2
- package/package.json +1 -1
- package/schemas/codex/image-ux-issue-ledger.schema.json +1 -1
- package/dist/core/image-ux-review/codex-app-generated-image-discovery.js +0 -100
package/README.md
CHANGED
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
Sneakoscope Codex (`sks`) is an open-source trust layer for Codex CLI and ChatGPT Desktop. It coordinates bounded AI coding agents, records machine-verifiable evidence, preserves project memory, and blocks release claims that are not supported by current tests or artifacts. Search visibility outcomes are measured separately; SKS does not promise rankings or traffic.
|
|
17
17
|
<!-- END SKS SEARCH VISIBILITY MARKETING -->
|
|
18
18
|
|
|
19
|
-
Current package: **SKS 10.1.
|
|
19
|
+
Current package: **SKS 10.1.5**. Install the latest stable release from npm.
|
|
20
20
|
|
|
21
21
|
[Quick start](#install-in-one-command) · [Commands](#everyday-commands) · [SKS Center](#sks-center-macos) · [Documentation](#documentation) · [Changelog](CHANGELOG.md)
|
|
22
22
|
|
|
@@ -111,6 +111,7 @@
|
|
|
111
111
|
{
|
|
112
112
|
"canonical_name": "sks-design-artifact-expert",
|
|
113
113
|
"trusted_sha256": [
|
|
114
|
+
"6db9a7088e5f8d21dec9c8eed00abe665e1e89f19dcbb6d8472d77e4551cb556",
|
|
114
115
|
"a09daba0a2e479a68ed81ec6fba8d70e54c8398ed86f3d1879f874b98480b97c",
|
|
115
116
|
"4a28d166eaf0bc4477b566b056034f972a7034165e36d8186daa9947bf92e3cf"
|
|
116
117
|
]
|
|
@@ -118,6 +119,7 @@
|
|
|
118
119
|
{
|
|
119
120
|
"canonical_name": "sks-design-system-builder",
|
|
120
121
|
"trusted_sha256": [
|
|
122
|
+
"47654c9f74317abbd0a5a75f89cd2d563708e8234e8887cc7ab39bf49030abaa",
|
|
121
123
|
"0a41e6ace960abaaf6abf5e7b1e53fd39f414e1e00b59fa725f2db9e3eb05b58",
|
|
122
124
|
"c4f0007cad5774510bdc55e2815ce0911c220afa8d5dd4efc327ba1231c8f3da"
|
|
123
125
|
]
|
|
@@ -125,6 +127,7 @@
|
|
|
125
127
|
{
|
|
126
128
|
"canonical_name": "sks-design-ui-editor",
|
|
127
129
|
"trusted_sha256": [
|
|
130
|
+
"6c24e950a12dec52c625964069c7c21a0220a58e0f69f977d802f44fdb03a940",
|
|
128
131
|
"83a806cc93a3c5342e0dccfc6a45983382d5bf74d1226c4e3288228db22b737a",
|
|
129
132
|
"1b65f0028a6dcb2f7eeab0b0df411a75546bc3aefa8a76067e1818da000c2249"
|
|
130
133
|
]
|
|
@@ -243,12 +246,14 @@
|
|
|
243
246
|
{
|
|
244
247
|
"canonical_name": "sks-image-ux-review",
|
|
245
248
|
"trusted_sha256": [
|
|
249
|
+
"54d4169dc7f362ac9fe2d090bd2612e41d30acbc3e883d6bd382929bdfb9459e",
|
|
246
250
|
"9293346873b5fb25a9d93b630064a2c8ceede2bfdfa4c6ffe7fbb7f64da6595c"
|
|
247
251
|
]
|
|
248
252
|
},
|
|
249
253
|
{
|
|
250
254
|
"canonical_name": "sks-imagegen",
|
|
251
255
|
"trusted_sha256": [
|
|
256
|
+
"478e3d8f805eed55c3f3e6c2069142482a7dbd8fa5d9a59f03b136e0e1cb77d0",
|
|
252
257
|
"a7f466ba1829a757f38432fbe8c3a672e22e91948537dafe8f8ce09561d2256e",
|
|
253
258
|
"7a1f9372b03975886233a623031f41e06fd782b1e7a3409517bb428d9c6b76dd"
|
|
254
259
|
]
|
|
@@ -256,6 +261,7 @@
|
|
|
256
261
|
{
|
|
257
262
|
"canonical_name": "sks-imagegen-source-scout",
|
|
258
263
|
"trusted_sha256": [
|
|
264
|
+
"95faf4358f1c6567ca6894bfb577629f14a23d623716be70325c0ff9a893d42e",
|
|
259
265
|
"95e71d4431a4c1f6911f0f76eaa1c2b475c52fd22d35c0a6c241e21e090507ad",
|
|
260
266
|
"d648b571c674ed3be862bc0e8b2110f88c2bee54292bb009df0b0b2dbd6d400b"
|
|
261
267
|
]
|
|
@@ -316,6 +322,7 @@
|
|
|
316
322
|
{
|
|
317
323
|
"canonical_name": "sks-ppt",
|
|
318
324
|
"trusted_sha256": [
|
|
325
|
+
"c9a0d90e12560dd3f04959869051370e6baf46eda6eb63f708ea1661c5c9d041",
|
|
319
326
|
"1d4de05afd42ee5739c0ed925af9e0ac4785fc746e659c60d3d908d465e6386c",
|
|
320
327
|
"02e8a0758ec6d056ce9851a5a4505b1d32e302e730be3eb169a41392a5d6b2e2",
|
|
321
328
|
"329fc6ee24bb04478b18fb6ccd3691cd7cbb50e1b77ca7b6136383d00b3b0bb4"
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { IMAGEGEN_MODEL } from '../core/imagegen/imagegen-model-policy.js';
|
|
1
2
|
import path from 'node:path';
|
|
2
3
|
import fsp from 'node:fs/promises';
|
|
3
4
|
import { stdin as input, stdout as output } from 'node:process';
|
|
@@ -60,7 +61,7 @@ export async function postinstall({ bootstrap }) {
|
|
|
60
61
|
console.log('Configure providers explicitly with `sks bridge provider configure codex-lb ...` or `sks bridge provider configure openrouter ...`.');
|
|
61
62
|
const imagegenRepair = await ensureCodexImagegenDuringInstall();
|
|
62
63
|
if (imagegenRepair.status === 'ready')
|
|
63
|
-
console.log(
|
|
64
|
+
console.log(("Image generation provider capability ready (requested model: " + IMAGEGEN_MODEL + "; output not verified)."));
|
|
64
65
|
else if (imagegenRepair.status === 'recovered')
|
|
65
66
|
console.log('Codex App Image Gen: recovered and re-detected. Start a new Codex/Work task; restart the desktop app only if the new task still lacks $imagegen.');
|
|
66
67
|
else if (imagegenRepair.status === 'blocked')
|
package/dist/commands/doctor.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { IMAGEGEN_MODEL } from '../core/imagegen/imagegen-model-policy.js';
|
|
1
2
|
import os from 'node:os';
|
|
2
3
|
import path from 'node:path';
|
|
3
4
|
import { projectRoot, exists, formatBytes, nowIso, readText, writeJsonAtomic } from '../core/fsx.js';
|
|
@@ -1188,7 +1189,7 @@ async function runDoctor(args = [], root, doctorFix, deps = {}) {
|
|
|
1188
1189
|
blockers: ['codex_imagegen_current_task_tool_manifest_unverified', 'codex_imagegen_real_output_unverified'],
|
|
1189
1190
|
manual_actions: [
|
|
1190
1191
|
'Start a fresh Codex/Work task so $imagegen is present in its tool manifest.',
|
|
1191
|
-
|
|
1192
|
+
("Invoke $imagegen with " + IMAGEGEN_MODEL + " and bind the selected raster output path to route evidence.")
|
|
1192
1193
|
],
|
|
1193
1194
|
communication_test: {
|
|
1194
1195
|
level: 'flag_level',
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"schema": "sks.skills-manifest.v1",
|
|
3
|
-
"package_version": "10.1.
|
|
3
|
+
"package_version": "10.1.5",
|
|
4
4
|
"skills": [
|
|
5
5
|
{
|
|
6
6
|
"canonical_name": "sks",
|
|
@@ -138,8 +138,9 @@
|
|
|
138
138
|
{
|
|
139
139
|
"canonical_name": "sks-design-artifact-expert",
|
|
140
140
|
"type": "official",
|
|
141
|
-
"content_sha256": "
|
|
141
|
+
"content_sha256": "6db9a7088e5f8d21dec9c8eed00abe665e1e89f19dcbb6d8472d77e4551cb556",
|
|
142
142
|
"hash_history": [
|
|
143
|
+
"a09daba0a2e479a68ed81ec6fba8d70e54c8398ed86f3d1879f874b98480b97c",
|
|
143
144
|
"4a28d166eaf0bc4477b566b056034f972a7034165e36d8186daa9947bf92e3cf"
|
|
144
145
|
],
|
|
145
146
|
"deprecated_aliases": []
|
|
@@ -147,8 +148,9 @@
|
|
|
147
148
|
{
|
|
148
149
|
"canonical_name": "sks-design-system-builder",
|
|
149
150
|
"type": "official",
|
|
150
|
-
"content_sha256": "
|
|
151
|
+
"content_sha256": "47654c9f74317abbd0a5a75f89cd2d563708e8234e8887cc7ab39bf49030abaa",
|
|
151
152
|
"hash_history": [
|
|
153
|
+
"0a41e6ace960abaaf6abf5e7b1e53fd39f414e1e00b59fa725f2db9e3eb05b58",
|
|
152
154
|
"c4f0007cad5774510bdc55e2815ce0911c220afa8d5dd4efc327ba1231c8f3da"
|
|
153
155
|
],
|
|
154
156
|
"deprecated_aliases": []
|
|
@@ -156,8 +158,9 @@
|
|
|
156
158
|
{
|
|
157
159
|
"canonical_name": "sks-design-ui-editor",
|
|
158
160
|
"type": "official",
|
|
159
|
-
"content_sha256": "
|
|
161
|
+
"content_sha256": "6c24e950a12dec52c625964069c7c21a0220a58e0f69f977d802f44fdb03a940",
|
|
160
162
|
"hash_history": [
|
|
163
|
+
"83a806cc93a3c5342e0dccfc6a45983382d5bf74d1226c4e3288228db22b737a",
|
|
161
164
|
"1b65f0028a6dcb2f7eeab0b0df411a75546bc3aefa8a76067e1818da000c2249"
|
|
162
165
|
],
|
|
163
166
|
"deprecated_aliases": []
|
|
@@ -305,15 +308,18 @@
|
|
|
305
308
|
{
|
|
306
309
|
"canonical_name": "sks-image-ux-review",
|
|
307
310
|
"type": "core",
|
|
308
|
-
"content_sha256": "
|
|
309
|
-
"hash_history": [
|
|
311
|
+
"content_sha256": "54d4169dc7f362ac9fe2d090bd2612e41d30acbc3e883d6bd382929bdfb9459e",
|
|
312
|
+
"hash_history": [
|
|
313
|
+
"9293346873b5fb25a9d93b630064a2c8ceede2bfdfa4c6ffe7fbb7f64da6595c"
|
|
314
|
+
],
|
|
310
315
|
"deprecated_aliases": []
|
|
311
316
|
},
|
|
312
317
|
{
|
|
313
318
|
"canonical_name": "sks-imagegen",
|
|
314
319
|
"type": "official",
|
|
315
|
-
"content_sha256": "
|
|
320
|
+
"content_sha256": "478e3d8f805eed55c3f3e6c2069142482a7dbd8fa5d9a59f03b136e0e1cb77d0",
|
|
316
321
|
"hash_history": [
|
|
322
|
+
"a7f466ba1829a757f38432fbe8c3a672e22e91948537dafe8f8ce09561d2256e",
|
|
317
323
|
"7a1f9372b03975886233a623031f41e06fd782b1e7a3409517bb428d9c6b76dd"
|
|
318
324
|
],
|
|
319
325
|
"deprecated_aliases": []
|
|
@@ -321,8 +327,9 @@
|
|
|
321
327
|
{
|
|
322
328
|
"canonical_name": "sks-imagegen-source-scout",
|
|
323
329
|
"type": "official",
|
|
324
|
-
"content_sha256": "
|
|
330
|
+
"content_sha256": "95faf4358f1c6567ca6894bfb577629f14a23d623716be70325c0ff9a893d42e",
|
|
325
331
|
"hash_history": [
|
|
332
|
+
"95e71d4431a4c1f6911f0f76eaa1c2b475c52fd22d35c0a6c241e21e090507ad",
|
|
326
333
|
"d648b571c674ed3be862bc0e8b2110f88c2bee54292bb009df0b0b2dbd6d400b"
|
|
327
334
|
],
|
|
328
335
|
"deprecated_aliases": []
|
|
@@ -388,8 +395,9 @@
|
|
|
388
395
|
{
|
|
389
396
|
"canonical_name": "sks-ppt",
|
|
390
397
|
"type": "official",
|
|
391
|
-
"content_sha256": "
|
|
398
|
+
"content_sha256": "c9a0d90e12560dd3f04959869051370e6baf46eda6eb63f708ea1661c5c9d041",
|
|
392
399
|
"hash_history": [
|
|
400
|
+
"1d4de05afd42ee5739c0ed925af9e0ac4785fc746e659c60d3d908d465e6386c",
|
|
393
401
|
"02e8a0758ec6d056ce9851a5a4505b1d32e302e730be3eb169a41392a5d6b2e2",
|
|
394
402
|
"329fc6ee24bb04478b18fb6ccd3691cd7cbb50e1b77ca7b6136383d00b3b0bb4"
|
|
395
403
|
],
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { IMAGEGEN_MODEL } from '../imagegen/imagegen-model-policy.js';
|
|
1
2
|
import path from 'node:path';
|
|
2
3
|
import { nowIso, readJson, readText, writeJsonAtomic } from '../fsx.js';
|
|
3
4
|
export const OFFICIAL_SUBAGENT_HELPER_POLICY_SCHEMA = 'sks.official-subagent-helper-policy.v1';
|
|
@@ -42,7 +43,7 @@ export async function writeOfficialSubagentHelperPolicy(root, input = {}) {
|
|
|
42
43
|
built_in_agents_allowed: builtInAgentsAllowed,
|
|
43
44
|
codex_app_capabilities_allowed: codexAppCapabilitiesAllowed,
|
|
44
45
|
codex_builtin_imagegen_helper_allowed: true,
|
|
45
|
-
preferred_image_generation_surface:
|
|
46
|
+
preferred_image_generation_surface: ("Selected image provider: " + IMAGEGEN_MODEL + ""),
|
|
46
47
|
codex_app_builtin_evidence_class: 'codex_app_builtin',
|
|
47
48
|
api_fallback_evidence_class: 'api_fallback',
|
|
48
49
|
provider_surface_evidence_required: true,
|
package/dist/core/bench.js
CHANGED
|
@@ -69,7 +69,7 @@ export const TRUST_VALIDATE_BENCH_COMMAND = 'sks trust validate bench-fixture --
|
|
|
69
69
|
export const CORE_BENCH_WARMUP_ITERATIONS = 1;
|
|
70
70
|
export const UX_REVIEW_STAGED_LATENCY_BUDGETS = Object.freeze({
|
|
71
71
|
source_screenshot_ingest: 500,
|
|
72
|
-
|
|
72
|
+
imagegen_generation: 120_000,
|
|
73
73
|
callout_extraction: 120_000,
|
|
74
74
|
fix_task_planning: 500,
|
|
75
75
|
recapture_re_review: 120_000,
|
package/dist/core/codex-app.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { IMAGEGEN_MODEL, CODEX_BUILTIN_IMAGEGEN_MODEL } from './imagegen/imagegen-model-policy.js';
|
|
1
2
|
import path from 'node:path';
|
|
2
3
|
import os from 'node:os';
|
|
3
4
|
import fsp from 'node:fs/promises';
|
|
@@ -483,7 +484,7 @@ function codexNativeSksMenuStatus() {
|
|
|
483
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 }) {
|
|
484
485
|
const lines = [];
|
|
485
486
|
if (!appInstalled) {
|
|
486
|
-
lines.push(
|
|
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
488
|
lines.push(`Docs: ${CODEX_APP_DOCS_URL}`);
|
|
488
489
|
}
|
|
489
490
|
if (!codex?.bin)
|
|
@@ -571,10 +572,10 @@ export function codexAppGuidance({ appInstalled, codex, mcpList, featureList, re
|
|
|
571
572
|
lines.push('Codex Chrome Extension is ready; SKS web/browser/webapp QA and UX review should use it before any other web surface.');
|
|
572
573
|
}
|
|
573
574
|
if (imageGenerationReady) {
|
|
574
|
-
lines.push(
|
|
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
576
|
}
|
|
576
577
|
else if (appInstalled || codex?.bin) {
|
|
577
|
-
lines.push(
|
|
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
579
|
lines.push('Run: sks doctor --fix to attempt Codex CLI/App image_generation repair, then rerun the blocked visual route.');
|
|
579
580
|
}
|
|
580
581
|
if (computerUseReady && !computerUseMcpListed) {
|
|
@@ -588,7 +589,7 @@ export function codexAppGuidance({ appInstalled, codex, mcpList, featureList, re
|
|
|
588
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.');
|
|
589
590
|
}
|
|
590
591
|
if (!lines.length)
|
|
591
|
-
lines.push(
|
|
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
593
|
return lines;
|
|
593
594
|
}
|
|
594
595
|
export function formatCodexAppStatus(status, { includeRaw = false } = {}) {
|
|
@@ -609,7 +610,7 @@ export function formatCodexAppStatus(status, { includeRaw = false } = {}) {
|
|
|
609
610
|
`Chrome Ext: ${status.chrome_extension?.ok ? 'ok' : `setup ${(status.chrome_extension?.blockers || []).join(', ') || 'required'}`}`,
|
|
610
611
|
`Computer Use:${status.mcp.has_computer_use ? status.mcp.computer_use_source === 'plugin_cache' ? ' installed (verify @Computer in thread)' : ' ok' : ' missing'}`,
|
|
611
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'}`,
|
|
612
|
-
`Image Gen: ${status.features?.image_generation ?
|
|
613
|
+
`Image Gen: ${status.features?.image_generation ? (`enabled (${CODEX_BUILTIN_IMAGEGEN_MODEL}; ${IMAGEGEN_MODEL} provider unverified)`) : status.features?.checked ? 'missing' : 'not checked'}`,
|
|
613
614
|
`Ready: ${status.ok ? 'yes' : 'no'}`,
|
|
614
615
|
'',
|
|
615
616
|
...status.guidance.map((line) => `- ${line}`)
|
|
@@ -7,7 +7,7 @@ import { buildOfficialPassthroughHeaders, buildProviderUpstreamHeaders, rewriteR
|
|
|
7
7
|
import { createDesktopBridgeRejectionLogger } from './rejection-log.js';
|
|
8
8
|
import { ensureDesktopBridgeRemoteTarget, isUnreachableUpstreamError, refreshDesktopBridgeRemoteTarget, resolveAndBindDesktopBridgeRouteContext, resolveCodexSessionIdentity, resolveDesktopBridgeTarget, safeBridgeErrorCode, singleBridgeHeader } from './security.js';
|
|
9
9
|
import { desktopBridgeListenOrigin } from './state.js';
|
|
10
|
-
import { DesktopBridgeError } from './types.js';
|
|
10
|
+
import { DEFAULT_DESKTOP_BRIDGE_MAX_REQUEST_BODY_BYTES, DesktopBridgeError, DesktopBridgeRequestBodyTooLargeError } from './types.js';
|
|
11
11
|
const MAX_UPSTREAM_ERROR_BODY_BYTES = 1024 * 1024;
|
|
12
12
|
function decodeBridgeRequestBody(body, encoding, maximum) {
|
|
13
13
|
const options = { maxOutputLength: maximum };
|
|
@@ -20,7 +20,9 @@ function decodeBridgeRequestBody(body, encoding, maximum) {
|
|
|
20
20
|
try {
|
|
21
21
|
return zlib.inflateSync(body, options);
|
|
22
22
|
}
|
|
23
|
-
catch {
|
|
23
|
+
catch (error) {
|
|
24
|
+
if (error.code === 'ERR_BUFFER_TOO_LARGE')
|
|
25
|
+
throw error;
|
|
24
26
|
return zlib.inflateRawSync(body, options);
|
|
25
27
|
}
|
|
26
28
|
case 'br':
|
|
@@ -38,6 +40,9 @@ function decodeBridgeRequestBody(body, encoding, maximum) {
|
|
|
38
40
|
catch (error) {
|
|
39
41
|
if (error instanceof DesktopBridgeError)
|
|
40
42
|
throw error;
|
|
43
|
+
if (error.code === 'ERR_BUFFER_TOO_LARGE') {
|
|
44
|
+
throw new DesktopBridgeRequestBodyTooLargeError(maximum, 'decoded');
|
|
45
|
+
}
|
|
41
46
|
throw new DesktopBridgeError('bridge_responses_body_invalid_json');
|
|
42
47
|
}
|
|
43
48
|
}
|
|
@@ -48,14 +53,14 @@ function bodyCarriesModel(rawUrl) {
|
|
|
48
53
|
async function readBoundedBody(req, maximum) {
|
|
49
54
|
const declared = Number(req.headers['content-length'] || 0);
|
|
50
55
|
if (Number.isFinite(declared) && declared > maximum)
|
|
51
|
-
throw new
|
|
56
|
+
throw new DesktopBridgeRequestBodyTooLargeError(maximum, 'encoded', declared);
|
|
52
57
|
const chunks = [];
|
|
53
58
|
let total = 0;
|
|
54
|
-
for await (const raw of req) {
|
|
59
|
+
for await (const raw of req.iterator({ destroyOnReturn: false })) {
|
|
55
60
|
const chunk = Buffer.isBuffer(raw) ? raw : Buffer.from(raw);
|
|
56
61
|
total += chunk.length;
|
|
57
62
|
if (total > maximum)
|
|
58
|
-
throw new
|
|
63
|
+
throw new DesktopBridgeRequestBodyTooLargeError(maximum, 'encoded', total);
|
|
59
64
|
chunks.push(chunk);
|
|
60
65
|
}
|
|
61
66
|
return Buffer.concat(chunks);
|
|
@@ -79,7 +84,7 @@ export async function prepareDesktopBridgeRequest(req, config) {
|
|
|
79
84
|
let payload = null;
|
|
80
85
|
let contentEncodingStripped = false;
|
|
81
86
|
if (bodyCarriesModel(req.url)) {
|
|
82
|
-
const maximum = config.maxRequestBodyBytes ??
|
|
87
|
+
const maximum = config.maxRequestBodyBytes ?? DEFAULT_DESKTOP_BRIDGE_MAX_REQUEST_BODY_BYTES;
|
|
83
88
|
body = await readBoundedBody(req, maximum);
|
|
84
89
|
const encoding = String(req.headers['content-encoding'] || '').trim().toLowerCase();
|
|
85
90
|
let decoded = body;
|
|
@@ -78,6 +78,9 @@ export function createDesktopBridgeRejectionLogger(options = {}) {
|
|
|
78
78
|
...(Number.isInteger(event.status) ? { status: event.status } : {}),
|
|
79
79
|
...(providerId ? { provider_id: providerId } : {}),
|
|
80
80
|
...(publicModel ? { public_model: publicModel } : {}),
|
|
81
|
+
...(Number.isSafeInteger(event.max_request_body_bytes) && event.max_request_body_bytes > 0 ? { max_request_body_bytes: event.max_request_body_bytes } : {}),
|
|
82
|
+
...(Number.isSafeInteger(event.request_body_bytes) && event.request_body_bytes >= 0 ? { request_body_bytes: event.request_body_bytes } : {}),
|
|
83
|
+
...(event.request_body_stage === 'encoded' || event.request_body_stage === 'decoded' ? { request_body_stage: event.request_body_stage } : {}),
|
|
81
84
|
});
|
|
82
85
|
};
|
|
83
86
|
}
|
|
@@ -5,7 +5,7 @@ import { BRIDGE_OFFICIAL_ROUTE_ID } from '../bridge-contracts.js';
|
|
|
5
5
|
import { buildOfficialPassthroughWebSocketHeaders, buildProviderWebSocketHeaders } from './header-policy.js';
|
|
6
6
|
import { createDesktopBridgeRejectionLogger } from './rejection-log.js';
|
|
7
7
|
import { assertDesktopBridgeRouteContext, ensureDesktopBridgeRemoteTarget, isUnreachableUpstreamError, refreshDesktopBridgeRemoteTarget, resolveAndBindDesktopBridgeRouteContext, resolveCodexSessionIdentity, resolveDesktopBridgeTarget, safeBridgeErrorCode } from './security.js';
|
|
8
|
-
import { DesktopBridgeError } from './types.js';
|
|
8
|
+
import { DEFAULT_DESKTOP_BRIDGE_MAX_REQUEST_BODY_BYTES, DesktopBridgeError } from './types.js';
|
|
9
9
|
const MAX_PENDING_MESSAGES = 256;
|
|
10
10
|
const CLOSE_GRACE_MS = 1_000;
|
|
11
11
|
const INITIAL_CREATE_TIMEOUT_MS = 60 * 60_000;
|
|
@@ -19,7 +19,7 @@ function bytes(data) {
|
|
|
19
19
|
}
|
|
20
20
|
export function forwardResponsesWebSocket(req, socket, head, config) {
|
|
21
21
|
const upgradeIdentity = resolveCodexSessionIdentity(req.headers);
|
|
22
|
-
const maxBytes = config.maxRequestBodyBytes ??
|
|
22
|
+
const maxBytes = config.maxRequestBodyBytes ?? DEFAULT_DESKTOP_BRIDGE_MAX_REQUEST_BODY_BYTES;
|
|
23
23
|
const server = new WebSocketServer({ noServer: true, clientTracking: false, perMessageDeflate: false, maxPayload: maxBytes });
|
|
24
24
|
try {
|
|
25
25
|
server.handleUpgrade(req, socket, head, (client) => {
|
|
@@ -569,6 +569,10 @@ export function validateDesktopBridgeConfig(config) {
|
|
|
569
569
|
throw new DesktopBridgeError('bridge_connect_timeout_invalid');
|
|
570
570
|
if (!Number.isFinite(config.idleTimeoutMs) || config.idleTimeoutMs < 1_000 || config.idleTimeoutMs > 86_400_000)
|
|
571
571
|
throw new DesktopBridgeError('bridge_idle_timeout_invalid');
|
|
572
|
+
if (config.maxRequestBodyBytes !== undefined
|
|
573
|
+
&& (!Number.isSafeInteger(config.maxRequestBodyBytes) || config.maxRequestBodyBytes < 1)) {
|
|
574
|
+
throw new DesktopBridgeError('bridge_request_body_limit_invalid');
|
|
575
|
+
}
|
|
572
576
|
if (config.requestTimeoutMs !== undefined
|
|
573
577
|
&& (!Number.isFinite(config.requestTimeoutMs) || config.requestTimeoutMs < 1_000 || config.requestTimeoutMs > 120_000)) {
|
|
574
578
|
throw new DesktopBridgeError('bridge_request_timeout_invalid');
|
|
@@ -5,7 +5,7 @@ import { destroyDesktopBridgeUpstreamAgents, forwardHttp, prepareDesktopBridgeRe
|
|
|
5
5
|
import { createDesktopBridgeRejectionLogger } from './rejection-log.js';
|
|
6
6
|
import { assertAllowedOrigin, assertAllowedPath, assertLoopbackPeer, assertLoopbackListenHost, assertWebSocketUpgrade, prepareDesktopBridgeConfig, safeBridgeErrorCode, validatePreparedDesktopBridgeConfig, } from './security.js';
|
|
7
7
|
import { createDesktopBridgePublicState, desktopBridgeListenOrigin, desktopBridgeStatePath, refreshDesktopBridgeState, removeDesktopBridgeStateIfOwned, writeDesktopBridgeState, } from './state.js';
|
|
8
|
-
import { DesktopBridgeError } from './types.js';
|
|
8
|
+
import { DesktopBridgeError, DesktopBridgeRequestBodyTooLargeError } from './types.js';
|
|
9
9
|
import { PACKAGE_VERSION } from '../../version.js';
|
|
10
10
|
import { DESKTOP_BRIDGE_CLIENT_PATH_PREFIX, DESKTOP_BRIDGE_DIAGNOSTIC_HEALTH_PATH, DESKTOP_BRIDGE_DIAGNOSTIC_PATH, DESKTOP_BRIDGE_DIAGNOSTIC_PROTOCOL } from './types.js';
|
|
11
11
|
import { forwardWebSocket, safeEndUpgradeSocket } from './websocket-forward.js';
|
|
@@ -84,6 +84,8 @@ function handleDiagnosticWebSocket(req, socket, head) {
|
|
|
84
84
|
consume();
|
|
85
85
|
}
|
|
86
86
|
function rejectionStatus(code) {
|
|
87
|
+
if (code === 'bridge_request_body_too_large')
|
|
88
|
+
return 413;
|
|
87
89
|
if (code === 'bridge_path_not_allowed')
|
|
88
90
|
return 404;
|
|
89
91
|
if (code === 'bridge_request_capacity_exhausted')
|
|
@@ -95,6 +97,8 @@ function rejectionStatus(code) {
|
|
|
95
97
|
return 400;
|
|
96
98
|
}
|
|
97
99
|
function rejectionStatusText(status) {
|
|
100
|
+
if (status === 413)
|
|
101
|
+
return 'Payload Too Large';
|
|
98
102
|
if (status === 404)
|
|
99
103
|
return 'Not Found';
|
|
100
104
|
if (status === 403)
|
|
@@ -114,6 +118,11 @@ function writeBridgeRejection(res, error, req) {
|
|
|
114
118
|
method: req?.method,
|
|
115
119
|
url: req?.url,
|
|
116
120
|
status: rejectionStatus(rejectedCode),
|
|
121
|
+
...(error instanceof DesktopBridgeRequestBodyTooLargeError ? {
|
|
122
|
+
max_request_body_bytes: error.maximumBytes,
|
|
123
|
+
request_body_bytes: error.observedBytes,
|
|
124
|
+
request_body_stage: error.stage,
|
|
125
|
+
} : {}),
|
|
117
126
|
});
|
|
118
127
|
if (res.headersSent) {
|
|
119
128
|
res.destroy(error instanceof Error ? error : undefined);
|
|
@@ -21,3 +21,15 @@ export class DesktopBridgeError extends Error {
|
|
|
21
21
|
this.code = code;
|
|
22
22
|
}
|
|
23
23
|
}
|
|
24
|
+
export const DEFAULT_DESKTOP_BRIDGE_MAX_REQUEST_BODY_BYTES = 128 * 1024 * 1024;
|
|
25
|
+
export class DesktopBridgeRequestBodyTooLargeError extends DesktopBridgeError {
|
|
26
|
+
maximumBytes;
|
|
27
|
+
stage;
|
|
28
|
+
observedBytes;
|
|
29
|
+
constructor(maximumBytes, stage, observedBytes) {
|
|
30
|
+
super('bridge_request_body_too_large');
|
|
31
|
+
this.maximumBytes = maximumBytes;
|
|
32
|
+
this.stage = stage;
|
|
33
|
+
this.observedBytes = observedBytes;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { IMAGEGEN_MODEL } from '../imagegen/imagegen-model-policy.js';
|
|
1
2
|
import { PACKAGE_VERSION, nowIso, sha256 } from '../fsx.js';
|
|
2
3
|
import { coreEngineeringDirectiveReference } from '../lean-engineering-policy.js';
|
|
3
4
|
import { normalizeDollarSkillName, prefixKnownSksDollarReferences, sksPrefixedDollarCommand, sksPrefixedSkillName } from '../routes/dollar-prefix.js';
|
|
@@ -60,10 +61,10 @@ const CORE_SKILL_DEFINITIONS = [
|
|
|
60
61
|
route: '$Image-UX-Review',
|
|
61
62
|
purpose: 'run one screenshot-to-generated-annotation-to-UX-report pipeline without duplicate picker skills.',
|
|
62
63
|
when: 'Use for $Image-UX-Review, $UX-Review, $Visual-Review, or $UI-UX-Review requests; all aliases resolve to this one canonical skill.',
|
|
63
|
-
workflow:
|
|
64
|
+
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."),
|
|
64
65
|
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.',
|
|
65
66
|
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.',
|
|
66
|
-
evidence: 'image-ux-screen-inventory.json, image-ux-
|
|
67
|
+
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.',
|
|
67
68
|
fallback: 'Block full verification if the real source screenshot, completed generated annotated image, generated-image callout extraction, or generated-image-based UX/UI report is unavailable.'
|
|
68
69
|
},
|
|
69
70
|
{
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { IMAGEGEN_MODEL } from '../imagegen/imagegen-model-policy.js';
|
|
1
2
|
import fs from 'node:fs/promises';
|
|
2
3
|
import path from 'node:path';
|
|
3
4
|
import { ensureDir, nowIso, writeJsonAtomic } from '../fsx.js';
|
|
@@ -79,16 +80,16 @@ async function stateForCapability(root, id, imageCapability, nativeFeatureMatrix
|
|
|
79
80
|
repair_actions: verified
|
|
80
81
|
? ['postcheck-imagegen-path-contract']
|
|
81
82
|
: builtInConfigured
|
|
82
|
-
? [
|
|
83
|
-
: [
|
|
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.")],
|
|
84
85
|
after: null,
|
|
85
86
|
artifact_path: path.join(reports, 'native-capability-repair-matrix.json'),
|
|
86
87
|
core_blockers: [],
|
|
87
88
|
route_blockers: verified ? {} : { 'route-image': [routeBlocker] },
|
|
88
89
|
manual_actions: verified ? [] : [
|
|
89
90
|
builtInConfigured
|
|
90
|
-
?
|
|
91
|
-
:
|
|
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.")
|
|
92
93
|
],
|
|
93
94
|
blockers: [],
|
|
94
95
|
warnings: verified ? [] : [
|