sneakoscope 6.0.2 → 6.1.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 (242) hide show
  1. package/README.md +5 -3
  2. package/config/codex-releases/{rust-v0.142.0.json → rust-v0.144.1.json} +6 -6
  3. package/crates/sks-core/Cargo.lock +1 -1
  4. package/crates/sks-core/Cargo.toml +1 -1
  5. package/dist/cli/install-helpers.js +255 -440
  6. package/dist/cli/router.js +53 -4
  7. package/dist/commands/codex-app.js +8 -3
  8. package/dist/commands/codex-lb.js +169 -40
  9. package/dist/commands/codex.js +6 -5
  10. package/dist/commands/doctor.js +60 -26
  11. package/dist/commands/versioning.js +7 -0
  12. package/dist/config/skills-manifest.json +57 -57
  13. package/dist/core/agents/agent-central-ledger.js +9 -0
  14. package/dist/core/agents/agent-cleanup-executor.js +334 -41
  15. package/dist/core/agents/agent-cleanup.js +20 -1
  16. package/dist/core/agents/agent-command-surface.js +2 -1
  17. package/dist/core/agents/agent-effort-policy.js +46 -33
  18. package/dist/core/agents/agent-janitor.js +9 -10
  19. package/dist/core/agents/agent-namespace-safety.js +56 -0
  20. package/dist/core/agents/agent-orchestrator.js +26 -4
  21. package/dist/core/agents/agent-output-validator.js +1 -1
  22. package/dist/core/agents/agent-proof-evidence.js +16 -2
  23. package/dist/core/agents/agent-role-config.js +3 -6
  24. package/dist/core/agents/agent-roster.js +2 -2
  25. package/dist/core/agents/agent-runner-codex-exec.js +2 -0
  26. package/dist/core/agents/agent-runner-process.js +1 -0
  27. package/dist/core/agents/fast-mode-policy.js +3 -5
  28. package/dist/core/agents/native-cli-session-swarm.js +18 -1
  29. package/dist/core/agents/native-worker-backend-router.js +180 -108
  30. package/dist/core/agents/parallel-write-fixture.js +15 -10
  31. package/dist/core/agents/runtime-proof-summary.js +21 -3
  32. package/dist/core/agents/work-partition/repo-inventory.js +68 -7
  33. package/dist/core/code-structure.js +5 -4
  34. package/dist/core/codex/codex-config-guard.js +31 -9
  35. package/dist/core/codex-app/codex-app-fast-ui-repair.js +51 -20
  36. package/dist/core/codex-app/codex-app-restart.js +38 -8
  37. package/dist/core/codex-app/codex-app-ui-state-snapshot.js +11 -3
  38. package/dist/core/codex-app/sks-menubar.js +100 -40
  39. package/dist/core/codex-app.js +60 -17
  40. package/dist/core/codex-compat/codex-hook-warning-detector.js +10 -1
  41. package/dist/core/codex-compat/codex-release-manifest.js +6 -6
  42. package/dist/core/codex-control/codex-0139-doctor-real-probe.js +7 -1
  43. package/dist/core/codex-control/codex-0139-image-path-real-probe.js +14 -8
  44. package/dist/core/codex-control/codex-0139-probe-runner.js +103 -28
  45. package/dist/core/codex-control/codex-0139-real-probe-summary.js +7 -3
  46. package/dist/core/codex-control/codex-0139-real-probes.js +21 -6
  47. package/dist/core/codex-control/codex-0139-sandbox-real-probe.js +39 -13
  48. package/dist/core/codex-control/codex-0139-web-search-probe.js +11 -8
  49. package/dist/core/codex-control/{codex-0142-capability.js → codex-0144-capability.js} +22 -22
  50. package/dist/core/codex-control/codex-0144-collab-agent-real-probe.js +63 -0
  51. package/dist/core/codex-control/codex-model-metadata.js +8 -4
  52. package/dist/core/codex-control/codex-multi-agent-event-normalizer.js +5 -1
  53. package/dist/core/codex-control/codex-reliability-shield.js +4 -1
  54. package/dist/core/codex-control/codex-sdk-adapter.js +53 -6
  55. package/dist/core/codex-control/codex-sdk-config-policy.js +2 -1
  56. package/dist/core/codex-control/codex-sdk-sandbox-policy.js +6 -3
  57. package/dist/core/codex-lb/codex-lb-env.js +107 -0
  58. package/dist/core/codex-lb/codex-lb-tool-catalog.js +478 -0
  59. package/dist/core/codex-native/codex-native-feature-broker.js +22 -22
  60. package/dist/core/codex-native/codex-native-feature-matrix.js +2 -2
  61. package/dist/core/codex-native/native-capability-postcheck.js +16 -8
  62. package/dist/core/codex-native/native-capability-repair-matrix.js +76 -27
  63. package/dist/core/codex-plugins/codex-plugin-json.js +67 -21
  64. package/dist/core/codex-plugins/codex-plugin-repair.js +118 -0
  65. package/dist/core/codex-runtime/codex-desktop-config-policy.js +306 -0
  66. package/dist/core/commands/agent-command.js +19 -0
  67. package/dist/core/commands/basic-cli.js +45 -24
  68. package/dist/core/commands/gc-command.js +27 -4
  69. package/dist/core/commands/image-ux-review-command.js +55 -24
  70. package/dist/core/commands/mad-sks-command.js +152 -132
  71. package/dist/core/commands/naruto-command.js +41 -10
  72. package/dist/core/commands/pipeline-command.js +1 -0
  73. package/dist/core/commands/wiki-command.js +179 -83
  74. package/dist/core/computer-use-live-evidence.js +166 -3
  75. package/dist/core/computer-use-status.js +5 -2
  76. package/dist/core/daemon/sksd-hook-daemon-entrypoint.js +2 -2
  77. package/dist/core/daemon/sksd-hook-daemon.js +171 -28
  78. package/dist/core/daemon/sksd-hook-dispatch.js +2 -2
  79. package/dist/core/dfix/verification-selector.js +6 -4
  80. package/dist/core/doctor/browser-use-repair.js +54 -13
  81. package/dist/core/doctor/codex-0139-doctor.js +3 -2
  82. package/dist/core/doctor/computer-use-repair.js +28 -39
  83. package/dist/core/doctor/doctor-codex-startup-repair.js +19 -9
  84. package/dist/core/doctor/doctor-context7-repair.js +1 -1
  85. package/dist/core/doctor/doctor-dirty-planner.js +1 -1
  86. package/dist/core/doctor/doctor-native-capability-repair.js +74 -3
  87. package/dist/core/doctor/imagegen-repair.js +47 -12
  88. package/dist/core/doctor/legacy-global-hook-cleanup.js +179 -0
  89. package/dist/core/feature-registry.js +25 -31
  90. package/dist/core/fsx.js +54 -6
  91. package/dist/core/harness-conflicts.js +1 -1
  92. package/dist/core/hooks-runtime/code-pack-freshness-preflight.js +5 -4
  93. package/dist/core/hooks-runtime/hook-invocation-dedupe.js +147 -0
  94. package/dist/core/hooks-runtime/hook-io.js +6 -0
  95. package/dist/core/hooks-runtime.js +17 -2
  96. package/dist/core/image/image-artifact-path-contract.js +8 -6
  97. package/dist/core/image/image-artifact-registry.js +5 -1
  98. package/dist/core/image-ux-review/imagegen-adapter.js +5 -2
  99. package/dist/core/imagegen/imagegen-capability.js +10 -13
  100. package/dist/core/imagegen/require-imagegen.js +37 -11
  101. package/dist/core/managed-assets/managed-assets-manifest.js +1 -5
  102. package/dist/core/naruto/naruto-work-graph.js +70 -4
  103. package/dist/core/naruto/naruto-write-e2e.js +3 -4
  104. package/dist/core/ops/reporting.js +3 -0
  105. package/dist/core/pipeline-internals/runtime-core.js +12 -7
  106. package/dist/core/pipeline-internals/runtime-gates.js +17 -1
  107. package/dist/core/ppt/style-tokens.js +1 -1
  108. package/dist/core/ppt-review/index.js +1 -1
  109. package/dist/core/ppt-review/slide-exporter.js +23 -17
  110. package/dist/core/ppt-review/slide-imagegen-review.js +1 -1
  111. package/dist/core/ppt-review/slide-issue-extraction.js +4 -2
  112. package/dist/core/product-design-plugin.js +2 -2
  113. package/dist/core/proof/route-finalizer.js +1 -1
  114. package/dist/core/proof-field.js +3 -3
  115. package/dist/core/provider/model-router.js +68 -3
  116. package/dist/core/release/gate-manifest.js +18 -12
  117. package/dist/core/release/gate-pack-manifest.js +1 -1
  118. package/dist/core/release/package-size-budget.js +2 -0
  119. package/dist/core/release/release-gate-affected-selector.js +1 -1
  120. package/dist/core/release/release-gate-dag.js +43 -3
  121. package/dist/core/release/release-gate-hermetic-env.js +28 -17
  122. package/dist/core/release/release-real-contract.js +416 -0
  123. package/dist/core/retention/retention-budget.js +25 -6
  124. package/dist/core/retention.js +980 -101
  125. package/dist/core/routes/constants.js +1 -1
  126. package/dist/core/routes/evidence.js +4 -4
  127. package/dist/core/routes/model-mode-router.js +3 -0
  128. package/dist/core/routes/ppt-policy.js +1 -1
  129. package/dist/core/routes.js +11 -12
  130. package/dist/core/secret-redaction.js +4 -0
  131. package/dist/core/triwiki/code-pack.js +8 -2
  132. package/dist/core/triwiki/triwiki-cache-key.js +108 -29
  133. package/dist/core/triwiki-attention.js +13 -6
  134. package/dist/core/triwiki-provenance.js +274 -0
  135. package/dist/core/triwiki-runtime.js +21 -7
  136. package/dist/core/triwiki-wrongness/wrongness-ledger.js +178 -59
  137. package/dist/core/triwiki-wrongness/wrongness-retrieval.js +11 -2
  138. package/dist/core/triwiki-wrongness/wrongness-trust-policy.js +2 -0
  139. package/dist/core/update/update-migration-state.js +1 -1
  140. package/dist/core/update/update-notice.js +23 -0
  141. package/dist/core/update-check.js +69 -25
  142. package/dist/core/version.js +1 -1
  143. package/dist/core/wiki-coordinate.js +128 -12
  144. package/dist/core/work-order-ledger.js +168 -9
  145. package/dist/core/zellij/zellij-command.js +12 -1
  146. package/dist/core/zellij/zellij-dashboard-pane.js +3 -3
  147. package/dist/core/zellij/zellij-launcher.js +15 -14
  148. package/dist/core/zellij/zellij-pane-proof.js +32 -6
  149. package/dist/core/zellij/zellij-worker-pane-manager.js +5 -3
  150. package/dist/scripts/agent-fast-mode-default-check.js +48 -29
  151. package/dist/scripts/agent-role-config-repair-check.js +25 -4
  152. package/dist/scripts/agent-wiki-context-proof-check.js +16 -2
  153. package/dist/scripts/all-feature-deep-completion-check.js +14 -4
  154. package/dist/scripts/build-dist.js +17 -5
  155. package/dist/scripts/canonical-test-runner.js +188 -0
  156. package/dist/scripts/check-command-module-budget.js +38 -16
  157. package/dist/scripts/check-legacy-free.js +1 -1
  158. package/dist/scripts/codex-0139-interrupt-agent-check.js +5 -1
  159. package/dist/scripts/{codex-0142-app-server-v2-check.js → codex-0144-app-server-v2-check.js} +11 -10
  160. package/dist/scripts/{codex-0142-binary-identity-check.js → codex-0144-binary-identity-check.js} +4 -4
  161. package/dist/scripts/codex-0144-capability-check.js +21 -0
  162. package/dist/scripts/{codex-0139-real-probes-check.js → codex-0144-core-real-probes-check.js} +19 -5
  163. package/dist/scripts/{codex-0142-doctor-wiring-check.js → codex-0144-doctor-wiring-check.js} +6 -6
  164. package/dist/scripts/{codex-0142-manifest-check.js → codex-0144-manifest-check.js} +11 -3
  165. package/dist/scripts/{codex-0142-policy-check.js → codex-0144-policy-check.js} +2 -2
  166. package/dist/scripts/{codex-0142-thread-store-check.js → codex-0144-thread-store-check.js} +3 -3
  167. package/dist/scripts/codex-app-provider-model-ui-check.js +57 -8
  168. package/dist/scripts/codex-app-ui-preservation-check.js +35 -4
  169. package/dist/scripts/codex-control-side-effect-scope-check.js +2 -2
  170. package/dist/scripts/codex-effort-auto-discovery-check.js +1 -1
  171. package/dist/scripts/codex-lb-fast-mode-truth-check.js +1 -0
  172. package/dist/scripts/{codex-lb-gpt55-fast-profile-check.js → codex-lb-gpt56-fast-profile-check.js} +56 -5
  173. package/dist/scripts/codex-model-metadata-check.js +1 -1
  174. package/dist/scripts/codex-sdk-sandbox-policy-check.js +5 -1
  175. package/dist/scripts/codex-sdk-version-compat-check.js +2 -1
  176. package/dist/scripts/dfix-fixture-check.js +1 -1
  177. package/dist/scripts/docs-truthfulness-check.js +1 -1
  178. package/dist/scripts/doctor-codex-startup-repair-check.js +35 -10
  179. package/dist/scripts/doctor-context7-repair-check.js +2 -1
  180. package/dist/scripts/doctor-fix-proves-codex-read-check.js +1 -1
  181. package/dist/scripts/doctor-fixes-codex-app-fast-ui-check.js +34 -7
  182. package/dist/scripts/doctor-imagegen-repair-check.js +14 -4
  183. package/dist/scripts/doctor-startup-config-repair-blackbox.js +1 -1
  184. package/dist/scripts/doctor-startup-config-repair-check.js +1 -1
  185. package/dist/scripts/gate-policy-audit-check.js +2 -2
  186. package/dist/scripts/install-update-preserves-config-check.js +1 -1
  187. package/dist/scripts/legacy-gate-inventory-check.js +7 -5
  188. package/dist/scripts/legacy-strong-inventory-check.js +7 -5
  189. package/dist/scripts/legacy-upgrade-matrix-check.js +5 -5
  190. package/dist/scripts/lib/native-cli-session-swarm-check-lib.js +175 -14
  191. package/dist/scripts/mad-sks-app-ui-no-mutation-check.js +166 -6
  192. package/dist/scripts/mutation-callsite-coverage-check.js +0 -11
  193. package/dist/scripts/naruto-shadow-clone-swarm-check.js +88 -50
  194. package/dist/scripts/npm-publish-performance-check.js +2 -1
  195. package/dist/scripts/package-published-contract-check.js +9 -0
  196. package/dist/scripts/packlist-performance-check.js +5 -2
  197. package/dist/scripts/postinstall-safe-side-effects-check.js +8 -3
  198. package/dist/scripts/ppt-no-mock-as-real-check.js +3 -1
  199. package/dist/scripts/product-design-plugin-routing-check.js +1 -1
  200. package/dist/scripts/release-check-stamp.js +182 -2
  201. package/dist/scripts/release-dag-full-coverage-check.js +7 -7
  202. package/dist/scripts/release-dynamic-presets-check.js +8 -0
  203. package/dist/scripts/release-gate-dag-runner-check.js +3 -2
  204. package/dist/scripts/release-gate-dag-runner.js +24 -11
  205. package/dist/scripts/release-gate-existence-audit.js +8 -9
  206. package/dist/scripts/release-gate-script-parity-check.js +1 -1
  207. package/dist/scripts/release-real-check.js +368 -157
  208. package/dist/scripts/release-runtime-truth-matrix-check.js +22 -0
  209. package/dist/scripts/route-proof-artifact-structure-check.js +1 -0
  210. package/dist/scripts/scheduler-batch-dispatch-check.js +1 -1
  211. package/dist/scripts/search-visibility-gate-lib.js +1 -1
  212. package/dist/scripts/seo-geo-route-identity-check.js +30 -4
  213. package/dist/scripts/sizecheck.js +7 -2
  214. package/dist/scripts/sks-1-11-gate-lib.js +53 -6
  215. package/dist/scripts/sks-menubar-install-check.js +7 -0
  216. package/dist/scripts/sks-uninstall-regression-check.js +1 -1
  217. package/dist/scripts/sksd-daemon-check.js +16 -6
  218. package/dist/scripts/update-default-command-check.js +4 -2
  219. package/dist/scripts/write-build-manifest.js +2 -1
  220. package/dist/scripts/zellij-layout-valid-check.js +31 -6
  221. package/dist/scripts/zellij-pane-proof-check.js +33 -2
  222. package/dist/scripts/zellij-real-session-cleanup-check.js +122 -2
  223. package/dist/scripts/zellij-real-session-launch-check.js +76 -5
  224. package/dist/scripts/zellij-slot-pane-renderer-check.js +4 -4
  225. package/package.json +27 -30
  226. package/schemas/codex/{app-server-0.142 → app-server-0.144}/codex_app_server_protocol.v2.schemas.json +1146 -781
  227. package/schemas/codex/codex-0139-real-probe-result.schema.json +39 -5
  228. package/schemas/codex/ppt-slide-issue-ledger.schema.json +2 -1
  229. package/dist/core/codex-control/codex-0139-multi-agent-real-probe.js +0 -107
  230. package/dist/scripts/agent-native-release-gate.js +0 -274
  231. package/dist/scripts/codex-0142-capability-check.js +0 -21
  232. package/dist/scripts/command-performance-scorecard-check.js +0 -204
  233. package/dist/scripts/config-managed-merge-callsite-coverage-check.js +0 -212
  234. package/dist/scripts/dollar-performance-scorecard-check.js +0 -257
  235. package/dist/scripts/gate-timing-check.js +0 -16
  236. package/dist/scripts/ops-maturity-scorecard-check.js +0 -12
  237. package/dist/scripts/performance-baseline-check.js +0 -12
  238. package/dist/scripts/performance-improvement-report-check.js +0 -58
  239. package/dist/scripts/release-parallel-check.js +0 -389
  240. package/dist/scripts/release-runner-efficiency-check.js +0 -15
  241. package/dist/scripts/retention-long-run-smoke-check.js +0 -299
  242. package/docs/assets/sneakoscope-architecture-pipeline.jpg +0 -0
