sneakoscope 8.2.0 → 8.2.1

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 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 8.2.0** — its own identity, read from `package.json` and subject to release-gate verification, not advice about what to install.
25
+ This README documents package **SKS 8.2.1** — its own identity, read from `package.json` and subject to release-gate verification, not advice about what to install.
26
26
 
27
27
  Use the official latest stable SKS and Codex CLI releases. The Codex compatibility SSOT is always the **current latest stable** host; capability probes measure what that host can actually do. Product docs do not crown a fixed `0.x.y` string as SSOT (release pins and schema directories are measured artifacts for the current package, not a permanent product version claim). 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 supported. Install SSOT is npm `sneakoscope@latest`; PATH `sks` and Menu Bar stamped generation must match that version or gates fail. 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 (Codex official multi-agent wrap-only; SKS does not reimplement a parallel runtime). Local code search is mode-separated (`sks search files|text|structure|symbol|context`); `context` is answered by the compiled TriWiki Context Graph (`context-graph.json` is exhaustive authority; `context-pack.json` and managed `AGENTS.md` are bounded projections) — see [docs/architecture/context-graph.md](https://github.com/mandarange/Sneakoscope-Codex/blob/main/docs/architecture/context-graph.md) and [docs/PRODUCT-CONTRACT.md](https://github.com/mandarange/Sneakoscope-Codex/blob/main/docs/PRODUCT-CONTRACT.md). See [CHANGELOG.md](https://github.com/mandarange/Sneakoscope-Codex/blob/main/CHANGELOG.md).
28
28
 
@@ -259,7 +259,7 @@ dependencies = [
259
259
 
260
260
  [[package]]
261
261
  name = "sks-core"
262
- version = "8.2.0"
262
+ version = "8.2.1"
263
263
  dependencies = [
264
264
  "globset",
265
265
  "grep-matcher",
@@ -1,6 +1,6 @@
1
1
  [package]
2
2
  name = "sks-core"
3
- version = "8.2.0"
3
+ version = "8.2.1"
4
4
  edition = "2021"
5
5
 
6
6
  [dependencies]
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "schema": "sks.skills-manifest.v1",
3
- "package_version": "8.2.0",
3
+ "package_version": "8.2.1",
4
4
  "skills": [
5
5
  {
6
6
  "canonical_name": "sks",
@@ -25,6 +25,7 @@ export const NATIVE_SOURCE_FILES = [
25
25
  'ProvidersOpenRouter.swift',
26
26
  'ProvidersBridgeCatalog.swift',
27
27
  'RemoteCodingViewController.swift',
28
+ 'RemoteCodingSettingsControls.swift',
28
29
  'DiagnosticsViewController.swift',
29
30
  'SettingsViewController.swift',
30
31
  'OperationModels.swift',
@@ -9,7 +9,6 @@ const CURRENT_COMPILED_TESTS = new Set([
9
9
  'dist/core/__tests__/codex-release-manifest-current.test.js',
10
10
  'dist/core/__tests__/release-gate-hermetic-env.test.js',
11
11
  'dist/core/__tests__/update-menubar-package-local.test.js',
12
- 'dist/core/__tests__/update-simulated-upgrade.test.js',
13
12
  'dist/core/__tests__/version-manager-current-docs.test.js',
14
13
  'dist/core/install/__tests__/installed-package-smoke.test.js',
15
14
  'dist/core/perf/__tests__/release-latency-slo.test.js'
@@ -11,6 +11,8 @@ export const FORBIDDEN_RECURSIVE_GATES = new Set([
11
11
  ]);
12
12
  export const ALWAYS_ON_GATES = new Set([
13
13
  'release:metadata-current',
14
+ 'release:version-truth',
15
+ 'install-surface:ssot',
14
16
  'architecture:guard',
15
17
  'safety:mutation-callsite-coverage',
16
18
  'side-effect:runtime-report',
@@ -25,6 +27,8 @@ export const ALWAYS_ON_GATES = new Set([
25
27
  ]);
26
28
  export const REQUIRED_FOR_PUBLISH = new Set([
27
29
  'release:metadata-current',
30
+ 'release:version-truth',
31
+ 'install-surface:ssot',
28
32
  'architecture:guard',
29
33
  'safety:mutation-callsite-coverage',
30
34
  'side-effect:runtime-report',
@@ -1,6 +1,8 @@
1
1
  import { spawnSync } from 'node:child_process';
2
2
  const ALWAYS_KEEP = new Set([
3
3
  'release:proof-truth',
4
+ 'release:version-truth',
5
+ 'install-surface:ssot',
4
6
  'typecheck',
5
7
  'schema:check'
6
8
  ]);
@@ -11,6 +11,7 @@ export const RELEASE_GATE_CONTRACT_IDS = Object.freeze([
11
11
  'commands:current-surface-only',
12
12
  'config:managed-merge',
13
13
  'docs:truthfulness',
14
+ 'install-surface:ssot',
14
15
  'latest-version:guidance',
15
16
  'migration:current-surface-e2e',
16
17
  'migration:upgrade-safety',
@@ -24,6 +25,7 @@ export const RELEASE_GATE_CONTRACT_IDS = Object.freeze([
24
25
  'release:metadata-current',
25
26
  'release:proof-truth',
26
27
  'release:provenance',
28
+ 'release:version-truth',
27
29
  'runtime:installed-smoke',
28
30
  'safety:mutation-callsite-coverage',
29
31
  'schema:check',
@@ -23,6 +23,7 @@ export async function probeTelegram(input) {
23
23
  blockers.push(`telegram_token_load_failed:${redactTelegramError(error)}`);
24
24
  }
25
25
  let identityValid = false;
26
+ let botId = null;
26
27
  let getMeCheckedAt = null;
27
28
  let getMeLatencyMs = null;
28
29
  if (!tokenConfigured)
@@ -30,7 +31,9 @@ export async function probeTelegram(input) {
30
31
  else {
31
32
  const started = Date.now();
32
33
  try {
33
- identityValid = (await input.client.getMe()).is_bot === true;
34
+ const identity = await input.client.getMe();
35
+ identityValid = identity.is_bot === true && Number.isSafeInteger(identity.id) && identity.id > 0;
36
+ botId = identityValid ? identity.id : null;
34
37
  if (!identityValid)
35
38
  blockers.push('telegram_getme_not_bot');
36
39
  }
@@ -72,6 +75,7 @@ export async function probeTelegram(input) {
72
75
  status: !tokenConfigured ? 'not_configured' : blockers.length ? 'degraded' : 'ready',
73
76
  token_configured: tokenConfigured,
74
77
  token_source: tokenConfigured ? (receiptProbe?.token_source ?? 'unknown') : 'none',
78
+ bot_id: botId,
75
79
  bot_identity_valid: identityValid,
76
80
  getme_checked_at: getMeCheckedAt,
77
81
  getme_latency_ms: getMeLatencyMs,
@@ -89,7 +93,7 @@ async function probeTelegramReceipt(receiptPath, now) {
89
93
  if (!liveness.ok) {
90
94
  return {
91
95
  schema: 'sks.telegram-doctor-probe.v1', ok: false, status: 'not_configured',
92
- token_configured: false, bot_identity_valid: false, paired_chat_count: 0,
96
+ token_configured: false, bot_id: null, bot_identity_valid: false, paired_chat_count: 0,
93
97
  token_source: 'none',
94
98
  audit_healthy: false, audit_last_error: null,
95
99
  getme_checked_at: null, getme_latency_ms: null,
@@ -122,6 +126,7 @@ async function probeTelegramReceipt(receiptPath, now) {
122
126
  status: !receipt.token_configured ? 'not_configured' : blockers.length ? 'degraded' : 'ready',
123
127
  token_configured: receipt.token_configured,
124
128
  token_source: receipt.token_source ?? (receipt.token_configured ? 'unknown' : 'none'),
129
+ bot_id: receipt.bot_id ?? null,
125
130
  bot_identity_valid: receipt.bot_identity_valid,
126
131
  getme_checked_at: receipt.getme_checked_at ?? null,
127
132
  getme_latency_ms: receipt.getme_latency_ms ?? null,
@@ -323,6 +323,10 @@ async function syncSourcePackageVersion(root, version) {
323
323
  rel: 'src/core/version.ts',
324
324
  replace: (text) => text.replace(/export const PACKAGE_VERSION = ['"][^'"]+['"];/, `export const PACKAGE_VERSION = '${version}';`)
325
325
  },
326
+ {
327
+ rel: 'plugins/sks/.codex-plugin/plugin.json',
328
+ replace: (text) => text.replace(/("version"\s*:\s*")[^"]+("(?=\s*[,}]))/, `$1${version}$2`)
329
+ },
326
330
  {
327
331
  rel: 'crates/sks-core/Cargo.toml',
328
332
  replace: (text) => text.replace(/^version\s*=\s*"[^"]+"/m, `version = "${version}"`)
@@ -1 +1 @@
1
- export const PACKAGE_VERSION = '8.2.0';
1
+ export const PACKAGE_VERSION = '8.2.1';
@@ -0,0 +1,160 @@
1
+ import Cocoa
2
+
3
+ final class RemoteCodingSettingsControls {
4
+ private static let tokenPattern = #"^\d{5,20}:[A-Za-z0-9_-]{20,128}$"#
5
+
6
+ let selectedBotDetail = NativeView.detail("No bot is configured.")
7
+ let pairingCommandField = NativeView.detail("Generate a code to create the /start pairing command.")
8
+ let botTokenField: NSSecureTextField
9
+ let setupButton: NSButton
10
+ let copyPairingButton: NSButton
11
+
12
+ private var pairingCommand: String?
13
+ private var selectedBotID: Int64?
14
+ private var selectedBotUsername: String?
15
+
16
+ init(target: AnyObject, submitTokenAction: Selector, copyPairingAction: Selector) {
17
+ let tokenField = NSSecureTextField(frame: NSRect(x: 0, y: 0, width: 360, height: 24))
18
+ tokenField.placeholderString = "Paste the complete BotFather HTTP API token"
19
+ tokenField.setContentHuggingPriority(.defaultLow, for: .horizontal)
20
+ tokenField.setContentCompressionResistancePriority(.defaultLow, for: .horizontal)
21
+ tokenField.setAccessibilityLabel("BotFather HTTP API token")
22
+ tokenField.setAccessibilityHelp("Required. Paste the complete token for any Telegram bot you own. SKS clears this field before verification and never displays the token again.")
23
+ tokenField.setAccessibilityIdentifier("sks-center-telegram-bot-token")
24
+ tokenField.target = target
25
+ tokenField.action = submitTokenAction
26
+ botTokenField = tokenField
27
+
28
+ setupButton = NativeView.button("Verify, Save & Apply", target: target, action: submitTokenAction)
29
+ setupButton.setAccessibilityIdentifier("sks-center-telegram-verify-save-apply")
30
+ setupButton.setAccessibilityHelp("Verify the entered bot token with Telegram, save it to the private SKS user secret file, and apply it to the resident poller.")
31
+
32
+ copyPairingButton = NativeView.button("Copy Pairing Command", target: target, action: copyPairingAction)
33
+ copyPairingButton.setAccessibilityHelp("Copy only the generated /start pairing command. The bot token is never copied or displayed.")
34
+
35
+ pairingCommandField.isSelectable = true
36
+ pairingCommandField.font = NSFont.monospacedSystemFont(ofSize: 12, weight: .regular)
37
+ pairingCommandField.setAccessibilityLabel("Telegram pairing command")
38
+ pairingCommandField.setAccessibilityIdentifier("sks-center-telegram-pairing-command")
39
+ selectedBotDetail.isSelectable = true
40
+ selectedBotDetail.setAccessibilityLabel("Selected Telegram bot")
41
+ selectedBotDetail.setAccessibilityIdentifier("sks-center-telegram-selected-bot")
42
+ }
43
+
44
+ func configure(delegate: NSTextFieldDelegate) {
45
+ botTokenField.delegate = delegate
46
+ }
47
+
48
+ func consumeTokenInput() -> String {
49
+ let value = botTokenField.stringValue.trimmingCharacters(in: .whitespacesAndNewlines)
50
+ botTokenField.stringValue = ""
51
+ return value
52
+ }
53
+
54
+ func updateActionControls(operationInFlight: Bool, tokenConfigured: Bool, environmentOverride: Bool) {
55
+ let hasTokenInput = !botTokenField.stringValue.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty
56
+ botTokenField.isEnabled = !operationInFlight && !environmentOverride
57
+ setupButton.title = tokenConfigured ? "Verify, Replace & Apply" : "Verify, Save & Apply"
58
+ setupButton.setAccessibilityLabel(setupButton.title)
59
+ setupButton.isEnabled = !operationInFlight && !environmentOverride && hasTokenInput
60
+ copyPairingButton.isEnabled = !operationInFlight && pairingCommand != nil
61
+ }
62
+
63
+ func renderSelectedBot(
64
+ botID: Int64?,
65
+ username: String? = nil,
66
+ configured: Bool,
67
+ identityValid: Bool
68
+ ) {
69
+ guard configured else {
70
+ selectedBotID = nil
71
+ selectedBotUsername = nil
72
+ selectedBotDetail.stringValue = "No bot is configured."
73
+ selectedBotDetail.setAccessibilityValue(selectedBotDetail.stringValue)
74
+ resetPairingCommand("Generate a code after connecting a bot.")
75
+ return
76
+ }
77
+ let retainedUsername = username ?? (botID == selectedBotID ? selectedBotUsername : nil)
78
+ selectedBotID = botID
79
+ selectedBotUsername = retainedUsername
80
+ if let botID, let retainedUsername, identityValid {
81
+ selectedBotDetail.stringValue = "@\(retainedUsername) · Bot ID \(botID)"
82
+ } else if let botID, identityValid {
83
+ selectedBotDetail.stringValue = "Bot ID \(botID) · verified by Telegram"
84
+ } else if let botID {
85
+ selectedBotDetail.stringValue = "Bot ID \(botID) · identity needs verification"
86
+ } else {
87
+ selectedBotDetail.stringValue = "Configured bot · identity details unavailable"
88
+ }
89
+ selectedBotDetail.setAccessibilityValue(selectedBotDetail.stringValue)
90
+ }
91
+
92
+ func setPairingCode(_ code: String) {
93
+ pairingCommand = "/start \(code)"
94
+ pairingCommandField.stringValue = pairingCommand ?? ""
95
+ pairingCommandField.setAccessibilityValue(pairingCommandField.stringValue)
96
+ }
97
+
98
+ func resetPairingCommand(_ detail: String) {
99
+ pairingCommand = nil
100
+ pairingCommandField.stringValue = detail
101
+ pairingCommandField.setAccessibilityValue(detail)
102
+ }
103
+
104
+ @discardableResult
105
+ func copyPairingCommand() -> Bool {
106
+ guard let pairingCommand else { return false }
107
+ let pasteboard = NSPasteboard.general
108
+ pasteboard.clearContents()
109
+ return pasteboard.setString(pairingCommand, forType: .string)
110
+ }
111
+
112
+ static func validTokenShape(_ value: String) -> Bool {
113
+ value.utf8.count <= 1024
114
+ && value.range(of: tokenPattern, options: .regularExpression) != nil
115
+ }
116
+
117
+ static func publicFailure(_ output: String, fallback: String) -> String {
118
+ guard let data = output.data(using: .utf8),
119
+ let row = try? JSONSerialization.jsonObject(with: data) as? [String: Any],
120
+ let error = row["error"] as? String else { return fallback }
121
+ switch error {
122
+ case "telegram_token_invalid", "telegram_token_stdin_empty":
123
+ return "That value is not a complete BotFather HTTP API token."
124
+ case "telegram_token_rejected":
125
+ return "Telegram rejected this token. In @BotFather, select the bot you want SKS to use and copy that bot's current complete token."
126
+ case "telegram_identity_verification_timeout":
127
+ return "Telegram identity verification timed out. Check the network connection and try the selected bot token again."
128
+ case "telegram_identity_verification_network_failed":
129
+ return "Telegram identity verification could not reach the Bot API. Check the network connection and try again."
130
+ case "telegram_identity_verification_failed":
131
+ return "Telegram returned an invalid bot identity response. Try the selected bot's current token again."
132
+ case let value where value.contains("401") || value.contains("Unauthorized"):
133
+ return "Telegram rejected this token. Copy the current token from @BotFather and try again."
134
+ case let value where value.contains("timeout") || value.contains("network"):
135
+ return "Telegram identity verification could not complete. Check the network connection and try again."
136
+ default:
137
+ return fallback
138
+ }
139
+ }
140
+
141
+ static func partialSetupRecovery(_ response: TelegramCenterSetupResponse?) -> String {
142
+ var parts: [String] = []
143
+ if response?.webhook_removed == true { parts.append("The existing webhook was removed without dropping pending updates.") }
144
+ if response?.bot_state_reset == true { parts.append("Bot-scoped pairing and poll state were reset safely.") }
145
+ if response?.token_stored == false { parts.append("The token was not stored; rerun secure setup to finish.") }
146
+ if let note = response?.recovery?.note, !note.isEmpty { parts.append(note) }
147
+ return parts.isEmpty
148
+ ? "Review the secret-free recovery status, then rerun secure setup."
149
+ : parts.joined(separator: " ")
150
+ }
151
+
152
+ static func tokenSourceDescription(_ source: String) -> String {
153
+ switch source {
154
+ case "env": return "operator environment token"
155
+ case "user_secret_file": return "private token file"
156
+ case "none": return "no token source"
157
+ default: return "token source unknown"
158
+ }
159
+ }
160
+ }
@@ -1,8 +1,7 @@
1
1
  import Cocoa
2
2
 
3
- final class RemoteCodingViewController: NSViewController, ControlCenterPage {
3
+ final class RemoteCodingViewController: NSViewController, ControlCenterPage, NSTextFieldDelegate {
4
4
  private static let botFatherURL = URL(string: "https://t.me/BotFather")!
5
- private static let tokenPattern = #"^\d{5,20}:[A-Za-z0-9_-]{20,128}$"#
6
5
 
7
6
  private let processClient: ProcessClient
8
7
  private let telegramService: TelegramMenuBarService
@@ -10,7 +9,11 @@ final class RemoteCodingViewController: NSViewController, ControlCenterPage {
10
9
  private let serviceDetail = NativeView.detail("Reading secret-free Telegram liveness status…")
11
10
  private let pairingDetail = NativeView.detail("No pairing code has been issued in this session.")
12
11
  private let serviceSpinner = NativeView.spinner(label: "Telegram operation in progress")
13
- private lazy var setupButton = NativeView.button("Enter Bot Token…", target: self, action: #selector(enterToken))
12
+ private lazy var settingsControls = RemoteCodingSettingsControls(
13
+ target: self,
14
+ submitTokenAction: #selector(enterToken),
15
+ copyPairingAction: #selector(copyPairingCommand)
16
+ )
14
17
  private lazy var pairButton = NativeView.button("Generate Pairing Code", target: self, action: #selector(generatePairingCode))
15
18
  private lazy var startButton = NativeView.button("Start", target: self, action: #selector(startService))
16
19
  private lazy var stopButton = NativeView.button("Stop", target: self, action: #selector(stopService))
@@ -31,7 +34,7 @@ final class RemoteCodingViewController: NSViewController, ControlCenterPage {
31
34
  override func loadView() {
32
35
  let botFatherButton = NativeView.button("Open @BotFather", target: self, action: #selector(openBotFather))
33
36
  botFatherButton.setAccessibilityHelp("Open the official Telegram BotFather chat in your default handler.")
34
- setupButton.setAccessibilityHelp("Enter a BotFather token securely. The token is verified live and stored in the private SKS user secret file.")
37
+ settingsControls.configure(delegate: self)
35
38
  pairButton.setAccessibilityHelp("With Telegram polling running, issue a short-lived, single-use code for pairing one intended private chat.")
36
39
  startButton.setAccessibilityHelp("Start Telegram polling for the current SKS companion session after a bot token is configured.")
37
40
  stopButton.setAccessibilityHelp("Stop polling for the current companion session without deleting the token or paired chats. A companion relaunch starts it again.")
@@ -47,12 +50,14 @@ final class RemoteCodingViewController: NSViewController, ControlCenterPage {
47
50
  views: [
48
51
  NativeView.detail(
49
52
  "1. Create or select any bot you own in @BotFather. 2. Copy that bot's complete HTTP API token. " +
50
- "3. Choose Enter Bot Token below. SKS binds the identity returned by Telegram getMe; it never assumes a bot name or username."
53
+ "3. Paste it below and choose Verify, Save & Apply. The token is the only value you enter: SKS derives the bot ID from Telegram getMe, and learns chat and user IDs through private-chat pairing."
51
54
  ),
52
55
  NativeView.detail(
53
56
  "The token is sent only through process stdin to the canonical SKS setup command, verified with Telegram getMe, and stored in the private user secret file. It is never shown again or written to the SKS action log. Revoke it in BotFather if you suspect exposure."
54
57
  ),
55
- NativeView.row([botFatherButton, setupButton])
58
+ ControlKit.keyValueRow("Active Bot", settingsControls.selectedBotDetail),
59
+ ControlKit.keyValueRow("Bot Token", settingsControls.botTokenField),
60
+ NativeView.row([botFatherButton, settingsControls.setupButton])
56
61
  ]
57
62
  )
58
63
 
@@ -61,10 +66,11 @@ final class RemoteCodingViewController: NSViewController, ControlCenterPage {
61
66
  subtitle: "Authorize only the intended Telegram account and private chat.",
62
67
  views: [
63
68
  NativeView.detail(
64
- "With Telegram polling running, generate a short-lived code, open your new bot from the intended private chat, and send /start followed by that code. Codes are single-use; group chats are rejected. After pairing, try /sks status {}."
69
+ "With Telegram polling running, generate a short-lived command, open the selected bot from the intended private chat, and send that command. SKS derives the chat and user IDs from Telegram; they are never typed into this screen. Codes are single-use and group chats are rejected. After pairing, try /sks status {}."
65
70
  ),
71
+ ControlKit.keyValueRow("Pair Command", settingsControls.pairingCommandField),
66
72
  pairingDetail,
67
- pairButton
73
+ NativeView.row([pairButton, settingsControls.copyPairingButton])
68
74
  ]
69
75
  )
70
76
 
@@ -97,6 +103,7 @@ final class RemoteCodingViewController: NSViewController, ControlCenterPage {
97
103
  }
98
104
 
99
105
  @objc private func enterToken() {
106
+ guard !operationInFlight else { return }
100
107
  if TelegramPrivateFileStore.operatorEnvironmentOverrideActive() {
101
108
  showAttention(
102
109
  "Environment-managed token is active",
@@ -104,31 +111,38 @@ final class RemoteCodingViewController: NSViewController, ControlCenterPage {
104
111
  )
105
112
  return
106
113
  }
107
- promptForToken(removeWebhook: false)
114
+ let normalizedToken = settingsControls.consumeTokenInput()
115
+ updateControls()
116
+ guard RemoteCodingSettingsControls.validTokenShape(normalizedToken) else {
117
+ showAttention(
118
+ "Token not saved",
119
+ detail: "That value does not match the BotFather token format. Copy the complete HTTP API token and try again."
120
+ )
121
+ return
122
+ }
123
+ saveToken(normalizedToken, removeWebhook: false)
108
124
  }
109
125
 
110
- private func promptForToken(removeWebhook: Bool) {
126
+ private func promptForWebhookRemovalToken() {
111
127
  guard !operationInFlight, let window = view.window else { return }
112
128
  AlertFactory.textSheet(
113
129
  window: window,
114
- title: "Enter Telegram Bot Token",
115
- message: removeWebhook
116
- ? "Paste this selected bot's BotFather token again. With your consent, SKS will remove that bot's existing webhook without dropping pending updates, verify its live identity, and store the token privately."
117
- : "Paste the complete HTTP API token for any bot you own in @BotFather. SKS will accept the identity returned by Telegram getMe without assuming a bot name, then store the token privately.",
130
+ title: "Authorize Telegram Webhook Removal",
131
+ message: "Paste this selected bot's BotFather token again. With your consent, SKS will remove that bot's existing webhook without dropping pending updates, verify its live identity, and store the token privately.",
118
132
  secure: true,
119
133
  placeholder: "123456789:BotFatherToken",
120
- actionTitle: removeWebhook ? "Remove Webhook & Save" : "Verify & Save"
134
+ actionTitle: "Remove Webhook & Save"
121
135
  ) { [weak self] token in
122
136
  guard let self, let token else { return }
123
137
  let normalizedToken = token.trimmingCharacters(in: .whitespacesAndNewlines)
124
- guard self.validTokenShape(normalizedToken) else {
138
+ guard RemoteCodingSettingsControls.validTokenShape(normalizedToken) else {
125
139
  self.showAttention(
126
140
  "Token not saved",
127
141
  detail: "That value does not match the BotFather token format. Copy the complete HTTP API token and try again."
128
142
  )
129
143
  return
130
144
  }
131
- self.saveToken(normalizedToken, removeWebhook: removeWebhook)
145
+ self.saveToken(normalizedToken, removeWebhook: true)
132
146
  }
133
147
  }
134
148
 
@@ -150,7 +164,10 @@ final class RemoteCodingViewController: NSViewController, ControlCenterPage {
150
164
  code.range(of: #"^\d{6}-[A-F0-9]{4}$"#, options: .regularExpression) != nil else {
151
165
  self.showAttention(
152
166
  "Pairing code unavailable",
153
- detail: self.publicFailure(result.output, fallback: "SKS could not create a pairing code. Refresh status and try again.")
167
+ detail: RemoteCodingSettingsControls.publicFailure(
168
+ result.output,
169
+ fallback: "SKS could not create a pairing code. Refresh status and try again."
170
+ )
154
171
  )
155
172
  return
156
173
  }
@@ -160,6 +177,7 @@ final class RemoteCodingViewController: NSViewController, ControlCenterPage {
160
177
  let postPair = response.post_pair_command ?? "/sks status {}"
161
178
  let confirmation = response.confirmation_grammar ?? "/confirm <nonce>"
162
179
  let statusGuidance = instruction.contains(postPair) ? "" : " Then try \(postPair)."
180
+ self.settingsControls.setPairingCode(code)
163
181
  self.pairingDetail.stringValue = "\(instruction)\(expiration)\(statusGuidance) Confirm prompted actions with \(confirmation)."
164
182
  self.pairingDetail.setAccessibilityValue(self.pairingDetail.stringValue)
165
183
  self.showProgress("Pairing code ready", detail: "Use the displayed code once in the intended private chat.")
@@ -167,6 +185,11 @@ final class RemoteCodingViewController: NSViewController, ControlCenterPage {
167
185
  }
168
186
  }
169
187
 
188
+ @objc private func copyPairingCommand() {
189
+ guard settingsControls.copyPairingCommand() else { return }
190
+ showProgress("Pairing command copied", detail: "Paste it once into the intended private chat with the selected bot.")
191
+ }
192
+
170
193
  @objc private func startService() { runLifecycle(.start) }
171
194
  @objc private func stopService() { runLifecycle(.stop) }
172
195
  @objc private func restartService() { runLifecycle(.restart) }
@@ -217,7 +240,7 @@ final class RemoteCodingViewController: NSViewController, ControlCenterPage {
217
240
 
218
241
  private func saveToken(_ token: String, removeWebhook: Bool) {
219
242
  let normalizedToken = token.trimmingCharacters(in: .whitespacesAndNewlines)
220
- guard validTokenShape(normalizedToken) else {
243
+ guard RemoteCodingSettingsControls.validTokenShape(normalizedToken) else {
221
244
  showAttention(
222
245
  "Token not saved",
223
246
  detail: "That value does not match the BotFather token format. Copy the complete token and try again."
@@ -261,13 +284,13 @@ final class RemoteCodingViewController: NSViewController, ControlCenterPage {
261
284
  if response?.partial_success == true {
262
285
  self.showAttention(
263
286
  "Telegram setup partially completed",
264
- detail: self.partialSetupRecovery(response)
287
+ detail: RemoteCodingSettingsControls.partialSetupRecovery(response)
265
288
  )
266
289
  return
267
290
  }
268
291
  self.showAttention(
269
292
  "Token not saved",
270
- detail: self.publicFailure(
293
+ detail: RemoteCodingSettingsControls.publicFailure(
271
294
  result.output,
272
295
  fallback: "Telegram setup could not complete. Check the connection and SKS diagnostics, then try again."
273
296
  )
@@ -280,6 +303,15 @@ final class RemoteCodingViewController: NSViewController, ControlCenterPage {
280
303
  let receipt = try await restart.value
281
304
  self?.endOperation()
282
305
  self?.render(receipt)
306
+ self?.settingsControls.renderSelectedBot(
307
+ botID: response.bot_id ?? receipt.bot_id,
308
+ username: response.bot_username,
309
+ configured: true,
310
+ identityValid: true
311
+ )
312
+ if response.bot_state_reset == true {
313
+ self?.settingsControls.resetPairingCommand("Generate a new code because the selected bot changed.")
314
+ }
283
315
  let selectedBot = response.bot_username.map { "@\($0)" } ?? "The selected bot"
284
316
  self?.showProgress(
285
317
  "Bot verified and connected",
@@ -309,7 +341,7 @@ final class RemoteCodingViewController: NSViewController, ControlCenterPage {
309
341
  actionTitle: "Continue"
310
342
  ) { [weak self] confirmed in
311
343
  guard confirmed else { return }
312
- self?.promptForToken(removeWebhook: true)
344
+ self?.promptForWebhookRemovalToken()
313
345
  }
314
346
  }
315
347
 
@@ -349,8 +381,13 @@ final class RemoteCodingViewController: NSViewController, ControlCenterPage {
349
381
  private func render(_ response: TelegramCenterDoctorResponse) {
350
382
  tokenConfigured = response.token_configured
351
383
  pollerRunning = response.poller.running
384
+ settingsControls.renderSelectedBot(
385
+ botID: response.bot_id,
386
+ configured: response.token_configured,
387
+ identityValid: response.bot_identity_valid
388
+ )
352
389
  let paired = response.paired_chat_count == 1 ? "1 paired chat" : "\(response.paired_chat_count) paired chats"
353
- let source = tokenSourceDescription(response.token_source)
390
+ let source = RemoteCodingSettingsControls.tokenSourceDescription(response.token_source)
354
391
  if response.ok {
355
392
  NativeView.setBadge(serviceBadge, text: "Ready", color: .systemGreen)
356
393
  serviceDetail.stringValue = "Bot identity verified · \(source) · \(paired) · poller running · audit healthy."
@@ -384,8 +421,13 @@ final class RemoteCodingViewController: NSViewController, ControlCenterPage {
384
421
  private func render(_ receipt: TelegramLivenessReceipt) {
385
422
  tokenConfigured = receipt.token_configured
386
423
  pollerRunning = receipt.running && receipt.poller.running
424
+ settingsControls.renderSelectedBot(
425
+ botID: receipt.bot_id,
426
+ configured: receipt.token_configured,
427
+ identityValid: receipt.bot_identity_valid
428
+ )
387
429
  let paired = receipt.paired_chat_count == 1 ? "1 paired chat" : "\(receipt.paired_chat_count) paired chats"
388
- let source = tokenSourceDescription(receipt.token_source.rawValue)
430
+ let source = RemoteCodingSettingsControls.tokenSourceDescription(receipt.token_source.rawValue)
389
431
  NativeView.setBadge(
390
432
  serviceBadge,
391
433
  text: pollerRunning ? "Running" : "Stopped",
@@ -424,7 +466,12 @@ final class RemoteCodingViewController: NSViewController, ControlCenterPage {
424
466
  }
425
467
 
426
468
  private func updateControls() {
427
- setupButton.isEnabled = !operationInFlight
469
+ let environmentOverride = TelegramPrivateFileStore.operatorEnvironmentOverrideActive()
470
+ settingsControls.updateActionControls(
471
+ operationInFlight: operationInFlight,
472
+ tokenConfigured: tokenConfigured,
473
+ environmentOverride: environmentOverride
474
+ )
428
475
  pairButton.isEnabled = !operationInFlight && tokenConfigured && pollerRunning
429
476
  startButton.isEnabled = !operationInFlight && tokenConfigured && !pollerRunning
430
477
  stopButton.isEnabled = !operationInFlight && pollerRunning
@@ -432,9 +479,10 @@ final class RemoteCodingViewController: NSViewController, ControlCenterPage {
432
479
  refreshButton.isEnabled = !operationInFlight
433
480
  }
434
481
 
435
- private func validTokenShape(_ value: String) -> Bool {
436
- value.utf8.count <= 1024
437
- && value.range(of: Self.tokenPattern, options: .regularExpression) != nil
482
+ func controlTextDidChange(_ notification: Notification) {
483
+ guard let field = notification.object as? NSTextField,
484
+ field === settingsControls.botTokenField else { return }
485
+ updateControls()
438
486
  }
439
487
 
440
488
  private func decode<T: Decodable>(_ type: T.Type, _ output: String) -> T? {
@@ -442,53 +490,4 @@ final class RemoteCodingViewController: NSViewController, ControlCenterPage {
442
490
  return try? JSONDecoder().decode(type, from: data)
443
491
  }
444
492
 
445
- private func publicFailure(_ output: String, fallback: String) -> String {
446
- guard let data = output.data(using: .utf8),
447
- let row = try? JSONSerialization.jsonObject(with: data) as? [String: Any],
448
- let error = row["error"] as? String else { return fallback }
449
- switch error {
450
- case "telegram_token_invalid", "telegram_token_stdin_empty":
451
- return "That value is not a complete BotFather HTTP API token."
452
- case "telegram_token_rejected":
453
- return "Telegram rejected this token. In @BotFather, select the bot you want SKS to use and copy that bot's current complete token."
454
- case "telegram_identity_verification_timeout":
455
- return "Telegram identity verification timed out. Check the network connection and try the selected bot token again."
456
- case "telegram_identity_verification_network_failed":
457
- return "Telegram identity verification could not reach the Bot API. Check the network connection and try again."
458
- case "telegram_identity_verification_failed":
459
- return "Telegram returned an invalid bot identity response. Try the selected bot's current token again."
460
- case let value where value.contains("401") || value.contains("Unauthorized"):
461
- return "Telegram rejected this token. Copy the current token from @BotFather and try again."
462
- case let value where value.contains("timeout") || value.contains("network"):
463
- return "Telegram identity verification could not complete. Check the network connection and try again."
464
- default:
465
- return fallback
466
- }
467
- }
468
-
469
- private func partialSetupRecovery(_ response: TelegramCenterSetupResponse?) -> String {
470
- var parts: [String] = []
471
- if response?.webhook_removed == true {
472
- parts.append("The existing webhook was removed without dropping pending updates.")
473
- }
474
- if response?.bot_state_reset == true {
475
- parts.append("Bot-scoped pairing and poll state were reset safely.")
476
- }
477
- if response?.token_stored == false {
478
- parts.append("The token was not stored; rerun secure setup to finish.")
479
- }
480
- if let note = response?.recovery?.note, !note.isEmpty { parts.append(note) }
481
- return parts.isEmpty
482
- ? "Review the secret-free recovery status, then rerun secure setup."
483
- : parts.joined(separator: " ")
484
- }
485
-
486
- private func tokenSourceDescription(_ source: String) -> String {
487
- switch source {
488
- case "env": return "operator environment token"
489
- case "user_secret_file": return "private token file"
490
- case "none": return "no token source"
491
- default: return "token source unknown"
492
- }
493
- }
494
493
  }
@@ -179,6 +179,7 @@ struct TelegramCenterDoctorResponse: Decodable {
179
179
  let status: String
180
180
  let token_configured: Bool
181
181
  let token_source: String
182
+ let bot_id: Int64?
182
183
  let bot_identity_valid: Bool
183
184
  let paired_chat_count: Int
184
185
  let audit_healthy: Bool
@@ -24,7 +24,7 @@ if (pluginVersion && packageVersion && pluginVersion !== packageVersion) {
24
24
  blockers.push(`marketplace_plugin_version_mismatch:${pluginVersion}!=${packageVersion}`);
25
25
  }
26
26
  else if (!pluginVersion) {
27
- notes.push('marketplace_plugin_version_absent');
27
+ blockers.push('marketplace_plugin_version_absent');
28
28
  }
29
29
  else {
30
30
  notes.push(`marketplace_plugin_version_matches:${pluginVersion}`);
@@ -78,7 +78,7 @@ else {
78
78
  const report = {
79
79
  schema: 'sks.install-surface-ssot-check.v1',
80
80
  ok: blockers.length === 0,
81
- install_ssot: 'npm:sneakoscope@latest',
81
+ install_ssot: 'package.json#version',
82
82
  package_version: packageVersion || null,
83
83
  plugin_version: pluginVersion || null,
84
84
  path_sks_version: pathVersion || null,
@@ -43,6 +43,7 @@ const requiredPackageScripts = [
43
43
  'typecheck',
44
44
  'release:check',
45
45
  'release:metadata',
46
+ 'release:version-truth',
46
47
  'release:check:affected',
47
48
  'release:check:fast',
48
49
  'release:check:confidence',
@@ -70,6 +71,7 @@ const requiredReleaseGates = [
70
71
  'commands:current-surface-only',
71
72
  'config:managed-merge',
72
73
  'docs:truthfulness',
74
+ 'install-surface:ssot',
73
75
  'latest-version:guidance',
74
76
  'migration:current-surface-e2e',
75
77
  'migration:upgrade-safety',
@@ -83,6 +85,7 @@ const requiredReleaseGates = [
83
85
  'release:latency-slo',
84
86
  'release:proof-truth',
85
87
  'release:provenance',
88
+ 'release:version-truth',
86
89
  'policy:gate-audit',
87
90
  'safety:mutation-callsite-coverage',
88
91
  'schema:check',
@@ -0,0 +1,149 @@
1
+ #!/usr/bin/env node
2
+ import fs from 'node:fs';
3
+ import path from 'node:path';
4
+ import { spawnSync } from 'node:child_process';
5
+ import { assertGate, emitGate, root } from './gate-lib.js';
6
+ const pkg = readJson('package.json');
7
+ const expected = String(pkg.version || '');
8
+ const mismatches = [];
9
+ const warnings = [];
10
+ let checked = 0;
11
+ checkJson('package.json', 'version', pkg.version);
12
+ const lock = readJson('package-lock.json');
13
+ checkJson('package-lock.json', 'version', lock.version);
14
+ checkJson('package-lock.json', 'packages[""].version', lock.packages?.['']?.version);
15
+ const plugin = readJson('plugins/sks/.codex-plugin/plugin.json');
16
+ checkJson('plugins/sks/.codex-plugin/plugin.json', 'version', plugin.version);
17
+ checkRegex('src/core/version.ts', /PACKAGE_VERSION\s*=\s*['"]([^'"]+)['"]/, 'PACKAGE_VERSION');
18
+ checkReExportOrRegex('src/core/fsx.ts', /PACKAGE_VERSION\s*}\s*from\s*['"]\.\/version(?:\.js)?['"]/, /PACKAGE_VERSION\s*=\s*['"]([^'"]+)['"]/, 'PACKAGE_VERSION');
19
+ checkReExportOrRegex('src/bin/sks.ts', /PACKAGE_VERSION\s*}\s*from\s*['"]\.\.\/core\/version(?:\.js)?['"]/, /FAST_PACKAGE_VERSION\s*=\s*['"]([^'"]+)['"]/, 'FAST_PACKAGE_VERSION');
20
+ checkRegex('crates/sks-core/Cargo.toml', /^version\s*=\s*"([^"]+)"/m, 'package.version');
21
+ checkCargoLock('crates/sks-core/Cargo.lock', 'sks-core');
22
+ const dist = readJson('dist/build-manifest.json', null);
23
+ checkJson('dist/build-manifest.json', 'package_version', dist?.package_version);
24
+ checkJson('dist/build-manifest.json', 'version', dist?.version);
25
+ checkChangelog();
26
+ checkReadme();
27
+ checkReleaseMetadataScript();
28
+ checkCargoMetadata();
29
+ const ok = mismatches.length === 0;
30
+ const report = {
31
+ schema: 'sks.release-version-truth.v1',
32
+ ok,
33
+ expected,
34
+ checked,
35
+ mismatches,
36
+ warnings,
37
+ generated_at: new Date().toISOString()
38
+ };
39
+ const out = path.join(root, '.sneakoscope', 'reports', 'release-version-truth.json');
40
+ fs.mkdirSync(path.dirname(out), { recursive: true });
41
+ fs.writeFileSync(out, `${JSON.stringify(report, null, 2)}\n`);
42
+ assertGate(ok, 'release version truth mismatch', { expected, mismatches });
43
+ emitGate('release:version-truth', { version: expected, checked, warnings: warnings.length });
44
+ function checkJson(file, field, actual) {
45
+ checked += 1;
46
+ if (actual !== expected)
47
+ mismatch(file, field, actual);
48
+ }
49
+ function checkRegex(file, re, field) {
50
+ checked += 1;
51
+ const text = readText(file);
52
+ const match = text.match(re);
53
+ if (!match)
54
+ mismatch(file, field, null);
55
+ else if (match[1] !== expected)
56
+ mismatch(file, field, match[1]);
57
+ }
58
+ function checkReExportOrRegex(file, reExportRe, literalRe, field) {
59
+ const text = readText(file);
60
+ if (reExportRe.test(text)) {
61
+ checked += 1;
62
+ return;
63
+ }
64
+ checkRegex(file, literalRe, field);
65
+ }
66
+ function checkCargoLock(file, name) {
67
+ checked += 1;
68
+ const text = readText(file);
69
+ const block = text.split(/\n\[\[package\]\]\n/).find((part) => new RegExp(`name\\s*=\\s*"${escapeRe(name)}"`).test(part));
70
+ const match = block?.match(/version\s*=\s*"([^"]+)"/);
71
+ if (!match)
72
+ mismatch(file, `${name}.version`, null);
73
+ else if (match[1] !== expected)
74
+ mismatch(file, `${name}.version`, match[1]);
75
+ }
76
+ function checkChangelog() {
77
+ checked += 1;
78
+ const text = readText('CHANGELOG.md');
79
+ const latest = latestVersionedChangelogSection(text);
80
+ if (latest !== expected)
81
+ mismatch('CHANGELOG.md', 'latest release section', latest);
82
+ }
83
+ function checkReadme() {
84
+ checked += 1;
85
+ const text = readText('README.md');
86
+ const displayed = text.match(/\*\*SKS ([0-9]+\.[0-9]+\.[0-9]+)\*\*/)?.[1] || null;
87
+ if (!displayed)
88
+ mismatch('README.md', 'displayed current version', null);
89
+ else if (displayed !== expected)
90
+ mismatch('README.md', 'displayed current version', displayed);
91
+ }
92
+ function checkReleaseMetadataScript() {
93
+ checked += 1;
94
+ const script = String(pkg.scripts?.['release:metadata'] || '');
95
+ if (!script.includes('dist/scripts/release-metadata-check.js')) {
96
+ mismatch('package.json', 'scripts.release:metadata', script || null, 'node ./dist/scripts/release-metadata-check.js');
97
+ }
98
+ }
99
+ function checkCargoMetadata() {
100
+ checked += 1;
101
+ const res = spawnSync('cargo', ['metadata', '--no-deps', '--manifest-path', path.join(root, 'crates/sks-core/Cargo.toml'), '--format-version', '1'], {
102
+ cwd: root,
103
+ encoding: 'utf8',
104
+ timeout: 30000
105
+ });
106
+ if (res.status !== 0) {
107
+ warnings.push({ file: 'crates/sks-core/Cargo.toml', message: 'cargo metadata unavailable', stderr_tail: tail(res.stderr) });
108
+ return;
109
+ }
110
+ try {
111
+ const metadata = JSON.parse(res.stdout);
112
+ const crate = metadata.packages?.find((row) => row.name === 'sks-core');
113
+ if (crate?.version !== expected)
114
+ mismatch('cargo metadata', 'sks-core.version', crate?.version || null);
115
+ }
116
+ catch (err) {
117
+ warnings.push({ file: 'cargo metadata', message: `unparseable:${err instanceof Error ? err.message : String(err)}` });
118
+ }
119
+ }
120
+ function mismatch(file, field, actual, wanted = expected) {
121
+ mismatches.push({ file, field, expected: wanted, actual: actual ?? null });
122
+ }
123
+ function readJson(rel, fallback) {
124
+ try {
125
+ return JSON.parse(readText(rel));
126
+ }
127
+ catch (err) {
128
+ if (arguments.length > 1)
129
+ return fallback;
130
+ throw err;
131
+ }
132
+ }
133
+ function readText(rel) {
134
+ return fs.readFileSync(path.join(root, rel), 'utf8');
135
+ }
136
+ function escapeRe(value) {
137
+ return String(value).replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
138
+ }
139
+ function latestVersionedChangelogSection(text) {
140
+ for (const match of text.matchAll(/^## \[([^\]]+)\]/gm)) {
141
+ if (/^[0-9]+\.[0-9]+\.[0-9]+$/.test(match[1]))
142
+ return match[1];
143
+ }
144
+ return null;
145
+ }
146
+ function tail(value, limit = 1000) {
147
+ const text = String(value || '');
148
+ return text.length > limit ? text.slice(-limit) : text;
149
+ }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "sneakoscope",
3
3
  "displayName": "ㅅㅋㅅ",
4
- "version": "8.2.0",
4
+ "version": "8.2.1",
5
5
  "description": "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.",
6
6
  "type": "module",
7
7
  "homepage": "https://github.com/mandarange/Sneakoscope-Codex#readme",
@@ -40,6 +40,7 @@
40
40
  "!dist/scripts/**",
41
41
  "dist/scripts/canonical-test-runner.js",
42
42
  "dist/scripts/desktop-bridge-transport-client.js",
43
+ "dist/scripts/release-version-truth-check.js",
43
44
  "dist/scripts/{agent-guidance-dedup-check.js,agent-message-bus-reader-check.js,all-feature-deep-completion-check.js,appshots-thread-attachment-discovery-check.js,architecture-guard-check.js,certificate-sla-check.js,check-runtime-schemas.js,cli-output-consistency-check.js,codex-current-app-server-v2-check.js,codex-current-binary-identity-check.js,codex-current-capability-check.js,codex-current-core-real-probes-check.js,codex-current-manifest-check.js,codex-current-policy-check.js,codex-current-thread-store-check.js,codex-agent-role-rich-content-check.js,codex-agent-role-sync-check.js,codex-agent-type-routing-check.js,codex-app-execution-profile-check.js,codex-app-fast-ui-preservation-check.js,codex-app-handoff-check.js,codex-app-handoff-launch-check.js,codex-config-load-probe.js,context-graph-check.js,codex-control-all-pipelines-check.js,codex-control-event-stream-ledger-check.js,codex-control-tool-output-continuity-audit-check.js,desktop-bridge-transport-check.js,desktop-bridge-latency-check.js,desktop-bridge-capabilities-check.js,desktop-bridge-real-evidence-check.js,codex-native-agent-role-content-check.js,codex-native-feature-broker-blackbox.js,codex-native-feature-broker-check.js,codex-native-harness-compat-check.js,codex-native-hook-lifecycle-proof-check.js,codex-native-runtime-e2e-fixture.js,codex-plugin-app-template-policy-check.js,codex-sdk-all-pipelines-check.js,codex-sdk-backend-router-check.js,codex-sdk-capability-check.js,codex-sdk-event-stream-ledger-check.js,codex-sdk-real-smoke-check.js,concurrent-session-collision-check.js,context7-evidence-dedupe-check.js,core-skill-card-schema-check.js,core-skill-deployment-snapshot-check.js,core-skill-heldout-validation-check.js,core-skill-no-inference-optimizer-check.js,core-skill-patch-check.js,core-skill-route-runtime-integration-check.js,current-command-surface-check.js,current-surface-update-e2e-check.js,current-upgrade-matrix-check.js,desktop-bridge-unification-check.js,dfix-fixture-check.js,dfix-patch-handoff-check.js,dfix-verification-check.js,dfix-verification-recommendation-check.js,docs-truthfulness-check.js,doctor-codex-app-harness-check.js,doctor-fix-proves-codex-read-check.js,doctor-fixes-codex-app-fast-ui-check.js,evidence-flagship-coverage-check.js,fast-codex-service-tier-proof-check.js,fixtures/fake-codex-config-loader.js,gate-policy-audit-check.js,geo-claim-evidence-check.js,geo-cli-blackbox-check.js,geo-crawler-policy-check.js,git-worktree-checkpoint-check.js,git-worktree-cross-rebase-check.js,git-worktree-diff-envelope-check.js,git-worktree-dirty-lock-check.js,git-worktree-dirty-main-detection-check.js,git-worktree-integration-primary-check.js,git-worktree-manifest-append-check.js,git-worktree-untracked-diff-check.js,goal-artifact-compat-check.js,harness-benchmark-check.js,helper-dedup-check.js,hook-latency-budget-check.js,image-artifact-path-contract-check.js,imagegen-real-smoke-check.js,init-deep-backup-retention-check.js,installed-package-smoke-check.js,lib/codex-sdk-gate-lib.js,lib/ensure-dist-fresh.js,lib/git-worktree-fixture.js,lib/valid-png-fixture.js,local-collab-all-pipelines-final-gpt-check.js,loop-directive-check-lib.js,loop-integration-finalizer-check.js,loop-worker-fixture-child.js,mad-preflight-blocks-unreadable-config-check.js,mad-sks-app-ui-no-mutation-check.js}",
44
45
  "dist/scripts/{latest-version-guidance-check.js,mad-sks-launch-sql-plane-boundary-check.js,mad-sks-sql-plane-capability-check.js,mad-sks-sql-plane-lifecycle-hook-decision-check.js,mad-sks-sql-plane-result-lifecycle-check.js,managed-config-merge-check.js,mcp-plugin-inventory-check.js,model-call-concurrency-check.js,mutation-callsite-analysis.js,mutation-callsite-coverage-check.js,naruto-ssot-gate-aliases-check.js,naruto-ssot-pipeline-default-check.js,naruto-ssot-route-normalization-check.js,naruto-ssot-routing-check.js,naruto-worktree-coding-blackbox.js,native-capability-repair-matrix-check.js,native-image-generation-repair-check.js,official-subagent-workflow-check.js,package-published-contract-check.js,packlist-performance-check.js,pipeline-codex-native-doctor-mad-routing-check.js,pipeline-codex-native-doctor-mad-routing-real-blackbox.js,pipeline-codex-native-image-routing-check.js,pipeline-codex-native-image-routing-real-blackbox.js,pipeline-codex-native-loop-routing-check.js,pipeline-codex-native-loop-routing-real-blackbox.js,pipeline-codex-native-qa-routing-check.js,pipeline-codex-native-qa-routing-real-blackbox.js,pipeline-codex-native-research-routing-check.js,pipeline-codex-native-research-routing-real-blackbox.js,ppt-full-e2e-blackbox-check.js,ppt-real-export-adapter-check.js,ppt-real-imagegen-smoke-check.js,ppt-real-imagegen-wiring-check.js,ppt-reexport-rereview-check.js,prepublish-fast-check.js,publish-preflight.js,prepublish-release-check-or-fast.js,probe-memoization-check.js,product-design-plugin-routing-check.js,prompt-placeholder-guard-check.js,proof-root-cause-policy-check.js,provider-badge-context-check.js,python-codex-sdk-all-pipelines-check.js,qa-loop-app-handoff-capability-check.js,qa-loop-app-handoff-check.js,qa-loop-app-handoff-cli-check.js,qa-loop-app-handoff-confirmation-check.js,qa-loop-app-handoff-gate-lifecycle-check.js,qa-loop-app-handoff-launch-check.js,qa-loop-app-handoff-status-lifecycle-check.js,qa-loop-budget-policy-check.js,qa-loop-effort-escalation-check.js,qa-loop-execution-profile-routing-check.js,qa-loop-image-path-exposure-check.js,qa-loop-image-path-prompt-injection-check.js,release-affected-selector-check.js,release-aggressive-resource-governor-check.js,release-cache-glob-hashing-check.js,release-cache-input-classifier-check.js,release-cache-neutralization-report-check.js,release-cache-version-neutral-fixture-check.js,release-check-stamp.js,release-dynamic-presets-check.js,release-full-parallelism-blackbox.js,release-gate-batch-runner-check.js,release-gate-budget-check.js,release-gate-dag-runner-check.js,release-gate-dag-runner.js,release-latency-slo-check.js,release-metadata-check.js,release-pack-receipt.js,release-parallel-speed-budget-check.js,release-physical-gates-check.js,release-proof-truth-check.js,release-provenance-check.js,release-real-check.js,release-runtime-truth-matrix-check.js,release-speed-summary.js,research-blueprint-densifier-check.js,research-claim-builder-check.js,research-complete-package-fixture-check.js,research-execution-profile-routing-check.js,research-final-reviewer-blackbox.js,responses-retry-policy-centralized-check.js,runtime-proof-summary-check.js,runtime-script-pack-closure-check.js,scheduler-batch-dispatch-check.js,scheduler-parallel-proof-consistency-check.js,scheduler-utilization-integral-check.js,search-visibility-gate-lib.js,secret-preservation-check.js,seo-audit-fixture-check.js,seo-cli-blackbox-check.js,seo-geo-geo-disambiguation-check.js,seo-geo-route-identity-check.js,seo-geo-skill-rich-content-check.js,seo-no-mutation-by-default-check.js,shared-memory-fixture-check.js,side-effect-runtime-report-check.js,skill-name-canonicalizer-check.js,skill-surface-modernization-check.js,skills-manifest-continuity-check.js,sks-cli-gate-lib.js}",
45
46
  "dist/scripts/{real-execution-check-lib.js,gate-lib.js,runtime-domain-gate-lib.js,typed-routing-gate-lib.js,codex-native-gate-lib.js,skill-fixture-check-lib.js,sks-uninstall-regression-check.js,sksd-daemon-check.js,super-search-provider-interface-check.js,triwiki-cache-key-check.js,triwiki-proof-bank-blackbox.js,triwiki-proof-bank-check.js,triwiki-proof-card-check.js,trust-fixture-check.js,type-surface-codex-app-check.js,ultra-router-auto-router-check.js,uninstall-inventory-check.js,install-surface-ssot-check.js,ux-review-extract-wires-real-extractor-check.js,ux-review-imagegen-blackbox-check.js,ux-review-patch-diff-recheck-check.js,ux-review-real-imagegen-smoke-check.js,ux-review-run-wires-imagegen-check.js,wrongness-fixture-check.js}",
@@ -703,6 +703,43 @@
703
703
  ],
704
704
  "output_contract": "sks.gate-result.v2"
705
705
  },
706
+ {
707
+ "id": "release:version-truth",
708
+ "command": "node ./dist/scripts/release-version-truth-check.js",
709
+ "deps": [],
710
+ "resource": [
711
+ "cpu-light",
712
+ "fs-read"
713
+ ],
714
+ "side_effect": "hermetic",
715
+ "timeout_ms": 60000,
716
+ "cache": {
717
+ "enabled": false,
718
+ "inputs": [
719
+ "package.json",
720
+ "package-lock.json",
721
+ "plugins/sks/.codex-plugin/plugin.json",
722
+ "src/core/version.ts",
723
+ "src/core/fsx.ts",
724
+ "src/bin/sks.ts",
725
+ "crates/sks-core/Cargo.toml",
726
+ "crates/sks-core/Cargo.lock",
727
+ "dist/build-manifest.json",
728
+ "CHANGELOG.md",
729
+ "README.md",
730
+ "src/scripts/release-version-truth-check.ts"
731
+ ]
732
+ },
733
+ "isolation": {
734
+ "home": "temp",
735
+ "codex_home": "temp",
736
+ "report_dir": "per-gate"
737
+ },
738
+ "preset": [
739
+ "release"
740
+ ],
741
+ "output_contract": "sks.gate-result.v2"
742
+ },
706
743
  {
707
744
  "id": "install-surface:ssot",
708
745
  "command": "node ./dist/scripts/install-surface-ssot-check.js",
@@ -714,7 +751,7 @@
714
751
  "side_effect": "hermetic",
715
752
  "timeout_ms": 60000,
716
753
  "cache": {
717
- "enabled": true,
754
+ "enabled": false,
718
755
  "inputs": [
719
756
  "package.json",
720
757
  "plugins/sks/.codex-plugin/plugin.json",
@@ -727,7 +764,7 @@
727
764
  "report_dir": "per-gate"
728
765
  },
729
766
  "preset": [
730
- "confidence"
767
+ "release"
731
768
  ],
732
769
  "output_contract": "sks.gate-result.v2"
733
770
  },