sneakoscope 8.6.5 → 8.7.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 (86) hide show
  1. package/README.md +1 -1
  2. package/config/skills-hash-ledger.v1.json +0 -14
  3. package/crates/sks-core/Cargo.lock +1 -1
  4. package/crates/sks-core/Cargo.toml +1 -1
  5. package/dist/cli/command-manifest-lite.js +0 -1
  6. package/dist/cli/command-registry.js +0 -1
  7. package/dist/commands/doctor.js +28 -24
  8. package/dist/config/skills-manifest.json +1 -19
  9. package/dist/core/agents/agent-orchestrator.js +3 -11
  10. package/dist/core/agents/agent-output-validator.js +1 -2
  11. package/dist/core/agents/agent-patch-schema.js +1 -2
  12. package/dist/core/agents/agent-proof-evidence.js +14 -19
  13. package/dist/core/agents/agent-recursion-guard.js +1 -1
  14. package/dist/core/agents/agent-schema.js +1 -1
  15. package/dist/core/agents/native-cli-worker-runtime.js +0 -4
  16. package/dist/core/agents/native-cli-worker.js +1 -1
  17. package/dist/core/agents/native-worker-backend-router.js +9 -64
  18. package/dist/core/codex-control/codex-control-proof.js +0 -1
  19. package/dist/core/codex-control/codex-task-runner.js +2 -118
  20. package/dist/core/codex-control/gpt-final-arbiter.js +11 -20
  21. package/dist/core/codex-control/gpt-final-gate.js +31 -0
  22. package/dist/core/codex-control/gpt-final-proof-pack.js +8 -9
  23. package/dist/core/codex-control/model-call-concurrency.js +0 -2
  24. package/dist/core/codex-lb/combined-catalog/contracts.js +1 -0
  25. package/dist/core/codex-lb/desktop-bridge/server.js +10 -3
  26. package/dist/core/codex-lb/desktop-bridge/websocket-forward.js +1 -1
  27. package/dist/core/codex-lb/desktop-bridge-migration.js +9 -1
  28. package/dist/core/codex-lb/desktop-controller-v3/catalog.js +2 -1
  29. package/dist/core/codex-lb/desktop-controller-v3/status.js +12 -3
  30. package/dist/core/commands/intent-normalization/normalizer.js +0 -2
  31. package/dist/core/commands/run-command.js +1 -30
  32. package/dist/core/doctor/doctor-dirty-planner.js +4 -0
  33. package/dist/core/doctor/doctor-readiness-matrix.js +0 -34
  34. package/dist/core/feature-fixtures.js +0 -10
  35. package/dist/core/git-simple.js +2 -136
  36. package/dist/core/init/skills.js +0 -2
  37. package/dist/core/install/installed-package-smoke.js +1 -0
  38. package/dist/core/loops/loop-gpt-final-arbiter.js +1 -2
  39. package/dist/core/loops/loop-planner.js +1 -1
  40. package/dist/core/naruto/hardware-capacity-probe.js +0 -1
  41. package/dist/core/naruto/naruto-concurrency-governor.js +4 -8
  42. package/dist/core/naruto/naruto-verification-dag.js +0 -1
  43. package/dist/core/pipeline/finalize-pipeline-result.js +1 -4
  44. package/dist/core/pipeline/gpt-final-required.js +4 -10
  45. package/dist/core/qa-loop/qa-loop-budget-policy.js +0 -1
  46. package/dist/core/release/release-gate-batch-runner.js +1 -1
  47. package/dist/core/release/release-gate-node.js +0 -1
  48. package/dist/core/release/release-gate-resource-governor.js +0 -1
  49. package/dist/core/research/research-claim-synthesizer.js +0 -2
  50. package/dist/core/research/research-falsification-runner.js +0 -2
  51. package/dist/core/research/research-stage-runner.js +2 -7
  52. package/dist/core/research/research-super-search.js +0 -2
  53. package/dist/core/research/research-synthesis-writer.js +0 -2
  54. package/dist/core/router/capability-card.js +0 -13
  55. package/dist/core/router/route-cache.js +0 -2
  56. package/dist/core/router/ultra-router.js +1 -1
  57. package/dist/core/routes/dollar-manifest-lite.js +0 -4
  58. package/dist/core/routes.js +0 -19
  59. package/dist/core/skills/skill-agent-metadata.js +0 -2
  60. package/dist/core/version.js +1 -1
  61. package/dist/scripts/gate-policy-audit-check.js +2 -2
  62. package/dist/scripts/{local-collab-all-pipelines-final-gpt-check.js → gpt-final-all-pipelines-check.js} +5 -6
  63. package/dist/scripts/qa-loop-budget-policy-check.js +1 -1
  64. package/package.json +2 -2
  65. package/release-gates.v2.json +3 -3
  66. package/schemas/codex/agent-result.schema.json +1 -6
  67. package/schemas/naruto/naruto-concurrency-governor.schema.json +0 -1
  68. package/schemas/release/release-gate-node.schema.json +1 -1
  69. package/dist/core/agents/agent-runner-ollama.js +0 -416
  70. package/dist/core/agents/ollama-worker-config.js +0 -266
  71. package/dist/core/commands/local-model-command.js +0 -165
  72. package/dist/core/local-llm/local-collaboration-policy.js +0 -92
  73. package/dist/core/local-llm/local-llm-backpressure.js +0 -19
  74. package/dist/core/local-llm/local-llm-capability.js +0 -28
  75. package/dist/core/local-llm/local-llm-client.js +0 -99
  76. package/dist/core/local-llm/local-llm-context-cache.js +0 -20
  77. package/dist/core/local-llm/local-llm-control-adapter.js +0 -100
  78. package/dist/core/local-llm/local-llm-json-repair.js +0 -51
  79. package/dist/core/local-llm/local-llm-metrics.js +0 -41
  80. package/dist/core/local-llm/local-llm-ollama-client.js +0 -66
  81. package/dist/core/local-llm/local-llm-openai-compatible-client.js +0 -29
  82. package/dist/core/local-llm/local-llm-schema-enforcer.js +0 -14
  83. package/dist/core/local-llm/local-llm-smoke.js +0 -82
  84. package/dist/core/local-llm/local-worker-eligibility.js +0 -26
  85. package/schemas/local-llm/local-collaboration-policy.schema.json +0 -57
  86. package/schemas/local-llm/local-model-config.schema.json +0 -74
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.6.5** — 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.7.0** — 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
 
@@ -389,20 +389,6 @@
389
389
  "16b2b813d202ca51d2ea4fe0da918eddf9494db7ab1356352d4188a5da3496b1"
390
390
  ]
391
391
  },
