sneakoscope 7.5.0 → 7.6.0

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 (167) hide show
  1. package/README.md +14 -7
  2. package/crates/sks-core/Cargo.lock +1 -1
  3. package/crates/sks-core/Cargo.toml +1 -1
  4. package/dist/cli/command-manifest-lite.js +2 -0
  5. package/dist/cli/command-registry.js +2 -0
  6. package/dist/cli/install-helpers-codex-lb-chain.js +42 -0
  7. package/dist/cli/install-helpers-codex-lb-config.js +114 -9
  8. package/dist/cli/install-helpers.js +729 -550
  9. package/dist/cli/router.js +24 -4
  10. package/dist/commands/codex-app.js +37 -1
  11. package/dist/commands/codex-lb.js +491 -300
  12. package/dist/config/skills-manifest.json +55 -48
  13. package/dist/core/align/align-route.js +127 -0
  14. package/dist/core/codex-app/codex-app-fast-ui-repair.js +8 -4
  15. package/dist/core/codex-app/codex-app-restart.js +83 -0
  16. package/dist/core/codex-app/codex-app-ui-state-snapshot.js +8 -4
  17. package/dist/core/codex-app/desktop-routing-snapshot.js +1 -1
  18. package/dist/core/codex-app/menubar/constants.js +5 -0
  19. package/dist/core/codex-app/menubar/generation-transaction-journal.js +1 -3
  20. package/dist/core/codex-app/menubar/installer.js +18 -0
  21. package/dist/core/codex-app/multi-provider-router.js +22 -10
  22. package/dist/core/codex-app/openrouter-activate.js +26 -1
  23. package/dist/core/codex-app.js +113 -21
  24. package/dist/core/codex-control/codex-app-server-runtime-env.js +86 -0
  25. package/dist/core/codex-control/codex-app-server-v2-client.js +78 -8
  26. package/dist/core/codex-control/codex-task-runner.js +2 -2
  27. package/dist/core/codex-lb/capability-runner.js +204 -0
  28. package/dist/core/codex-lb/capability-types.js +1 -0
  29. package/dist/core/codex-lb/codex-lb-env.js +9 -13
  30. package/dist/core/codex-lb/codex-lb-setup.js +45 -8
  31. package/dist/core/codex-lb/codex-lb-tool-catalog.js +52 -74
  32. package/dist/core/codex-lb/codex-lb-tool-output-recovery.js +1 -1
  33. package/dist/core/codex-lb/desktop-auth-invariant.js +185 -0
  34. package/dist/core/codex-lb/desktop-bridge/client.js +34 -0
  35. package/dist/core/codex-lb/desktop-bridge/header-policy.js +106 -0
  36. package/dist/core/codex-lb/desktop-bridge/http-forward.js +101 -0
  37. package/dist/core/codex-lb/desktop-bridge/index.js +10 -0
  38. package/dist/core/codex-lb/desktop-bridge/launchd.js +81 -0
  39. package/dist/core/codex-lb/desktop-bridge/location-rewrite.js +27 -0
  40. package/dist/core/codex-lb/desktop-bridge/security.js +274 -0
  41. package/dist/core/codex-lb/desktop-bridge/server.js +179 -0
  42. package/dist/core/codex-lb/desktop-bridge/state.js +119 -0
  43. package/dist/core/codex-lb/desktop-bridge/types.js +16 -0
  44. package/dist/core/codex-lb/desktop-bridge/websocket-forward.js +151 -0
  45. package/dist/core/codex-lb/desktop-center-credentials.js +189 -0
  46. package/dist/core/codex-lb/desktop-controller.js +1410 -0
  47. package/dist/core/codex-lb/desktop-mode.js +32 -0
  48. package/dist/core/codex-lb/desktop-real-evidence.js +168 -0
  49. package/dist/core/codex-lb/desktop-service.js +613 -0
  50. package/dist/core/codex-lb/legacy-migration.js +575 -0
  51. package/dist/core/codex-lb/migration-receipt.js +246 -0
  52. package/dist/core/codex-lb/probes/auxiliary-surfaces-probe.js +60 -0
  53. package/dist/core/codex-lb/probes/bridge-probe.js +75 -0
  54. package/dist/core/codex-lb/probes/catalog-probe.js +128 -0
  55. package/dist/core/codex-lb/probes/computer-use-probe.js +50 -0
  56. package/dist/core/codex-lb/probes/image-generation-probe.js +47 -0
  57. package/dist/core/codex-lb/probes/probe-evidence.js +39 -0
  58. package/dist/core/codex-lb/probes/voice-realtime-probe.js +44 -0
  59. package/dist/core/codex-lb/trusted-deep-evidence.js +403 -0
  60. package/dist/core/codex-native/core-skill-manifest.js +13 -0
  61. package/dist/core/codex-runtime/codex-desktop-config-policy.js +2 -1
  62. package/dist/core/commands/align-command.js +220 -0
  63. package/dist/core/commands/image-ux-review-command.js +37 -18
  64. package/dist/core/commands/naruto-command.js +18 -6
  65. package/dist/core/commands/telegram-command.js +294 -39
  66. package/dist/core/doctor/skill-legacy-surface.js +1 -3
  67. package/dist/core/evidence/evidence-freshness.js +14 -0
  68. package/dist/core/feature-fixtures.js +9 -1
  69. package/dist/core/feature-registry.js +3 -1
  70. package/dist/core/hooks-runtime/hook-context.js +15 -2
  71. package/dist/core/hooks-runtime/managed-skill-generation-heal.js +46 -0
  72. package/dist/core/hooks-runtime/naruto-terminal-finalization.js +1 -0
  73. package/dist/core/hooks-runtime/tool-output-quarantine.js +1 -1
  74. package/dist/core/hooks-runtime.js +5 -3
  75. package/dist/core/image-ux-review/imagegen-adapter.js +10 -5
  76. package/dist/core/image-ux-review.js +70 -27
  77. package/dist/core/imagegen/codex-lb-imagegen-target.js +1 -2
  78. package/dist/core/imagegen/imagegen-capability.js +1 -2
  79. package/dist/core/init/skills.js +3 -3
  80. package/dist/core/init.js +1 -1
  81. package/dist/core/managed-assets/managed-assets-manifest.js +2 -1
  82. package/dist/core/perf/release-latency-slo.js +12 -6
  83. package/dist/core/pipeline-internals/runtime-core.js +34 -0
  84. package/dist/core/pipeline-internals/runtime-gates.js +5 -2
  85. package/dist/core/preflight/parallel-preflight-engine.js +1 -1
  86. package/dist/core/proof/auto-finalize.js +98 -6
  87. package/dist/core/proof/route-proof-gate.js +12 -1
  88. package/dist/core/proof/route-proof-policy.js +8 -8
  89. package/dist/core/release/package-size-budget.js +2 -2
  90. package/dist/core/release/release-proof-io.js +1 -3
  91. package/dist/core/release/release-real-contract.js +5 -4
  92. package/dist/core/release/release-stamp-proof.js +1 -3
  93. package/dist/core/remote/audit-idempotency.js +50 -18
  94. package/dist/core/remote/codex-public-activity.js +283 -0
  95. package/dist/core/remote/index.js +1 -0
  96. package/dist/core/remote/ssh-worker-client.js +4 -1
  97. package/dist/core/remote/worker.js +206 -27
  98. package/dist/core/research/research-adversarial-review.js +1 -3
  99. package/dist/core/research/research-claim-synthesizer.js +1 -3
  100. package/dist/core/research/research-falsification-runner.js +1 -3
  101. package/dist/core/research/research-source-evidence.js +1 -3
  102. package/dist/core/routes/constants.js +1 -1
  103. package/dist/core/routes/dollar-manifest-lite.js +2 -0
  104. package/dist/core/routes.js +18 -2
  105. package/dist/core/secret-redaction.js +6 -0
  106. package/dist/core/telegram/bot-api.js +26 -6
  107. package/dist/core/telegram/center-snapshot.js +718 -0
  108. package/dist/core/telegram/config.js +157 -31
  109. package/dist/core/telegram/hub.js +285 -31
  110. package/dist/core/telegram/index.js +2 -0
  111. package/dist/core/telegram/ingress-spool.js +419 -0
  112. package/dist/core/telegram/ledgers.js +188 -29
  113. package/dist/core/telegram/messages.js +26 -6
  114. package/dist/core/telegram/owner-lock.js +6 -1
  115. package/dist/core/telegram/runtime-projection.js +38 -3
  116. package/dist/core/telegram/runtime.js +298 -63
  117. package/dist/core/telegram/service.js +137 -8
  118. package/dist/core/telegram/setup.js +96 -28
  119. package/dist/core/text/strings.js +3 -0
  120. package/dist/core/version.js +1 -1
  121. package/dist/native/sks-menubar/Sources/AlertFactory.swift +11 -3
  122. package/dist/native/sks-menubar/Sources/AppDelegate.swift +9 -0
  123. package/dist/native/sks-menubar/Sources/ControlCenterWindowController.swift +25 -3
  124. package/dist/native/sks-menubar/Sources/ControlKit.swift +19 -8
  125. package/dist/native/sks-menubar/Sources/DiagnosticsViewController.swift +1 -2
  126. package/dist/native/sks-menubar/Sources/MCPServersViewController.swift +45 -17
  127. package/dist/native/sks-menubar/Sources/OverviewSummary.swift +162 -0
  128. package/dist/native/sks-menubar/Sources/OverviewViewController.swift +136 -190
  129. package/dist/native/sks-menubar/Sources/ProcessClient.swift +107 -11
  130. package/dist/native/sks-menubar/Sources/ProvidersMultiProvider.swift +5 -1
  131. package/dist/native/sks-menubar/Sources/ProvidersOpenRouter.swift +16 -4
  132. package/dist/native/sks-menubar/Sources/ProvidersRoleModels.swift +4 -1
  133. package/dist/native/sks-menubar/Sources/ProvidersRoutingTruth.swift +131 -0
  134. package/dist/native/sks-menubar/Sources/ProvidersViewController.swift +288 -341
  135. package/dist/native/sks-menubar/Sources/RemoteTelegramCenterState.swift +447 -0
  136. package/dist/native/sks-menubar/Sources/RemoteTelegramRendering.swift +484 -0
  137. package/dist/native/sks-menubar/Sources/RemoteTelegramViewController.swift +364 -115
  138. package/dist/native/sks-menubar/Sources/SettingsViewController.swift +73 -12
  139. package/dist/native/sks-menubar/Sources/SidebarItem.swift +3 -3
  140. package/dist/native/sks-menubar/Sources/StatusItemController.swift +13 -13
  141. package/dist/native/sks-menubar/Sources/TelegramHubSupervisor.swift +469 -0
  142. package/dist/native/sks-menubar/Sources/UpdatesViewController.swift +1 -6
  143. package/dist/native/sks-menubar/Tests/AppRuntimeTestSupport.swift +12 -0
  144. package/dist/native/sks-menubar/Tests/NativeTelegramRegressionRunner.swift +55 -0
  145. package/dist/native/sks-menubar/Tests/ProcessClientTests.swift +33 -0
  146. package/dist/native/sks-menubar/Tests/ProvidersViewControllerTests.swift +142 -0
  147. package/dist/native/sks-menubar/Tests/RemoteTelegramCenterStateTests.swift +56 -0
  148. package/dist/native/sks-menubar/Tests/TelegramHubSupervisorTests.swift +55 -0
  149. package/dist/scripts/codex-lb-catalog-passthrough-check.js +120 -0
  150. package/dist/scripts/codex-lb-desktop-auth-invariant-check.js +169 -0
  151. package/dist/scripts/codex-lb-desktop-bridge-check.js +394 -0
  152. package/dist/scripts/codex-lb-desktop-bridge-latency-check.js +196 -0
  153. package/dist/scripts/codex-lb-desktop-capabilities-check.js +287 -0
  154. package/dist/scripts/codex-lb-desktop-real-evidence-check.js +123 -0
  155. package/dist/scripts/codex-lb-fast-mode-truth-check.js +10 -3
  156. package/dist/scripts/codex-lb-fast-ui-preservation-check.js +81 -40
  157. package/dist/scripts/codex-lb-gpt56-fast-profile-check.js +99 -37
  158. package/dist/scripts/doctor-fixes-codex-app-fast-ui-check.js +1 -1
  159. package/dist/scripts/gate-policy-audit-check.js +1 -1
  160. package/dist/scripts/helper-dedup-check.js +0 -1
  161. package/dist/scripts/release-metadata-check.js +1 -1
  162. package/dist/scripts/release-real-check.js +7 -0
  163. package/package.json +5 -2
  164. package/release-gates.v2.json +2 -1
  165. package/runtime-required-scripts.json +30 -0
  166. package/dist/cli/install-helpers-codex-lb-selftest-chain.js +0 -112
  167. package/dist/cli/install-helpers-codex-lb-selftest.js +0 -482