@@ -10,8 +10,9 @@ import { normalizeAgentPatchEnvelope } from './agent-patch-schema.js';
10
10
  import { runCodexTask } from '../codex-control/codex-control-plane.js';
11
11
  import { CODEX_AGENT_WORKER_RESULT_SCHEMA_ID, codexAgentWorkerResultSchema } from '../codex-control/schemas/agent-worker-result.schema.js';
12
12
  import { leanEngineeringCompactText, leanPolicyReference } from '../lean-engineering-policy.js';
13
- import { readLbHealth } from '../codex-lb/codex-lb-env.js';
14
- import { categoryForWorkerRole, modelRouteReason, routeModel } from '../provider/model-router.js';
13
+ import { readCodexLbModelCatalog, readLbHealth } from '../codex-lb/codex-lb-env.js';
14
+ import { categoryForWorkerRole, isNarutoGpt56Model, modelRouteReason, routeModel } from '../provider/model-router.js';
15
+ import { codexTimeoutClassForRoute } from '../codex-control/codex-reliability-shield.js';
15
16
  export const NATIVE_WORKER_BACKEND_ROUTER_SCHEMA = 'sks.native-worker-backend-router.v1';
16
17
  export async function runNativeWorkerBackendRouter(input) {
17
18
  const root = path.resolve(input.agentRoot);
@@ -19,6 +20,7 @@ export async function runNativeWorkerBackendRouter(input) {
19
20
  const requestedBackend = String(input.backend || '');
20
21
  let backend = normalizeBackend(requestedBackend);
21
22
  backend = await maybeAutoSelectOllamaBackend(backend, input);
23
+ const narutoRequest = isNarutoWorkerRequest(input);
22
24
  const reportRel = path.join(input.workerDirRel, 'worker-backend-router-report.json');
23
25
  const startedAt = nowIso();
24
26
  let result;
@@ -27,7 +29,12 @@ export async function runNativeWorkerBackendRouter(input) {
27
29
  let proofLevel = 'blocked';
28
30
  let outputLastMessagePath = null;
29
31
  let modelRouting = null;
30
- if (!input.guard?.ok) {
32
+ const narutoBackendBlocker = narutoWorkerBackendBlocker(backend, narutoRequest);
33
+ if (narutoBackendBlocker) {
34
+ const blocker = narutoBackendBlocker;
35
+ result = validateAgentWorkerResult(blockedResult(input, [blocker]));
36
+ }
37
+ else if (!input.guard?.ok) {
31
38
  result = validateAgentWorkerResult(blockedResult(input, ['native_cli_worker_recursion_guard_missing']));
32
39
  }
33
40
  else if (requestedBackend === 'codex-exec') {
@@ -96,104 +103,110 @@ export async function runNativeWorkerBackendRouter(input) {
96
103
  else if (backend === 'codex-sdk' || backend === 'zellij' || backend === 'local-llm') {
97
104
  const localPreferred = backend === 'local-llm';
98
105
  modelRouting = await resolveWorkerModelRouting(input);
99
- const sdkTask = await runCodexTask({
100
- route: String(input.intake.route || '$Agent'),
101
- tier: 'worker',
102
- missionId: String(input.intake.mission_id || input.intake.parent_mission_id || ''),
103
- workItemId: String(input.slice?.id || ''),
104
- slotId: String(input.agent.slot_id || input.agent.id || ''),
105
- generationIndex: Number(input.agent.generation_index || 1),
106
- sessionId: String(input.agent.session_id || ''),
107
- cwd: String(input.intake.cwd || root),
108
- prompt: buildWorkerPrompt(input.slice),
109
- model: modelRouting.choice.model,
110
- reasoningEffort: modelRouting.choice.reasoning,
111
- modelReasoningEffort: modelRouting.choice.reasoning,
112
- serviceTier: modelRouting.choice.serviceTier,
113
- inputFiles: input.intake.input_files || [],
114
- inputImages: input.intake.input_images || [],
115
- outputSchemaId: CODEX_AGENT_WORKER_RESULT_SCHEMA_ID,
116
- outputSchema: codexAgentWorkerResultSchema,
117
- sandboxPolicy: hasWriteLease(input.slice, input.intake) ? 'workspace-write' : 'read-only',
118
- requestedScopeContract: {
119
- id: String(input.intake.lease_id || input.slice?.id || ''),
106
+ if (modelRouting.blockers.length) {
107
+ proofLevel = 'blocked';
108
+ result = validateAgentWorkerResult(blockedResult(input, modelRouting.blockers));
109
+ }
110
+ else {
111
+ const sdkTask = await runCodexTask({
120
112
  route: String(input.intake.route || '$Agent'),
121
- read_only: !hasWriteLease(input.slice, input.intake),
122
- allowed_paths: writePaths(input.slice, input.intake),
123
- write_paths: writePaths(input.slice, input.intake),
124
- model_route_reason: modelRouting.reason,
113
+ tier: 'worker',
114
+ missionId: String(input.intake.mission_id || input.intake.parent_mission_id || ''),
115
+ workItemId: String(input.slice?.id || ''),
116
+ slotId: String(input.agent.slot_id || input.agent.id || ''),
117
+ generationIndex: Number(input.agent.generation_index || 1),
118
+ sessionId: String(input.agent.session_id || ''),
119
+ cwd: String(input.intake.cwd || root),
120
+ prompt: buildWorkerPrompt(input.slice),
121
+ model: modelRouting.choice.model,
122
+ reasoningEffort: modelRouting.choice.reasoning,
123
+ modelReasoningEffort: modelRouting.choice.reasoning,
124
+ serviceTier: modelRouting.choice.serviceTier,
125
+ inputFiles: input.intake.input_files || [],
126
+ inputImages: input.intake.input_images || [],
127
+ outputSchemaId: CODEX_AGENT_WORKER_RESULT_SCHEMA_ID,
128
+ outputSchema: codexAgentWorkerResultSchema,
129
+ sandboxPolicy: hasWriteLease(input.slice, input.intake) ? 'workspace-write' : 'read-only',
130
+ requestedScopeContract: {
131
+ id: String(input.intake.lease_id || input.slice?.id || ''),
132
+ route: String(input.intake.route || '$Agent'),
133
+ read_only: !hasWriteLease(input.slice, input.intake),
134
+ allowed_paths: writePaths(input.slice, input.intake),
135
+ write_paths: writePaths(input.slice, input.intake),
136
+ model_route_reason: modelRouting.reason,
137
+ service_tier: modelRouting.choice.serviceTier,
138
+ user_confirmed_full_access: false,
139
+ mad_sks_authorized: input.intake.mad_sks_authorized === true || process.env.SKS_MAD_SKS_ACTIVE === '1'
140
+ },
141
+ backendPreference: localPreferred ? ['local-llm', 'codex-sdk'] : ['codex-sdk'],
142
+ allowLocalLlm: localPreferred,
143
+ ...(localPreferred ? { localLlmPolicy: {
144
+ mode: 'local_preferred',
145
+ requiresGptFinal: true
146
+ } } : {}),
147
+ mutationLedgerRoot: path.join(root, input.workerDirRel),
148
+ zellijPaneId: await readZellijPaneId(root, input.workerDirRel),
149
+ reliabilityPolicy: {
150
+ maxEmptyResultRetries: 1,
151
+ timeoutClass: codexTimeoutClassForRoute(input.intake.route, 'standard')
152
+ }
153
+ });
154
+ outputLastMessagePath = sdkTask.workerResultPath;
155
+ const sdkWorkerResult = normalizeSdkWorkerResultPaths(await readJson(sdkTask.workerResultPath, null), input, pathRoot);
156
+ patchEnvelopes = normalizeSdkPatchEnvelopes(sdkWorkerResult?.patch_envelopes || [], input, sdkTask.sdkThreadId, pathRoot);
157
+ proofLevel = sdkTask.ok ? (patchEnvelopes.length ? 'model_authored' : sdkTask.backend === 'local-llm' ? 'local_llm_worker_proven' : 'codex_sdk_thread_proven') : 'blocked';
158
+ const sdkReport = {
159
+ schema: 'sks.codex-sdk-worker-adapter.v1',
160
+ backend: sdkTask.backend,
161
+ backend_family: sdkTask.backend_family,
162
+ sdk_thread_id: sdkTask.sdkThreadId,
163
+ sdk_run_id: sdkTask.sdkRunId,
164
+ local_llm_proof_path: sdkTask.localLlmProofPath || null,
165
+ stream_event_count: sdkTask.streamEventCount,
166
+ structured_output_valid: sdkTask.structuredOutputValid,
167
+ worker_result_path: sdkTask.workerResultPath,
168
+ patch_envelope_path: sdkTask.patchEnvelopePath || null,
169
+ model: modelRouting.choice.model,
170
+ model_reasoning_effort: modelRouting.choice.reasoning,
125
171
  service_tier: modelRouting.choice.serviceTier,
126
- user_confirmed_full_access: false,
127
- mad_sks_authorized: input.intake.mad_sks_authorized === true || process.env.SKS_MAD_SKS_ACTIVE === '1'
128
- },
129
- backendPreference: localPreferred ? ['local-llm', 'codex-sdk'] : ['codex-sdk'],
130
- allowLocalLlm: localPreferred,
131
- ...(localPreferred ? { localLlmPolicy: {
132
- mode: 'local_preferred',
133
- requiresGptFinal: true
134
- } } : {}),
135
- mutationLedgerRoot: path.join(root, input.workerDirRel),
136
- zellijPaneId: await readZellijPaneId(root, input.workerDirRel),
137
- reliabilityPolicy: {
138
- maxEmptyResultRetries: 1,
139
- timeoutClass: 'standard'
140
- }
141
- });
142
- outputLastMessagePath = sdkTask.workerResultPath;
143
- const sdkWorkerResult = normalizeSdkWorkerResultPaths(await readJson(sdkTask.workerResultPath, null), input, pathRoot);
144
- patchEnvelopes = normalizeSdkPatchEnvelopes(sdkWorkerResult?.patch_envelopes || [], input, sdkTask.sdkThreadId, pathRoot);
145
- proofLevel = sdkTask.ok ? (patchEnvelopes.length ? 'model_authored' : sdkTask.backend === 'local-llm' ? 'local_llm_worker_proven' : 'codex_sdk_thread_proven') : 'blocked';
146
- const sdkReport = {
147
- schema: 'sks.codex-sdk-worker-adapter.v1',
148
- backend: sdkTask.backend,
149
- backend_family: sdkTask.backend_family,
150
- sdk_thread_id: sdkTask.sdkThreadId,
151
- sdk_run_id: sdkTask.sdkRunId,
152
- local_llm_proof_path: sdkTask.localLlmProofPath || null,
153
- stream_event_count: sdkTask.streamEventCount,
154
- structured_output_valid: sdkTask.structuredOutputValid,
155
- worker_result_path: sdkTask.workerResultPath,
156
- patch_envelope_path: sdkTask.patchEnvelopePath || null,
157
- model: modelRouting.choice.model,
158
- model_reasoning_effort: modelRouting.choice.reasoning,
159
- service_tier: modelRouting.choice.serviceTier,
160
- model_route_reason: modelRouting.reason,
161
- blockers: sdkTask.blockers
162
- };
163
- childReports = [sdkReport];
164
- result = validateAgentWorkerResult({
165
- ...sdkWorkerResult,
166
- agent_id: workerOwnerId(input),
167
- session_id: input.agent.session_id,
168
- persona_id: input.agent.persona_id || input.agent.id,
169
- task_slice_id: input.slice?.id || '',
170
- backend: sdkTask.backend === 'local-llm' ? 'local-llm' : 'codex-sdk',
171
- patch_envelopes: patchEnvelopes,
172
- ...(patchEnvelopes.length ? {} : { no_patch_reason: buildNoPatchReason(input, sdkTask.backend || backend) }),
173
- codex_child_report: sdkReport,
174
- codex_sdk_thread: sdkReport,
175
- model_authored_patch_envelopes: patchEnvelopes.length > 0,
176
- fixture_patch_envelopes: false,
177
- artifacts: [...new Set([
178
- ...(sdkWorkerResult?.artifacts || []),
179
- path.relative(root, sdkTask.workerResultPath),
180
- path.join(input.workerDirRel, 'codex-control-proof.json'),
181
- path.join(input.workerDirRel, 'codex-thread-registry.json'),
182
- sdkTask.backend === 'local-llm' ? path.join(input.workerDirRel, 'local-llm-events.jsonl') : path.join(input.workerDirRel, 'codex-sdk-events.jsonl'),
183
- ...(sdkTask.localLlmProofPath ? [path.relative(root, sdkTask.localLlmProofPath)] : [])
184
- ])],
185
- blockers: [...(sdkWorkerResult?.blockers || []), ...sdkTask.blockers],
186
- verification: {
187
- status: sdkTask.ok ? 'passed' : 'failed',
188
- checks: [
189
- ...(sdkWorkerResult?.verification?.checks || []),
190
- sdkTask.backend === 'local-llm' ? 'local-llm-control-plane' : 'codex-sdk-control-plane',
191
- sdkTask.backend === 'local-llm' ? 'local-llm-event-stream' : 'codex-sdk-event-stream',
192
- sdkTask.backend === 'local-llm' ? 'local-llm-structured-output' : 'codex-sdk-structured-output',
193
- ...(sdkTask.backend === 'local-llm' ? ['gpt-final-required-before-acceptance'] : [])
194
- ]
195
- }
196
- });
172
+ model_route_reason: modelRouting.reason,
173
+ blockers: sdkTask.blockers
174
+ };
175
+ childReports = [sdkReport];
176
+ result = validateAgentWorkerResult({
177
+ ...sdkWorkerResult,
178
+ agent_id: workerOwnerId(input),
179
+ session_id: input.agent.session_id,
180
+ persona_id: input.agent.persona_id || input.agent.id,
181
+ task_slice_id: input.slice?.id || '',
182
+ backend: sdkTask.backend === 'local-llm' ? 'local-llm' : 'codex-sdk',
183
+ patch_envelopes: patchEnvelopes,
184
+ ...(patchEnvelopes.length ? {} : { no_patch_reason: buildNoPatchReason(input, sdkTask.backend || backend) }),
185
+ codex_child_report: sdkReport,
186
+ codex_sdk_thread: sdkReport,
187
+ model_authored_patch_envelopes: patchEnvelopes.length > 0,
188
+ fixture_patch_envelopes: false,
189
+ artifacts: [...new Set([
190
+ ...(sdkWorkerResult?.artifacts || []),
191
+ path.relative(root, sdkTask.workerResultPath),
192
+ path.join(input.workerDirRel, 'codex-control-proof.json'),
193
+ path.join(input.workerDirRel, 'codex-thread-registry.json'),
194
+ sdkTask.backend === 'local-llm' ? path.join(input.workerDirRel, 'local-llm-events.jsonl') : path.join(input.workerDirRel, 'codex-sdk-events.jsonl'),
195
+ ...(sdkTask.localLlmProofPath ? [path.relative(root, sdkTask.localLlmProofPath)] : [])
196
+ ])],
197
+ blockers: [...(sdkWorkerResult?.blockers || []), ...sdkTask.blockers],
198
+ verification: {
199
+ status: sdkTask.ok ? 'passed' : 'failed',
200
+ checks: [
201
+ ...(sdkWorkerResult?.verification?.checks || []),
202
+ sdkTask.backend === 'local-llm' ? 'local-llm-control-plane' : 'codex-sdk-control-plane',
203
+ sdkTask.backend === 'local-llm' ? 'local-llm-event-stream' : 'codex-sdk-event-stream',
204
+ sdkTask.backend === 'local-llm' ? 'local-llm-structured-output' : 'codex-sdk-structured-output',
205
+ ...(sdkTask.backend === 'local-llm' ? ['gpt-final-required-before-acceptance'] : [])
206
+ ]
207
+ }
208
+ });
209
+ }
197
210
  }
198
211
  else {
199
212
  const zellijRun = await runZellijAgent(input.agent, input.slice, {
@@ -262,24 +275,69 @@ export async function runNativeWorkerBackendRouter(input) {
262
275
  patchEnvelopes
263
276
  };
264
277
  }
265
- async function resolveWorkerModelRouting(input) {
266
- const category = categoryForWorkerRole(String(input.agent?.role || input.slice?.role || input.slice?.type || input.agent?.persona_id || 'executor'));
267
- const lbHealth = await readLbHealth().catch(() => null);
268
- const explicitModel = String(process.env.SKS_WORKER_MODEL || process.env.SKS_AGENT_MODEL || '').trim();
269
- const explicitReasoning = normalizeModelReasoning(process.env.SKS_WORKER_REASONING || process.env.SKS_WORKER_MODEL_REASONING || '');
270
- const explicitTier = normalizeServiceTier(process.env.SKS_WORKER_SERVICE_TIER || process.env.SKS_SERVICE_TIER || '');
271
- const routed = explicitModel
278
+ export async function resolveWorkerModelRouting(input, deps = {}) {
279
+ const narutoOnly = Boolean(input.agent?.naruto_role) || /\$?naruto/i.test(String(input.intake?.route || ''));
280
+ const taskKindText = [
281
+ input.slice?.work_item_kind,
282
+ input.slice?.kind,
283
+ input.slice?.type,
284
+ input.slice?.title,
285
+ input.slice?.required_role,
286
+ input.slice?.role,
287
+ input.agent?.naruto_role,
288
+ input.agent?.role,
289
+ input.agent?.persona_id
290
+ ].map((value) => String(value || '')).join(' ');
291
+ const riskText = [taskKindText, input.slice?.risk, input.slice?.risk_focus, input.slice?.acceptance, input.slice?.parent_prompt, input.slice?.description, input.intake?.prompt].map((value) => String(value || '')).join(' ');
292
+ const category = categoryForWorkerRole(String(input.agent?.role || 'executor'), taskKindText);
293
+ const env = deps.env || process.env;
294
+ const lbHealth = Object.prototype.hasOwnProperty.call(deps, 'lbHealth') ? deps.lbHealth : await readLbHealth().catch(() => null);
295
+ const lbCatalog = narutoOnly
296
+ ? Object.prototype.hasOwnProperty.call(deps, 'lbCatalog')
297
+ ? deps.lbCatalog
298
+ : input.intake?.naruto_model_catalog || await readCodexLbModelCatalog().catch(() => null)
299
+ : null;
300
+ const explicitModel = String(env.SKS_WORKER_MODEL || env.SKS_AGENT_MODEL || '').trim();
301
+ const explicitReasoningRaw = String(env.SKS_WORKER_REASONING || env.SKS_WORKER_MODEL_REASONING || '').trim();
302
+ const explicitTierRaw = String(env.SKS_WORKER_SERVICE_TIER || env.SKS_SERVICE_TIER || '').trim();
303
+ const explicitReasoning = normalizeModelReasoning(explicitReasoningRaw);
304
+ const explicitTier = normalizeServiceTier(explicitTierRaw);
305
+ const explicitNarutoModelInvalid = narutoOnly && Boolean(explicitModel) && !isNarutoGpt56Model(explicitModel);
306
+ const explicitNarutoReasoningInvalid = narutoOnly && Boolean(explicitReasoningRaw) && !explicitReasoning;
307
+ const explicitNarutoTierInvalid = narutoOnly && Boolean(explicitTierRaw) && !explicitTier;
308
+ const routed = explicitModel && !narutoOnly
272
309
  ? {
273
310
  model: explicitModel,
274
311
  reasoning: explicitReasoning || normalizeModelReasoning(input.agent?.model_reasoning_effort) || 'medium',
275
312
  serviceTier: explicitTier || input.fastModePolicy.service_tier || 'fast'
276
313
  }
277
- : await routeModel(category, { lbHealth, model: input.agent?.model || null });
314
+ : await routeModel(category, {
315
+ lbHealth,
316
+ ...(narutoOnly ? {
317
+ narutoOnly: true,
318
+ taskText: taskKindText,
319
+ riskText,
320
+ availableModels: lbCatalog?.models || [],
321
+ availableModelEfforts: lbCatalog?.model_efforts || {},
322
+ ...(explicitModel ? { model: explicitModel } : {})
323
+ } : { model: input.agent?.model || null })
324
+ });
325
+ const blockers = [
326
+ ...(narutoOnly && !lbCatalog?.ok ? (lbCatalog?.blockers || ['codex_lb_model_catalog_unavailable']) : []),
327
+ ...(explicitNarutoModelInvalid ? ['naruto_worker_model_outside_gpt_5_6_family'] : []),
328
+ ...(explicitNarutoReasoningInvalid ? ['naruto_reasoning_override_invalid'] : []),
329
+ ...(explicitNarutoTierInvalid ? ['naruto_service_tier_override_invalid'] : []),
330
+ ...(narutoOnly && explicitReasoning && explicitReasoning !== routed.reasoning ? ['naruto_reasoning_override_conflicts_with_policy'] : []),
331
+ ...(narutoOnly && explicitTier && explicitTier !== 'fast' ? ['naruto_service_tier_override_conflicts_with_policy'] : []),
332
+ ...(narutoOnly && !routed.model ? ['naruto_required_gpt_5_6_model_unavailable'] : [])
333
+ ];
278
334
  return {
279
335
  category,
280
336
  choice: routed,
281
337
  explicit: Boolean(explicitModel),
282
338
  lb_health: lbHealth,
339
+ lb_catalog: lbCatalog,
340
+ blockers: [...new Set(blockers)],
283
341
  reason: modelRouteReason(category, routed, {
284
342
  explicit: Boolean(explicitModel),
285
343
  quotaLow: lbHealth?.quota_low === true,
@@ -289,7 +347,7 @@ async function resolveWorkerModelRouting(input) {
289
347
  }
290
348
  function normalizeModelReasoning(value) {
291
349
  const text = String(value || '').toLowerCase();
292
- return text === 'low' || text === 'medium' || text === 'high' || text === 'xhigh' ? text : null;
350
+ return text === 'low' || text === 'medium' || text === 'high' || text === 'xhigh' || text === 'max' || text === 'ultra' ? text : null;
293
351
  }
294
352
  function normalizeServiceTier(value) {
295
353
  const text = String(value || '').toLowerCase();
@@ -298,6 +356,8 @@ function normalizeServiceTier(value) {
298
356
  async function maybeAutoSelectOllamaBackend(backend, input) {
299
357
  if (backend !== 'codex-sdk')
300
358
  return backend;
359
+ if (isNarutoWorkerRequest(input))
360
+ return backend;
301
361
  if (input.intake?.backend_explicit === true || input.intake?.no_ollama === true)
302
362
  return backend;
303
363
  const config = await resolveOllamaWorkerConfig({
@@ -310,6 +370,18 @@ async function maybeAutoSelectOllamaBackend(backend, input) {
310
370
  const policy = classifyOllamaWorkerSlice(input.slice, { route: input.intake?.route, agent: input.agent });
311
371
  return policy.ok ? 'local-llm' : backend;
312
372
  }
373
+ function isNarutoWorkerRequest(input) {
374
+ return Boolean(input.agent?.naruto_role) || /\$?naruto/i.test(String(input.intake?.route || ''));
375
+ }
376
+ export function narutoWorkerBackendBlocker(backend, narutoRequest = true) {
377
+ if (!narutoRequest)
378
+ return null;
379
+ if (backend === 'process')
380
+ return 'naruto_gpt_5_6_family_only_process_backend_forbidden';
381
+ if (backend === 'ollama' || backend === 'local-llm')
382
+ return 'naruto_gpt_5_6_family_only_local_backend_forbidden';
383
+ return null;
384
+ }
313
385
  function normalizeBackend(value) {
314
386
  return value === 'fake' || value === 'process' || value === 'codex-sdk' || value === 'zellij' || value === 'ollama' || value === 'local-llm' ? value : null;
315
387
  }
@@ -175,24 +175,29 @@ async function runTypecheck(repoRoot) {
175
175
  return runCommand([localTsc, '-p', 'tsconfig.json', '--noEmit'], repoRoot);
176
176
  }
177
177
  async function cleanupWorktreesAndBranches(repoRoot, tmpRoot, workers, before, keepTmp) {
178
+ const removeResults = [];
178
179
  for (const worker of workers) {
179
- await runCommand(['git', 'worktree', 'remove', '--force', path.join(tmpRoot, 'worktrees', worker.id)], repoRoot);
180
+ removeResults.push(await runCommand(['git', 'worktree', 'remove', '--force', path.join(tmpRoot, 'worktrees', worker.id)], repoRoot));
180
181
  }
181
- await runCommand(['git', 'worktree', 'prune'], repoRoot);
182
+ const prune = await runCommand(['git', 'worktree', 'prune'], repoRoot);
183
+ const branchResults = [];
182
184
  for (const worker of workers) {
183
- await runCommand(['git', 'branch', '-D', worker.branch], repoRoot);
185
+ branchResults.push(await runCommand(['git', 'branch', '-D', worker.branch], repoRoot));
184
186
  }
185
187
  const after = await runCommand(['git', 'worktree', 'list', '--porcelain'], repoRoot);
188
+ const branches = await runCommand(['git', 'branch', '--list', ...workers.map((worker) => worker.branch)], repoRoot);
186
189
  const status = await runCommand(['git', 'status', '--short'], repoRoot);
187
190
  if (!keepTmp)
188
- await fsp.rm(tmpRoot, { recursive: true, force: true });
191
+ await fsp.rm(tmpRoot, { recursive: true, force: true, maxRetries: 5, retryDelay: 50 });
189
192
  const tmpRemoved = keepTmp ? false : !(await exists(tmpRoot));
193
+ const workerWorktreesRemoved = after.ok && workers.every((worker) => !after.stdout_tail.includes(worker.id));
194
+ const workerBranchesRemoved = branches.ok && branches.stdout_tail.trim().length === 0;
190
195
  return {
191
- ok: workers.every((worker) => !after.stdout_tail.includes(worker.id) && !after.stdout_tail.includes(worker.branch)) && status.stdout_tail.trim().length === 0 && tmpRemoved,
196
+ ok: removeResults.every((result) => result.ok) && prune.ok && branchResults.every((result) => result.ok) && workerWorktreesRemoved && workerBranchesRemoved && status.ok && status.stdout_tail.trim().length === 0 && tmpRemoved,
192
197
  worktree_list_before_cleanup: before,
193
198
  worktree_list_after_cleanup: after.stdout_tail,
194
- worker_worktrees_removed: workers.every((worker) => !after.stdout_tail.includes(worker.id)),
195
- worker_branches_removed: workers.every((worker) => !after.stdout_tail.includes(worker.branch)),
199
+ worker_worktrees_removed: workerWorktreesRemoved,
200
+ worker_branches_removed: workerBranchesRemoved,
196
201
  parent_dirty_after_cleanup: status.stdout_tail.trim().length > 0,
197
202
  tmp_removed: tmpRemoved
198
203
  };
@@ -200,12 +205,12 @@ async function cleanupWorktreesAndBranches(repoRoot, tmpRoot, workers, before, k
200
205
  async function bestEffortCleanup(repoRoot, tmpRoot, keepTmp) {
201
206
  const before = await runCommand(['git', 'worktree', 'list', '--porcelain'], repoRoot);
202
207
  if (!keepTmp)
203
- await fsp.rm(tmpRoot, { recursive: true, force: true });
208
+ await fsp.rm(tmpRoot, { recursive: true, force: true, maxRetries: 5, retryDelay: 50 });
204
209
  return {
205
- ok: !keepTmp && !(await exists(tmpRoot)),
210
+ ok: false,
206
211
  worktree_list_before_cleanup: before.stdout_tail,
207
212
  worktree_list_after_cleanup: '',
208
- worker_worktrees_removed: true,
213
+ worker_worktrees_removed: false,
209
214
  worker_branches_removed: false,
210
215
  parent_dirty_after_cleanup: false,
211
216
  tmp_removed: !keepTmp && !(await exists(tmpRoot))
@@ -15,6 +15,7 @@ export async function buildRuntimeProofSummary(root, missionIdInput = 'latest',
15
15
  const scheduler = await readJson(path.join(agentsDir, 'agent-scheduler-state.json'), null);
16
16
  const swarm = await readJson(path.join(agentsDir, 'agent-native-cli-session-swarm.json'), null);
17
17
  const telemetry = await readJson(path.join(dir, 'zellij', 'slot-telemetry.snapshot.json'), null);
18
+ const stopGate = await readJson(path.join(dir, 'stop-gate.json'), null);
18
19
  const governor = await readJson(path.join(agentsDir, 'naruto-concurrency-governor.json'), null);
19
20
  const messagesAll = await readAgentMessageBus(root, missionId, { max: 500 });
20
21
  const recentMessages = await readAgentMessageBus(root, missionId, { max: opts.maxMessages || 8 });
@@ -23,15 +24,17 @@ export async function buildRuntimeProofSummary(root, missionIdInput = 'latest',
23
24
  const failedMessages = messagesAll.filter((row) => row.event_type === 'worker_failed');
24
25
  const errorMessages = messagesAll.filter((row) => row.level === 'error');
25
26
  const telemetryAgeMs = telemetry?.updated_at ? Math.max(0, Date.now() - Date.parse(telemetry.updated_at)) : Number.MAX_SAFE_INTEGER;
27
+ const terminalProofAccepted = canonicalTerminalProofAccepted(stopGate, missionId);
26
28
  const visiblePanes = Number(parallel?.visible_panes ?? swarm?.zellij_pane_worker_sessions ?? telemetryVisiblePaneCount(telemetry) ?? 0);
27
29
  const targetActive = Number(scheduler?.target_active_slots ?? parallel?.target_active_slots ?? swarm?.target_active_slots ?? governor?.target_active_slots ?? 0);
28
30
  const headlessWorkers = Number(parallel?.headless_workers ?? swarm?.headless_overflow_worker_count ?? Math.max(0, targetActive - visiblePanes));
31
+ const parallelBlockers = parallel?.passed === false ? parallel.blockers || ['parallel_runtime_proof_failed'] : [];
29
32
  const blockers = [
30
33
  ...(!parallel ? ['parallel_runtime_proof_missing'] : []),
31
34
  ...(!scheduler ? ['agent_scheduler_state_missing'] : []),
32
- ...(parallel?.passed === false ? parallel.blockers || ['parallel_runtime_proof_failed'] : []),
35
+ ...(terminalProofAccepted ? parallelBlockers.filter((blocker) => String(blocker) !== 'speedup_ratio_below_target') : parallelBlockers),
33
36
  ...(errorMessages.length ? ['agent_message_bus_error_blockers'] : []),
34
- ...(telemetryAgeMs > 3000 ? ['zellij_telemetry_stale'] : []),
37
+ ...(telemetryAgeMs > 3000 && !terminalProofAccepted ? ['zellij_telemetry_stale'] : []),
35
38
  ...(zellijSummary?.blockers || [])
36
39
  ].map(String);
37
40
  const summary = {
@@ -76,6 +79,11 @@ export async function buildRuntimeProofSummary(root, missionIdInput = 'latest',
76
79
  duplicate_slot_anchor_count: Number(zellijSummary?.duplicate_slot_anchor_count || 0)
77
80
  },
78
81
  loops: loopSummary,
82
+ terminal_proof: {
83
+ accepted: terminalProofAccepted,
84
+ gate_file: terminalProofAccepted ? 'stop-gate.json' : null,
85
+ terminal_state: terminalProofAccepted ? String(stopGate?.terminal_state || 'completed') : null
86
+ },
79
87
  blockers
80
88
  };
81
89
  await writeJsonAtomic(path.join(agentsDir, 'runtime-proof-summary.json'), summary);
@@ -83,7 +91,8 @@ export async function buildRuntimeProofSummary(root, missionIdInput = 'latest',
83
91
  }
84
92
  export function renderRuntimeProofSummary(summary) {
85
93
  return [
86
- `Parallel proof: ${summary.parallel.proof_passed ? 'passed' : 'blocked'}`,
94
+ `Parallel proof: ${summary.parallel.proof_passed ? 'passed' : summary.terminal_proof?.accepted ? 'terminal gate accepted' : 'blocked'}`,
95
+ `Canonical terminal proof: ${summary.terminal_proof?.accepted ? 'accepted' : 'not available'}`,
87
96
  `Active workers: ${summary.parallel.max_active_workers}`,
88
97
  `Unique PIDs: ${summary.parallel.unique_worker_pids}`,
89
98
  `Speedup: ${summary.parallel.speedup_ratio}x`,
@@ -102,6 +111,15 @@ export function renderRuntimeProofSummary(summary) {
102
111
  ...(summary.blockers.length ? [`Blockers: ${summary.blockers.join(', ')}`] : [])
103
112
  ].join('\n');
104
113
  }
114
+ function canonicalTerminalProofAccepted(gate, missionId) {
115
+ const blockers = Array.isArray(gate?.blockers) ? gate.blockers : [];
116
+ return gate?.schema === 'sks.stop-gate.v1'
117
+ && String(gate?.mission_id || '') === missionId
118
+ && gate?.passed === true
119
+ && gate?.terminal === true
120
+ && String(gate?.terminal_state || '') === 'completed'
121
+ && blockers.length === 0;
122
+ }
105
123
  function messageStatusLabel(row) {
106
124
  if (row.event_type === 'worker_completed')
107
125
  return '[done]';
@@ -1,9 +1,50 @@
1
1
  import fs from 'node:fs/promises';
2
2
  import path from 'node:path';
3
- const IGNORE = new Set(['.git', 'node_modules', 'dist', 'target', '.sneakoscope', '.codex', '.agents', '.next', '.turbo']);
3
+ const IGNORE = new Set([
4
+ '.agents', '.cache', '.claude', '.codex', '.git', '.git-worktrees', '.hg', '.mypy_cache', '.next', '.npm', '.nuxt',
5
+ '.nyc_output', '.parcel-cache', '.pnpm-store', '.pytest_cache', '.ruff_cache', '.sneakoscope', '.svelte-kit', '.svn',
6
+ '.tmp', '.turbo', '.venv', '.worktrees', '.yarn', '__pycache__', 'build', 'coverage', 'dist', 'logs', 'node_modules',
7
+ 'out', 'target', 'temp', 'tmp', 'venv'
8
+ ]);
9
+ const PRIORITY_DIRS = ['src', 'test', 'docs', 'schemas', 'scripts', 'crates', 'bin'];
10
+ const REPRESENTATIVE_DIRS = ['src', 'test', 'docs'];
11
+ const CORE_FILES = ['package.json', 'package-lock.json', 'README.md', 'CHANGELOG.md', 'LICENSE', 'tsconfig.json', 'release-gates.v2.json', 'runtime-required-scripts.json', 'AGENTS.md'];
4
12
  export async function collectRepoInventory(root, opts = {}) {
5
13
  const files = [];
6
- await walk(root, root, files, opts.maxFiles || Number(process.env.SKS_AGENT_REPO_INVENTORY_MAX_FILES || 10000));
14
+ const seen = new Set();
15
+ const requestedMax = Number(opts.maxFiles ?? process.env.SKS_AGENT_REPO_INVENTORY_MAX_FILES ?? 10000);
16
+ const maxFiles = Number.isFinite(requestedMax) ? Math.max(1, Math.floor(requestedMax)) : 10000;
17
+ const add = (file) => {
18
+ if (files.length >= maxFiles || seen.has(file))
19
+ return;
20
+ seen.add(file);
21
+ files.push(file);
22
+ };
23
+ // Seed representative source/test/docs entries before any large tree can
24
+ // exhaust the cap, then expand the priority roots in a stable order.
25
+ for (const name of REPRESENTATIVE_DIRS) {
26
+ const representative = await firstFile(root, path.join(root, name));
27
+ if (representative)
28
+ add(representative);
29
+ }
30
+ for (const name of CORE_FILES) {
31
+ const full = path.join(root, name);
32
+ if ((await fs.stat(full).catch(() => null))?.isFile())
33
+ add(name);
34
+ }
35
+ for (const name of PRIORITY_DIRS)
36
+ await walk(root, path.join(root, name), files, seen, maxFiles);
37
+ for (const entry of await sortedEntries(root)) {
38
+ if (files.length >= maxFiles)
39
+ break;
40
+ if (IGNORE.has(entry.name) || PRIORITY_DIRS.includes(entry.name) || CORE_FILES.includes(entry.name))
41
+ continue;
42
+ const full = path.join(root, entry.name);
43
+ if (entry.isDirectory())
44
+ await walk(root, full, files, seen, maxFiles);
45
+ else if (entry.isFile())
46
+ add(entry.name);
47
+ }
7
48
  const classify = (re) => files.filter((file) => re.test(file));
8
49
  return {
9
50
  schema: 'sks.agent-repo-inventory.v1',
@@ -19,11 +60,10 @@ export async function collectRepoInventory(root, opts = {}) {
19
60
  files
20
61
  };
21
62
  }
22
- async function walk(root, dir, out, maxFiles) {
63
+ async function walk(root, dir, out, seen, maxFiles) {
23
64
  if (out.length >= maxFiles)
24
65
  return;
25
- const entries = await fs.readdir(dir, { withFileTypes: true }).catch(() => []);
26
- for (const entry of entries) {
66
+ for (const entry of await sortedEntries(dir)) {
27
67
  if (out.length >= maxFiles)
28
68
  return;
29
69
  if (IGNORE.has(entry.name))
@@ -31,9 +71,30 @@ async function walk(root, dir, out, maxFiles) {
31
71
  const full = path.join(dir, entry.name);
32
72
  const rel = path.relative(root, full).replace(/\\/g, '/');
33
73
  if (entry.isDirectory())
34
- await walk(root, full, out, maxFiles);
35
- else if (entry.isFile())
74
+ await walk(root, full, out, seen, maxFiles);
75
+ else if (entry.isFile() && !seen.has(rel)) {
76
+ seen.add(rel);
36
77
  out.push(rel);
78
+ }
37
79
  }
38
80
  }
81
+ async function firstFile(root, dir) {
82
+ for (const entry of await sortedEntries(dir)) {
83
+ if (IGNORE.has(entry.name))
84
+ continue;
85
+ const full = path.join(dir, entry.name);
86
+ if (entry.isFile())
87
+ return path.relative(root, full).replace(/\\/g, '/');
88
+ if (entry.isDirectory()) {
89
+ const nested = await firstFile(root, full);
90
+ if (nested)
91
+ return nested;
92
+ }
93
+ }
94
+ return null;
95
+ }
96
+ async function sortedEntries(dir) {
97
+ return (await fs.readdir(dir, { withFileTypes: true }).catch(() => []))
98
+ .sort((a, b) => a.name < b.name ? -1 : a.name > b.name ? 1 : 0);
99
+ }
39
100
  //# sourceMappingURL=repo-inventory.js.map
@@ -194,10 +194,11 @@ async function collectChangedScope(root, opts) {
194
194
  async function listSourceFiles(root, dir = root, out = []) {
195
195
  const entries = await fsp.readdir(dir, { withFileTypes: true }).catch(() => []);
196
196
  for (const entry of entries) {
197
- if (entry.name.startsWith('.') && !['.agents'].includes(entry.name)) {
198
- if (SKIP_DIRS.has(entry.name))
199
- continue;
200
- }
197
+ // Hidden runtime/worktree directories can contain complete repository copies.
198
+ // Only .agents is a source-bearing project directory; all other hidden trees
199
+ // are state, caches, or external workspaces and must stay outside this scan.
200
+ if (entry.name.startsWith('.') && entry.name !== '.agents')
201
+ continue;
201
202
  const full = path.join(dir, entry.name);
202
203
  if (entry.isDirectory()) {
203
204
  if (!SKIP_DIRS.has(entry.name))