sneakoscope 10.6.2 → 10.7.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.
Files changed (135) hide show
  1. package/README.md +28 -6
  2. package/config/perf-budgets.v1.json +1 -2
  3. package/config/skills-hash-ledger.v1.json +7 -2
  4. package/crates/sks-core/Cargo.lock +1 -1
  5. package/crates/sks-core/Cargo.toml +1 -1
  6. package/dist/bin/sks-dispatch.js +6 -3
  7. package/dist/cli/args.js +3 -1
  8. package/dist/cli/command-manifest-lite.js +48 -114
  9. package/dist/cli/command-registry.js +1 -18
  10. package/dist/cli/commands-fast.js +11 -4
  11. package/dist/cli/help-fast.js +11 -22
  12. package/dist/cli/help.js +3 -3
  13. package/dist/cli/install-helpers-codex-lb-config.js +11 -8
  14. package/dist/cli/install-helpers.js +1 -1
  15. package/dist/cli/router.js +12 -26
  16. package/dist/commands/codex-app.js +2 -2
  17. package/dist/commands/doctor-helpers.js +1 -1
  18. package/dist/commands/mad-sks.js +2 -2
  19. package/dist/config/skills-manifest.json +13 -8
  20. package/dist/core/agent-bridge/async-command.js +2 -2
  21. package/dist/core/agents/agent-recursion-guard.js +0 -2
  22. package/dist/core/agents/agent-role-config.js +6 -2
  23. package/dist/core/agents/sks-model-pin-hygiene.js +150 -0
  24. package/dist/core/auto-review.js +15 -172
  25. package/dist/core/code-structure.js +0 -1
  26. package/dist/core/codex/codex-config-guard.js +18 -13
  27. package/dist/core/codex-app/codex-app-ui-state-snapshot.js +7 -1
  28. package/dist/core/codex-control/codex-reliability-shield.js +64 -15
  29. package/dist/core/codex-control/codex-sdk-adapter.js +38 -5
  30. package/dist/core/codex-lb/bridge-contracts.js +5 -0
  31. package/dist/core/codex-lb/combined-catalog/builder.js +4 -2
  32. package/dist/core/codex-lb/combined-catalog/latest-generation.js +7 -34
  33. package/dist/core/codex-lb/combined-catalog/normalize.js +3 -1
  34. package/dist/core/codex-lb/desktop-bridge/codex-lb-turn-state.js +35 -0
  35. package/dist/core/codex-lb/desktop-bridge/compaction-adapter.js +3 -0
  36. package/dist/core/codex-lb/desktop-bridge/header-policy.js +10 -4
  37. package/dist/core/codex-lb/desktop-bridge/http-forward.js +92 -30
  38. package/dist/core/codex-lb/desktop-bridge/provider-handoff.js +79 -0
  39. package/dist/core/codex-lb/desktop-bridge/responses-websocket.js +57 -13
  40. package/dist/core/codex-lb/desktop-bridge/security.js +101 -55
  41. package/dist/core/codex-lb/desktop-bridge/server.js +10 -2
  42. package/dist/core/codex-lb/desktop-bridge/types.js +3 -0
  43. package/dist/core/codex-lb/desktop-bridge/websocket-forward.js +3 -0
  44. package/dist/core/codex-lb/desktop-controller-v3/catalog.js +13 -0
  45. package/dist/core/codex-lb/desktop-controller-v3/provider-commands.js +0 -9
  46. package/dist/core/codex-lb/desktop-service.js +10 -13
  47. package/dist/core/codex-lb/request-route-resolver.js +1 -1
  48. package/dist/core/codex-runtime/codex-desktop-config-policy.js +0 -1
  49. package/dist/core/commands/agent-bridge-command.js +1 -1
  50. package/dist/core/commands/basic-cli.js +60 -233
  51. package/dist/core/commands/command-utils.js +1 -1
  52. package/dist/core/commands/gc-command.js +30 -29
  53. package/dist/core/commands/image-ux-review-command.js +1 -1
  54. package/dist/core/commands/install-package-command.js +1 -1
  55. package/dist/core/commands/intent-normalization/normalizer.js +2 -2
  56. package/dist/core/commands/pipeline-command.js +13 -5
  57. package/dist/core/commands/plan-command.js +2 -3
  58. package/dist/core/commands/research-command.js +0 -3
  59. package/dist/core/commands/review-command.js +1 -1
  60. package/dist/core/commands/seo-command.js +27 -20
  61. package/dist/core/commands/status-command.js +8 -2
  62. package/dist/core/doctor/command-alias-cleanup.js +6 -6
  63. package/dist/core/evaluation.js +1 -1
  64. package/dist/core/feature-fixtures.js +9 -43
  65. package/dist/core/feature-registry.js +9 -27
  66. package/dist/core/git-hygiene/shared-memory-publish.js +1 -1
  67. package/dist/core/hooks-runtime/jev-spawn-routing.js +1 -5
  68. package/dist/core/hooks-runtime/parent-orchestration-gate.js +6 -8
  69. package/dist/core/hooks-runtime/stop-repeat-guard.js +0 -13
  70. package/dist/core/hooks-runtime.js +13 -9
  71. package/dist/core/init/skills.js +27 -16
  72. package/dist/core/init.js +0 -9
  73. package/dist/core/install/installed-package-smoke.js +3 -1
  74. package/dist/core/perf/import-graph-budget.js +0 -1
  75. package/dist/core/perf/release-latency-slo.js +2 -30
  76. package/dist/core/pipeline-internals/pipeline-stage-builder.js +2 -4
  77. package/dist/core/pipeline-internals/runtime-core.js +2 -38
  78. package/dist/core/proof/route-proof-policy.js +2 -4
  79. package/dist/core/proof/runtime-truth-matrix.js +2 -2
  80. package/dist/core/proof-field.js +104 -39
  81. package/dist/core/provider/provider-context.js +4 -1
  82. package/dist/core/questions.js +11 -7
  83. package/dist/core/release/gate-affected-globs.js +0 -2
  84. package/dist/core/research/research-reviewer-contract.js +34 -0
  85. package/dist/core/research/research-work-graph.js +1 -1
  86. package/dist/core/research.js +1 -1
  87. package/dist/core/routes/constants.js +0 -1
  88. package/dist/core/routes/diagnostic-allowlist.js +1 -3
  89. package/dist/core/routes/light-routes.js +1 -2
  90. package/dist/core/routes.js +1 -1
  91. package/dist/core/safety/command-contract/contracts.js +5 -1
  92. package/dist/core/search/context.js +2 -2
  93. package/dist/core/search-visibility/marketing-truthfulness.js +10 -7
  94. package/dist/core/search-visibility/marketing.js +194 -149
  95. package/dist/core/skill-forge.js +1 -361
  96. package/dist/core/strategy/adhd-orchestrating-gate.js +3 -3
  97. package/dist/core/triwiki/context-graph/extractors/topology/commands.js +2 -6
  98. package/dist/core/triwiki-wrongness/wrongness-cli.js +9 -27
  99. package/dist/core/update/update-migration-state.js +10 -40
  100. package/dist/core/version.js +1 -1
  101. package/package.json +2 -3
  102. package/release-gates.v2.json +1 -32
  103. package/dist/cli/recallpulse-command.js +0 -144
  104. package/dist/commands/auto-review.js +0 -5
  105. package/dist/commands/codex-native.js +0 -77
  106. package/dist/commands/recallpulse.js +0 -5
  107. package/dist/core/codex-native/codex-native-interop-policy.js +0 -127
  108. package/dist/core/commands/autoresearch-command.js +0 -4
  109. package/dist/core/commands/code-structure-command.js +0 -52
  110. package/dist/core/commands/goal-command.js +0 -43
  111. package/dist/core/commands/recallpulse-command.js +0 -4
  112. package/dist/core/commands/remote-command.js +0 -119
  113. package/dist/core/commands/skill-dream-command.js +0 -43
  114. package/dist/core/commands/wrongness-command.js +0 -2
  115. package/dist/core/goal-workflow.js +0 -80
  116. package/dist/core/mcp/mcp-tool-name-normalizer.js +0 -28
  117. package/dist/core/recallpulse/policy.js +0 -207
  118. package/dist/core/recallpulse.js +0 -947
  119. package/dist/core/remote/audit-idempotency.js +0 -241
  120. package/dist/core/remote/index.js +0 -10
  121. package/dist/core/remote/machine-registry.js +0 -167
  122. package/dist/core/remote/owner-proof.js +0 -216
  123. package/dist/core/remote/protocol.js +0 -249
  124. package/dist/core/remote/readiness.js +0 -156
  125. package/dist/core/remote/session-index.js +0 -61
  126. package/dist/core/remote/session-snapshot.js +0 -197
  127. package/dist/core/remote/ssh-worker-client.js +0 -377
  128. package/dist/core/remote/types.js +0 -10
  129. package/dist/core/remote/worker.js +0 -360
  130. package/dist/core/search/context-graph-seeds.js +0 -15
  131. package/dist/core/verification/context-graph-affected.js +0 -312
  132. package/dist/core/verification/verification-artifact-lock.js +0 -21
  133. package/dist/core/verification/verification-dag.js +0 -89
  134. package/dist/core/verification/verification-result.js +0 -19
  135. package/dist/core/verification/verification-worker-pool.js +0 -204