package/README.md CHANGED
@@ -22,7 +22,7 @@ Proof-first orchestration for Codex CLI, ChatGPT Desktop, AI coding agents, mult
22
22
  Sneakoscope Codex (`sks`) is an open-source trust layer for Codex CLI and ChatGPT Desktop. It coordinates bounded AI coding agents, records machine-verifiable evidence, preserves project memory, and blocks release claims that are not supported by current tests or artifacts. Search visibility outcomes are measured separately; SKS does not promise rankings or traffic.
23
23
  <!-- END SKS SEARCH VISIBILITY MARKETING -->
24
24
 
25
- This README documents package **SKS 7.5.0** — its own identity, read from `package.json` and verified by the release gate, not advice about what to install.
25
+ This README documents package **SKS 7.6.0** — its own identity, read from `package.json` and verified by the release gate, not advice about what to install.
26
26
 
27
27
  Use the official latest stable SKS and Codex CLI releases. SKS stays version-agnostic: older hosts keep working where capabilities allow, while Menu Bar / Center induce updates to the latest stable build. Run `sks update-check` for what is installed and read the capability report for what is actually supported — feature availability is decided by capability probes, not by a version number printed in a document. It resolves managed SKS skills from the authoritative global install, preserves a runnable Naruto child slot when `max_threads=2`, and keeps Menu Bar repair transactional so stamped generations remain verifiable. Naruto uses stable opt-in multi-agent V2 when the host exposes it. Local code search is mode-separated (`sks search files|text|structure|symbol|context`); `context` is answered by the compiled TriWiki Context Graph with evidence paths rather than lexical guessing — see [docs/architecture/context-graph.md](docs/architecture/context-graph.md) and [docs/architecture/search-engine-target.md](docs/architecture/search-engine-target.md). See [CHANGELOG.md](CHANGELOG.md).
