sneakoscope 8.0.2 → 8.0.4

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 (376) hide show
  1. package/README.md +150 -37
  2. package/config/skills-hash-ledger.v1.json +1 -1
  3. package/crates/sks-core/Cargo.lock +1 -1
  4. package/crates/sks-core/Cargo.toml +1 -1
  5. package/dist/bin/fast-inline.js +55 -27
  6. package/dist/bin/install.js +6 -32
  7. package/dist/bin/sks-dispatch.js +1 -1
  8. package/dist/cli/args.js +0 -2
  9. package/dist/cli/cli-theme.js +18 -9
  10. package/dist/cli/command-manifest-lite.js +6 -6
  11. package/dist/cli/command-registry.js +6 -6
  12. package/dist/cli/feature-commands.js +9 -7
  13. package/dist/cli/install-helpers-codex-lb-chain.js +198 -7
  14. package/dist/cli/install-helpers-codex-lb-config.js +78 -10
  15. package/dist/cli/install-helpers-install-support.js +9 -6
  16. package/dist/cli/install-helpers.js +101 -49
  17. package/dist/cli/install-tool-helpers.js +2 -82
  18. package/dist/cli/output.js +6 -1
  19. package/dist/cli/router.js +101 -2
  20. package/dist/commands/codex-lb.js +119 -19
  21. package/dist/commands/doctor-profile.js +1 -1
  22. package/dist/commands/doctor.js +727 -144
  23. package/dist/commands/mad-sks.js +1 -5
  24. package/dist/config/skills-manifest.json +4 -2
  25. package/dist/core/agents/agent-codex-cockpit.js +0 -3
  26. package/dist/core/agents/agent-effort-policy.js +5 -5
  27. package/dist/core/agents/agent-janitor.js +0 -20
  28. package/dist/core/agents/agent-orchestrator.js +9 -56
  29. package/dist/core/agents/agent-output-validator.js +2 -3
  30. package/dist/core/agents/agent-patch-schema.js +2 -2
  31. package/dist/core/agents/agent-proof-evidence.js +0 -65
  32. package/dist/core/agents/agent-recursion-guard.js +1 -1
  33. package/dist/core/agents/agent-runner-codex-exec.js +5 -3
  34. package/dist/core/agents/agent-scheduler.js +327 -85
  35. package/dist/core/agents/agent-schema.js +1 -1
  36. package/dist/core/agents/agent-trust-report.js +0 -36
  37. package/dist/core/agents/agent-worker-pipeline.js +0 -1
  38. package/dist/core/agents/fast-mode-policy.js +1 -3
  39. package/dist/core/agents/native-cli-worker-runtime-proof.js +1 -1
  40. package/dist/core/agents/native-cli-worker-runtime.js +69 -647
  41. package/dist/core/agents/native-cli-worker.js +6 -7
  42. package/dist/core/agents/native-worker-backend-router.js +2 -32
  43. package/dist/core/agents/no-subagent-scaling-policy.js +1 -1
  44. package/dist/core/agents/parallel-runtime-proof.js +1 -6
  45. package/dist/core/agents/runtime-proof-summary.js +1 -35
  46. package/dist/core/architecture-hardening/contracts/contracts.js +193 -0
  47. package/dist/core/architecture-hardening/migration/migration.js +111 -0
  48. package/dist/core/architecture-hardening/state/state-service.js +155 -0
  49. package/dist/core/artifact-schemas.js +0 -3
  50. package/dist/core/codex/codex-config-guard.js +238 -52
  51. package/dist/core/codex-adapter.js +5 -3
  52. package/dist/core/codex-app/auxiliary-oauth-policy.js +36 -0
  53. package/dist/core/codex-app/catalog-compat/catalog-service.js +104 -0
  54. package/dist/core/codex-app/child-policy/child-policy.js +35 -0
  55. package/dist/core/codex-app/codex-app-handoff.js +0 -1
  56. package/dist/core/codex-app/codex-hook-lifecycle.js +1 -1
  57. package/dist/core/codex-app/codex-init-deep.js +1 -1
  58. package/dist/core/codex-app/menubar/app-bundle.js +2 -0
  59. package/dist/core/codex-app/menubar/constants.js +14 -1
  60. package/dist/core/codex-app/menubar/global-install.js +288 -0
  61. package/dist/core/codex-app/menubar/installer.js +79 -14
  62. package/dist/core/codex-app/menubar/launch-agent.js +267 -45
  63. package/dist/core/codex-app/menubar/paths.js +3 -0
  64. package/dist/core/codex-app/menubar/rollback.js +55 -7
  65. package/dist/core/codex-app/menubar/status.js +75 -4
  66. package/dist/core/codex-app/provider-child-policy.js +64 -0
  67. package/dist/core/codex-app/provider-mode.js +91 -0
  68. package/dist/core/codex-app/provider-operation-stages.js +20 -0
  69. package/dist/core/codex-app/provider-session-policy.js +85 -0
  70. package/dist/core/codex-app/session-policy/session-pinning.js +68 -0
  71. package/dist/core/codex-app.js +3 -2
  72. package/dist/core/codex-control/codex-0139-image-path-real-probe.js +3 -1
  73. package/dist/core/codex-control/codex-0139-web-search-probe.js +3 -1
  74. package/dist/core/codex-control/codex-app-server-runtime-env.js +13 -4
  75. package/dist/core/codex-control/codex-app-server-v2-client.js +3 -3
  76. package/dist/core/codex-control/codex-control-proof.js +0 -1
  77. package/dist/core/codex-control/codex-task-runner.js +1 -4
  78. package/dist/core/codex-exec-output-schema.js +4 -1
  79. package/dist/core/codex-lb/codex-lb-env.js +63 -72
  80. package/dist/core/codex-lb/codex-lb-setup.js +15 -2
  81. package/dist/core/codex-lb/desktop-bridge/header-policy.js +6 -0
  82. package/dist/core/codex-lb/desktop-bridge/http-forward.js +48 -6
  83. package/dist/core/codex-lb/desktop-bridge/security.js +134 -0
  84. package/dist/core/codex-lb/desktop-bridge/server.js +9 -3
  85. package/dist/core/codex-lb/desktop-bridge/state.js +26 -6
  86. package/dist/core/codex-lb/desktop-bridge/types.js +1 -0
  87. package/dist/core/codex-lb/desktop-center-credentials.js +517 -58
  88. package/dist/core/codex-lb/desktop-controller.js +177 -56
  89. package/dist/core/codex-lb/desktop-service.js +179 -40
  90. package/dist/core/codex-lb/legacy-migration.js +1 -3
  91. package/dist/core/codex-lb/native-openai-transport/transport.js +68 -0
  92. package/dist/core/codex-lb/probes/cli-image-tool-probe.js +1 -1
  93. package/dist/core/codex-lb/provider-routing/provider-router.js +58 -0
  94. package/dist/core/codex-lb/routing-truth.js +327 -0
  95. package/dist/core/codex-native/codex-native-feature-broker.js +4 -0
  96. package/dist/core/codex-native/codex-native-pattern-analysis.js +1 -2
  97. package/dist/core/codex-native/core-skill-manifest.js +1 -1
  98. package/dist/core/codex-plugins/codex-plugin-json.js +26 -6
  99. package/dist/core/codex-plugins/codex-plugin-repair.js +32 -6
  100. package/dist/core/commands/basic-cli.js +9 -7
  101. package/dist/core/commands/computer-use-command.js +1 -1
  102. package/dist/core/commands/image-ux-review-command.js +16 -9
  103. package/dist/core/commands/install-package-command.js +105 -0
  104. package/dist/core/commands/intent-normalization/normalizer.js +96 -0
  105. package/dist/core/commands/mad-sks-command.js +23 -274
  106. package/dist/core/commands/mad-sks-headless.js +11 -30
  107. package/dist/core/commands/naruto-command.js +0 -25
  108. package/dist/core/commands/qa-loop-command.js +104 -22
  109. package/dist/core/commands/remote-command.js +2 -2
  110. package/dist/core/commands/research-command.js +10 -5
  111. package/dist/core/commands/telegram-command.js +407 -0
  112. package/dist/core/config-adopt/config-adopt-command.js +35 -0
  113. package/dist/core/config-adopt/config-adopt.js +346 -0
  114. package/dist/core/config-adopt/index.js +3 -0
  115. package/dist/core/doctor/command-alias-cleanup.js +4 -1
  116. package/dist/core/doctor/current-project-guidance-nested.js +37 -6
  117. package/dist/core/doctor/current-project-guidance.js +15 -9
  118. package/dist/core/doctor/doctor-dirty-planner.js +1 -4
  119. package/dist/core/doctor/doctor-readiness-matrix.js +15 -18
  120. package/dist/core/doctor/retired-managed-residue-private.js +4 -3
  121. package/dist/core/doctor/retired-managed-residue-runtime.js +2 -2
  122. package/dist/core/doctor/skill-legacy-surface.js +11 -10
  123. package/dist/core/doctor/sks-menubar-doctor.js +4 -0
  124. package/dist/core/evaluation.js +0 -19
  125. package/dist/core/evidence/v2/evidence-key.js +105 -0
  126. package/dist/core/feature-fixtures.js +12 -7
  127. package/dist/core/feature-registry.js +52 -21
  128. package/dist/core/hooks-runtime/hook-context.js +9 -0
  129. package/dist/core/hooks-runtime/managed-skill-admission.js +54 -4
  130. package/dist/core/hooks-runtime/official-subagent-lifecycle.js +69 -52
  131. package/dist/core/hooks-runtime/stop-finalization.js +226 -0
  132. package/dist/core/hooks-runtime/stop-repeat-guard.js +21 -2
  133. package/dist/core/hooks-runtime/subagent-skill-availability-contract.js +2 -2
  134. package/dist/core/hooks-runtime/subagent-skill-availability-evidence.js +3 -3
  135. package/dist/core/hooks-runtime/subagent-skill-availability-guards.js +43 -5
  136. package/dist/core/hooks-runtime/subagent-skill-availability.js +64 -30
  137. package/dist/core/hooks-runtime/subagent-stop-hook.js +15 -2
  138. package/dist/core/hooks-runtime.js +179 -212
  139. package/dist/core/image/reference-evidence/reference-registry.js +145 -0
  140. package/dist/core/image-ux-review/imagegen-adapter.js +21 -9
  141. package/dist/core/image-ux-review/reference-policy/reference-policy.js +9 -0
  142. package/dist/core/imagegen/codex-lb-imagegen-target.js +8 -0
  143. package/dist/core/imagegen/imagegen-capability.js +59 -2
  144. package/dist/core/imagegen/require-imagegen.js +2 -2
  145. package/dist/core/init/skills.js +17 -3
  146. package/dist/core/init.js +3 -3
  147. package/dist/core/install/installed-package-smoke.js +23 -5
  148. package/dist/core/json/canonical.js +9 -0
  149. package/dist/core/locks/file-lock.js +0 -1
  150. package/dist/core/loops/loop-continuation-enforcer.js +65 -7
  151. package/dist/core/loops/loop-decomposer.js +0 -1
  152. package/dist/core/loops/loop-gate-runner.js +65 -4
  153. package/dist/core/loops/loop-gate-selector.js +0 -2
  154. package/dist/core/loops/loop-proof-validation.js +38 -0
  155. package/dist/core/loops/loop-risk-classifier.js +1 -1
  156. package/dist/core/loops/loop-runtime.js +14 -2
  157. package/dist/core/loops/loop-scheduler.js +7 -2
  158. package/dist/core/loops/loop-worker-runtime.js +0 -15
  159. package/dist/core/loops/loop-worktree-runtime.js +52 -4
  160. package/dist/core/managed-assets/managed-assets-manifest.js +14 -14
  161. package/dist/core/naruto/hardware-capacity-probe.js +9 -6
  162. package/dist/core/naruto/naruto-active-pool.js +2 -14
  163. package/dist/core/naruto/naruto-concurrency-governor.js +71 -31
  164. package/dist/core/naruto/naruto-loop-worker-router.js +0 -2
  165. package/dist/core/naruto/naruto-verification-dag.js +0 -1
  166. package/dist/core/naruto/naruto-write-e2e.js +1 -2
  167. package/dist/core/naruto/resource-pressure-monitor.js +0 -4
  168. package/dist/core/observability/architecture-hardening/safe-projection.js +65 -0
  169. package/dist/core/perf/import-graph-budget.js +0 -1
  170. package/dist/core/perf/release-latency-slo.js +3 -2
  171. package/dist/core/preflight/parallel-preflight-engine.js +2 -15
  172. package/dist/core/product-design-app-server.js +13 -1
  173. package/dist/core/proof/fake-real-proof-policy.js +2 -17
  174. package/dist/core/proof/route-proof-gate.js +2 -10
  175. package/dist/core/proof/route-proof-policy.js +1 -1
  176. package/dist/core/proof/runtime-evidence-policy.js +185 -0
  177. package/dist/core/proof/runtime-truth-matrix.js +64 -39
  178. package/dist/core/proof/validation.js +27 -11
  179. package/dist/core/provider/provider-context.js +18 -2
  180. package/dist/core/providers/openrouter/openrouter-account.js +3 -2
  181. package/dist/core/python-tools/python-tool-runner.js +1 -1
  182. package/dist/core/qa-loop/qa-execution-control.js +57 -0
  183. package/dist/core/questions.js +1 -1
  184. package/dist/core/release/extreme-parallel-scheduler.js +0 -3
  185. package/dist/core/release/gate-manifest.js +3 -7
  186. package/dist/core/release/gate-pack-manifest.js +3 -7
  187. package/dist/core/release/package-size-budget.js +2 -2
  188. package/dist/core/release/physical-release-gates.js +189 -0
  189. package/dist/core/release/publish-preflight.js +113 -0
  190. package/dist/core/release/release-gate-affected-selector.js +0 -2
  191. package/dist/core/release/release-gate-batch-runner.js +1 -1
  192. package/dist/core/release/release-gate-node.js +0 -1
  193. package/dist/core/release/release-gate-resource-governor.js +0 -1
  194. package/dist/core/release/release-pack-receipt.js +5 -8
  195. package/dist/core/release/release-real-contract.js +0 -6
  196. package/dist/core/release/resource-class-budget.js +0 -1
  197. package/dist/core/release/stage-publish.js +178 -36
  198. package/dist/core/research/research-adversarial-review.js +103 -9
  199. package/dist/core/research.js +1 -1
  200. package/dist/core/retention.js +0 -1
  201. package/dist/core/routes/constants.js +1 -1
  202. package/dist/core/routes/diagnostic-allowlist.js +0 -1
  203. package/dist/core/routes/dollar-manifest-lite.js +1 -1
  204. package/dist/core/routes.js +46 -15
  205. package/dist/core/runtime/execution-control.js +226 -0
  206. package/dist/core/runtime/progress-recovery/progress-recovery.js +89 -0
  207. package/dist/core/runtime/task-profile.js +10 -4
  208. package/dist/core/runtime/verification-budget.js +10 -1
  209. package/dist/core/safety/intent-contract/intent-contract.js +94 -0
  210. package/dist/core/safety/mutation-guard.js +0 -2
  211. package/dist/core/safety/mutation-ledger.js +0 -2
  212. package/dist/core/safety/requested-scope-contract.js +0 -0
  213. package/dist/core/search-visibility/discovery.js +1 -1
  214. package/dist/core/search-visibility/index.js +12 -0
  215. package/dist/core/search-visibility/verifier.js +112 -3
  216. package/dist/core/security/private-credential-file.js +209 -0
  217. package/dist/core/session/project-namespace.js +0 -5
  218. package/dist/core/skills/skill-agent-metadata.js +1 -3
  219. package/dist/core/strategy/adhd-orchestrating-gate.js +0 -1
  220. package/dist/core/subagents/agent-catalog.js +19 -34
  221. package/dist/core/subagents/model-policy.js +65 -24
  222. package/dist/core/subagents/naruto-help-contract.js +8 -8
  223. package/dist/core/subagents/naruto-host-credentials.js +13 -0
  224. package/dist/core/subagents/official-subagent-config.js +16 -6
  225. package/dist/core/subagents/official-subagent-preparation.js +35 -16
  226. package/dist/core/subagents/official-subagent-prompt.js +7 -7
  227. package/dist/core/subagents/official-subagent-runner.js +27 -4
  228. package/dist/core/subagents/role-model-preferences.js +1 -1
  229. package/dist/core/subagents/thread-budget.js +19 -12
  230. package/dist/core/subagents/wave-lifecycle.js +18 -6
  231. package/dist/core/telegram/access.js +58 -0
  232. package/dist/core/telegram/client.js +157 -0
  233. package/dist/core/telegram/confirmation.js +37 -0
  234. package/dist/core/telegram/doctor.js +154 -0
  235. package/dist/core/telegram/index.js +9 -0
  236. package/dist/core/telegram/keychain.js +317 -0
  237. package/dist/core/telegram/liveness.js +118 -0
  238. package/dist/core/telegram/poller.js +90 -0
  239. package/dist/core/telegram/redaction.js +15 -0
  240. package/dist/core/telegram/state-lock.js +416 -0
  241. package/dist/core/telegram/types.js +1 -0
  242. package/dist/core/text/strings.js +3 -0
  243. package/dist/core/triwiki/context-graph/store/evidence-write-lock.js +29 -0
  244. package/dist/core/triwiki/context-graph/store/fragment-cache.js +24 -0
  245. package/dist/core/triwiki/context-graph/store/snapshot-store.js +69 -21
  246. package/dist/core/triwiki/triwiki-gate-impact-map.js +2 -2
  247. package/dist/core/triwiki/triwiki-module-card.js +1 -2
  248. package/dist/core/update/installed-cli-resolution.js +170 -0
  249. package/dist/core/update/update-diagnostics.js +52 -0
  250. package/dist/core/update/update-migration-state.js +30 -12
  251. package/dist/core/update/update-operation.js +2 -1
  252. package/dist/core/update/update-stage-diagnostics.js +38 -0
  253. package/dist/core/update/update-status.js +2 -9
  254. package/dist/core/update-check.js +279 -91
  255. package/dist/core/version.js +1 -1
  256. package/dist/native/sks-menubar/Sources/AppDelegate.swift +19 -1
  257. package/dist/native/sks-menubar/Sources/AppIdentity.swift +7 -0
  258. package/dist/native/sks-menubar/Sources/ControlCenterWindowController.swift +6 -2
  259. package/dist/native/sks-menubar/Sources/OperationCoordinator.swift +159 -92
  260. package/dist/native/sks-menubar/Sources/OperationModels.swift +389 -0
  261. package/dist/native/sks-menubar/Sources/OverviewViewController.swift +57 -0
  262. package/dist/native/sks-menubar/Sources/ProcessClient.swift +3 -1
  263. package/dist/native/sks-menubar/Sources/ProvidersConnectTest.swift +115 -0
  264. package/dist/native/sks-menubar/Sources/ProvidersFastMode.swift +17 -0
  265. package/dist/native/sks-menubar/Sources/ProvidersMultiProvider.swift +3 -0
  266. package/dist/native/sks-menubar/Sources/ProvidersOpenRouter.swift +58 -17
  267. package/dist/native/sks-menubar/Sources/ProvidersReliability.swift +302 -0
  268. package/dist/native/sks-menubar/Sources/ProvidersRoleModels.swift +5 -0
  269. package/dist/native/sks-menubar/Sources/ProvidersRoutingTruth.swift +190 -0
  270. package/dist/native/sks-menubar/Sources/ProvidersViewController.swift +158 -126
  271. package/dist/native/sks-menubar/Sources/RemoteCodingViewController.swift +462 -26
  272. package/dist/native/sks-menubar/Sources/SKSKeychainStore.swift +344 -0
  273. package/dist/native/sks-menubar/Sources/SecureProcessEnvelope.swift +27 -0
  274. package/dist/native/sks-menubar/Sources/SingletonInstanceGuard.swift +328 -0
  275. package/dist/native/sks-menubar/Sources/StatusItemController.swift +10 -2
  276. package/dist/native/sks-menubar/Sources/TelegramPrivateFileStore.swift +498 -0
  277. package/dist/native/sks-menubar/Sources/TelegramPrivateFileSupport.swift +236 -0
  278. package/dist/native/sks-menubar/Sources/TelegramProcessGateway.swift +454 -0
  279. package/dist/native/sks-menubar/Sources/TelegramRuntimeSupport.swift +56 -0
  280. package/dist/native/sks-menubar/Sources/TelegramStateLock.swift +448 -0
  281. package/dist/native/sks-menubar/Sources/TelegramSupport.swift +187 -0
  282. package/dist/native/sks-menubar/Sources/TelegramTransport.swift +499 -0
  283. package/dist/native/sks-menubar/Sources/main.swift +15 -1
  284. package/dist/scripts/all-feature-deep-completion-check.js +5 -1
  285. package/dist/scripts/check-publish-tag.js +56 -0
  286. package/dist/scripts/codex-lb-fast-mode-truth-check.js +10 -3
  287. package/dist/scripts/codex-lb-fast-ui-preservation-check.js +12 -3
  288. package/dist/scripts/codex-lb-gpt56-fast-profile-check.js +4 -2
  289. package/dist/scripts/codex-native-agent-role-content-check.js +3 -3
  290. package/dist/scripts/codex-native-gate-lib.js +14 -7
  291. package/dist/scripts/current-command-surface-check.js +7 -7
  292. package/dist/scripts/current-surface-update-e2e-check.js +4 -3
  293. package/dist/scripts/current-upgrade-matrix-check.js +5 -24
  294. package/dist/scripts/docs-truthfulness-check.js +17 -13
  295. package/dist/scripts/gate-lib.js +0 -2
  296. package/dist/scripts/gate-policy-audit-check.js +3 -2
  297. package/dist/scripts/harness-benchmark-check.js +1 -1
  298. package/dist/scripts/init-deep-backup-retention-check.js +1 -1
  299. package/dist/scripts/lib/codex-sdk-gate-lib.js +1 -2
  300. package/dist/scripts/loop-directive-check-lib.js +28 -38
  301. package/dist/scripts/mad-sks-app-ui-no-mutation-check.js +14 -180
  302. package/dist/scripts/mad-sks-launch-sql-plane-boundary-check.js +2 -11
  303. package/dist/scripts/official-subagent-workflow-check.js +1 -1
  304. package/dist/scripts/packlist-performance-check.js +1 -2
  305. package/dist/scripts/prepublish-release-check-or-fast.js +32 -0
  306. package/dist/scripts/publish-preflight.js +12 -0
  307. package/dist/scripts/release-affected-selector-check.js +2 -2
  308. package/dist/scripts/release-gate-batch-runner-check.js +2 -2
  309. package/dist/scripts/release-metadata-check.js +8 -12
  310. package/dist/scripts/release-real-check.js +2 -54
  311. package/dist/scripts/runtime-domain-gate-lib.js +2 -96
  312. package/dist/scripts/runtime-proof-summary-check.js +2 -6
  313. package/dist/scripts/search-visibility-gate-lib.js +0 -1
  314. package/dist/scripts/sks-cli-gate-lib.js +1 -1
  315. package/dist/scripts/typed-routing-gate-lib.js +7 -59
  316. package/docs/demo.tape +1 -1
  317. package/infra-harness-gates.json +1 -1456
  318. package/package.json +10 -7
  319. package/release-gates.v2.json +0 -1
  320. package/schemas/agents/parallel-runtime-proof.schema.json +0 -2
  321. package/schemas/codex/agent-result.schema.json +0 -6
  322. package/schemas/naruto/naruto-concurrency-governor.schema.json +1 -3
  323. package/schemas/release/release-gate-node.schema.json +1 -1
  324. package/dist/commands/zellij-lane.js +0 -22
  325. package/dist/commands/zellij-monitor-pane.js +0 -26
  326. package/dist/commands/zellij-slot-column-anchor.js +0 -22
  327. package/dist/commands/zellij-slot-pane.js +0 -80
  328. package/dist/commands/zellij-viewport-pane.js +0 -57
  329. package/dist/commands/zellij.js +0 -422
  330. package/dist/core/agents/agent-runner-zellij.js +0 -164
  331. package/dist/core/agents/agent-slot-pane-binding-proof.js +0 -96
  332. package/dist/core/agents/parallel-write-fixture.js +0 -305
  333. package/dist/core/agents/worker-pane-communication-contract.js +0 -100
  334. package/dist/core/agents/zellij-lane-supervisor.js +0 -428
  335. package/dist/core/agents/zellij-right-lane-cockpit.js +0 -66
  336. package/dist/core/doctor/doctor-zellij-repair.js +0 -40
  337. package/dist/core/ops/upgrade-migration-fixtures.js +0 -119
  338. package/dist/core/proof/route-finalizer-fixtures.js +0 -21
  339. package/dist/core/zellij/homebrew-policy.js +0 -43
  340. package/dist/core/zellij/zellij-capability.js +0 -126
  341. package/dist/core/zellij/zellij-clipboard-config.js +0 -52
  342. package/dist/core/zellij/zellij-command.js +0 -149
  343. package/dist/core/zellij/zellij-fake-adapter.js +0 -186
  344. package/dist/core/zellij/zellij-lane-renderer.js +0 -706
  345. package/dist/core/zellij/zellij-lane-runtime.js +0 -189
  346. package/dist/core/zellij/zellij-launcher.js +0 -268
  347. package/dist/core/zellij/zellij-layout-builder.js +0 -191
  348. package/dist/core/zellij/zellij-monitor-renderer.js +0 -52
  349. package/dist/core/zellij/zellij-official-subagent-activity.js +0 -526
  350. package/dist/core/zellij/zellij-official-subagent-telemetry.js +0 -258
  351. package/dist/core/zellij/zellij-pane-proof.js +0 -226
  352. package/dist/core/zellij/zellij-right-column-manager.js +0 -308
  353. package/dist/core/zellij/zellij-screen-proof.js +0 -120
  354. package/dist/core/zellij/zellij-self-heal-types.js +0 -44
  355. package/dist/core/zellij/zellij-self-heal.js +0 -408
  356. package/dist/core/zellij/zellij-slot-column-anchor.js +0 -304
  357. package/dist/core/zellij/zellij-slot-pane-renderer.js +0 -521
  358. package/dist/core/zellij/zellij-slot-telemetry.js +0 -384
  359. package/dist/core/zellij/zellij-theme.js +0 -66
  360. package/dist/core/zellij/zellij-ui-mode.js +0 -34
  361. package/dist/core/zellij/zellij-update.js +0 -348
  362. package/dist/core/zellij/zellij-viewport-binder.js +0 -61
  363. package/dist/core/zellij/zellij-worker-pane-manager.js +0 -881
  364. package/dist/core/zellij/zellij-worker-pane-summary.js +0 -64
  365. package/dist/native/sks-menubar/Tests/AppRuntimeTestSupport.swift +0 -26
  366. package/dist/native/sks-menubar/Tests/OperationCoordinatorTests.swift +0 -174
  367. package/dist/native/sks-menubar/Tests/ProcessClientTests.swift +0 -20
  368. package/dist/native/sks-menubar/Tests/ProvidersViewControllerTests.swift +0 -142
  369. package/dist/scripts/zellij-pane-proof-check.js +0 -88
  370. package/dist/scripts/zellij-real-session-cleanup-check.js +0 -139
  371. package/dist/scripts/zellij-real-session-launch-check.js +0 -126
  372. package/dist/scripts/zellij-screen-proof-check.js +0 -43
  373. package/schemas/zellij/zellij-right-column-state.schema.json +0 -40
  374. package/schemas/zellij/zellij-slot-telemetry.schema.json +0 -89
  375. package/schemas/zellij/zellij-worker-pane.schema.json +0 -53
  376. package/scripts/build-clean-atomic.mjs +0 -323