392
- {
393
- "canonical_name": "sks-with-local-llm-off",
394
- "trusted_sha256": [
395
- "4609c43a671c649b2574aebf035e0e8200b29bb893d176567e92f14d2f3aa92c",
396
- "86d3a860b438c91c2a5b4cc8ac9c8e7477008f9b689602ddcf14a9e3b759923d"
397
- ]
398
- },
399
- {
400
- "canonical_name": "sks-with-local-llm-on",
401
- "trusted_sha256": [
402
- "11da3f94d77b0f9fe76dee2e99d058cf1495fdc4eaf3e2fb6e43dae66f7d2cd3",
403
- "27e1ff08b95428d6b623d06358d5d114ff02673a5c97d8f180dd75859682cd6c"
404
- ]
405
- },
406
392
  {
407
393
  "canonical_name": "sks-work",
408
394
  "trusted_sha256": [
@@ -259,7 +259,7 @@ dependencies = [
259
259
 
260
260
  [[package]]
261
261
  name = "sks-core"
262
- version = "8.6.5"
262
+ version = "8.7.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 = "8.6.5"
3
+ version = "8.7.0"
4
4
  edition = "2021"
5
5
 
6
6
  [dependencies]
@@ -47,7 +47,6 @@ const COMMAND_MANIFEST_LITE_BASE = [
47
47
  { name: 'commit', summary: 'Create a simple git commit', maturity: 'stable' },
48
48
  { name: 'commit-and-push', summary: 'Create a simple git commit and push', maturity: 'stable' },
49
49
  { name: 'dfix', summary: 'Run DFix diagnose/plan/patch/verify loop', maturity: 'stable', mutatesRouteState: true },
50
- { name: 'with-local-llm', summary: 'Enable or inspect local Ollama worker backend', maturity: 'beta' },
51
50
  { name: 'naruto', summary: 'Run the $sks-naruto Codex official subagent workflow', maturity: 'labs', mutatesRouteState: true },
52
51
  { name: 'stop-gate', summary: 'Check canonical stop-gate resolution for a route/mission', maturity: 'beta', readonly: true, skipMigrationGate: true, allowedDuringActiveRoute: true, diagnostic: true },
53
52
  { name: 'route', summary: 'Inspect or close active route state', maturity: 'beta', skipMigrationGate: true, allowedDuringActiveRoute: true, diagnostic: true },
@@ -195,7 +195,6 @@ const COMMAND_DEFINITIONS = {
195
195
  commit: entry('stable', 'Create a simple git commit', 'dist/commands/commit.js', directCommand(() => import('../commands/commit.js'), 'dist/commands/commit.js')),
196
196
  'commit-and-push': entry('stable', 'Create a simple git commit and push', 'dist/commands/commit-and-push.js', directCommand(() => import('../commands/commit-and-push.js'), 'dist/commands/commit-and-push.js')),
197
197
  dfix: routeStateMutator(entry('stable', 'Run DFix diagnose/plan/patch/verify loop', 'dist/core/commands/dfix-command.js', commandArgsCommand(() => import('../core/commands/dfix-command.js'), 'dfixCommand', 'dist/core/commands/dfix-command.js')), ['dfix-gate.json']),
198
- 'with-local-llm': entry('beta', 'Enable or inspect local Ollama worker backend', 'dist/core/commands/local-model-command.js', argsCommand(() => import('../core/commands/local-model-command.js'), 'localModelCommand', 'dist/core/commands/local-model-command.js')),
199
198
  naruto: routeStateMutator(entry('labs', 'Run the $sks-naruto Codex official subagent workflow', 'dist/core/commands/naruto-command.js', argsCommand(() => import('../core/commands/naruto-command.js'), 'narutoCommand', 'dist/core/commands/naruto-command.js')), ['naruto-gate.json', 'stop-gate.json']),
200
199
  'stop-gate': readOnly(entry('beta', 'Check canonical stop-gate resolution for a route/mission', 'dist/core/commands/stop-gate-command.js', commandArgsCommand(() => import('../core/commands/stop-gate-command.js'), 'stopGateCommand', 'dist/core/commands/stop-gate-command.js'))),
201
200
  route: activeRouteDiagnostic(entry('beta', 'Inspect or close active route state', 'dist/core/commands/route-command.js', subcommand(() => import('../core/commands/route-command.js'), 'routeCommand', 'dist/core/commands/route-command.js', 'status'))),
@@ -15,7 +15,6 @@ import { inspectCodexConfigReadability } from '../core/codex/codex-config-readab
15
15
  import { inspectOAuthCallbackPortConflict, oauthCallbackDoctorGuidance } from '../core/codex/oauth-callback-port-diagnostic.js';
16
16
  import { inventoryCodexPermissionProfiles } from '../core/codex/codex-permission-profiles.js';
17
17
  import { resolveProviderContext } from '../core/provider/provider-context.js';
18
- import { readLocalModelConfig } from '../core/agents/ollama-worker-config.js';
19
18
  import { writeCodexCurrentAppCapabilityArtifacts } from '../core/codex-control/codex-current-app-capability.js';
20
19
  import { writeCodexPluginInventoryArtifacts, pluginAppTemplatePolicy } from '../core/codex-plugins/codex-plugin-json.js';
21
20
  import { writeMcpPluginInventoryArtifacts } from '../core/mcp/mcp-plugin-inventory.js';
@@ -59,6 +58,7 @@ export async function restartStaleDesktopBridgeRuntime(input) {
59
58
  ? { restarted: true, warnings: [`desktop_bridge_runtime_restarted:${running}:${PACKAGE_VERSION}`], blockers: [] }
60
59
  : { restarted: false, warnings: [], blockers: [`desktop_bridge_runtime_version_stale:${running}:${PACKAGE_VERSION}`] };
61
60
  }
61
+ export const CATALOG_REPAIR_MAX_ATTEMPTS = 2;
62
62
  export function deferCommandAliasCleanupToMigrationReceipt(result) {
63
63
  const observedBlockers = Array.isArray(result?.blockers)
64
64
  ? result.blockers.map(String).filter(Boolean)
@@ -443,7 +443,6 @@ async function runDoctorJsonFastPath(args = [], root) {
443
443
  doctor_fix_transaction: null,
444
444
  doctor_fix_postcheck: null,
445
445
  postcheck: null,
446
- local_model: null,
447
446
  agent_role_config: { schema: 'sks.agent-role-config-repair.v1', ok: true, apply: false, skipped: true, blockers: [] },
448
447
  codex_permission_profiles: { skipped: true, reason: 'doctor_json_fast_path_optional_diagnostics_skipped' },
449
448
  command_aliases: { schema: 'sks.command-alias-cleanup.v1', ok: true, skipped: true, reason: 'doctor_json_fast_path_no_write' },
@@ -668,7 +667,7 @@ async function runDoctor(args = [], root, doctorFix, deps = {}) {
668
667
  const codexApp = deepDiagnostics
669
668
  ? await codexAppIntegrationStatus({ codex }).catch((err) => ({ ok: false, error: err.message }))
670
669
  : { ok: false, skipped: true, warnings: ['codex_app_optional_diagnostic_skipped'] };
671
- const desktopBridge = await inspectDoctorDesktopBridgeStatus({
670
+ const desktopBridgeBeforeFix = await inspectDoctorDesktopBridgeStatus({
672
671
  processEnv: process.env
673
672
  }, { desktopBridgeStatusImpl: deps.desktopBridgeStatusImpl });
674
673
  const providerContext = deepDiagnostics
@@ -1033,11 +1032,12 @@ async function runDoctor(args = [], root, doctorFix, deps = {}) {
1033
1032
  rollback_evidence: 'combined_catalog_previous_generation_preserved'
1034
1033
  };
1035
1034
  try {
1035
+ const bridgeHome = path.resolve(process.env.HOME || os.homedir());
1036
1036
  const restarted = await restartStaleDesktopBridgeRuntime({
1037
- home: path.resolve(process.env.HOME || os.homedir()),
1037
+ home: bridgeHome,
1038
1038
  fix: doctorFix,
1039
1039
  });
1040
- const status = await desktopBridgeStatusV3({ home: root, env: process.env });
1040
+ const status = await desktopBridgeStatusV3({ home: bridgeHome, env: process.env });
1041
1041
  const blockers = (status?.readiness?.blockers || []).map(String);
1042
1042
  const stale = blockers.filter((blocker) => blocker.endsWith('_catalog_stale'));
1043
1043
  if (!status?.management?.managed || stale.length === 0) {
@@ -1049,15 +1049,27 @@ async function runDoctor(args = [], root, doctorFix, deps = {}) {
1049
1049
  blockers: restarted.blockers
1050
1050
  };
1051
1051
  }
1052
- const sync = await executeDesktopBridgeCommandV3({ operation: 'catalog.sync' }, { home: root, env: process.env });
1053
- const synced = sync?.ok === true && sync?.execution?.ok === true;
1052
+ const attempts = [];
1053
+ let syncedAndVerified = false;
1054
+ for (let attempt = 1; attempt <= CATALOG_REPAIR_MAX_ATTEMPTS; attempt += 1) {
1055
+ const sync = await executeDesktopBridgeCommandV3({ operation: 'catalog.sync' }, { home: bridgeHome, env: process.env });
1056
+ const commandOk = sync?.ok === true && sync?.execution?.ok === true;
1057
+ const after = await desktopBridgeStatusV3({ home: bridgeHome, env: process.env });
1058
+ const stillStale = (after?.readiness?.blockers || [])
1059
+ .map(String).filter((blocker) => blocker.endsWith('_catalog_stale'));
1060
+ if (commandOk && stillStale.length === 0) {
1061
+ syncedAndVerified = true;
1062
+ break;
1063
+ }
1064
+ attempts.push(`catalog_sync_attempt_${attempt}:${commandOk ? `still_stale:${stillStale.join(',')}` : (sync?.execution?.blockers || ['failed']).map(String).join(',')}`);
1065
+ }
1054
1066
  return {
1055
1067
  ...base,
1056
- ok: synced && restarted.blockers.length === 0,
1057
- repaired: synced || restarted.restarted,
1058
- warnings: restarted.warnings,
1068
+ ok: syncedAndVerified && restarted.blockers.length === 0,
1069
+ repaired: syncedAndVerified || restarted.restarted,
1070
+ warnings: [...restarted.warnings, ...(syncedAndVerified ? attempts : [])],
1059
1071
  blockers: [
1060
- ...(synced ? [] : (sync?.execution?.blockers || ['desktop_bridge_catalog_sync_failed']).map(String)),
1072
+ ...(syncedAndVerified ? [] : ['desktop_bridge_catalog_still_stale_after_repair', ...attempts]),
1061
1073
  ...restarted.blockers
1062
1074
  ]
1063
1075
  };
@@ -1092,7 +1104,11 @@ async function runDoctor(args = [], root, doctorFix, deps = {}) {
1092
1104
  }))
1093
1105
  : null;
1094
1106
  const doctorFixPostcheck = doctorFix ? (await import('../core/doctor/doctor-repair-postcheck.js')).doctorRepairPostcheck(doctorFixTransaction) : null;
1095
- const localModel = await readLocalModelConfig().catch(() => null);
1107
+ const desktopBridge = doctorFixTransaction
1108
+ ? await inspectDoctorDesktopBridgeStatus({
1109
+ processEnv: process.env
1110
+ }, { desktopBridgeStatusImpl: deps.desktopBridgeStatusImpl })
1111
+ : desktopBridgeBeforeFix;
1096
1112
  const permissionProfiles = await inventoryCodexPermissionProfiles(root, { writeReport: true });
1097
1113
  const startupRoleRepair = startupConfigRepair?.role_repair;
1098
1114
  const agentRoleConfigRepair = doctorFix && startupRoleRepair
@@ -1355,7 +1371,6 @@ async function runDoctor(args = [], root, doctorFix, deps = {}) {
1355
1371
  require_legacy_global_hook_cleanup: requireLegacyGlobalHookCleanup,
1356
1372
  require_legacy_generation_convergence: doctorFix && !migrationReceiptOwnsReconcile,
1357
1373
  skills: skillsReconcile,
1358
- local_model: localModel,
1359
1374
  agent_role_config: agentRoleConfigRepair,
1360
1375
  repair: configRepair,
1361
1376
  codex_app_ui: codexAppUi,
@@ -1532,7 +1547,6 @@ async function runDoctor(args = [], root, doctorFix, deps = {}) {
1532
1547
  required_blockers: doctorFixPostcheck.required_blockers || [],
1533
1548
  optional_warnings: doctorFixPostcheck.optional_warnings || []
1534
1549
  } : null,
1535
- local_model: localModel,
1536
1550
  agent_role_config: agentRoleConfigRepair,
1537
1551
  official_subagent_config: officialSubagentConfig,
1538
1552
  codex_permission_profiles: permissionProfiles,
@@ -1790,16 +1804,6 @@ async function runDoctor(args = [], root, doctorFix, deps = {}) {
1790
1804
  if (!desktopBridge.ok)
1791
1805
  for (const action of desktopBridge.recovery_actions || [])
1792
1806
  console.log(` action: ${action}`);
1793
- if (localModel) {
1794
- console.log('Local LLM:');
1795
- console.log(` enabled: ${localModel.enabled ? 'yes' : 'no'}`);
1796
- console.log(` status: ${localModel.status}`);
1797
- console.log(` provider: ${localModel.provider}`);
1798
- console.log(` model: ${localModel.model}`);
1799
- console.log(` endpoint: ${localModel.base_url}`);
1800
- console.log(` last smoke: ${localModel.last_smoke?.ok ? `ok ${localModel.last_smoke.latency_ms || 0}ms ${localModel.last_smoke.tokens_per_second || 0} tok/s` : 'missing'}`);
1801
- console.log(' final arbiter: GPT required');
1802
- }
1803
1807
  console.log(`Permissions: config profile and permission profile are tracked separately (${permissionProfiles.codex_config_profile_field}, ${permissionProfiles.codex_permission_profile_field})`);
1804
1808
  console.log('Ready:');
1805
1809
  console.log(` cli_ready: ${ready.cli_ready ? 'yes' : 'no'}`);
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "schema": "sks.skills-manifest.v1",
3
- "package_version": "8.6.5",
3
+ "package_version": "8.7.0",
4
4
  "skills": [
5
5
  {
6
6
  "canonical_name": "sks",
@@ -485,24 +485,6 @@
485
485
  ],
486
486
  "deprecated_aliases": []
487
487
  },
488
- {
489
- "canonical_name": "sks-with-local-llm-off",
490
- "type": "official",
491
- "content_sha256": "4609c43a671c649b2574aebf035e0e8200b29bb893d176567e92f14d2f3aa92c",
492
- "hash_history": [
493
- "86d3a860b438c91c2a5b4cc8ac9c8e7477008f9b689602ddcf14a9e3b759923d"
494
- ],
495
- "deprecated_aliases": []
496
- },
497
- {
498
- "canonical_name": "sks-with-local-llm-on",
499
- "type": "official",
500
- "content_sha256": "11da3f94d77b0f9fe76dee2e99d058cf1495fdc4eaf3e2fb6e43dae66f7d2cd3",
501
- "hash_history": [
502
- "27e1ff08b95428d6b623d06358d5d114ff02673a5c97d8f180dd75859682cd6c"
503
- ],
504
- "deprecated_aliases": []
505
- },
506
488
  {
507
489
  "canonical_name": "sks-work",
508
490
  "type": "official",
@@ -43,7 +43,6 @@ import { createNativeCliWorkerRuntimeRecorder } from './native-cli-worker-runtim
43
43
  import { writeNativeCliWorkerRuntimeProof } from './native-cli-worker-runtime-proof.js';
44
44
  import { writeNoSubagentScalingPolicy } from './no-subagent-scaling-policy.js';
45
45
  import { writeOfficialSubagentHelperPolicy } from './official-subagent-helper-policy.js';
46
- import { resolveLocalCollaborationPolicy, localCollaborationParticipated } from '../local-llm/local-collaboration-policy.js';
47
46
  import { runFinalGptReviewStage } from '../pipeline/final-gpt-review-stage.js';
48
47
  import { selectFinalGptPatchSource } from '../pipeline/final-gpt-patch-stage.js';
49
48
  import { allocateWorkerWorktree, allocateWorkerWorktreesBatch } from '../git/git-worktree-manager.js';
@@ -334,7 +333,6 @@ export async function runNativeAgentOrchestrator(opts = {}) {
334
333
  targetActiveSlots,
335
334
  backend,
336
335
  backendExplicit: opts.backendExplicit === true,
337
- noOllama: opts.noOllama === true,
338
336
  route,
339
337
  fastModePolicy,
340
338
  projectRoot: root
@@ -496,20 +494,16 @@ export async function runNativeAgentOrchestrator(opts = {}) {
496
494
  const officialSubagentHelperPolicy = await writeOfficialSubagentHelperPolicy(ledgerRoot, { nativeProof: nativeCliWorkerRuntimeProof });
497
495
  const noSubagentScalingPolicy = await writeNoSubagentScalingPolicy(ledgerRoot, { nativeProof: nativeCliWorkerRuntimeProof, officialSubagentHelperPolicy });
498
496
  const fastModePropagation = await writeFastModePropagationProof(ledgerRoot, { policy: fastModePolicy, backend, results });
499
- const localCollaborationPolicy = resolveLocalCollaborationPolicy();
500
- await writeJsonAtomic(path.join(ledgerRoot, 'local-collaboration-policy.json'), localCollaborationPolicy);
501
- const localParticipated = localCollaborationParticipated(results);
502
497
  const candidatePatchEnvelopes = results.flatMap((result) => Array.isArray(result.patch_envelopes) ? result.patch_envelopes : []);
503
498
  const worktreeParticipated = candidatePatchEnvelopes.some((envelope) => envelope?.source === 'git-worktree-diff' || envelope?.git_worktree?.worktree_path)
504
499
  || results.some((result) => result?.git_worktree_diff || result?.git_worktree_checkpoint);
505
- const gptFinalRequired = localParticipated || worktreeParticipated;
500
+ const gptFinalRequired = worktreeParticipated;
506
501
  const gptFinalArbiter = gptFinalRequired
507
502
  ? await runFinalGptReviewStage({
508
503
  schema: 'sks.gpt-final-arbiter-input.v1',
509
504
  route,
510
505
  mission_id: missionId,
511
- local_mode: localCollaborationPolicy.mode,
512
- local_outputs: results.map((result) => ({
506
+ candidate_outputs: results.map((result) => ({
513
507
  worker_id: result.agent_id,
514
508
  backend: result.backend_router_report?.selected_backend || result.backend || backend,
515
509
  status: result.status,
@@ -607,7 +601,6 @@ export async function runNativeAgentOrchestrator(opts = {}) {
607
601
  gitWorktreeRuntime,
608
602
  triwikiContext,
609
603
  selectedCoreSkill,
610
- localCollaborationPolicy,
611
604
  gptFinalArbiter,
612
605
  finalGptPatchStage
613
606
  });
@@ -651,7 +644,6 @@ export async function runNativeAgentOrchestrator(opts = {}) {
651
644
  fast_mode_policy: fastModePolicy,
652
645
  fast_mode_propagation: fastModePropagation,
653
646
  git_worktree_runtime: gitWorktreeRuntime,
654
- local_collaboration_policy: localCollaborationPolicy,
655
647
  gpt_final_arbiter: gptFinalArbiter,
656
648
  final_gpt_patch_stage: finalGptPatchStage,
657
649
  patch_handoff: patchHandoff,
@@ -1089,7 +1081,7 @@ function sameTournamentGroupEntry(a, b) {
1089
1081
  function attachNarutoRuntimeProof(result, agent, slice) {
1090
1082
  const controlPlane = result?.codex_child_report || result?.codex_sdk_thread || result?.backend_router_report || null;
1091
1083
  const selectedBackend = String(result?.backend_router_report?.selected_backend || result?.backend || '');
1092
- const actualWorkerControlPlane = selectedBackend === 'codex-sdk' || selectedBackend === 'local-llm'
1084
+ const actualWorkerControlPlane = selectedBackend === 'codex-sdk'
1093
1085
  ? Boolean(controlPlane?.sdk_thread_id || controlPlane?.worker_result_path || result?.codex_child_report?.worker_result_path)
1094
1086
  : false;
1095
1087
  result.naruto_runtime = {
@@ -34,7 +34,7 @@ export const AGENT_RESULT_RUNTIME_SCHEMA = {
34
34
  task_slice_id: { type: 'string' },
35
35
  work_item_kind: { type: 'string' },
36
36
  status: { enum: ['done', 'blocked', 'failed'] },
37
- backend: { enum: ['fake', 'process', 'codex-sdk', 'python-codex-sdk', 'ollama', 'local-llm'] },
37
+ backend: { enum: ['fake', 'process', 'codex-sdk', 'python-codex-sdk'] },
38
38
  summary: { type: 'string' },
39
39
  findings: { type: 'array', items: { type: 'string' } },
40
40
  proposed_changes: { type: 'array', items: { type: 'string' } },
@@ -93,7 +93,6 @@ export const AGENT_RESULT_RUNTIME_SCHEMA = {
93
93
  worker_process_id: { type: 'number' },
94
94
  backend_child_process_id: { type: 'number' },
95
95
  backend_sdk_thread_id: { type: 'string' },
96
- backend_ollama_request_id: { type: 'string' },
97
96
  fast_mode: { type: 'boolean' },
98
97
  service_tier: { enum: ['fast', 'standard'] },
99
98
  lease_id: { type: 'string' },
@@ -17,7 +17,6 @@ export function normalizeAgentPatchEnvelope(input) {
17
17
  ...(hasFiniteNumber(input?.worker_process_id) ? { worker_process_id: Number(input.worker_process_id) } : {}),
18
18
  ...(hasFiniteNumber(input?.backend_child_process_id) ? { backend_child_process_id: Number(input.backend_child_process_id) } : {}),
19
19
  ...(input?.backend_sdk_thread_id ? { backend_sdk_thread_id: String(input.backend_sdk_thread_id) } : {}),
20
- ...(input?.backend_ollama_request_id ? { backend_ollama_request_id: String(input.backend_ollama_request_id) } : {}),
21
20
  ...(input?.fast_mode === undefined ? {} : { fast_mode: Boolean(input.fast_mode) }),
22
21
  ...(input?.service_tier === 'fast' || input?.service_tier === 'standard' ? { service_tier: input.service_tier } : {}),
23
22
  ...(input?.lease_id ? { lease_id: String(input.lease_id) } : {}),
@@ -57,7 +56,7 @@ export function validateAgentPatchEnvelope(envelope) {
57
56
  violations.push('operations_missing');
58
57
  if (envelope.source && !['fixture', 'model_authored', 'process_generated', 'git-worktree-diff'].includes(envelope.source))
59
58
  violations.push('source_invalid');
60
- if (envelope.source === 'model_authored' && !hasFiniteNumber(envelope.backend_child_process_id) && !envelope.backend_sdk_thread_id && !envelope.backend_ollama_request_id)
59
+ if (envelope.source === 'model_authored' && !hasFiniteNumber(envelope.backend_child_process_id) && !envelope.backend_sdk_thread_id)
61
60
  violations.push('model_authored_backend_proof_missing');
62
61
  if (envelope.source === 'fixture' && envelope.backend_child_process_id !== undefined)
63
62
  violations.push('fixture_backend_child_process_id_present');
@@ -7,7 +7,8 @@ import { assertAgentTerminalSessionsClosed } from './agent-terminal-session.js';
7
7
  import { assertAgentSessionGenerationsClosed } from './agent-session-generation.js';
8
8
  import { writeFakeRealProofPolicyReport } from '../proof/fake-real-proof-policy.js';
9
9
  import { buildRuntimeTruthMatrix, writeRuntimeTruthMatrix } from '../proof/runtime-truth-matrix.js';
10
- import { evaluateLocalCollaborationFinalGate, localCollaborationParticipated, resolveLocalCollaborationPolicy } from '../local-llm/local-collaboration-policy.js';
10
+ import { evaluateGptFinalGate } from '../codex-control/gpt-final-gate.js';
11
+ import { gptFinalRequiredForPipeline } from '../pipeline/gpt-final-required.js';
11
12
  export async function writeAgentProofEvidence(root, input) {
12
13
  const lifecycle = await assertAllAgentSessionsClosed(root);
13
14
  const terminal = await assertAgentTerminalSessionsClosed(root);
@@ -26,22 +27,18 @@ export async function writeAgentProofEvidence(root, input) {
26
27
  const patchRollbackProof = await readJson(path.join(root, 'agent-patch-rollback-proof.json'), null);
27
28
  const patchProof = await readJson(path.join(root, 'agent-patch-proof.json'), null);
28
29
  const patchHandoff = input.patchHandoff || await readJson(path.join(root, 'agent-patch-handoff-runtime.json'), null);
29
- const localCollaborationPolicy = input.localCollaborationPolicy || await readJson(path.join(root, 'local-collaboration-policy.json'), null) || resolveLocalCollaborationPolicy();
30
30
  const gptFinalArbiter = input.gptFinalArbiter || await readJson(path.join(root, 'gpt-final-arbiter', 'gpt-final-arbiter.json'), null);
31
31
  const narutoWorkGraph = await readJson(path.join(root, 'naruto-work-graph.json'), null);
32
32
  const narutoRoleDistribution = await readJson(path.join(root, 'naruto-role-distribution.json'), null);
33
33
  const narutoConcurrencyGovernor = await readJson(path.join(root, 'naruto-concurrency-governor.json'), null);
34
34
  const narutoActivePool = await readJson(path.join(root, 'naruto-active-pool.json'), null);
35
35
  const narutoVerificationDag = await readJson(path.join(root, 'naruto-verification-dag.json'), null);
36
- const localParticipated = localCollaborationParticipated(input.results || []) || Number(gptFinalArbiter?.local_outputs_count || 0) > 0;
36
+ const gptFinalRequired = gptFinalRequiredForPipeline({ candidateResults: input.results || [] }).gpt_final_required;
37
37
  const finalGptPatchStage = input.finalGptPatchStage || null;
38
- const localFinalGate = gptFinalArbiter?.final_gate || evaluateLocalCollaborationFinalGate({
39
- policy: localCollaborationPolicy,
40
- localParticipated,
38
+ const gptFinalGate = gptFinalArbiter?.final_gate || evaluateGptFinalGate({
39
+ required: gptFinalRequired,
41
40
  gptFinalStatus: gptFinalArbiter?.result?.status || null,
42
- gptFinalAvailable: Boolean(gptFinalArbiter),
43
- gptFinalBackend: gptFinalArbiter?.backend || null,
44
- applyPatches: parallelWritePolicy?.apply_patches === true
41
+ gptFinalAvailable: Boolean(gptFinalArbiter)
45
42
  });
46
43
  const nativeCliWorkerRuntimeProof = input.nativeCliWorkerRuntimeProof || await readJson(path.join(root, 'native-cli-worker-runtime-proof.json'), null);
47
44
  const noSubagentScalingPolicy = input.noSubagentScalingPolicy || await readJson(path.join(root, 'no-subagent-scaling-policy.json'), null);
@@ -173,9 +170,9 @@ export async function writeAgentProofEvidence(root, input) {
173
170
  ...(patchHandoff && !patchApplyOk ? ['patch_apply_not_ok'] : []),
174
171
  ...(patchHandoff && !patchVerificationOk ? ['patch_verification_not_ok'] : []),
175
172
  ...(patchHandoff && !patchRollbackOk ? ['patch_rollback_not_ok'] : []),
176
- ...(localParticipated && localFinalGate.ok !== true ? localFinalGate.blockers || ['gpt_final_arbiter_gate_not_ok'] : []),
177
- ...(localParticipated && gptFinalArbiter?.ok !== true ? gptFinalArbiter?.blockers || ['gpt_final_arbiter_not_ok'] : []),
178
- ...(localParticipated && finalGptPatchStage?.ok === false ? finalGptPatchStage.blockers || ['final_gpt_patch_stage_not_ok'] : []),
173
+ ...(gptFinalRequired && gptFinalGate.ok !== true ? gptFinalGate.blockers || ['gpt_final_arbiter_gate_not_ok'] : []),
174
+ ...(gptFinalRequired && gptFinalArbiter?.ok !== true ? gptFinalArbiter?.blockers || ['gpt_final_arbiter_not_ok'] : []),
175
+ ...(gptFinalRequired && finalGptPatchStage?.ok === false ? finalGptPatchStage.blockers || ['final_gpt_patch_stage_not_ok'] : []),
179
176
  ...(isNarutoRoute && !narutoWorkGraph ? ['naruto_work_graph_missing'] : []),
180
177
  ...(isNarutoRoute && narutoWorkGraph?.ok === false ? narutoWorkGraph.blockers || ['naruto_work_graph_not_ok'] : []),
181
178
  ...(isNarutoRoute && !narutoRoleDistribution ? ['naruto_role_distribution_missing'] : []),
@@ -236,15 +233,13 @@ export async function writeAgentProofEvidence(root, input) {
236
233
  parallel_write_apply_patches: parallelWritePolicy?.apply_patches === true,
237
234
  parallel_write_dry_run_patches: parallelWritePolicy?.dry_run_patches === true,
238
235
  parallel_write_max_write_agents: Number(parallelWritePolicy?.max_write_agents || 0),
239
- local_collaboration_policy: 'local-collaboration-policy.json',
240
- local_collaboration_mode: localCollaborationPolicy.mode || null,
241
- local_collaboration_participated: localParticipated,
242
236
  gpt_final_arbiter: gptFinalArbiter ? 'gpt-final-arbiter/gpt-final-arbiter.json' : null,
243
- gpt_final_status: gptFinalArbiter?.result?.status || (localParticipated ? 'missing' : 'not_required_no_local_outputs'),
237
+ gpt_final_required: gptFinalRequired,
238
+ gpt_final_status: gptFinalArbiter?.result?.status || (gptFinalRequired ? 'missing' : 'not_required_no_worktree_candidates'),
244
239
  gpt_final_backend: gptFinalArbiter?.backend || null,
245
- gpt_final_patch_source: finalGptPatchStage?.final_patch_source || (localParticipated ? 'blocked' : 'not_applicable'),
246
- gpt_final_gate_ok: localFinalGate.ok === true,
247
- gpt_final_gate: localFinalGate,
240
+ gpt_final_patch_source: finalGptPatchStage?.final_patch_source || (gptFinalRequired ? 'blocked' : 'not_applicable'),
241
+ gpt_final_gate_ok: gptFinalGate.ok === true,
242
+ gpt_final_gate: gptFinalGate,
248
243
  naruto_work_graph: narutoWorkGraph ? 'naruto-work-graph.json' : null,
249
244
  naruto_total_work_items: Number(narutoWorkGraph?.total_work_items || 0),
250
245
  naruto_mixed_work_kinds: narutoWorkGraph?.mixed_work_kinds || [],
@@ -399,7 +399,7 @@ function transcriptGroupForChannel(channel) {
399
399
  function isWorkerExecutionSurface(rel, channel) {
400
400
  if (channel === 'stdout' || channel === 'stderr' || channel === 'agent_result')
401
401
  return true;
402
- return /(?:^|\/)agent-worker-pipeline\.(?:ts|mjs|js)$/.test(rel) || /(?:^|\/)agent-runner-(?:process|ollama)\.(?:ts|mjs|js)$/.test(rel);
402
+ return /(?:^|\/)agent-worker-pipeline\.(?:ts|mjs|js)$/.test(rel) || /(?:^|\/)agent-runner-process\.(?:ts|mjs|js)$/.test(rel);
403
403
  }
404
404
  function classifyNonRecursivePipelinePath(file) {
405
405
  const normalized = normalizePath(file);
@@ -12,7 +12,7 @@ export const OFFICIAL_SUBAGENT_EXECUTION_STAGE_ID = 'official_subagent_execution
12
12
  export const MAX_AGENT_COUNT = 20;
13
13
  export const DEFAULT_AGENT_CONCURRENCY = DEFAULT_NARUTO_MAX_THREADS;
14
14
  export const HARD_AGENT_CONCURRENCY = HARD_NARUTO_MAX_THREADS;
15
- export const AGENT_BACKENDS = ['fake', 'process', 'codex-sdk', 'ollama', 'local-llm'];
15
+ export const AGENT_BACKENDS = ['fake', 'process', 'codex-sdk'];
16
16
  export function normalizeAgentBackend(input) {
17
17
  const value = String(input || 'codex-sdk');
18
18
  return AGENT_BACKENDS.includes(value) ? value : null;
@@ -45,7 +45,6 @@ class NativeCliWorkerRuntimeRecorder {
45
45
  route: this.input.route,
46
46
  backend: this.input.backend,
47
47
  backend_explicit: this.input.backendExplicit === true,
48
- no_ollama: this.input.noOllama === true || ctx.opts.noOllama === true,
49
48
  agent_root: this.root,
50
49
  main_repo_root: worktree?.main_repo_root || ctx.opts.cwd || packageRoot(),
51
50
  cwd: workerCwd,
@@ -58,9 +57,6 @@ class NativeCliWorkerRuntimeRecorder {
58
57
  patch_envelope_path: patchRel,
59
58
  service_tier: this.input.fastModePolicy.service_tier,
60
59
  fast_mode: this.input.fastModePolicy.fast_mode,
61
- ollama_enabled: ctx.opts.ollamaEnabled === true || this.input.backend === 'ollama' || this.input.backend === 'local-llm',
62
- ollama_model: ctx.opts.ollamaModel || null,
63
- ollama_base_url: ctx.opts.ollamaBaseUrl || null,
64
60
  source_intelligence_refs: ctx.agent.source_intelligence_refs || null,
65
61
  goal_mode_ref: ctx.agent.goal_mode_ref || null,
66
62
  strategy_refs: ctx.slice?.strategy_refs || null,
@@ -206,7 +206,7 @@ export async function runNativeCliWorker(input = {}) {
206
206
  structured_output_valid: routed.report?.structured_output_valid === true,
207
207
  backend_router_report: routed.report,
208
208
  backend_child_process_ids: routed.report.child_process_ids,
209
- backend_child_execution: routed.report.child_process_ids.length > 0 || Boolean(routed.report?.sdk_thread_id) || backend === 'fake' || backend === 'ollama',
209
+ backend_child_execution: routed.report.child_process_ids.length > 0 || Boolean(routed.report?.sdk_thread_id) || backend === 'fake',
210
210
  recursion_guard_env: process.env.SKS_DISABLE_ROUTE_RECURSION === '1',
211
211
  worker_env: process.env.SKS_AGENT_WORKER === '1',
212
212
  fast_mode_report: {
@@ -2,8 +2,6 @@ import path from 'node:path';
2
2
  import { nowIso, readJson, writeJsonAtomic } from '../fsx.js';
3
3
  import { buildFixturePatchEnvelopes } from './agent-runner-fake.js';
4
4
  import { runProcessAgent } from './agent-runner-process.js';
5
- import { classifyOllamaWorkerSlice, runOllamaAgent } from './agent-runner-ollama.js';
6
- import { resolveOllamaWorkerConfig } from './ollama-worker-config.js';
7
5
  import { validateAgentWorkerResult } from './agent-worker-pipeline.js';
8
6
  import { normalizeAgentPatchEnvelope } from './agent-patch-schema.js';
9
7
  import { runCodexTask } from '../codex-control/codex-control-plane.js';
@@ -19,7 +17,6 @@ export async function runNativeWorkerBackendRouter(input) {
19
17
  const pathRoot = path.resolve(input.intake?.cwd || input.intake?.projectRoot || input.agentRoot);
20
18
  const requestedBackend = String(input.backend || '');
21
19
  let backend = normalizeBackend(requestedBackend);
22
- backend = await maybeAutoSelectOllamaBackend(backend, input);
23
20
  const narutoRequest = isNarutoWorkerRequest(input);
24
21
  const reportRel = path.join(input.workerDirRel, 'worker-backend-router-report.json');
25
22
  const startedAt = nowIso();
@@ -74,31 +71,7 @@ export async function runNativeWorkerBackendRouter(input) {
74
71
  verification: { status: processRun.status === 'done' ? 'passed' : 'failed', checks: [...(processRun.verification?.checks || []), 'native-worker-backend-router', 'process-child-execution'] }
75
72
  });
76
73
  }
77
- else if (backend === 'ollama') {
78
- const ollamaRun = await runOllamaAgent(input.agent, input.slice, {
79
- ...input.intake,
80
- missionId: input.intake.mission_id || input.intake.parent_mission_id || '',
81
- agentRoot: root,
82
- workerDirRel: input.workerDirRel,
83
- cwd: input.intake.cwd || root,
84
- route: input.intake.route || '$Naruto',
85
- fastMode: input.fastModePolicy.fast_mode,
86
- serviceTier: input.fastModePolicy.service_tier
87
- });
88
- patchEnvelopes = Array.isArray(ollamaRun.patch_envelopes) ? ollamaRun.patch_envelopes : [];
89
- proofLevel = ollamaRun.status === 'done' ? (patchEnvelopes.length ? 'model_authored' : 'ollama_worker_proven') : 'blocked';
90
- result = validateAgentWorkerResult({
91
- ...ollamaRun,
92
- backend: 'ollama',
93
- patch_envelopes: patchEnvelopes,
94
- ...(patchEnvelopes.length ? {} : { no_patch_reason: buildNoPatchReason(input, backend) }),
95
- model_authored_patch_envelopes: patchEnvelopes.length > 0,
96
- fixture_patch_envelopes: false,
97
- verification: { status: ollamaRun.status === 'done' ? 'passed' : 'failed', checks: [...(ollamaRun.verification?.checks || []), 'native-worker-backend-router', 'ollama-api-generate'] }
98
- });
99
- }
100
- else if (backend === 'codex-sdk' || backend === 'local-llm') {
101
- const localPreferred = backend === 'local-llm';
74
+ else if (backend === 'codex-sdk') {
102
75
  modelRouting = await resolveWorkerModelRouting(input);
103
76
  if (modelRouting.blockers.length) {
104
77
  proofLevel = 'blocked';
@@ -135,12 +108,7 @@ export async function runNativeWorkerBackendRouter(input) {
135
108
  user_confirmed_full_access: false,
136
109
  mad_sks_authorized: input.intake.mad_sks_authorized === true || process.env.SKS_MAD_SKS_ACTIVE === '1'
137
110
  },
138
- backendPreference: localPreferred ? ['local-llm', 'codex-sdk'] : ['codex-sdk'],
139
- allowLocalLlm: localPreferred,
140
- ...(localPreferred ? { localLlmPolicy: {
141
- mode: 'local_preferred',
142
- requiresGptFinal: true
143
- } } : {}),
111
+ backendPreference: ['codex-sdk'],
144
112
  mutationLedgerRoot: path.join(root, input.workerDirRel),
145
113
  reliabilityPolicy: {
146
114
  maxEmptyResultRetries: 1,
@@ -150,14 +118,13 @@ export async function runNativeWorkerBackendRouter(input) {
150
118
  outputLastMessagePath = sdkTask.workerResultPath;
151
119
  const sdkWorkerResult = normalizeSdkWorkerResultPaths(await readJson(sdkTask.workerResultPath, null), input, pathRoot);
152
120
  patchEnvelopes = normalizeSdkPatchEnvelopes(sdkWorkerResult?.patch_envelopes || [], input, sdkTask.sdkThreadId, pathRoot);
153
- proofLevel = sdkTask.ok ? (patchEnvelopes.length ? 'model_authored' : sdkTask.backend === 'local-llm' ? 'local_llm_worker_proven' : 'codex_sdk_thread_proven') : 'blocked';
121
+ proofLevel = sdkTask.ok ? (patchEnvelopes.length ? 'model_authored' : 'codex_sdk_thread_proven') : 'blocked';
154
122
  const sdkReport = {
155
123
  schema: 'sks.codex-sdk-worker-adapter.v1',
156
124
  backend: sdkTask.backend,
157
125
  backend_family: sdkTask.backend_family,
158
126
  sdk_thread_id: sdkTask.sdkThreadId,
159
127
  sdk_run_id: sdkTask.sdkRunId,
160
- local_llm_proof_path: sdkTask.localLlmProofPath || null,
161
128
  stream_event_count: sdkTask.streamEventCount,
162
129
  structured_output_valid: sdkTask.structuredOutputValid,
163
130
  worker_result_path: sdkTask.workerResultPath,
@@ -175,7 +142,7 @@ export async function runNativeWorkerBackendRouter(input) {
175
142
  session_id: input.agent.session_id,
176
143
  persona_id: input.agent.persona_id || input.agent.id,
177
144
  task_slice_id: input.slice?.id || '',
178
- backend: sdkTask.backend === 'local-llm' ? 'local-llm' : 'codex-sdk',
145
+ backend: 'codex-sdk',
179
146
  patch_envelopes: patchEnvelopes,
180
147
  ...(patchEnvelopes.length ? {} : { no_patch_reason: buildNoPatchReason(input, sdkTask.backend || backend) }),
181
148
  codex_child_report: sdkReport,
@@ -187,18 +154,16 @@ export async function runNativeWorkerBackendRouter(input) {
187
154
  path.relative(root, sdkTask.workerResultPath),
188
155
  path.join(input.workerDirRel, 'codex-control-proof.json'),
189
156
  path.join(input.workerDirRel, 'codex-thread-registry.json'),
190
- sdkTask.backend === 'local-llm' ? path.join(input.workerDirRel, 'local-llm-events.jsonl') : path.join(input.workerDirRel, 'codex-sdk-events.jsonl'),
191
- ...(sdkTask.localLlmProofPath ? [path.relative(root, sdkTask.localLlmProofPath)] : [])
157
+ path.join(input.workerDirRel, 'codex-sdk-events.jsonl')
192
158
  ])],
193
159
  blockers: [...(sdkWorkerResult?.blockers || []), ...sdkTask.blockers],
194
160
  verification: {
195
161
  status: sdkTask.ok ? 'passed' : 'failed',
196
162
  checks: [
197
163
  ...(sdkWorkerResult?.verification?.checks || []),
198
- sdkTask.backend === 'local-llm' ? 'local-llm-control-plane' : 'codex-sdk-control-plane',
199
- sdkTask.backend === 'local-llm' ? 'local-llm-event-stream' : 'codex-sdk-event-stream',
200
- sdkTask.backend === 'local-llm' ? 'local-llm-structured-output' : 'codex-sdk-structured-output',
201
- ...(sdkTask.backend === 'local-llm' ? ['gpt-final-required-before-acceptance'] : [])
164
+ 'codex-sdk-control-plane',
165
+ 'codex-sdk-event-stream',
166
+ 'codex-sdk-structured-output'
202
167
  ]
203
168
  }
204
169
  });
@@ -232,7 +197,6 @@ export async function runNativeWorkerBackendRouter(input) {
232
197
  sdk_run_id: childReports.find((report) => report?.sdk_run_id)?.sdk_run_id || null,
233
198
  stream_event_count: Number(childReports.find((report) => report?.stream_event_count)?.stream_event_count || 0),
234
199
  structured_output_valid: childReports.some((report) => report?.structured_output_valid === true),
235
- ollama_request_ids: patchEnvelopes.map((envelope) => envelope.backend_ollama_request_id).filter(Boolean),
236
200
  blockers: result.blockers || []
237
201
  };
238
202
  await writeJsonAtomic(path.join(root, reportRel), report);
@@ -348,23 +312,6 @@ function normalizeServiceTier(value) {
348
312
  const text = String(value || '').toLowerCase();
349
313
  return text === 'standard' ? 'standard' : text === 'fast' || text === 'priority' ? 'fast' : null;
350
314
  }
351
- async function maybeAutoSelectOllamaBackend(backend, input) {
352
- if (backend !== 'codex-sdk')
353
- return backend;
354
- if (isNarutoWorkerRequest(input))
355
- return backend;
356
- if (input.intake?.backend_explicit === true || input.intake?.no_ollama === true)
357
- return backend;
358
- const config = await resolveOllamaWorkerConfig({
359
- ollamaEnabled: input.intake?.ollama_enabled === true,
360
- model: input.intake?.ollama_model || null,
361
- baseUrl: input.intake?.ollama_base_url || null
362
- }).catch(() => null);
363
- if (!config?.ok || config.enabled !== true || config.status !== 'verified')
364
- return backend;
365
- const policy = classifyOllamaWorkerSlice(input.slice, { route: input.intake?.route, agent: input.agent });
366
- return policy.ok ? 'local-llm' : backend;
367
- }
368
315
  function isNarutoWorkerRequest(input) {
369
316
  return Boolean(input.agent?.naruto_role) || /\$?naruto/i.test(String(input.intake?.route || ''));
370
317
  }
@@ -373,12 +320,10 @@ export function narutoWorkerBackendBlocker(backend, narutoRequest = true) {
373
320
  return null;
374
321
  if (backend === 'process')
375
322
  return 'naruto_gpt_5_6_family_only_process_backend_forbidden';
376
- if (backend === 'ollama' || backend === 'local-llm')
377
- return 'naruto_gpt_5_6_family_only_local_backend_forbidden';
378
323
  return null;
379
324
  }
380
325
  function normalizeBackend(value) {
381
- return value === 'fake' || value === 'process' || value === 'codex-sdk' || value === 'ollama' || value === 'local-llm' ? value : null;
326
+ return value === 'fake' || value === 'process' || value === 'codex-sdk' ? value : null;
382
327
  }
383
328
  function envelopeOpts(input, source, childPid) {
384
329
  return {
@@ -23,7 +23,6 @@ export async function writeCodexControlProof(root, input) {
23
23
  output_schema_id: input.task.outputSchemaId,
24
24
  worker_result_path: input.result.workerResultPath,
25
25
  patch_envelope_path: input.result.patchEnvelopePath || null,
26
- local_llm_proof_path: input.result.localLlmProofPath || null,
27
26
  python_sdk_proof_path: input.result.pythonSdkProofPath || null,
28
27
  sandbox: input.sandbox || null,
29
28
  env: input.envProof || null,