@@ -1,4 +1,5 @@
1
- import { COMMAND_MANIFEST_LITE } from './command-manifest-lite.js';
1
+ import { COMMAND_MANIFEST_LITE, visibleCommandManifest } from './command-manifest-lite.js';
2
+ import { sksTextLogo } from './output.js';
2
3
  export function commandsJsonFast() {
3
4
  const commands = COMMAND_MANIFEST_LITE
4
5
  .map((entry) => fastCommandRow(entry))
@@ -9,10 +10,18 @@ export function commandsJsonFast() {
9
10
  commands
10
11
  }, null, 2));
11
12
  }
13
+ export function commandsTextFast() {
14
+ const commands = visibleCommandManifest();
15
+ console.log(`${sksTextLogo()}\n\nCommands\n`);
16
+ const width = Math.max(...commands.map((entry) => entry.name.length)) + 2;
17
+ for (const entry of commands)
18
+ console.log(`sks ${entry.name.padEnd(width)}${entry.summary}`);
19
+ console.log('\nRun `sks help <command>` for its usage.');
20
+ }
12
21
  function fastCommandRow(entry) {
13
22
  const row = {
14
23
  name: entry.name,
15
- usage: `sks ${entry.name}`,
24
+ usage: entry.usage || `sks ${entry.name}`,
16
25
  description: entry.summary,
17
26
  maturity: entry.maturity
18
27
  };
@@ -20,8 +29,6 @@ function fastCommandRow(entry) {
20
29
  row.readonly = true;
21
30
  if (entry.mutatesRouteState === true)
22
31
  row.mutating = true;
23
- if (entry.deprecated === true)
24
- row.deprecated = true;
25
32
  if (entry.hidden === true)
26
33
  row.hidden = true;
27
34
  return row;
@@ -1,35 +1,24 @@
1
- import { COMMAND_MANIFEST_LITE } from './command-manifest-lite.js';
1
+ import { visibleCommandManifest } from './command-manifest-lite.js';
2
2
  import { PACKAGE_VERSION } from '../core/version.js';
3
3
  export function helpFast() {
4
4
  console.log(`SKS
5
5
  SNEAKOSCOPE CODEX v${PACKAGE_VERSION}
6
6
 
7
- 3-pillar frontdoor
7
+ Ask Codex for work directly; the main agent does ordinary work and SKS hooks keep it safe.
8
8
 
9
9
  $sks-plan "task" plan only; writes .sneakoscope/plans, no code edits
10
10
  $sks-work execute the latest plan with Naruto child agents
11
11
 
12
- Local surfaces
13
-
14
12
  sks review --staged machine-first diff review
15
- sks doctor --fix repair/validate the harness
16
-
17
- Discovery
13
+ sks doctor --fix repair and validate the install
14
+ sks help <command> usage of one command (or a $ route)
15
+ sks dollar-commands every Codex App $ route
18
16
 
19
- sks commands [--json] all commands
20
- sks dollar-commands all Codex App $ routes
21
- sks help [topic] focused help
17
+ Commands
22
18
  `);
23
- for (const row of commandRows().filter((entry) => entry.maturity !== 'labs').slice(0, 18)) {
24
- console.log(` ${row.usage.padEnd(58)} ${row.description}`);
25
- }
26
- console.log('\nRun `sks commands` for the full catalog.');
27
- }
28
- function commandRows() {
29
- return COMMAND_MANIFEST_LITE.map((entry) => ({
30
- name: entry.name,
31
- usage: `sks ${entry.name}`,
32
- description: entry.summary,
33
- maturity: entry.maturity
34
- })).sort((a, b) => a.name.localeCompare(b.name));
19
+ const commands = visibleCommandManifest().filter((entry) => entry.maturity !== 'labs');
20
+ const width = Math.max(...commands.map((entry) => entry.name.length)) + 2;
21
+ for (const entry of commands)
22
+ console.log(` sks ${entry.name.padEnd(width)}${entry.summary}`);
23
+ console.log('\nLabs commands (optional routes) are listed by `sks commands`.');
35
24
  }
package/dist/cli/help.js CHANGED
@@ -6,10 +6,10 @@ export function isHelpRequest(args) {
6
6
  export function renderManifestHelp(command, entry) {
7
7
  if (!entry)
8
8
  return `Usage: sks ${command}\n\nNo manifest entry is registered for this command.`;
9
- const lines = [`Usage: sks ${entry.name} [options]`, '', entry.summary];
9
+ const lines = [`Usage: ${entry.usage || `sks ${entry.name} [options]`}`, '', entry.summary];
10
+ if (entry.description && entry.description !== entry.summary)
11
+ lines.push(entry.description);
10
12
  const notes = [];
11
- if (entry.deprecated)
12
- notes.push('deprecated — kept only for compatibility');
13
13
  if (entry.maturity !== 'stable')
14
14
  notes.push(`maturity: ${entry.maturity}`);
15
15
  if (entry.readonly)
@@ -4,13 +4,16 @@ import { escapeRegExp } from '../core/text/regex.js';
4
4
  export const DESKTOP_BRIDGE_MANAGED_MARKER = '# sks-desktop-bridge-managed';
5
5
  export const DESKTOP_BRIDGE_MANAGED_BASE_URL_MARKER = '# sks-desktop-bridge-managed-base-url';
6
6
  export const DESKTOP_BRIDGE_MANAGED_MODEL_CATALOG_MARKER = '# sks-desktop-bridge-managed-model-catalog';
7
- export function bindCodexClientProvider(text, provider) {
8
- const selected = topLevelTomlString(text, 'model_provider');
9
- if (selected && selected !== 'openai' && selected !== 'codex-lb')
10
- return text;
11
- if (selected === provider)
12
- return text;
13
- return upsertTopLevelTomlString(String(text || ''), 'model_provider', provider);
7
+ export function repairManagedCodexLbClientSelection(text) {
8
+ const source = String(text || '');
9
+ if (topLevelTomlString(source, 'model_provider') !== 'codex-lb')
10
+ return source;
11
+ if (!topLevelHasLine(source, DESKTOP_BRIDGE_MANAGED_MARKER) || hasCodexLbProviderTable(source))
12
+ return source;
13
+ return upsertTopLevelTomlString(source, 'model_provider', 'openai');
14
+ }
15
+ export function hasCodexLbProviderTable(text) {
16
+ return /^\s*\[model_providers\.(?:"codex-lb"|codex-lb)\]\s*(?:#.*)?$/m.test(text);
14
17
  }
15
18
  export function upsertDesktopBridgeManagedConfig(text, input) {
16
19
  const bridgeBaseUrl = normalizeManagedBridgeBaseUrl(input.bridgeBaseUrl);
@@ -39,7 +42,7 @@ export function upsertDesktopBridgeManagedConfig(text, input) {
39
42
  if (existingCatalog && !catalogOwned) {
40
43
  throw new Error('historical_user_owned_config_conflict:model_catalog_json');
41
44
  }
42
- const keepCodexLb = selectedProvider === 'codex-lb';
45
+ const keepCodexLb = selectedProvider === 'codex-lb' && hasCodexLbProviderTable(next);
43
46
  next = removeManagedBridgeTopLevelBindings(next);
44
47
  next = upsertTopLevelTomlString(next, 'model_provider', keepCodexLb ? 'codex-lb' : 'openai');
45
48
  next = addTopLevelMarkerBeforeKey(next, 'model_provider', DESKTOP_BRIDGE_MANAGED_MARKER);
@@ -24,7 +24,7 @@ export async function postinstall({ bootstrap }) {
24
24
  if (menuBar.status === 'skipped')
25
25
  console.log(describePostinstallMenuBar(menuBar));
26
26
  console.log('Next: run `sks bootstrap` when you are ready to initialize SKS.');
27
- console.log('Dependency diagnostics remain explicit: sks deps check');
27
+ console.log('Dependency diagnostics remain explicit: sks doctor');
28
28
  console.log('Explicit lifecycle opt-in: SKS_POSTINSTALL_BOOTSTRAP=1 npm i -g sneakoscope');
29
29
  console.log('Optional Homebrew/npm-global tool repair remains off unless SKS_POSTINSTALL_AUTO_INSTALL_CLI_TOOLS=1 is also set.');
30
30
  const reason = process.env.SKS_POSTINSTALL_NO_BOOTSTRAP === '1'
@@ -1,4 +1,3 @@
1
- import { AsyncLocalStorage } from 'node:async_hooks';
2
1
  import { createHash } from 'node:crypto';
3
2
  import { COMMAND_ALIASES_LITE, COMMAND_MANIFEST_BY_NAME, COMMAND_NAME_SET, } from './command-manifest-lite.js';
4
3
  import { ui as cliUi } from './cli-theme.js';
@@ -6,7 +5,6 @@ import { helpResult, isHelpRequest, renderManifestHelp } from './help.js';
6
5
  import { findRetiredGlobalExecutionArgumentErrors } from './global-mode-router.js';
7
6
  import { normalizeIntentCommand, } from '../core/commands/intent-normalization/normalizer.js';
8
7
  import { narutoUsesCurrentSession } from '../core/subagents/naruto-execution-mode.js';
9
- const routerIntentStorage = new AsyncLocalStorage();
10
8
  export function prepareRouterExecutionIntent(argv, inheritance = {}) {
11
9
  const effectiveArgv = argv.length ? [...argv] : ['doctor'];
12
10
  const rawCommand = effectiveArgv[0]?.startsWith('$')
@@ -66,9 +64,8 @@ export function normalizeCommand(args = []) {
66
64
  export async function dispatch(args) {
67
65
  const argv = args ?? process.argv.slice(2);
68
66
  try {
69
- let intent = null;
70
67
  try {
71
- intent = prepareRouterExecutionIntent(argv);
68
+ prepareRouterExecutionIntent(argv);
72
69
  }
73
70
  catch (error) {
74
71
  const code = error instanceof Error ? error.message : String(error);
@@ -85,9 +82,7 @@ export async function dispatch(args) {
85
82
  throw error;
86
83
  }
87
84
  }
88
- return intent
89
- ? await routerIntentStorage.run(intent.contract, () => dispatchInner(argv))
90
- : await dispatchInner(argv);
85
+ return await dispatchInner(argv);
91
86
  }
92
87
  catch (err) {
93
88
  const message = err instanceof Error ? err.message : String(err);
@@ -178,16 +173,14 @@ async function dispatchInner(argv) {
178
173
  process.exitCode = 1;
179
174
  return commandGate;
180
175
  }
181
- const { ensureCurrentMigrationBeforeCommand } = await import('../core/update/update-migration-state.js');
182
- const migrationGate = await ensureCurrentMigrationBeforeCommand({
183
- command,
184
- args: rest,
185
- skipMigrationGate: entry.skipMigrationGate === true
186
- || entry.readonly === true
187
- || safeReadOnlySubcommand(command, rest)
188
- || safeActiveRouteVisualQuery(command, rest)
189
- });
190
- if (!migrationGate.ok) {
176
+ const skipMigrationGate = entry.skipMigrationGate === true
177
+ || entry.readonly === true
178
+ || safeReadOnlySubcommand(command, rest)
179
+ || safeActiveRouteVisualQuery(command, rest);
180
+ const migrationGate = skipMigrationGate
181
+ ? null
182
+ : await (await import('../core/update/update-migration-state.js')).ensureCurrentMigrationBeforeCommand({ command, args: rest, skipMigrationGate: false });
183
+ if (migrationGate && !migrationGate.ok) {
191
184
  console.error('SKS project migration blocked.');
192
185
  console.error(`Scope: ${migrationGate.scope || 'project'}`);
193
186
  console.error(`Stage: ${migrationGate.failed_stage_id || migrationGate.status}`);
@@ -306,12 +299,6 @@ export function safeReadOnlySubcommand(command, args) {
306
299
  if (command === 'codex-app' && ['context-1m', 'context-management'].includes(sub) && (nested === 'status' || nested === '' || nested.startsWith('--'))) {
307
300
  return !args.some((arg) => ['--fix', '--yes', '-y', '--write', '--apply', '--execute', '--force', '--real'].includes(String(arg)));
308
301
  }
309
- if (command === 'remote' && ['readiness', 'status', 'show'].includes(sub)) {
310
- return !args.some((arg) => ['--fix', '--yes', '-y', '--write', '--apply', '--execute', '--force', '--real'].includes(String(arg)));
311
- }
312
- if (command === 'remote' && ['machines', 'machine'].includes(sub) && ['list', 'validate'].includes(nested)) {
313
- return !args.some((arg) => ['--fix', '--yes', '-y', '--write', '--apply', '--execute', '--force', '--real'].includes(String(arg)));
314
- }
315
302
  if (!['status', 'show', 'list', 'observe', 'watch', 'doctor', 'help'].includes(sub))
316
303
  return false;
317
304
  return !args.some((arg) => ['--fix', '--yes', '-y', '--write', '--apply', '--execute', '--force', '--real'].includes(String(arg)));
@@ -367,8 +354,7 @@ export function safeActiveRouteContinuation(command, args, state = {}) {
367
354
  return subcommand === 'run' && !requestedMission;
368
355
  }
369
356
  const expectedRoutes = new Map([
370
- ['research', ['RESEARCH']],
371
- ['autoresearch', ['AUTORESEARCH', 'RESEARCH']],
357
+ ['research', ['RESEARCH', 'AUTORESEARCH']],
372
358
  ['qa-loop', ['QALOOP']]
373
359
  ]).get(command);
374
360
  if (!expectedRoutes)
@@ -410,5 +396,5 @@ function activeRouteStateBlocksCommand(state = {}) {
410
396
  return false;
411
397
  if (/(?:DONE|COMPLETE|CLOSED|BLOCKED|FAILED)$/i.test(String(state.phase || '')))
412
398
  return false;
413
- return Boolean(state.route || state.route_command || ['NARUTO', 'QALOOP', 'RESEARCH', 'MADSKS', 'GOAL'].includes(mode));
399
+ return Boolean(state.route || state.route_command || ['NARUTO', 'QALOOP', 'RESEARCH', 'MADSKS'].includes(mode));
414
400
  }
@@ -70,7 +70,7 @@ export async function run(_command, args = []) {
70
70
  if (action === 'agent-role-sync')
71
71
  return printCodexAppResult(args, await syncCodexAgentRoles({ root: await sksRoot(), apply: flag(args, '--apply') || flag(args, '--fix') }));
72
72
  if (action === 'init-deep')
73
- return printCodexAppResult(args, await runCodexInitDeep({ root: await sksRoot(), apply: !flag(args, '--check-only') && !flag(args, '--dry-run') }));
73
+ return printCodexAppResult(args, await runCodexInitDeep({ root: await sksRoot(), apply: !flag(args, '--check-only') && !flag(args, '--dry-run'), directoryLocal: flag(args, '--directory-local') }));
74
74
  if (action === 'hook-lifecycle')
75
75
  return printCodexAppResult(args, await buildCodexHookLifecycle({ root: await sksRoot(), apply: flag(args, '--apply') || flag(args, '--fix') }));
76
76
  if (action === 'execution-profile')
@@ -151,7 +151,7 @@ export async function run(_command, args = []) {
151
151
  process.exitCode = 1;
152
152
  return;
153
153
  }
154
- console.error('Usage: sks codex-app check|status|restart|context-management [status|on|off]|context-1m [status|on|off] [--no-restart]|harness-matrix|skill-sync|agent-role-sync|init-deep|hook-lifecycle|execution-profile|role-models|set-role-model --role <name> [--provider <id>] --model <catalog-slug> --reasoning <effort>|reset-role-model --role <name>|product-design [--check-only]|ensure-product-design|chrome-extension|pat status|remote-control [--json]');
154
+ console.error('Usage: sks codex-app check|status|restart|context-management [status|on|off]|context-1m [status|on|off] [--no-restart]|harness-matrix|skill-sync|agent-role-sync|init-deep [--directory-local]|hook-lifecycle|execution-profile|role-models|set-role-model --role <name> [--provider <id>] --model <catalog-slug> --reasoning <effort>|reset-role-model --role <name>|product-design [--check-only]|ensure-product-design|chrome-extension|pat status|remote-control [--json]');
155
155
  console.error('Provider routing moved to: sks bridge provider configure|validate|enable; sks bridge catalog sync; sks bridge route set-default.');
156
156
  process.exitCode = 1;
157
157
  }
@@ -19,7 +19,7 @@ export function buildRuntimeReadiness(matrix) {
19
19
  ].join(' '));
20
20
  }
21
21
  if (matrix?.features?.project_memory?.ok !== true)
22
- repairActions.push('Project memory: sks codex-native init-deep --apply --directory-local');
22
+ repairActions.push('Project memory: sks codex-app init-deep --directory-local');
23
23
  return {
24
24
  schema: 'sks.runtime-readiness-story.v1',
25
25
  codex_native: codexNative,
@@ -1,6 +1,6 @@
1
- import { madHighCommand } from '../core/commands/mad-sks-command.js';
2
- import { PACKAGE_VERSION } from '../core/fsx.js';
3
1
  export async function run(_command, args = []) {
2
+ const { madHighCommand } = await import('../core/commands/mad-sks-command.js');
3
+ const { PACKAGE_VERSION } = await import('../core/version.js');
4
4
  return madHighCommand(['--mad-sks', ...args], {
5
5
  packageVersion: PACKAGE_VERSION
6
6
  });
@@ -1,12 +1,14 @@
1
1
  {
2
2
  "schema": "sks.skills-manifest.v1",
3
- "package_version": "10.6.2",
3
+ "package_version": "10.7.1",
4
4
  "skills": [
5
5
  {
6
6
  "canonical_name": "sks",
7
7
  "type": "official",
8
- "content_sha256": "d5adbf63047d4882258d70bb46017e4aa7b6d5804154c68ef4204d0e0e5916d6",
8
+ "content_sha256": "eb09af342c2f2bc3d269e6d1c2f92d718ed069582d1165bfe46600b5c2225a8b",
9
9
  "hash_history": [
10
+ "32d97c9b68a0a97794f48bd2f200bb3c0cd68816c00fef3397e86df671342ac5",
11
+ "d5adbf63047d4882258d70bb46017e4aa7b6d5804154c68ef4204d0e0e5916d6",
10
12
  "8aa34586ba331f0447668c2ce863fe6c9ec4f881828ebed26ca5ecc754d66840",
11
13
  "d0288d27c8bc1c89decb258c6805ed4286cd0d65371ef0eec453be233b39a2a1",
12
14
  "905fc5472d36f0780b56f0e09404f42ea20293b1a4615d2050b7db3043231dbd",
@@ -309,8 +311,9 @@
309
311
  {
310
312
  "canonical_name": "sks-help",
311
313
  "type": "official",
312
- "content_sha256": "17c2a63b163b266dc0d0a503a275d41a5388e1f44be9250b84017f1a549159d4",
314
+ "content_sha256": "3a20901121eb9a11a31ea797a44c8136a09f26f9862f52a923634aba0767dc0c",
313
315
  "hash_history": [
316
+ "17c2a63b163b266dc0d0a503a275d41a5388e1f44be9250b84017f1a549159d4",
314
317
  "8b6d7f0cffbd3b141f53a6937fb3d58ba363d495d6da561d8f463ee3b265d975",
315
318
  "0b67a2ed2eb1f3f80cf1645bee0c189ecc442d2ec84b1e0b218d800298487920"
316
319
  ],
@@ -456,8 +459,9 @@
456
459
  {
457
460
  "canonical_name": "sks-ppt",
458
461
  "type": "official",
459
- "content_sha256": "a25e537ff49b5bffdc093a5f772a8d218003ca1bb81e0aa304561684a9551b31",
462
+ "content_sha256": "93887312718febbb795cab3d09b1d47a30485eee7c6416fb02c78c65ab5c4686",
460
463
  "hash_history": [
464
+ "a25e537ff49b5bffdc093a5f772a8d218003ca1bb81e0aa304561684a9551b31",
461
465
  "fba3f438b9f22dae0813cd12bf310539a7d2b71c8cd9322eb840514e24884eaf",
462
466
  "c9a0d90e12560dd3f04959869051370e6baf46eda6eb63f708ea1661c5c9d041",
463
467
  "1d4de05afd42ee5739c0ed925af9e0ac4785fc746e659c60d3d908d465e6386c",
@@ -493,16 +497,16 @@
493
497
  {
494
498
  "canonical_name": "sks-reasoning-router",
495
499
  "type": "official",
496
- "content_sha256": "2ec66071b1c021e8c2ddd8f1ecefd16502c8325adab2c3c804a9e8d4123b1a8d",
500
+ "content_sha256": "00403fa829bc673966c2e125d5a2d42111ed6fd8c821b1f0e50176127658b888",
497
501
  "hash_history": [
502
+ "2ec66071b1c021e8c2ddd8f1ecefd16502c8325adab2c3c804a9e8d4123b1a8d",
498
503
  "b0f458caa1c3bd7bb7241a09b80fce5700aeb99b340e84c08a9b2b66bc875ba7",
499
504
  "41e14e8d5b93d743096664869ee68c41c86e911b0bbc165bdcd10e4a45faa4b6",
500
505
  "03d68436e568b3cee2bffc6ca58819019ca406f7b648ef4704e3465c7c83c114",
501
506
  "647f730520a1c7dc89c2642f5b8502624c65a861ae41aecf1fb137db40fd0611",
502
507
  "da0ddb58adc68ddeebdb9c45bf111c26eaa64d3e9dffe1dd39d7f30b943b8b88",
503
508
  "1595beabf2d31397217311fa1323bd62c801cf6c87db9029ff544c457efec8bb",
504
- "a7d879d157c6d5b6b81a67dba7b5b731ac18ea986841fe1ab2cafbd6623481c3",
505
- "dc0b8c6a4093269c2c36b58432b25409704d06fea8ca558f43b598625ca0d9de"
509
+ "a7d879d157c6d5b6b81a67dba7b5b731ac18ea986841fe1ab2cafbd6623481c3"
506
510
  ],
507
511
  "deprecated_aliases": []
508
512
  },
@@ -521,8 +525,9 @@
521
525
  {
522
526
  "canonical_name": "sks-release-review",
523
527
  "type": "official",
524
- "content_sha256": "36846d6180051c85e3093e7e405ad9d4d447f7295769f71f8450c18afee50e98",
528
+ "content_sha256": "dfc2af7dd2c41ab2529ed54b2dca0dfd85e2de0d3304afbfe4a420e6627ce01a",
525
529
  "hash_history": [
530
+ "36846d6180051c85e3093e7e405ad9d4d447f7295769f71f8450c18afee50e98",
526
531
  "bb6ef28431fd6c390041c9a2855b906fd01a1f6da02111f094258914cf826bb9",
527
532
  "7cf879a2efd61822d3dccd4eb69fb704bfbab4b114b820b6dfa0d13b5f20e9fa"
528
533
  ],
@@ -9,7 +9,7 @@ import { bridgeClientUrl } from '../codex-lb/desktop-controller-v3/shared.js';
9
9
  import { runProcess } from '../fsx.js';
10
10
  import { createResponsesTransport } from './responses-transport.js';
11
11
  import { latestModelForTier } from '../subagents/model-tiers.js';
12
- const USAGE = 'sks agent-bridge async --prompt "task" [--tools status,stats] [--json]';
12
+ const USAGE = 'sks agent-bridge async --prompt "task" [--tools status,search] [--json]';
13
13
  const MAX_PROMPT_BYTES = 16 * 1024;
14
14
  export function redactAsyncToolOutput(stdout) {
15
15
  try {
@@ -21,7 +21,7 @@ export function redactAsyncToolOutput(stdout) {
21
21
  }
22
22
  export function parseAsyncCommandArgs(args) {
23
23
  let prompt = '';
24
- let selected = 'status,stats';
24
+ let selected = 'status,search';
25
25
  const seen = new Set();
26
26
  for (let i = 0; i < args.length; i++) {
27
27
  const flag = args[i];
@@ -4,9 +4,7 @@ export const AGENT_RECURSION_GUARD_REPORT_SCHEMA = 'sks.agent-recursion-guard.v1
4
4
  export const AGENT_RECURSIVE_COMMAND_DENYLIST = Object.freeze([
5
5
  'sks naruto run',
6
6
  'sks research run',
7
- 'sks autoresearch run',
8
7
  'sks qa-loop',
9
- 'sks goal',
10
8
  '$Naruto',
11
9
  '$Work',
12
10
  '$Research',
@@ -5,6 +5,7 @@ import { nowIso, readText, writeJsonAtomic } from '../fsx.js';
5
5
  import { inspectConfinedPath, moveConfinedPath, removeConfinedDirectoryIfEmpty, removeManagedPathVerified, uniqueConfinedPath, walkConfinedEntries } from '../managed-path-safety.js';
6
6
  import { MANAGED_OFFICIAL_SUBAGENT_ROLES, RETIRED_MANAGED_AGENT_ROLE_TOMBSTONES, managedAgentRoleOwnsText } from '../managed-assets/managed-assets-manifest.js';
7
7
  import { installOfficialSubagentAgentConfigs, refreshGlobalOfficialSubagentAgentConfigs } from '../subagents/official-subagent-config.js';
8
+ import { reconcileStaleSksModelPins } from './sks-model-pin-hygiene.js';
8
9
  export const AGENT_ROLE_CONFIG_REPAIR_SCHEMA = 'sks.agent-role-config-repair.v1';
9
10
  export async function repairAgentRoleConfigs(input) {
10
11
  const root = path.resolve(input.root);
@@ -18,6 +19,7 @@ export async function repairAgentRoleConfigs(input) {
18
19
  ...(input.globalRuntimeRoot ? { globalRuntimeRoot: input.globalRuntimeRoot } : {}),
19
20
  fix: input.apply === true
20
21
  });
22
+ const modelPinHygiene = await reconcileStaleSksModelPins({ root, codexHome, fix: input.apply === true });
21
23
  const officialRepair = await installOfficialSubagentAgentConfigs(root, { apply: input.apply === true });
22
24
  const globalRepair = path.join(root, '.codex') === codexHome
23
25
  ? null
@@ -38,7 +40,7 @@ export async function repairAgentRoleConfigs(input) {
38
40
  schema: AGENT_ROLE_CONFIG_REPAIR_SCHEMA,
39
41
  generated_at: nowIso(),
40
42
  ok: input.apply
41
- ? requiredFixes === appliedFixes && manualBlockers.length === 0 && retiredRoleCleanup.ok
43
+ ? requiredFixes === appliedFixes && manualBlockers.length === 0 && retiredRoleCleanup.ok && modelPinHygiene.errors.length === 0
42
44
  : manualBlockers.length === 0 && retiredRoleCleanup.ok && (globalRepair?.stale.length || 0) === 0,
43
45
  apply: input.apply === true,
44
46
  missing,
@@ -51,12 +53,14 @@ export async function repairAgentRoleConfigs(input) {
51
53
  manual_blockers: manualBlockers,
52
54
  manifest_role_ids: MANAGED_OFFICIAL_SUBAGENT_ROLES.map((role) => role.id),
53
55
  retired_role_cleanup: retiredRoleCleanup,
56
+ model_pin_hygiene: modelPinHygiene,
54
57
  warnings_suppressed: true,
55
58
  blockers: [
56
59
  ...manualBlockers,
57
60
  ...(!input.apply ? (globalRepair?.stale.map((file) => `stale_global_official_subagent_agent:${globalPath(file)}`) || []) : []),
58
61
  ...(input.apply && requiredFixes !== appliedFixes ? ['agent_role_config_repair_incomplete'] : []),
59
- ...(!retiredRoleCleanup.ok ? ['retired_agent_role_cleanup_incomplete'] : [])
62
+ ...(!retiredRoleCleanup.ok ? ['retired_agent_role_cleanup_incomplete'] : []),
63
+ ...modelPinHygiene.errors.map((error) => `model_pin_hygiene_failed:${error}`)
60
64
  ]
61
65
  };
62
66
  if (input.reportPath)
@@ -0,0 +1,150 @@
1
+ import fsp from 'node:fs/promises';
2
+ import path from 'node:path';
3
+ import { readText, writeTextAtomic } from '../fsx.js';
4
+ import { hasCodexLbProviderTable } from '../../cli/install-helpers-codex-lb-config.js';
5
+ import { hasSksManagedCodexConfigMarker, writeCodexConfigGuarded } from '../codex/codex-config-guard.js';
6
+ import { bridgeRouteIndexPath, combinedBridgeCatalogPath } from '../codex-lb/combined-catalog.js';
7
+ import { readActiveCombinedBridgeCatalog } from '../codex-lb/combined-catalog/persistence.js';
8
+ import { backupInvalidToml } from '../subagents/official-subagent-config.js';
9
+ export const MODEL_PIN_HYGIENE_SCHEMA = 'sks.model-pin-hygiene.v1';
10
+ const LEGACY_ROLE_NAMES = new Set(['sks-planner', 'sks-implementer', 'sks-explorer', 'sks-checker']);
11
+ async function catalogPinState(codexHome) {
12
+ const read = await readActiveCombinedBridgeCatalog(combinedBridgeCatalogPath(codexHome), bridgeRouteIndexPath(codexHome)).catch(() => null);
13
+ if (!read?.ok)
14
+ return null;
15
+ const rows = new Map();
16
+ for (const row of read.catalog.models) {
17
+ for (const id of [row.public_id, row.slug])
18
+ if (typeof id === 'string' && id)
19
+ rows.set(id, row);
20
+ }
21
+ return (model) => {
22
+ const row = rows.get(model);
23
+ if (!row)
24
+ return 'unlisted';
25
+ const visibility = String(row.visibility || 'list').toLowerCase();
26
+ const upgrade = row.upgrade && typeof row.upgrade === 'object' ? row.upgrade.model : null;
27
+ return visibility === 'hide' || visibility === 'hidden' || (typeof upgrade === 'string' && upgrade) ? 'superseded' : 'current';
28
+ };
29
+ }
30
+ function topLevelEnd(lines) {
31
+ const end = lines.findIndex((line) => /^\s*\[/.test(line) || /^\s*developer_instructions\s*=/.test(line));
32
+ return end === -1 ? lines.length : end;
33
+ }
34
+ function stalePinLines(text, pinState, codexLbProviderDefined) {
35
+ const lines = text.split('\n');
36
+ const indexes = [];
37
+ const labels = [];
38
+ for (let index = 0; index < topLevelEnd(lines); index += 1) {
39
+ const match = /^\s*(model|model_provider)\s*=\s*"([^"]*)"\s*(?:#.*)?$/.exec(lines[index] || '');
40
+ if (!match)
41
+ continue;
42
+ const [, key, value] = match;
43
+ const stale = key === 'model_provider'
44
+ ? value === 'codex-lb' && !codexLbProviderDefined
45
+ : pinState !== null && pinState(value) !== 'current';
46
+ if (!stale)
47
+ continue;
48
+ indexes.push(index);
49
+ labels.push(`${key} = "${value}"`);
50
+ }
51
+ return { indexes, labels };
52
+ }
53
+ function withoutLines(text, indexes) {
54
+ const drop = new Set(indexes);
55
+ return text.split('\n').filter((_, index) => !drop.has(index)).join('\n');
56
+ }
57
+ const CODEX_LB_SELECTION_EVIDENCE = [
58
+ /^\s*model_provider\s*=\s*["']codex-lb["']\s*(?:#.*)?$/,
59
+ /^\s*\[model_providers\.(?:"codex-lb"|codex-lb)\]\s*(?:#.*)?$/
60
+ ];
61
+ function sksOwnedProjectConfig(text) {
62
+ const withoutSelection = text.split('\n')
63
+ .filter((line) => !CODEX_LB_SELECTION_EVIDENCE.some((pattern) => pattern.test(line)))
64
+ .join('\n');
65
+ return hasSksManagedCodexConfigMarker(withoutSelection);
66
+ }
67
+ function isLegacySksRole(file, text) {
68
+ if (/sks_managed_body_sha256/.test(text))
69
+ return false;
70
+ const name = /^\s*name\s*=\s*"([^"]+)"/m.exec(text)?.[1] ?? path.basename(file, '.toml');
71
+ return /^\s*description\s*=\s*"SKS managed\b/m.test(text) || LEGACY_ROLE_NAMES.has(name);
72
+ }
73
+ async function regularFile(file) {
74
+ const stat = await fsp.lstat(file).catch(() => null);
75
+ return Boolean(stat?.isFile() && !stat.isSymbolicLink());
76
+ }
77
+ async function roleFiles(dir) {
78
+ const entries = await fsp.readdir(dir).catch(() => []);
79
+ return entries.filter((name) => name.endsWith('.toml')).sort().map((name) => path.join(dir, name));
80
+ }
81
+ export async function reconcileStaleSksModelPins(input) {
82
+ const root = path.resolve(input.root);
83
+ const codexHome = path.resolve(input.codexHome);
84
+ const pinState = await catalogPinState(codexHome);
85
+ const report = {
86
+ schema: MODEL_PIN_HYGIENE_SCHEMA,
87
+ fix: input.fix,
88
+ catalog_available: pinState !== null,
89
+ changes: [],
90
+ remaining: [],
91
+ errors: []
92
+ };
93
+ const projectConfig = path.join(root, '.codex', 'config.toml');
94
+ const projectText = projectConfig !== path.join(codexHome, 'config.toml') && await regularFile(projectConfig)
95
+ ? await readText(projectConfig, '')
96
+ : null;
97
+ const providerDefinedAbove = hasCodexLbProviderTable(await readText(path.join(codexHome, 'config.toml'), ''))
98
+ || (projectText !== null && hasCodexLbProviderTable(projectText));
99
+ const agentDirs = [...new Set([path.join(codexHome, 'agents'), path.join(root, '.codex', 'agents')])];
100
+ for (const dir of agentDirs) {
101
+ for (const file of await roleFiles(dir)) {
102
+ if (!(await regularFile(file)))
103
+ continue;
104
+ const text = await readText(file, '');
105
+ if (!isLegacySksRole(file, text))
106
+ continue;
107
+ const pins = stalePinLines(text, pinState, providerDefinedAbove || hasCodexLbProviderTable(text));
108
+ if (!pins.indexes.length)
109
+ continue;
110
+ if (!input.fix) {
111
+ report.remaining.push({ file, removed: pins.labels, backup_path: null });
112
+ continue;
113
+ }
114
+ try {
115
+ const backup = await backupInvalidToml(file, text, 'model-pin-hygiene');
116
+ const mode = (await fsp.stat(file)).mode & 0o777;
117
+ await writeTextAtomic(file, withoutLines(text, pins.indexes), { mode });
118
+ report.changes.push({ file, removed: pins.labels, backup_path: backup });
119
+ }
120
+ catch (error) {
121
+ report.errors.push(`${file}: ${error instanceof Error ? error.message : String(error)}`);
122
+ report.remaining.push({ file, removed: pins.labels, backup_path: null });
123
+ }
124
+ }
125
+ }
126
+ if (projectText !== null) {
127
+ const text = projectText;
128
+ const pins = sksOwnedProjectConfig(text) ? stalePinLines(text, pinState, providerDefinedAbove) : { indexes: [], labels: [] };
129
+ if (pins.indexes.length && !input.fix)
130
+ report.remaining.push({ file: projectConfig, removed: pins.labels, backup_path: null });
131
+ else if (pins.indexes.length) {
132
+ const write = await writeCodexConfigGuarded({
133
+ root,
134
+ configPath: projectConfig,
135
+ before: text,
136
+ mutate: () => withoutLines(text, pins.indexes),
137
+ cause: 'model-pin-hygiene',
138
+ backupTag: 'model-pin-hygiene',
139
+ verifyUnchangedBeforeWrite: true
140
+ });
141
+ if (write.ok)
142
+ report.changes.push({ file: projectConfig, removed: pins.labels, backup_path: write.backup_path });
143
+ else {
144
+ report.errors.push(`${projectConfig}: ${write.status}`);
145
+ report.remaining.push({ file: projectConfig, removed: pins.labels, backup_path: null });
146
+ }
147
+ }
148
+ }
149
+ return report;
150
+ }