@@ -1,126 +0,0 @@
1
- #!/usr/bin/env node
2
- import fs from 'node:fs/promises';
3
- import { createHash } from 'node:crypto';
4
- import path from 'node:path';
5
- import { pathToFileURL } from 'node:url';
6
- import { ensureDistFresh, root } from './lib/ensure-dist-fresh.js';
7
- const freshness = ensureDistFresh({ rebuild: true });
8
- if (!freshness.ok)
9
- fail('dist_not_fresh', { freshness });
10
- const args = process.argv.slice(2);
11
- const runSuffix = `${process.pid}-${Date.now().toString(36)}`;
12
- const missionId = readArg(args, '--mission') || `M-zellij-real-check-${runSuffix}`;
13
- const sessionName = readArg(args, '--session') || `sks-real-${runSuffix}`;
14
- const requireReal = process.env.SKS_REQUIRE_ZELLIJ === '1' || args.includes('--require-real');
15
- const mainOnly = args.includes('--main-only') || process.env.SKS_ZELLIJ_MAIN_ONLY === '1';
16
- const ownedSession = args.includes('--owned-session');
17
- const ownerToken = String(process.env.SKS_ZELLIJ_CHECK_OWNER_TOKEN || '');
18
- const launcher = await import(pathToFileURL(path.join(root, 'dist', 'core', 'zellij', 'zellij-launcher.js')).href);
19
- const command = await import(pathToFileURL(path.join(root, 'dist', 'core', 'zellij', 'zellij-command.js')).href);
20
- const screenProof = await import(pathToFileURL(path.join(root, 'dist', 'core', 'zellij', 'zellij-screen-proof.js')).href);
21
- const socketDir = command.resolveZellijProcessEnvMeta().zellij_socket_dir;
22
- const missionRoot = path.join(root, '.sneakoscope', 'missions', missionId);
23
- const ownershipPath = path.join(missionRoot, 'zellij-real-session-ownership.json');
24
- const expectedLayoutPath = path.join(root, '.sneakoscope', 'layouts', `mad-${missionId}.kdl`);
25
- let ownership = null;
26
- if (ownedSession) {
27
- if (!isSafeOwnedSocketDir(socketDir))
28
- fail('zellij_owned_socket_dir_invalid', { socket_dir: socketDir });
29
- if (ownerToken.length < 32)
30
- fail('zellij_owner_token_missing', { owner_token_present: ownerToken.length > 0 });
31
- const [markerExists, socketExists] = await Promise.all([exists(ownershipPath), exists(socketDir)]);
32
- if (markerExists)
33
- fail('zellij_ownership_marker_collision', { ownership_path: ownershipPath });
34
- if (socketExists)
35
- fail('zellij_owned_socket_dir_collision', { socket_dir: socketDir });
36
- ownership = {
37
- schema: 'sks.zellij-real-session-ownership.v1',
38
- mission_id: missionId,
39
- session_name: sessionName,
40
- socket_dir: socketDir,
41
- owner_token_sha256: hashOwnerToken(ownerToken),
42
- cleanup_authorized: true,
43
- layout_cleanup_authorized: true,
44
- layout_path: expectedLayoutPath,
45
- layout_sha256: null,
46
- state: 'prepared',
47
- session_created: false
48
- };
49
- await fs.mkdir(missionRoot, { recursive: true });
50
- await fs.writeFile(ownershipPath, `${JSON.stringify(ownership, null, 2)}\n`, { flag: 'wx', mode: 0o600 });
51
- }
52
- const report = await launcher.launchMadZellijUi(['--session', sessionName], {
53
- root,
54
- missionId,
55
- ledgerRoot: path.join(root, '.sneakoscope', 'missions', missionId, 'agents'),
56
- dryRun: false,
57
- requireZellij: requireReal,
58
- slotCount: 1
59
- });
60
- const sessionCollision = Array.isArray(report?.launch?.create_background?.warnings)
61
- && report.launch.create_background.warnings.some((warning) => String(warning).startsWith('zellij_session_already_exists:'));
62
- const layoutPathValid = !ownedSession || path.resolve(String(report?.layout_path || '')) === path.resolve(expectedLayoutPath);
63
- const layoutSha256 = ownedSession && layoutPathValid ? await sha256File(expectedLayoutPath) : null;
64
- if (ownership) {
65
- ownership = {
66
- ...ownership,
67
- state: report?.launch?.create_background?.ok === true && !sessionCollision ? 'launched' : 'launch_failed',
68
- session_created: report?.launch?.create_background?.ok === true && !sessionCollision,
69
- layout_path_valid: layoutPathValid,
70
- layout_sha256: layoutSha256,
71
- launch_exit_code: report?.launch?.create_background?.exit_code ?? null
72
- };
73
- await fs.writeFile(ownershipPath, `${JSON.stringify(ownership, null, 2)}\n`, { mode: 0o600 });
74
- }
75
- const heartbeatPath = path.join(root, '.sneakoscope', 'missions', missionId, 'zellij-lane-renderer-heartbeat.jsonl');
76
- const heartbeat = mainOnly
77
- ? { ok: true, heartbeat_present: false, waited_ms: 0, timeout_ms: 0, blocker: null, skipped: true }
78
- : await screenProof.waitForLaneHeartbeat(heartbeatPath, { timeoutMs: 5000 });
79
- const blockers = [
80
- ...(sessionCollision ? ['zellij_session_name_collision'] : []),
81
- ...(ownedSession && !layoutPathValid ? ['zellij_owned_layout_path_invalid'] : []),
82
- ...(ownedSession && !layoutSha256 ? ['zellij_owned_layout_hash_missing'] : []),
83
- ...(requireReal && report.ok !== true ? ['zellij_real_session_launch_failed'] : []),
84
- ...(requireReal && heartbeat.blocker ? [heartbeat.blocker] : [])
85
- ];
86
- const gate = {
87
- schema: 'sks.zellij-real-session-launch-check.v1',
88
- ok: requireReal ? (report.ok === true && heartbeat.ok === true && blockers.length === 0) : (report.ok === true && blockers.length === 0),
89
- integration_optional: !requireReal,
90
- main_only: mainOnly,
91
- mission_id: missionId,
92
- session_name: sessionName,
93
- owned_session: ownedSession,
94
- ownership_path: ownership ? ownershipPath : null,
95
- socket_dir: socketDir,
96
- heartbeat: { path: heartbeatPath, present: heartbeat.heartbeat_present, waited_ms: heartbeat.waited_ms, timeout_ms: heartbeat.timeout_ms },
97
- blockers,
98
- report
99
- };
100
- await fs.mkdir(path.join(root, '.sneakoscope', 'reports'), { recursive: true });
101
- await fs.writeFile(path.join(root, '.sneakoscope', 'reports', 'zellij-real-session-launch.json'), `${JSON.stringify(gate, null, 2)}\n`);
102
- emit(gate);
103
- function emit(report) { console.log(JSON.stringify(report, null, 2)); if (!report.ok)
104
- process.exitCode = 1; }
105
- function fail(blocker, detail) { emit({ schema: 'sks.zellij-real-session-launch-check.v1', ok: false, blockers: [blocker], detail }); process.exit(1); }
106
- function readArg(args, name) {
107
- const index = args.indexOf(name);
108
- return index >= 0 ? args[index + 1] || null : null;
109
- }
110
- function hashOwnerToken(value) {
111
- return createHash('sha256').update(String(value)).digest('hex');
112
- }
113
- async function sha256File(file) {
114
- return fs.readFile(file).then((data) => createHash('sha256').update(data).digest('hex')).catch(() => null);
115
- }
116
- function isSafeOwnedSocketDir(value) {
117
- if (!value)
118
- return false;
119
- const resolved = path.resolve(String(value));
120
- return path.dirname(resolved) === '/tmp' && /^sks-zj-rr-[A-Za-z0-9-]+$/.test(path.basename(resolved));
121
- }
122
- async function exists(value) {
123
- if (!value)
124
- return false;
125
- return fs.access(value).then(() => true).catch(() => false);
126
- }
@@ -1,43 +0,0 @@
1
- #!/usr/bin/env node
2
- import path from 'node:path';
3
- import { pathToFileURL } from 'node:url';
4
- import { ensureDistFresh, root } from './lib/ensure-dist-fresh.js';
5
- const freshness = ensureDistFresh({ rebuild: true });
6
- if (!freshness.ok)
7
- fail('dist_not_fresh', { freshness });
8
- const mod = await import(pathToFileURL(path.join(root, 'dist', 'core', 'zellij', 'zellij-screen-proof.js')).href);
9
- const args = process.argv.slice(2);
10
- const missionId = readArg(args, '--mission');
11
- const mainOnly = args.includes('--main-only') || process.env.SKS_ZELLIJ_MAIN_ONLY === '1';
12
- if (missionId && !mainOnly)
13
- await waitForHeartbeat([
14
- path.join(root, '.sneakoscope', 'missions', missionId, 'zellij-lane-renderer-heartbeat.jsonl'),
15
- path.join(root, '.sneakoscope', 'missions', missionId, 'agents', 'zellij-lane-renderer-heartbeat.jsonl')
16
- ]);
17
- const report = await mod.writeZellijScreenProof(root, {
18
- require: process.env.SKS_REQUIRE_ZELLIJ === '1' || args.includes('--require-real'),
19
- missionId: missionId || undefined,
20
- ledgerRoot: missionId ? path.join(root, '.sneakoscope', 'missions', missionId) : undefined,
21
- mainOnly
22
- });
23
- const requiredTextOk = ['SKS Lane', 'Mission', 'Mode', 'Workers', 'Current', 'Queue', 'Safety', 'Blockers', 'Reports', 'Keys:'].every((label) => report.required_text?.includes(label));
24
- emit({ ...report, required_text_fixture_ok: requiredTextOk, ok: report.ok && requiredTextOk });
25
- function emit(report) { console.log(JSON.stringify(report, null, 2)); if (!report.ok)
26
- process.exitCode = 1; }
27
- function fail(blocker, detail) { emit({ schema: 'sks.zellij-screen-proof-check.v1', ok: false, blockers: [blocker], detail }); process.exit(1); }
28
- function readArg(args, name) {
29
- const index = args.indexOf(name);
30
- return index >= 0 ? args[index + 1] || null : null;
31
- }
32
- async function waitForHeartbeat(files) {
33
- const fs = await import('node:fs/promises');
34
- const deadline = Date.now() + 5000;
35
- while (Date.now() < deadline) {
36
- for (const file of files) {
37
- const text = await fs.readFile(file, 'utf8').catch(() => '');
38
- if (text.trim())
39
- return;
40
- }
41
- await new Promise((resolve) => setTimeout(resolve, 250));
42
- }
43
- }
@@ -1,40 +0,0 @@
1
- {
2
- "$schema": "https://json-schema.org/draft/2020-12/schema",
3
- "$id": "sks.zellij-right-column-state.v1",
4
- "type": "object",
5
- "required": ["schema", "mission_id", "session_name", "status", "visible_worker_panes", "headless_workers", "blockers"],
6
- "properties": {
7
- "schema": { "const": "sks.zellij-right-column-state.v1" },
8
- "mission_id": { "type": "string" },
9
- "session_name": { "type": "string" },
10
- "status": { "enum": ["absent", "creating", "active", "draining", "closed"] },
11
- "right_anchor_pane_id": { "type": ["string", "null"] },
12
- "visible_worker_panes": {
13
- "type": "array",
14
- "items": {
15
- "type": "object",
16
- "required": ["slot_id", "generation_index", "y_order", "status"],
17
- "properties": {
18
- "pane_id": { "type": ["string", "null"] },
19
- "slot_id": { "type": "string" },
20
- "generation_index": { "type": "integer" },
21
- "y_order": { "type": "integer" },
22
- "status": { "enum": ["launching", "running", "draining", "closed", "failed"] }
23
- }
24
- }
25
- },
26
- "headless_workers": {
27
- "type": "array",
28
- "items": {
29
- "type": "object",
30
- "required": ["slot_id", "generation_index", "reason"],
31
- "properties": {
32
- "slot_id": { "type": "string" },
33
- "generation_index": { "type": "integer" },
34
- "reason": { "type": "string" }
35
- }
36
- }
37
- },
38
- "blockers": { "type": "array", "items": { "type": "string" } }
39
- }
40
- }
@@ -1,89 +0,0 @@
1
- {
2
- "$schema": "https://json-schema.org/draft/2020-12/schema",
3
- "$id": "sks.zellij-slot-telemetry.v1",
4
- "title": "SKS Zellij Slot Telemetry",
5
- "oneOf": [
6
- { "$ref": "#/$defs/event" },
7
- { "$ref": "#/$defs/snapshot" }
8
- ],
9
- "$defs": {
10
- "event": {
11
- "type": "object",
12
- "required": ["schema", "ts", "mission_id", "slot_id", "generation_index", "worker_id", "event_type", "status"],
13
- "properties": {
14
- "schema": { "const": "sks.zellij-slot-telemetry-event.v1" },
15
- "ts": { "type": "string" },
16
- "mission_id": { "type": "string" },
17
- "slot_id": { "type": "string" },
18
- "generation_index": { "type": "integer", "minimum": 1 },
19
- "worker_id": { "type": "string" },
20
- "event_type": {
21
- "enum": [
22
- "slot_reserved",
23
- "worker_spawned",
24
- "heartbeat",
25
- "task_started",
26
- "task_progress",
27
- "artifact_written",
28
- "patch_candidate",
29
- "verification_started",
30
- "verification_passed",
31
- "verification_failed",
32
- "worker_completed",
33
- "worker_failed",
34
- "headless_overflow"
35
- ]
36
- },
37
- "status": {
38
- "enum": ["queued", "launching", "running", "verifying", "completed", "failed", "headless", "drained"]
39
- },
40
- "role": { "type": "string" },
41
- "backend": { "type": "string" },
42
- "provider": { "type": "string" },
43
- "service_tier": { "type": "string" },
44
- "worktree_id": { "type": ["string", "null"] },
45
- "worktree_path": { "type": ["string", "null"] },
46
- "task_title": { "type": "string" },
47
- "current_file": { "type": ["string", "null"] },
48
- "progress": {
49
- "type": "object",
50
- "required": ["done", "total", "label"],
51
- "properties": {
52
- "done": { "type": "integer", "minimum": 0 },
53
- "total": { "type": "integer", "minimum": 0 },
54
- "label": { "type": "string" }
55
- },
56
- "additionalProperties": false
57
- },
58
- "artifact_paths": { "type": "array", "items": { "type": "string" } },
59
- "log_tail": { "type": "string" },
60
- "blockers": { "type": "array", "items": { "type": "string" } }
61
- },
62
- "additionalProperties": false
63
- },
64
- "snapshot": {
65
- "type": "object",
66
- "required": ["schema", "mission_id", "updated_at", "slots", "counts"],
67
- "properties": {
68
- "schema": { "const": "sks.zellij-slot-telemetry-snapshot.v1" },
69
- "mission_id": { "type": "string" },
70
- "updated_at": { "type": "string" },
71
- "slots": { "type": "object" },
72
- "counts": {
73
- "type": "object",
74
- "required": ["queued", "running", "verifying", "completed", "failed", "headless"],
75
- "properties": {
76
- "queued": { "type": "integer", "minimum": 0 },
77
- "running": { "type": "integer", "minimum": 0 },
78
- "verifying": { "type": "integer", "minimum": 0 },
79
- "completed": { "type": "integer", "minimum": 0 },
80
- "failed": { "type": "integer", "minimum": 0 },
81
- "headless": { "type": "integer", "minimum": 0 }
82
- },
83
- "additionalProperties": false
84
- }
85
- },
86
- "additionalProperties": false
87
- }
88
- }
89
- }
@@ -1,53 +0,0 @@
1
- {
2
- "$schema": "https://json-schema.org/draft/2020-12/schema",
3
- "$id": "https://sneakoscope.local/schemas/zellij/zellij-worker-pane.schema.json",
4
- "title": "SKS Zellij Worker Pane",
5
- "type": "object",
6
- "required": [
7
- "schema",
8
- "ok",
9
- "status",
10
- "session_name",
11
- "slot_id",
12
- "generation_index",
13
- "session_id",
14
- "pane_name",
15
- "pane_kind",
16
- "pane_id",
17
- "pane_id_source",
18
- "worker_artifact_dir",
19
- "worker_result_path",
20
- "heartbeat_path",
21
- "parent_child_transport",
22
- "scaling_primitive",
23
- "blockers"
24
- ],
25
- "properties": {
26
- "schema": { "const": "sks.zellij-worker-pane.v1" },
27
- "ok": { "type": "boolean" },
28
- "status": { "enum": ["launching", "running", "closed", "failed"] },
29
- "session_name": { "type": "string", "minLength": 1 },
30
- "slot_id": { "type": "string", "pattern": "^slot-[0-9]{3}$" },
31
- "generation_index": { "type": "integer", "minimum": 1 },
32
- "session_id": { "type": "string", "minLength": 1 },
33
- "pane_name": { "type": "string", "pattern": "^slot-[0-9]{3}/gen-[0-9]+$" },
34
- "pane_kind": { "const": "worker_codex_cli" },
35
- "pane_id": { "type": ["string", "null"] },
36
- "pane_id_source": {
37
- "enum": [
38
- "zellij_worker_new_pane_stdout",
39
- "zellij_worker_list_panes",
40
- "zellij_worker_pane_stdout_missing",
41
- "zellij_worker_pane_launch_failed"
42
- ]
43
- },
44
- "worker_artifact_dir": { "type": "string", "minLength": 1 },
45
- "worker_result_path": { "type": "string", "minLength": 1 },
46
- "heartbeat_path": { "type": "string", "minLength": 1 },
47
- "patch_envelope_path": { "type": "string" },
48
- "parent_child_transport": { "const": "worker-result-json-and-heartbeat" },
49
- "scaling_primitive": { "const": "native_cli_process_in_zellij_worker_pane" },
50
- "blockers": { "type": "array", "items": { "type": "string" } }
51
- },
52
- "additionalProperties": true
53
- }
@@ -1,323 +0,0 @@
1
- #!/usr/bin/env node
2
- import { spawn, spawnSync } from 'node:child_process';
3
- import { randomBytes } from 'node:crypto';
4
- import fsp from 'node:fs/promises';
5
- import path from 'node:path';
6
- import { fileURLToPath } from 'node:url';
7
-
8
- const modulePath = fileURLToPath(import.meta.url);
9
- const root = path.resolve(path.dirname(modulePath), '..');
10
- const ATOMIC_BUILD_LOCK_SCHEMA = 'sks.atomic-build-lock.v1';
11
- const CORRUPT_LOCK_GRACE_MS = 120_000;
12
-
13
- export async function buildCleanAtomic() {
14
- const cacheRoot = path.join(root, '.sneakoscope', 'cache', 'atomic-build');
15
- const liveDist = path.join(root, 'dist');
16
- const lock = await acquireAtomicBuildLock({ cacheRoot });
17
- try {
18
- await recoverInterruptedAtomicBuild({ cacheRoot, liveDist });
19
- const buildId = `${Date.now()}-${process.pid}-${randomBytes(4).toString('hex')}`;
20
- const stageParent = path.join(cacheRoot, buildId);
21
- const stageDist = path.join(stageParent, 'dist');
22
- const backupDist = path.join(stageParent, 'previous-dist');
23
- const buildInfo = path.join(stageParent, 'tsconfig.build.tsbuildinfo');
24
- const tsc = path.join(root, 'node_modules', 'typescript', 'bin', 'tsc');
25
- const buildEnvironment = {
26
- ...process.env,
27
- SKS_BUILD_SOURCE_ROOT: root,
28
- SKS_BUILD_OUTPUT_DIR: stageDist
29
- };
30
-
31
- let liveMoved = false;
32
- let preserveRecovery = false;
33
- try {
34
- await fsp.mkdir(stageParent, { recursive: true });
35
- await run(process.execPath, [
36
- tsc,
37
- '-p',
38
- path.join(root, 'tsconfig.build.json'),
39
- '--outDir',
40
- stageDist,
41
- '--tsBuildInfoFile',
42
- buildInfo
43
- ], process.env);
44
- await run(
45
- process.execPath,
46
- [path.join(stageDist, 'scripts', 'ensure-bin-executable.js')],
47
- buildEnvironment
48
- );
49
- await run(
50
- process.execPath,
51
- [path.join(stageDist, 'scripts', 'build-dist.js')],
52
- buildEnvironment
53
- );
54
- await Promise.all([
55
- fsp.access(path.join(stageDist, 'bin', 'sks.js')),
56
- fsp.access(path.join(stageDist, 'config', 'skills-manifest.json')),
57
- fsp.access(path.join(stageDist, '.sks-build-stamp.json'))
58
- ]);
59
-
60
- try {
61
- await fsp.rename(liveDist, backupDist);
62
- liveMoved = true;
63
- } catch (error) {
64
- if (error?.code !== 'ENOENT') throw error;
65
- }
66
- try {
67
- await fsp.rename(stageDist, liveDist);
68
- } catch (error) {
69
- if (liveMoved) {
70
- try {
71
- await restorePreviousDistAfterFailedPromotion({
72
- backupDist,
73
- liveDist,
74
- promotionError: error
75
- });
76
- liveMoved = false;
77
- } catch (combinedError) {
78
- preserveRecovery = true;
79
- throw combinedError;
80
- }
81
- }
82
- throw error;
83
- }
84
- const reportStamp = path.join(root, '.sneakoscope', 'reports', 'dist-build-stamp.json');
85
- await fsp.mkdir(path.dirname(reportStamp), { recursive: true });
86
- await fsp.copyFile(path.join(liveDist, '.sks-build-stamp.json'), reportStamp);
87
- if (liveMoved) {
88
- await fsp.rm(backupDist, { recursive: true, force: true });
89
- liveMoved = false;
90
- }
91
- } finally {
92
- if (liveMoved && !preserveRecovery) {
93
- const liveExists = await pathExists(liveDist);
94
- if (!liveExists) {
95
- try {
96
- await fsp.rename(backupDist, liveDist);
97
- liveMoved = false;
98
- } catch (restoreError) {
99
- preserveRecovery = true;
100
- console.error(
101
- `atomic_build_restore_failed:recovery_preserved:${backupDist}:${
102
- String(restoreError?.message || restoreError)
103
- }`
104
- );
105
- }
106
- } else {
107
- // A post-promotion step failed. Keep the previous generation
108
- // available for explicit or next-start recovery.
109
- preserveRecovery = true;
110
- }
111
- }
112
- if (!preserveRecovery) {
113
- await fsp.rm(stageParent, { recursive: true, force: true }).catch(() => undefined);
114
- }
115
- }
116
- } finally {
117
- await lock.release();
118
- }
119
- }
120
-
121
- export async function recoverInterruptedAtomicBuild({
122
- cacheRoot,
123
- liveDist,
124
- fsApi = fsp
125
- }) {
126
- if (await pathExists(liveDist, fsApi)) return { recovered: false, source: null };
127
- let entries;
128
- try {
129
- entries = await fsApi.readdir(cacheRoot, { withFileTypes: true });
130
- } catch (error) {
131
- if (error?.code === 'ENOENT') return { recovered: false, source: null };
132
- throw error;
133
- }
134
- const candidates = [];
135
- for (const entry of entries) {
136
- if (!entry.isDirectory() || entry.name.startsWith('.')) continue;
137
- const candidate = path.join(cacheRoot, entry.name, 'previous-dist');
138
- try {
139
- const stat = await fsApi.lstat(candidate);
140
- if (stat.isDirectory() && !stat.isSymbolicLink()) {
141
- candidates.push({ candidate, mtimeMs: stat.mtimeMs });
142
- }
143
- } catch (error) {
144
- if (error?.code !== 'ENOENT') throw error;
145
- }
146
- }
147
- candidates.sort((left, right) => right.mtimeMs - left.mtimeMs);
148
- const selected = candidates[0]?.candidate || null;
149
- if (!selected) return { recovered: false, source: null };
150
- await fsApi.rename(selected, liveDist);
151
- return { recovered: true, source: selected };
152
- }
153
-
154
- export async function acquireAtomicBuildLock({
155
- cacheRoot,
156
- fsApi = fsp,
157
- heartbeatMs = 5_000
158
- }) {
159
- const lockPath = path.join(path.resolve(cacheRoot), '.build.lock');
160
- await fsApi.mkdir(path.dirname(lockPath), { recursive: true });
161
- const token = `${process.pid}-${Date.now()}-${randomBytes(8).toString('hex')}`;
162
- const owner = {
163
- schema: ATOMIC_BUILD_LOCK_SCHEMA,
164
- token,
165
- pid: process.pid,
166
- process_start: processStartIdentity(process.pid),
167
- acquired_at: new Date().toISOString(),
168
- heartbeat_at: new Date().toISOString()
169
- };
170
- let acquired = false;
171
- for (let attempt = 0; attempt < 2 && !acquired; attempt += 1) {
172
- let createdLock = false;
173
- try {
174
- await fsApi.mkdir(lockPath);
175
- createdLock = true;
176
- await writeAtomicBuildLockOwner(lockPath, owner, fsApi);
177
- acquired = true;
178
- } catch (error) {
179
- if (createdLock) {
180
- await fsApi.rm(lockPath, { recursive: true, force: true }).catch(() => undefined);
181
- }
182
- if (error?.code !== 'EEXIST') throw error;
183
- if (attempt > 0 || !await reclaimStaleAtomicBuildLock(lockPath, fsApi)) {
184
- throw new Error(`atomic_build_already_running:${lockPath}`);
185
- }
186
- }
187
- }
188
- if (!acquired) throw new Error(`atomic_build_already_running:${lockPath}`);
189
- const heartbeat = setInterval(() => {
190
- owner.heartbeat_at = new Date().toISOString();
191
- writeAtomicBuildLockOwner(lockPath, owner, fsApi).catch(() => undefined);
192
- }, Math.max(250, heartbeatMs));
193
- if (typeof heartbeat.unref === 'function') heartbeat.unref();
194
- let released = false;
195
- return {
196
- lockPath,
197
- token,
198
- async release() {
199
- if (released) return;
200
- released = true;
201
- clearInterval(heartbeat);
202
- const current = await readAtomicBuildLockOwner(lockPath, fsApi);
203
- if (current?.token !== token) return;
204
- const claimed = `${lockPath}.release-${token}`;
205
- try {
206
- await fsApi.rename(lockPath, claimed);
207
- } catch (error) {
208
- if (error?.code === 'ENOENT') return;
209
- throw error;
210
- }
211
- await fsApi.rm(claimed, { recursive: true, force: true });
212
- }
213
- };
214
- }
215
-
216
- async function reclaimStaleAtomicBuildLock(lockPath, fsApi) {
217
- const current = await readAtomicBuildLockOwner(lockPath, fsApi);
218
- let stale = false;
219
- if (current?.schema === ATOMIC_BUILD_LOCK_SCHEMA
220
- && Number.isSafeInteger(current.pid)
221
- && current.pid > 0) {
222
- stale = !processIdentityAlive(current.pid, current.process_start);
223
- } else {
224
- try {
225
- const stat = await fsApi.stat(lockPath);
226
- stale = Date.now() - stat.mtimeMs > CORRUPT_LOCK_GRACE_MS;
227
- } catch {
228
- return true;
229
- }
230
- }
231
- if (!stale) return false;
232
- const claimed = `${lockPath}.stale-${Date.now()}-${randomBytes(4).toString('hex')}`;
233
- try {
234
- await fsApi.rename(lockPath, claimed);
235
- } catch {
236
- return false;
237
- }
238
- await fsApi.rm(claimed, { recursive: true, force: true }).catch(() => undefined);
239
- return true;
240
- }
241
-
242
- async function writeAtomicBuildLockOwner(lockPath, owner, fsApi) {
243
- const file = path.join(lockPath, 'owner.json');
244
- const tmp = `${file}.${owner.token}.tmp`;
245
- try {
246
- await fsApi.writeFile(tmp, `${JSON.stringify(owner)}\n`, { mode: 0o600 });
247
- await fsApi.rename(tmp, file);
248
- } finally {
249
- await fsApi.rm(tmp, { force: true }).catch(() => undefined);
250
- }
251
- }
252
-
253
- async function readAtomicBuildLockOwner(lockPath, fsApi) {
254
- try {
255
- return JSON.parse(await fsApi.readFile(path.join(lockPath, 'owner.json'), 'utf8'));
256
- } catch {
257
- return null;
258
- }
259
- }
260
-
261
- function processIdentityAlive(pid, expectedStart) {
262
- try {
263
- process.kill(pid, 0);
264
- } catch (error) {
265
- return error?.code !== 'ESRCH';
266
- }
267
- if (!expectedStart) return true;
268
- const observed = processStartIdentity(pid);
269
- return observed === null || observed === expectedStart;
270
- }
271
-
272
- function processStartIdentity(pid) {
273
- const result = spawnSync('/bin/ps', ['-o', 'lstart=', '-p', String(pid)], {
274
- encoding: 'utf8',
275
- stdio: ['ignore', 'pipe', 'ignore']
276
- });
277
- if (result.status !== 0) return null;
278
- return String(result.stdout || '').trim() || null;
279
- }
280
-
281
- async function pathExists(target, fsApi = fsp) {
282
- try {
283
- await fsApi.access(target);
284
- return true;
285
- } catch {
286
- return false;
287
- }
288
- }
289
-
290
- export async function restorePreviousDistAfterFailedPromotion({
291
- backupDist,
292
- liveDist,
293
- promotionError,
294
- fsApi = fsp
295
- }) {
296
- try {
297
- await fsApi.rename(backupDist, liveDist);
298
- } catch (restoreError) {
299
- throw new AggregateError(
300
- [promotionError, restoreError],
301
- `atomic_build_promotion_and_restore_failed:recovery_preserved:${backupDist}`
302
- );
303
- }
304
- }
305
-
306
- async function run(command, args, env) {
307
- await new Promise((resolve, reject) => {
308
- const child = spawn(command, args, {
309
- cwd: root,
310
- env,
311
- stdio: 'inherit'
312
- });
313
- child.once('error', reject);
314
- child.once('exit', (code, signal) => {
315
- if (code === 0) resolve();
316
- else reject(new Error(`atomic_build_step_failed:${path.basename(args[0] || command)}:${code ?? signal}`));
317
- });
318
- });
319
- }
320
-
321
- if (process.argv[1] && path.resolve(process.argv[1]) === modulePath) {
322
- await buildCleanAtomic();
323
- }