28
28
 
@@ -65,7 +65,11 @@ The SKS menu bar shows the installed Codex CLI version and latest known version.
65
65
 
66
66
  ### Telegram remote coding on this Mac
67
67
 
68
- Open **SKS Center → Remote & Telegram**, create a bot with BotFather, send `/start` to that bot from the Telegram account you want to pair, then choose **Connect Bot & Register Coding Session…** and paste the token. SKS verifies the bot, stores the token only in macOS Keychain, pairs only that private chat/user, and registers one dedicated session bound to the current project. Choose **Start Hub**, then send ordinary text to the bot. On the first real message, the Hub creates the Codex thread and starts its first turn in the same App Server connection so the thread is durably resumable; later messages resume that exact thread and return the final response to Telegram.
68
+ Open **SKS Center → Remote & Telegram**, create a bot with BotFather, send `/start` to that bot from the Telegram account you want to pair, then choose **Connect This Project…** and paste the token. SKS verifies the bot, stores the token only in macOS Keychain, pairs only that private chat/user, and registers one dedicated session bound to the current project. Choose **Start Hub**, then send ordinary text to the bot. On the first real message, the Hub creates the Codex thread and starts its first turn in the same App Server connection so the thread is durably resumable; later messages resume that exact thread and return the final response to Telegram.
69
+
70
+ Telegram runtime configuration is v2-only. A legacy v1 file cannot start the Hub; Center shows a one-time reconnect prompt, and explicit reconnect/setup atomically writes the verified bot/private-pair identity, token fingerprint, and generation contract as `sks.telegram-config.v2`.
71
+
72
+ After connection, Center exposes the registered-session selector, the real user/Codex conversation from that Telegram-bound App Server thread, and a live public activity feed for turn, tool, command, file, search, and subagent lifecycle events. **Older**, **Newer**, and **Latest** page the complete stored turn history through opaque App Server cursors. On Latest, Center checks only the bounded local journal every 2.5 seconds and reloads the heavier App Server conversation when a completed-turn revision changes or the user refreshes/navigates; an older page never jumps away while you read it. The feed intentionally excludes reasoning text, raw tool output, arguments/results, credentials, and paths outside the project, and each page/activity view keeps explicit byte and item bounds. Center also shows the ordinary-text workflow and every supported Telegram command.
69
73
 
70
74
  The Hub runs as a user LaunchAgent and uses `caffeinate -i` while the logged-in Mac is available. The Mac still needs to remain powered on, logged in, awake, and network-connected; closing the lid or logging out can stop access. Telegram input has no arbitrary shell path, runs with approvals disabled and network access disabled inside the Codex workspace sandbox, and cannot target an unpaired chat or another project.
71
75
 
@@ -241,16 +245,19 @@ It shows the current quickstart flow: one-line install, `$sks-plan`, `sks review
241
245
  - macOS optional: menu bar integration and `/usr/bin/open`
242
246
  - The menubar icon shows and hides itself automatically as the Codex desktop app launches/quits; set `quit_with_codex: true` in `~/.codex/sks-menubar/config.json` to have the menubar fully quit with Codex instead of just hiding (default `false`).
243
247
  - Native input dialogs (API keys, codex-lb setup) pass secrets to `sks` via `--api-key-stdin` instead of a visible Terminal window or process arguments.
244
- - Auth/provider changes require a successful app restart; skipped or failed restarts fail the action.
245
- - `sks update` preserves the selected codex-lb or ChatGPT OAuth mode, model, reasoning, catalog, and routing state.
246
- - Providers exposes **Restore Chat / Pro (OAuth)** as an explicit auth-mode switch while retaining saved codex-lb credentials.
248
+ - Codex Desktop always keeps its real ChatGPT OAuth identity. codex-lb setup stores a separate gateway endpoint/key and never replaces `~/.codex/auth.json`.
249
+ - Providers separates **Desktop Full Capability**, **CLI Provider**, and **Capability Matrix**. Desktop Full Capability keeps the built-in OpenAI provider and routes supported traffic through a loopback bridge; CLI Provider is selected only for the CLI process.
250
+ - Authentication and routing modes do not toggle Codex App's native model picker, Fast, image, Browser Use, Computer Use, voice, plugins/apps, or other built-in surfaces. Capability status describes evidence for the codex-lb data path, not permission to use the native feature.
251
+ - `sks update`, setup, repair, and routing changes preserve OAuth, user model/reasoning/Fast settings, unknown catalog fields, and unrelated provider configuration. Legacy shared-auth routing requires explicit `sks codex-lb migrate-legacy-desktop --restart-app`; without a real restart and post-restart identity check it cannot finalize a migration receipt.
252
+ - The remote codex-lb service remains independently hosted and operated. SKS uses only the configured URL and gateway key; it does not deploy, restart, or change credentials on that host.
253
+ - Full release proof blocks with `real_required_missing` until fresh trust-anchored evidence covers the real Desktop feature/lifecycle matrix and the separately hosted other-Mac runtime; fixtures and configuration cannot satisfy that boundary.
247
254
  - Update installs always rebuild the companion with the newly installed SKS package, preventing a previous-version updater from restoring a stale menu binary.
248
255
  - The menubar dropdown's `View Last Log` item opens the most recent background action's log file, so you don't need to keep a Terminal window open to see command output.
249
256
  - `Manage MCP Servers…` provides a resizable native table and add/remove/enable/disable controls for global Codex MCP configuration. Secret environment values and command arguments are accepted through native dialogs/stdin but omitted from list output and logs.
250
257
  - `sks menubar status --json` reports a `codex_sync` object with `bundle_id`, `codex_running`, and `icon_visible_expected` to show Codex-lifecycle detection state.
251
258
  - The menu displays the installed Codex CLI version, adds an `⬆` status icon when `sks codex update-status` sees a newer release, runs the official self-updater through `Update Codex CLI Now`, and exposes `Run sks doctor --fix` as a background repair action.
252
- - Fast mode has a verified status row and direct On/Off actions. Status failures render as unavailable with neither choice falsely selected.
253
- - If Codex shows `[No tool output found for custom tool call ...]`, SKS blocks reuse of that structurally ambiguous thread. Upgrade codex-lb (or explicitly run `sks codex-lb use-oauth`), inspect possible side effects, then continue the persisted mission in a fresh Codex task. SKS never rewrites session JSONL or fabricates a successful tool output.
259
+ - **Codex Fast** is labeled as the official 1.5× Codex speed option, with a verified service-tier status row and direct On/Off actions. Center explains that ChatGPT-sign-in GPT-5.6/GPT-5.5 use 2.5× Standard credits and GPT-5.4 uses 2×, while API-key token pricing and API Priority processing are separate. Model selection, Codex-Spark, and reasoning effort remain independent; status failures render as unavailable with neither choice falsely selected.
260
+ - If Codex shows `[No tool output found for custom tool call ...]`, SKS blocks reuse of that structurally ambiguous thread. Upgrade codex-lb or run `sks codex-lb disable`, inspect possible side effects, then continue the persisted mission in a fresh Codex task. SKS never rewrites session JSONL or fabricates a successful tool output.
254
261
  - Zellij optional but recommended for terminal worker panes
255
262
 
256
263
  ## License
@@ -259,7 +259,7 @@ dependencies = [
259
259
 
260
260
  [[package]]
261
261
  name = "sks-core"
262
- version = "7.5.0"
262
+ version = "7.6.0"
263
263
  dependencies = [
264
264
  "globset",
265
265
  "grep-matcher",
@@ -1,6 +1,6 @@
1
1
  [package]
2
2
  name = "sks-core"
3
- version = "7.5.0"
3
+ version = "7.6.0"
4
4
  edition = "2021"
5
5
 
6
6
  [dependencies]
@@ -73,6 +73,7 @@ const COMMAND_MANIFEST_LITE_BASE = [
73
73
  { name: 'versioning', summary: 'Manage release version metadata', maturity: 'stable' },
74
74
  { name: 'reasoning', summary: 'Show reasoning route', maturity: 'labs' },
75
75
  { name: 'aliases', summary: 'Show command aliases', maturity: 'stable' },
76
+ { name: 'align', summary: 'Prepare or inspect the $sks-align GPT-5.6 / openai/skills modernization mission', maturity: 'beta', mutatesRouteState: true },
76
77
  { name: 'selftest', summary: 'Run local mock selftest', maturity: 'stable' },
77
78
  { name: 'goal', summary: 'Print stateless Codex native Goal controls', maturity: 'beta' },
78
79
  { name: 'seo-geo-optimizer', summary: 'Run unified SEO/GEO optimizer audit/plan/apply/verify plus research/strategy (--include-marketing) on the search-visibility kernel', maturity: 'beta' },
@@ -111,6 +112,7 @@ const SAFE_COMMAND_CONTRACT_LITE = {
111
112
  requiredCapabilities: []
112
113
  };
113
114
  const COMMAND_CONTRACT_OVERRIDES_LITE = {
115
+ align: { latency: 'long', supportsJson: true, inputProfile: 'json-only' },
114
116
  autoresearch: { latency: 'long' },
115
117
  bench: { latency: 'long' },
116
118
  check: { risk: 'R1', latency: 'long' },
@@ -223,6 +223,7 @@ const COMMAND_DEFINITIONS = {
223
223
  versioning: entry('stable', 'Manage release version metadata', 'dist/commands/versioning.js', directCommand(() => import('../commands/versioning.js'), 'dist/commands/versioning.js')),
224
224
  reasoning: entry('labs', 'Show reasoning route', 'dist/core/commands/basic-cli.js', basicArgs('reasoningCommand')),
225
225
  aliases: entry('stable', 'Show command aliases', 'dist/core/commands/basic-cli.js', basicNoArgs('aliasesCommand')),
226
+ align: routeStateMutator(entry('beta', 'Prepare or inspect the $sks-align GPT-5.6 / openai/skills modernization mission', 'dist/core/commands/align-command.js', subcommand(() => import('../core/commands/align-command.js'), 'alignCommand', 'dist/core/commands/align-command.js', 'prepare')), ['align-gate.json']),
226
227
  selftest: entry('stable', 'Run local mock selftest', 'dist/core/commands/basic-cli.js', basicArgs('selftestCommand')),
227
228
  goal: entry('beta', 'Print stateless Codex native Goal controls', 'dist/core/commands/goal-command.js', subcommand(() => import('../core/commands/goal-command.js'), 'goalCommand', 'dist/core/commands/goal-command.js')),
228
229
  'seo-geo-optimizer': entry('beta', 'Run unified SEO/GEO optimizer audit/plan/apply/verify plus research/strategy (--include-marketing) on the search-visibility kernel', 'dist/core/commands/seo-command.js', argsCommand(() => import('../core/commands/seo-command.js'), 'seoGeoOptimizerCommand', 'dist/core/commands/seo-command.js')),
@@ -256,6 +257,7 @@ const COMMAND_DEFINITIONS = {
256
257
  'agent-bridge': readOnly(entry('beta', 'Publish the agent-bridge manifest and print host registration snippets for external agent systems', 'dist/core/commands/agent-bridge-command.js', subcommand(() => import('../core/commands/agent-bridge-command.js'), 'agentBridgeCommand', 'dist/core/commands/agent-bridge-command.js', 'setup')))
257
258
  };
258
259
  const COMMANDS_WITH_LEGACY_CONTRACT_OVERRIDES = applyCommandContractOverrides(COMMAND_DEFINITIONS, {
260
+ align: { latency: 'long', supportsJson: true, inputProfile: 'json-only' },
259
261
  autoresearch: { latency: 'long' },
260
262
  bench: { latency: 'long' },
261
263
  check: { risk: 'R1', latency: 'long' },
@@ -4,6 +4,7 @@ import fsp from 'node:fs/promises';
4
4
  import { ensureDir, packageRoot, readText, writeTextAtomic } from '../core/fsx.js';
5
5
  import { recordCodexLbHealthEvent } from '../core/codex-lb-circuit.js';
6
6
  import { codexLbBaseUrlSecurityBlocker } from '../core/codex-lb/codex-lb-env.js';
7
+ import { probeEvidence } from '../core/codex-lb/probes/probe-evidence.js';
7
8
  import { CODEX_LB_CANONICAL_FAST_SERVICE_TIER, codexLbEnvPath, parseCodexLbEnvKey, redactSecretText } from './install-helpers-codex-lb-shared.js';
8
9
  function codexLbResponsesEndpoint(baseUrl = '') {
9
10
  const base = String(baseUrl || '').trim().replace(/\/+$/, '');
@@ -288,6 +289,47 @@ export async function checkCodexLbResponseChain(status = {}, opts = {}) {
288
289
  error: redactSecretText(second.error_payload?.error?.message || second.error_payload?.response?.error?.message || second.text || 'codex-lb chained Responses request failed', [apiKey])
289
290
  }, { endpoint, home, opts, env }), opts);
290
291
  }
292
+ export async function runCodexLbTextResponsesProbe(status = {}, opts = {}) {
293
+ const result = await checkCodexLbResponseChain(status, opts);
294
+ return codexLbResponseChainCapabilityEvidence(result, {
295
+ checkedAt: typeof opts.nowIso === 'function' ? opts.nowIso() : new Date().toISOString()
296
+ });
297
+ }
298
+ export function codexLbResponseChainCapabilityEvidence(result = {}, opts = {}) {
299
+ const checkedAt = opts.checkedAt || new Date().toISOString();
300
+ if (result?.skipped === true || result?.status === 'skipped') {
301
+ return probeEvidence({
302
+ skipped: true,
303
+ source: 'config',
304
+ evidence: {
305
+ probe: 'text_responses',
306
+ status: result?.status || 'skipped',
307
+ reason: result?.reason || null
308
+ }
309
+ }, checkedAt);
310
+ }
311
+ const verified = result?.ok === true && result?.status === 'chain_ok';
312
+ const blockers = verified
313
+ ? []
314
+ : [
315
+ ...(Array.isArray(result?.blockers) ? result.blockers : []),
316
+ `text_responses_${String(result?.status || 'probe_failed')}`
317
+ ];
318
+ return probeEvidence({
319
+ attempted: true,
320
+ verified,
321
+ source: 'transport',
322
+ blockers,
323
+ evidence: {
324
+ probe: 'text_responses',
325
+ status: result?.status || null,
326
+ cached: result?.cached === true,
327
+ http_status: result?.http_status || null,
328
+ response_chain_completed: verified,
329
+ service_tier: result?.service_tier_evidence || null
330
+ }
331
+ }, checkedAt);
332
+ }
291
333
  async function recordCodexLbChainHealth(result, opts = {}) {
292
334
  if (!result || result.skipped || opts.recordCircuit === false)
293
335
  return result;
@@ -4,24 +4,129 @@ import { ensureDir, readText } from '../core/fsx.js';
4
4
  import { GLM_CODEX_CONFIG_PROVIDER_ID, GLM_52_OPENROUTER_MODEL, OPENROUTER_AUTH_COMMAND, OPENROUTER_AUTH_REFRESH_INTERVAL_MS, OPENROUTER_AUTH_TIMEOUT_MS, openRouterAuthCommandArgs, OPENROUTER_DEFAULT_PROFILE_ID, RETIRED_GLM_DESKTOP_CONFIG_PROFILE_IDS } from '../core/codex-app/openrouter-provider.js';
5
5
  import { openRouterSecretPaths, resolveOpenRouterApiKey } from '../core/providers/openrouter/openrouter-secret-store.js';
6
6
  import { reconcileRetiredSksConfigText } from '../core/auto-review.js';
7
- import { removeTopLevelTomlKeyIfValue, safeWriteCodexConfigToml, upsertTopLevelTomlString, upsertTomlTable } from '../core/codex-runtime/codex-desktop-config-policy.js';
7
+ import { ensureTrailingNewline, removeTopLevelTomlKeyIfValue, safeWriteCodexConfigToml, upsertTopLevelTomlString, upsertTomlTable } from '../core/codex-runtime/codex-desktop-config-policy.js';
8
8
  import { codexLbConfigPath, normalizeCodexLbBaseUrl } from './install-helpers-codex-lb-shared.js';
9
9
  import { escapeRegExp } from '../core/text/regex.js';
10
- export function upsertCodexLbConfig(text = '', baseUrl, selectDefault = true) {
11
- let next = selectDefault
10
+ export const CODEX_LB_DESKTOP_BRIDGE_MARKER = '# sks-codex-lb-managed-desktop-bridge';
11
+ export const CODEX_LB_DESKTOP_COMPAT_MARKER = '# sks-codex-lb-managed-desktop-compat';
12
+ export const CODEX_LB_MODEL_CATALOG_MARKER = '# sks-codex-lb-managed-model-catalog';
13
+ const LEGACY_CODEX_LB_OPENAI_ROUTING_MARKER = '# sks-codex-lb-managed-openai-base-url';
14
+ export function upsertCodexLbNativeDesktopConfig(text, input) {
15
+ let next = String(text || '');
16
+ const selectedProvider = topLevelTomlString(next, 'model_provider');
17
+ if (selectedProvider && selectedProvider !== 'openai' && selectedProvider !== 'codex-lb') {
18
+ throw new Error('codex_lb_user_owned_model_provider_conflict');
19
+ }
20
+ if (selectedProvider === 'codex-lb' && !topLevelHasLine(next, CODEX_LB_DESKTOP_COMPAT_MARKER)) {
21
+ throw new Error('codex_lb_legacy_desktop_config_requires_migration');
22
+ }
23
+ if (topLevelHasLine(next, LEGACY_CODEX_LB_OPENAI_ROUTING_MARKER)
24
+ && !topLevelHasLine(next, CODEX_LB_DESKTOP_BRIDGE_MARKER)) {
25
+ throw new Error('codex_lb_legacy_desktop_config_requires_migration');
26
+ }
27
+ const modelCatalog = topLevelTomlString(next, 'model_catalog_json');
28
+ if (modelCatalog && !topLevelHasLine(next, CODEX_LB_MODEL_CATALOG_MARKER)) {
29
+ throw new Error('codex_lb_user_owned_model_catalog_json_conflict');
30
+ }
31
+ next = removeTopLevelTomlKeyIfValue(next, 'model_provider', 'codex-lb');
32
+ next = removeTopLevelLine(next, CODEX_LB_DESKTOP_COMPAT_MARKER);
33
+ next = removeManagedModelCatalogJson(next);
34
+ next = upsertManagedTopLevelTomlString(next, 'openai_base_url', input.bridgeBaseUrl, CODEX_LB_DESKTOP_BRIDGE_MARKER);
35
+ next = upsertTomlTable(next, 'model_providers.codex-lb', cliProviderBlock(input.remoteBaseUrl));
36
+ return ensureTrailingNewline(next);
37
+ }
38
+ export function upsertCodexLbCompatDesktopConfig(text, input) {
39
+ let next = removeManagedDesktopBridgeRouting(String(text || ''));
40
+ next = removeManagedModelCatalogJson(next);
41
+ next = upsertManagedTopLevelTomlString(next, 'model_provider', 'codex-lb', CODEX_LB_DESKTOP_COMPAT_MARKER);
42
+ const block = [
43
+ '[model_providers.codex-lb]',
44
+ 'name = "OpenAI"',
45
+ `base_url = ${JSON.stringify(input.remoteBaseUrl)}`,
46
+ 'wire_api = "responses"',
47
+ 'requires_openai_auth = true',
48
+ 'supports_websockets = true',
49
+ 'env_http_headers = { "X-Codex-LB-API-Key" = "CODEX_LB_API_KEY" }'
50
+ ].join('\n');
51
+ next = upsertTomlTable(next, 'model_providers.codex-lb', block);
52
+ return ensureTrailingNewline(next);
53
+ }
54
+ export function upsertCodexLbCliProviderConfig(text, input) {
55
+ let next = input.selectGlobally === true
12
56
  ? upsertTopLevelTomlString(text, 'model_provider', 'codex-lb')
13
57
  : removeTopLevelTomlKeyIfValue(text, 'model_provider', 'codex-lb');
14
- const block = [
58
+ next = upsertTomlTable(next, 'model_providers.codex-lb', cliProviderBlock(input.remoteBaseUrl));
59
+ return ensureTrailingNewline(next);
60
+ }
61
+ export function removeCodexLbManagedDesktopConfig(text) {
62
+ let next = removeManagedDesktopBridgeRouting(String(text || ''));
63
+ if (topLevelHasLine(next, CODEX_LB_DESKTOP_COMPAT_MARKER)) {
64
+ next = removeTopLevelTomlKeyIfValue(next, 'model_provider', 'codex-lb');
65
+ next = removeTopLevelLine(next, CODEX_LB_DESKTOP_COMPAT_MARKER);
66
+ }
67
+ next = removeManagedModelCatalogJson(next);
68
+ return ensureTrailingNewline(next);
69
+ }
70
+ export function removeManagedModelCatalogJson(text) {
71
+ if (!topLevelHasLine(text, CODEX_LB_MODEL_CATALOG_MARKER))
72
+ return text;
73
+ const withoutKey = removeTopLevelTomlKey(text, 'model_catalog_json');
74
+ return removeTopLevelLine(withoutKey, CODEX_LB_MODEL_CATALOG_MARKER);
75
+ }
76
+ export function removeManagedDesktopBridgeRouting(text) {
77
+ const markers = [
78
+ CODEX_LB_DESKTOP_BRIDGE_MARKER,
79
+ LEGACY_CODEX_LB_OPENAI_ROUTING_MARKER
80
+ ].filter((marker) => topLevelHasLine(text, marker));
81
+ if (markers.length === 0)
82
+ return text;
83
+ let next = removeTopLevelTomlKey(text, 'openai_base_url');
84
+ for (const marker of markers)
85
+ next = removeTopLevelLine(next, marker);
86
+ return next;
87
+ }
88
+ export function upsertCodexLbConfig(text = '', baseUrl, selectDefault = true) {
89
+ return upsertCodexLbCliProviderConfig(text, {
90
+ remoteBaseUrl: String(baseUrl || ''),
91
+ selectGlobally: selectDefault === true
92
+ });
93
+ }
94
+ function cliProviderBlock(remoteBaseUrl) {
95
+ return [
15
96
  '[model_providers.codex-lb]',
16
- 'name = "openai"',
17
- `base_url = "${baseUrl}"`,
97
+ 'name = "codex-lb"',
98
+ `base_url = ${JSON.stringify(remoteBaseUrl)}`,
18
99
  'wire_api = "responses"',
19
100
  'env_key = "CODEX_LB_API_KEY"',
20
101
  'supports_websockets = true',
21
- 'requires_openai_auth = true'
102
+ 'requires_openai_auth = false'
22
103
  ].join('\n');
23
- next = upsertTomlTable(next, 'model_providers.codex-lb', block);
24
- return `${next.trim()}\n`;
104
+ }
105
+ function upsertManagedTopLevelTomlString(text, key, value, marker, legacyMarkers = []) {
106
+ const acceptedMarkers = [marker, ...legacyMarkers];
107
+ const existing = topLevelTomlString(text, key);
108
+ const ownedMarker = acceptedMarkers.find((candidate) => topLevelHasLine(text, candidate));
109
+ if (existing && !ownedMarker) {
110
+ if (existing === value)
111
+ return text;
112
+ throw new Error(`codex_lb_user_owned_${key}_conflict`);
113
+ }
114
+ let next = text;
115
+ for (const candidate of acceptedMarkers)
116
+ next = removeTopLevelLine(next, candidate);
117
+ next = upsertTopLevelTomlString(next, key, value);
118
+ return addTopLevelMarkerBeforeKey(next, key, marker);
119
+ }
120
+ function removeTopLevelTomlKey(text, key) {
121
+ const lines = String(text || '').split('\n');
122
+ const firstTable = lines.findIndex((line) => /^\s*\[.+\]\s*$/.test(line));
123
+ const end = firstTable === -1 ? lines.length : firstTable;
124
+ const keyPattern = new RegExp(`^\\s*${escapeRegExp(key)}\\s*=`);
125
+ return lines
126
+ .filter((line, index) => index >= end || !keyPattern.test(line))
127
+ .join('\n')
128
+ .replace(/^\n+/, '')
129
+ .replace(/\n{3,}/g, '\n\n');
25
130
  }
26
131
  const CODEX_LB_SHARED_OPENAI_ROUTING_MARKER = '# sks-codex-lb-managed-openai-base-url';
27
132
  export function codexLbSharedOpenAiRoutingState(text = '', baseUrl = '') {