@cmetech/otto 1.1.1 → 1.2.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 (423) hide show
  1. package/dist/coworker/persona-commands.d.ts +1 -0
  2. package/dist/coworker/persona-commands.js +5 -0
  3. package/dist/coworker/persona-commands.test.d.ts +1 -0
  4. package/dist/coworker/persona-commands.test.js +45 -0
  5. package/dist/resources/.managed-resources-content-hash +1 -1
  6. package/dist/resources/extensions/_coworker-paths.js +8 -0
  7. package/dist/resources/extensions/coworker-artifacts/artifacts-command.js +31 -0
  8. package/dist/resources/extensions/coworker-artifacts/artifacts-singleton.js +17 -0
  9. package/dist/resources/extensions/coworker-artifacts/extension-manifest.json +13 -0
  10. package/dist/resources/extensions/coworker-artifacts/index.js +125 -0
  11. package/dist/resources/extensions/coworker-artifacts/list-tool.js +27 -0
  12. package/dist/resources/extensions/coworker-artifacts/open-tool.js +25 -0
  13. package/dist/resources/extensions/coworker-memory/extension-manifest.json +13 -0
  14. package/dist/resources/extensions/coworker-memory/index.js +219 -0
  15. package/dist/resources/extensions/coworker-memory/memorize-tool.js +10 -0
  16. package/dist/resources/extensions/coworker-memory/memory-command.js +157 -0
  17. package/dist/resources/extensions/coworker-memory/memory-singleton.js +55 -0
  18. package/dist/resources/extensions/coworker-memory/recall-tool.js +18 -0
  19. package/dist/resources/extensions/coworker-memory/session-hooks.js +45 -0
  20. package/dist/resources/extensions/coworker-scratchpad/attach-banners.js +53 -0
  21. package/dist/resources/extensions/coworker-scratchpad/extension-manifest.json +13 -0
  22. package/dist/resources/extensions/coworker-scratchpad/format-age.js +9 -0
  23. package/dist/resources/extensions/coworker-scratchpad/helpers.js +38 -0
  24. package/dist/resources/extensions/coworker-scratchpad/index.js +199 -0
  25. package/dist/resources/extensions/coworker-scratchpad/mime-bundle.js +20 -0
  26. package/dist/resources/extensions/coworker-scratchpad/scratchpad-tool.js +118 -0
  27. package/dist/resources/extensions/coworker-scratchpad/session-sidecar.js +60 -0
  28. package/dist/resources/extensions/coworker-scratchpad/sp-command.js +597 -0
  29. package/dist/resources/extensions/coworker-scratchpad/workspace-pointer.js +41 -0
  30. package/dist/resources/extensions/coworker-scratchpad/workspace-root.js +17 -0
  31. package/dist/resources/extensions/coworker-vault/audit-command.js +35 -0
  32. package/dist/resources/extensions/coworker-vault/connect-command.js +42 -0
  33. package/dist/resources/extensions/coworker-vault/datasource-command.js +50 -0
  34. package/dist/resources/extensions/coworker-vault/extension-manifest.json +12 -0
  35. package/dist/resources/extensions/coworker-vault/index.js +171 -0
  36. package/dist/resources/extensions/coworker-vault/test-helpers.js +86 -0
  37. package/dist/resources/extensions/coworker-vault/vault-singleton.js +24 -0
  38. package/dist/resources/extensions/otto/commands/release-notes/_data.js +71 -0
  39. package/dist/resources/extensions/otto/commands/release-notes/command.js +15 -4
  40. package/dist/resources/extensions/subagent/index.js +8 -1
  41. package/dist/resources/extensions/subagent/launch.js +37 -5
  42. package/dist/resources/extensions/subagent/run-store.js +1 -0
  43. package/dist/resources/extensions/workflow/bootstrap/register-extension.js +2 -0
  44. package/dist/resources/extensions/workflow/bootstrap/register-hooks.js +10 -0
  45. package/dist/resources/extensions/workflow/persona-status.js +87 -0
  46. package/package.json +25 -10
  47. package/packages/contracts/package.json +1 -1
  48. package/packages/coworker-artifacts/dist/artifact-store.d.ts +25 -0
  49. package/packages/coworker-artifacts/dist/artifact-store.js +187 -0
  50. package/packages/coworker-artifacts/dist/dir-snapshot.d.ts +7 -0
  51. package/packages/coworker-artifacts/dist/dir-snapshot.js +54 -0
  52. package/packages/coworker-artifacts/dist/errors.d.ts +18 -0
  53. package/packages/coworker-artifacts/dist/errors.js +37 -0
  54. package/packages/coworker-artifacts/dist/index.d.ts +7 -0
  55. package/packages/coworker-artifacts/dist/index.js +7 -0
  56. package/packages/coworker-artifacts/dist/readme-renderer.d.ts +5 -0
  57. package/packages/coworker-artifacts/dist/readme-renderer.js +47 -0
  58. package/packages/coworker-artifacts/dist/resolve-uri.d.ts +3 -0
  59. package/packages/coworker-artifacts/dist/resolve-uri.js +29 -0
  60. package/packages/coworker-artifacts/dist/slug.d.ts +4 -0
  61. package/packages/coworker-artifacts/dist/slug.js +32 -0
  62. package/packages/coworker-artifacts/dist/types.d.ts +52 -0
  63. package/packages/coworker-artifacts/dist/types.js +1 -0
  64. package/packages/coworker-artifacts/package.json +20 -0
  65. package/packages/coworker-artifacts/src/artifact-store.test.ts +188 -0
  66. package/packages/coworker-artifacts/src/artifact-store.ts +206 -0
  67. package/packages/coworker-artifacts/src/artifacts-integration.test.ts +109 -0
  68. package/packages/coworker-artifacts/src/dir-snapshot.test.ts +71 -0
  69. package/packages/coworker-artifacts/src/dir-snapshot.ts +52 -0
  70. package/packages/coworker-artifacts/src/errors.test.ts +37 -0
  71. package/packages/coworker-artifacts/src/errors.ts +28 -0
  72. package/packages/coworker-artifacts/src/index.test.ts +22 -0
  73. package/packages/coworker-artifacts/src/index.ts +7 -0
  74. package/packages/coworker-artifacts/src/readme-renderer.test.ts +72 -0
  75. package/packages/coworker-artifacts/src/readme-renderer.ts +56 -0
  76. package/packages/coworker-artifacts/src/resolve-uri.test.ts +46 -0
  77. package/packages/coworker-artifacts/src/resolve-uri.ts +29 -0
  78. package/packages/coworker-artifacts/src/slug.test.ts +47 -0
  79. package/packages/coworker-artifacts/src/slug.ts +31 -0
  80. package/packages/coworker-artifacts/src/types.ts +61 -0
  81. package/packages/coworker-artifacts/tsconfig.json +15 -0
  82. package/packages/coworker-artifacts/tsconfig.publish.json +4 -0
  83. package/packages/coworker-memory/dist/context-injection.d.ts +9 -0
  84. package/packages/coworker-memory/dist/context-injection.js +41 -0
  85. package/packages/coworker-memory/dist/errors.d.ts +25 -0
  86. package/packages/coworker-memory/dist/errors.js +51 -0
  87. package/packages/coworker-memory/dist/index.d.ts +12 -0
  88. package/packages/coworker-memory/dist/index.js +12 -0
  89. package/packages/coworker-memory/dist/layer-a-store.d.ts +16 -0
  90. package/packages/coworker-memory/dist/layer-a-store.js +78 -0
  91. package/packages/coworker-memory/dist/local-sqlite-backend.d.ts +28 -0
  92. package/packages/coworker-memory/dist/local-sqlite-backend.js +167 -0
  93. package/packages/coworker-memory/dist/memory-backend.d.ts +14 -0
  94. package/packages/coworker-memory/dist/memory-backend.js +1 -0
  95. package/packages/coworker-memory/dist/memory-recorder.d.ts +50 -0
  96. package/packages/coworker-memory/dist/memory-recorder.js +69 -0
  97. package/packages/coworker-memory/dist/migrations/001-init.sql +38 -0
  98. package/packages/coworker-memory/dist/migrations/002-artifact-kind.sql +50 -0
  99. package/packages/coworker-memory/dist/paste-detector.d.ts +5 -0
  100. package/packages/coworker-memory/dist/paste-detector.js +14 -0
  101. package/packages/coworker-memory/dist/persona-seed.d.ts +10 -0
  102. package/packages/coworker-memory/dist/persona-seed.js +38 -0
  103. package/packages/coworker-memory/dist/recall-formatter.d.ts +2 -0
  104. package/packages/coworker-memory/dist/recall-formatter.js +14 -0
  105. package/packages/coworker-memory/dist/scope-resolver.d.ts +9 -0
  106. package/packages/coworker-memory/dist/scope-resolver.js +10 -0
  107. package/packages/coworker-memory/dist/types.d.ts +51 -0
  108. package/packages/coworker-memory/dist/types.js +2 -0
  109. package/packages/coworker-memory/dist/workspace-id.d.ts +3 -0
  110. package/packages/coworker-memory/dist/workspace-id.js +54 -0
  111. package/packages/coworker-memory/package.json +35 -0
  112. package/packages/coworker-memory/src/activator-integration.test.ts +141 -0
  113. package/packages/coworker-memory/src/context-injection.test.ts +72 -0
  114. package/packages/coworker-memory/src/context-injection.ts +57 -0
  115. package/packages/coworker-memory/src/errors.test.ts +45 -0
  116. package/packages/coworker-memory/src/errors.ts +42 -0
  117. package/packages/coworker-memory/src/index.test.ts +21 -0
  118. package/packages/coworker-memory/src/index.ts +12 -0
  119. package/packages/coworker-memory/src/layer-a-store.test.ts +85 -0
  120. package/packages/coworker-memory/src/layer-a-store.ts +88 -0
  121. package/packages/coworker-memory/src/local-sqlite-backend.test.ts +110 -0
  122. package/packages/coworker-memory/src/local-sqlite-backend.ts +185 -0
  123. package/packages/coworker-memory/src/memory-backend.ts +10 -0
  124. package/packages/coworker-memory/src/memory-integration.test.ts +89 -0
  125. package/packages/coworker-memory/src/memory-recorder.test.ts +101 -0
  126. package/packages/coworker-memory/src/memory-recorder.ts +95 -0
  127. package/packages/coworker-memory/src/migrations/001-init.sql +38 -0
  128. package/packages/coworker-memory/src/migrations/002-artifact-kind.sql +50 -0
  129. package/packages/coworker-memory/src/paste-detector.test.ts +23 -0
  130. package/packages/coworker-memory/src/paste-detector.ts +18 -0
  131. package/packages/coworker-memory/src/persona-seed.test.ts +57 -0
  132. package/packages/coworker-memory/src/persona-seed.ts +46 -0
  133. package/packages/coworker-memory/src/recall-formatter.test.ts +34 -0
  134. package/packages/coworker-memory/src/recall-formatter.ts +15 -0
  135. package/packages/coworker-memory/src/scope-resolver.test.ts +23 -0
  136. package/packages/coworker-memory/src/scope-resolver.ts +18 -0
  137. package/packages/coworker-memory/src/types.ts +61 -0
  138. package/packages/coworker-memory/src/workspace-id.test.ts +48 -0
  139. package/packages/coworker-memory/src/workspace-id.ts +56 -0
  140. package/packages/coworker-memory/tsconfig.json +15 -0
  141. package/packages/coworker-memory/tsconfig.publish.json +4 -0
  142. package/packages/coworker-persona/dist/commands.d.ts +7 -0
  143. package/packages/coworker-persona/dist/commands.js +35 -0
  144. package/packages/coworker-persona/dist/defaults/manifest.yaml +12 -0
  145. package/packages/coworker-persona/dist/defaults/steering/identity.md +3 -0
  146. package/packages/coworker-persona/dist/index.d.ts +3 -0
  147. package/packages/coworker-persona/dist/index.js +3 -0
  148. package/packages/coworker-persona/dist/manifest.d.ts +24 -0
  149. package/packages/coworker-persona/dist/manifest.js +21 -0
  150. package/packages/coworker-persona/dist/registry.d.ts +22 -0
  151. package/packages/coworker-persona/dist/registry.js +142 -0
  152. package/packages/coworker-persona/package.json +28 -0
  153. package/packages/coworker-persona/scripts/copy-defaults.cjs +17 -0
  154. package/packages/coworker-persona/src/commands.ts +47 -0
  155. package/packages/coworker-persona/src/defaults/manifest.yaml +12 -0
  156. package/packages/coworker-persona/src/defaults/steering/identity.md +3 -0
  157. package/packages/coworker-persona/src/index.ts +3 -0
  158. package/packages/coworker-persona/src/manifest.test.ts +67 -0
  159. package/packages/coworker-persona/src/manifest.ts +49 -0
  160. package/packages/coworker-persona/src/registry.test.ts +89 -0
  161. package/packages/coworker-persona/src/registry.ts +147 -0
  162. package/packages/coworker-persona/tsconfig.json +15 -0
  163. package/packages/coworker-persona/tsconfig.publish.json +4 -0
  164. package/packages/coworker-scratchpad/dist/cell-archive.d.ts +39 -0
  165. package/packages/coworker-scratchpad/dist/cell-archive.js +77 -0
  166. package/packages/coworker-scratchpad/dist/cell-tree.d.ts +14 -0
  167. package/packages/coworker-scratchpad/dist/cell-tree.js +72 -0
  168. package/packages/coworker-scratchpad/dist/child-process-runtime.d.ts +129 -0
  169. package/packages/coworker-scratchpad/dist/child-process-runtime.js +427 -0
  170. package/packages/coworker-scratchpad/dist/collector-registry.d.ts +12 -0
  171. package/packages/coworker-scratchpad/dist/collector-registry.js +29 -0
  172. package/packages/coworker-scratchpad/dist/detect-kind.d.ts +3 -0
  173. package/packages/coworker-scratchpad/dist/detect-kind.js +19 -0
  174. package/packages/coworker-scratchpad/dist/file-collector.d.ts +15 -0
  175. package/packages/coworker-scratchpad/dist/file-collector.js +99 -0
  176. package/packages/coworker-scratchpad/dist/index.d.ts +13 -0
  177. package/packages/coworker-scratchpad/dist/index.js +13 -0
  178. package/packages/coworker-scratchpad/dist/kernel-bindings.d.ts +49 -0
  179. package/packages/coworker-scratchpad/dist/kernel-bindings.js +220 -0
  180. package/packages/coworker-scratchpad/dist/kernel-entry.d.ts +1 -0
  181. package/packages/coworker-scratchpad/dist/kernel-entry.js +355 -0
  182. package/packages/coworker-scratchpad/dist/kernel-protocol.d.ts +171 -0
  183. package/packages/coworker-scratchpad/dist/kernel-protocol.js +48 -0
  184. package/packages/coworker-scratchpad/dist/kernel-spawn.d.ts +3 -0
  185. package/packages/coworker-scratchpad/dist/kernel-spawn.js +54 -0
  186. package/packages/coworker-scratchpad/dist/namespace-codec.d.ts +22 -0
  187. package/packages/coworker-scratchpad/dist/namespace-codec.js +61 -0
  188. package/packages/coworker-scratchpad/dist/scratchpad-lock.d.ts +24 -0
  189. package/packages/coworker-scratchpad/dist/scratchpad-lock.js +86 -0
  190. package/packages/coworker-scratchpad/dist/scratchpad-manager.d.ts +193 -0
  191. package/packages/coworker-scratchpad/dist/scratchpad-manager.js +866 -0
  192. package/packages/coworker-scratchpad/dist/staleness-banner.d.ts +12 -0
  193. package/packages/coworker-scratchpad/dist/staleness-banner.js +27 -0
  194. package/packages/coworker-scratchpad/package.json +31 -0
  195. package/packages/coworker-scratchpad/src/cell-archive.test.ts +150 -0
  196. package/packages/coworker-scratchpad/src/cell-archive.ts +97 -0
  197. package/packages/coworker-scratchpad/src/cell-tree.test.ts +105 -0
  198. package/packages/coworker-scratchpad/src/cell-tree.ts +90 -0
  199. package/packages/coworker-scratchpad/src/child-process-runtime.test.ts +413 -0
  200. package/packages/coworker-scratchpad/src/child-process-runtime.ts +493 -0
  201. package/packages/coworker-scratchpad/src/collector-registry.test.ts +69 -0
  202. package/packages/coworker-scratchpad/src/collector-registry.ts +33 -0
  203. package/packages/coworker-scratchpad/src/detect-kind.test.ts +33 -0
  204. package/packages/coworker-scratchpad/src/detect-kind.ts +22 -0
  205. package/packages/coworker-scratchpad/src/file-collector.test.ts +109 -0
  206. package/packages/coworker-scratchpad/src/file-collector.ts +114 -0
  207. package/packages/coworker-scratchpad/src/index.ts +74 -0
  208. package/packages/coworker-scratchpad/src/kernel-bindings.test.ts +188 -0
  209. package/packages/coworker-scratchpad/src/kernel-bindings.ts +279 -0
  210. package/packages/coworker-scratchpad/src/kernel-entry.test.ts +123 -0
  211. package/packages/coworker-scratchpad/src/kernel-entry.ts +390 -0
  212. package/packages/coworker-scratchpad/src/kernel-protocol.test.ts +105 -0
  213. package/packages/coworker-scratchpad/src/kernel-protocol.ts +230 -0
  214. package/packages/coworker-scratchpad/src/kernel-spawn.test.ts +60 -0
  215. package/packages/coworker-scratchpad/src/kernel-spawn.ts +54 -0
  216. package/packages/coworker-scratchpad/src/namespace-codec.test.ts +102 -0
  217. package/packages/coworker-scratchpad/src/namespace-codec.ts +90 -0
  218. package/packages/coworker-scratchpad/src/scratchpad-lock.test.ts +98 -0
  219. package/packages/coworker-scratchpad/src/scratchpad-lock.ts +102 -0
  220. package/packages/coworker-scratchpad/src/scratchpad-manager.test.ts +1343 -0
  221. package/packages/coworker-scratchpad/src/scratchpad-manager.ts +891 -0
  222. package/packages/coworker-scratchpad/src/staleness-banner.test.ts +53 -0
  223. package/packages/coworker-scratchpad/src/staleness-banner.ts +33 -0
  224. package/packages/coworker-scratchpad/src/vault-integration.test.ts +221 -0
  225. package/packages/coworker-scratchpad/tsconfig.json +15 -0
  226. package/packages/coworker-scratchpad/tsconfig.publish.json +4 -0
  227. package/packages/coworker-types/dist/artifacts.d.ts +31 -0
  228. package/packages/coworker-types/dist/artifacts.js +2 -0
  229. package/packages/coworker-types/dist/contracts.d.ts +32 -0
  230. package/packages/coworker-types/dist/contracts.js +1 -0
  231. package/packages/coworker-types/dist/index.d.ts +5 -0
  232. package/packages/coworker-types/dist/index.js +5 -0
  233. package/packages/coworker-types/dist/memory.d.ts +61 -0
  234. package/packages/coworker-types/dist/memory.js +3 -0
  235. package/packages/coworker-types/dist/scratchpad.d.ts +43 -0
  236. package/packages/coworker-types/dist/scratchpad.js +2 -0
  237. package/packages/coworker-types/dist/vault.d.ts +34 -0
  238. package/packages/coworker-types/dist/vault.js +2 -0
  239. package/packages/coworker-types/package.json +24 -0
  240. package/packages/coworker-types/src/artifacts.test.ts +52 -0
  241. package/packages/coworker-types/src/artifacts.ts +35 -0
  242. package/packages/coworker-types/src/contracts.test.ts +43 -0
  243. package/packages/coworker-types/src/contracts.ts +36 -0
  244. package/packages/coworker-types/src/index.ts +5 -0
  245. package/packages/coworker-types/src/memory.test.ts +50 -0
  246. package/packages/coworker-types/src/memory.ts +79 -0
  247. package/packages/coworker-types/src/scratchpad.test.ts +46 -0
  248. package/packages/coworker-types/src/scratchpad.ts +51 -0
  249. package/packages/coworker-types/src/smoke.test.ts +34 -0
  250. package/packages/coworker-types/src/vault.test.ts +49 -0
  251. package/packages/coworker-types/src/vault.ts +40 -0
  252. package/packages/coworker-types/tsconfig.json +15 -0
  253. package/packages/coworker-types/tsconfig.publish.json +4 -0
  254. package/packages/coworker-utils/dist/audit-log.d.ts +34 -0
  255. package/packages/coworker-utils/dist/audit-log.js +88 -0
  256. package/packages/coworker-utils/dist/index.d.ts +6 -0
  257. package/packages/coworker-utils/dist/index.js +6 -0
  258. package/packages/coworker-utils/dist/lease.d.ts +7 -0
  259. package/packages/coworker-utils/dist/lease.js +67 -0
  260. package/packages/coworker-utils/dist/logger.d.ts +13 -0
  261. package/packages/coworker-utils/dist/logger.js +26 -0
  262. package/packages/coworker-utils/dist/migration-runner.d.ts +7 -0
  263. package/packages/coworker-utils/dist/migration-runner.js +36 -0
  264. package/packages/coworker-utils/dist/ndjson-channel.d.ts +3 -0
  265. package/packages/coworker-utils/dist/ndjson-channel.js +38 -0
  266. package/packages/coworker-utils/dist/secret-scanner.d.ts +10 -0
  267. package/packages/coworker-utils/dist/secret-scanner.js +42 -0
  268. package/packages/coworker-utils/package.json +24 -0
  269. package/packages/coworker-utils/src/audit-log.test.ts +140 -0
  270. package/packages/coworker-utils/src/audit-log.ts +107 -0
  271. package/packages/coworker-utils/src/index.ts +6 -0
  272. package/packages/coworker-utils/src/lease.test.ts +64 -0
  273. package/packages/coworker-utils/src/lease.ts +76 -0
  274. package/packages/coworker-utils/src/logger.test.ts +50 -0
  275. package/packages/coworker-utils/src/logger.ts +45 -0
  276. package/packages/coworker-utils/src/migration-runner.test.ts +65 -0
  277. package/packages/coworker-utils/src/migration-runner.ts +50 -0
  278. package/packages/coworker-utils/src/ndjson-channel.test.ts +76 -0
  279. package/packages/coworker-utils/src/ndjson-channel.ts +41 -0
  280. package/packages/coworker-utils/src/secret-scanner.test.ts +61 -0
  281. package/packages/coworker-utils/src/secret-scanner.ts +56 -0
  282. package/packages/coworker-utils/tsconfig.json +15 -0
  283. package/packages/coworker-utils/tsconfig.publish.json +4 -0
  284. package/packages/coworker-vault/dist/data-vault.d.ts +41 -0
  285. package/packages/coworker-vault/dist/data-vault.js +223 -0
  286. package/packages/coworker-vault/dist/engine-registry.d.ts +34 -0
  287. package/packages/coworker-vault/dist/engine-registry.js +90 -0
  288. package/packages/coworker-vault/dist/engines/jira.yaml +17 -0
  289. package/packages/coworker-vault/dist/errors.d.ts +28 -0
  290. package/packages/coworker-vault/dist/errors.js +57 -0
  291. package/packages/coworker-vault/dist/index.d.ts +6 -0
  292. package/packages/coworker-vault/dist/index.js +6 -0
  293. package/packages/coworker-vault/dist/injector.d.ts +19 -0
  294. package/packages/coworker-vault/dist/injector.js +77 -0
  295. package/packages/coworker-vault/dist/types.d.ts +28 -0
  296. package/packages/coworker-vault/dist/types.js +1 -0
  297. package/packages/coworker-vault/dist/vault-keep.d.ts +4 -0
  298. package/packages/coworker-vault/dist/vault-keep.js +21 -0
  299. package/packages/coworker-vault/package.json +29 -0
  300. package/packages/coworker-vault/src/data-vault.test.ts +199 -0
  301. package/packages/coworker-vault/src/data-vault.ts +257 -0
  302. package/packages/coworker-vault/src/engine-registry.test.ts +120 -0
  303. package/packages/coworker-vault/src/engine-registry.ts +107 -0
  304. package/packages/coworker-vault/src/engines/jira.yaml +17 -0
  305. package/packages/coworker-vault/src/errors.test.ts +58 -0
  306. package/packages/coworker-vault/src/errors.ts +50 -0
  307. package/packages/coworker-vault/src/index.test.ts +24 -0
  308. package/packages/coworker-vault/src/index.ts +6 -0
  309. package/packages/coworker-vault/src/injector.test.ts +109 -0
  310. package/packages/coworker-vault/src/injector.ts +98 -0
  311. package/packages/coworker-vault/src/types.ts +33 -0
  312. package/packages/coworker-vault/src/vault-keep.test.ts +49 -0
  313. package/packages/coworker-vault/src/vault-keep.ts +31 -0
  314. package/packages/coworker-vault/tsconfig.json +15 -0
  315. package/packages/coworker-vault/tsconfig.publish.json +4 -0
  316. package/packages/daemon/package.json +3 -3
  317. package/packages/mcp-server/package.json +3 -3
  318. package/packages/mcp-server/tsconfig.tsbuildinfo +1 -1
  319. package/packages/native/package.json +1 -1
  320. package/packages/native/tsconfig.tsbuildinfo +1 -1
  321. package/packages/pi-agent-core/package.json +1 -1
  322. package/packages/pi-agent-core/tsconfig.tsbuildinfo +1 -1
  323. package/packages/pi-ai/package.json +1 -1
  324. package/packages/pi-ai/tsconfig.tsbuildinfo +1 -1
  325. package/packages/pi-coding-agent/dist/core/extensions/runner.d.ts +6 -1
  326. package/packages/pi-coding-agent/dist/core/extensions/runner.d.ts.map +1 -1
  327. package/packages/pi-coding-agent/dist/core/extensions/runner.js +22 -3
  328. package/packages/pi-coding-agent/dist/core/extensions/runner.js.map +1 -1
  329. package/packages/pi-coding-agent/dist/core/resolve-config-value.test.js +11 -0
  330. package/packages/pi-coding-agent/dist/core/resolve-config-value.test.js.map +1 -1
  331. package/packages/pi-coding-agent/dist/modes/rpc/raw-stdout.d.ts +47 -0
  332. package/packages/pi-coding-agent/dist/modes/rpc/raw-stdout.d.ts.map +1 -0
  333. package/packages/pi-coding-agent/dist/modes/rpc/raw-stdout.js +107 -0
  334. package/packages/pi-coding-agent/dist/modes/rpc/raw-stdout.js.map +1 -0
  335. package/packages/pi-coding-agent/dist/modes/rpc/raw-stdout.regression.test.d.ts +19 -0
  336. package/packages/pi-coding-agent/dist/modes/rpc/raw-stdout.regression.test.d.ts.map +1 -0
  337. package/packages/pi-coding-agent/dist/modes/rpc/raw-stdout.regression.test.js +121 -0
  338. package/packages/pi-coding-agent/dist/modes/rpc/raw-stdout.regression.test.js.map +1 -0
  339. package/packages/pi-coding-agent/dist/modes/rpc/rpc-mode.d.ts.map +1 -1
  340. package/packages/pi-coding-agent/dist/modes/rpc/rpc-mode.js +17 -1
  341. package/packages/pi-coding-agent/dist/modes/rpc/rpc-mode.js.map +1 -1
  342. package/packages/pi-coding-agent/package.json +2 -2
  343. package/packages/pi-coding-agent/src/core/extensions/runner.ts +22 -3
  344. package/packages/pi-coding-agent/src/core/resolve-config-value.test.ts +11 -0
  345. package/packages/pi-coding-agent/src/modes/rpc/raw-stdout.regression.test.ts +129 -0
  346. package/packages/pi-coding-agent/src/modes/rpc/raw-stdout.ts +117 -0
  347. package/packages/pi-coding-agent/src/modes/rpc/rpc-mode.ts +18 -1
  348. package/packages/pi-coding-agent/tsconfig.tsbuildinfo +1 -1
  349. package/packages/pi-tui/package.json +1 -1
  350. package/packages/pi-tui/tsconfig.tsbuildinfo +1 -1
  351. package/packages/rpc-client/package.json +2 -2
  352. package/packages/rpc-client/tsconfig.tsbuildinfo +1 -1
  353. package/pkg/package.json +1 -1
  354. package/scripts/install.js +6 -5
  355. package/src/resources/extensions/_coworker-paths.test.ts +40 -0
  356. package/src/resources/extensions/_coworker-paths.ts +10 -0
  357. package/src/resources/extensions/coworker-artifacts/artifacts-command.test.ts +54 -0
  358. package/src/resources/extensions/coworker-artifacts/artifacts-command.ts +43 -0
  359. package/src/resources/extensions/coworker-artifacts/artifacts-singleton.test.ts +25 -0
  360. package/src/resources/extensions/coworker-artifacts/artifacts-singleton.ts +29 -0
  361. package/src/resources/extensions/coworker-artifacts/extension-manifest.json +13 -0
  362. package/src/resources/extensions/coworker-artifacts/index.test.ts +46 -0
  363. package/src/resources/extensions/coworker-artifacts/index.ts +154 -0
  364. package/src/resources/extensions/coworker-artifacts/list-tool.test.ts +29 -0
  365. package/src/resources/extensions/coworker-artifacts/list-tool.ts +53 -0
  366. package/src/resources/extensions/coworker-artifacts/open-tool.test.ts +30 -0
  367. package/src/resources/extensions/coworker-artifacts/open-tool.ts +43 -0
  368. package/src/resources/extensions/coworker-memory/extension-manifest.json +13 -0
  369. package/src/resources/extensions/coworker-memory/index.test.ts +137 -0
  370. package/src/resources/extensions/coworker-memory/index.ts +257 -0
  371. package/src/resources/extensions/coworker-memory/memorize-tool.test.ts +41 -0
  372. package/src/resources/extensions/coworker-memory/memorize-tool.ts +20 -0
  373. package/src/resources/extensions/coworker-memory/memory-command.test.ts +134 -0
  374. package/src/resources/extensions/coworker-memory/memory-command.ts +131 -0
  375. package/src/resources/extensions/coworker-memory/memory-singleton.test.ts +41 -0
  376. package/src/resources/extensions/coworker-memory/memory-singleton.ts +89 -0
  377. package/src/resources/extensions/coworker-memory/recall-tool.test.ts +50 -0
  378. package/src/resources/extensions/coworker-memory/recall-tool.ts +35 -0
  379. package/src/resources/extensions/coworker-memory/session-hooks.test.ts +77 -0
  380. package/src/resources/extensions/coworker-memory/session-hooks.ts +61 -0
  381. package/src/resources/extensions/coworker-scratchpad/attach-banners.test.ts +124 -0
  382. package/src/resources/extensions/coworker-scratchpad/attach-banners.ts +67 -0
  383. package/src/resources/extensions/coworker-scratchpad/extension-manifest.json +13 -0
  384. package/src/resources/extensions/coworker-scratchpad/format-age.test.ts +30 -0
  385. package/src/resources/extensions/coworker-scratchpad/format-age.ts +6 -0
  386. package/src/resources/extensions/coworker-scratchpad/helpers.test.ts +93 -0
  387. package/src/resources/extensions/coworker-scratchpad/helpers.ts +42 -0
  388. package/src/resources/extensions/coworker-scratchpad/index.test.ts +514 -0
  389. package/src/resources/extensions/coworker-scratchpad/index.ts +207 -0
  390. package/src/resources/extensions/coworker-scratchpad/mime-bundle.test.ts +61 -0
  391. package/src/resources/extensions/coworker-scratchpad/mime-bundle.ts +23 -0
  392. package/src/resources/extensions/coworker-scratchpad/scratchpad-tool.test.ts +137 -0
  393. package/src/resources/extensions/coworker-scratchpad/scratchpad-tool.ts +165 -0
  394. package/src/resources/extensions/coworker-scratchpad/session-sidecar.test.ts +133 -0
  395. package/src/resources/extensions/coworker-scratchpad/session-sidecar.ts +68 -0
  396. package/src/resources/extensions/coworker-scratchpad/sp-command.test.ts +836 -0
  397. package/src/resources/extensions/coworker-scratchpad/sp-command.ts +602 -0
  398. package/src/resources/extensions/coworker-scratchpad/workspace-pointer.test.ts +74 -0
  399. package/src/resources/extensions/coworker-scratchpad/workspace-pointer.ts +55 -0
  400. package/src/resources/extensions/coworker-scratchpad/workspace-root.test.ts +51 -0
  401. package/src/resources/extensions/coworker-scratchpad/workspace-root.ts +16 -0
  402. package/src/resources/extensions/coworker-vault/audit-command.test.ts +109 -0
  403. package/src/resources/extensions/coworker-vault/audit-command.ts +56 -0
  404. package/src/resources/extensions/coworker-vault/connect-command.test.ts +103 -0
  405. package/src/resources/extensions/coworker-vault/connect-command.ts +69 -0
  406. package/src/resources/extensions/coworker-vault/datasource-command.test.ts +80 -0
  407. package/src/resources/extensions/coworker-vault/datasource-command.ts +81 -0
  408. package/src/resources/extensions/coworker-vault/extension-manifest.json +12 -0
  409. package/src/resources/extensions/coworker-vault/index.test.ts +82 -0
  410. package/src/resources/extensions/coworker-vault/index.ts +181 -0
  411. package/src/resources/extensions/coworker-vault/test-helpers.ts +120 -0
  412. package/src/resources/extensions/coworker-vault/vault-singleton.test.ts +27 -0
  413. package/src/resources/extensions/coworker-vault/vault-singleton.ts +40 -0
  414. package/src/resources/extensions/otto/commands/release-notes/_data.ts +85 -0
  415. package/src/resources/extensions/otto/commands/release-notes/command.ts +16 -3
  416. package/src/resources/extensions/subagent/index.ts +9 -0
  417. package/src/resources/extensions/subagent/launch.test.ts +97 -0
  418. package/src/resources/extensions/subagent/launch.ts +42 -5
  419. package/src/resources/extensions/subagent/run-store.ts +3 -1
  420. package/src/resources/extensions/workflow/bootstrap/register-extension.ts +2 -0
  421. package/src/resources/extensions/workflow/bootstrap/register-hooks.ts +10 -0
  422. package/src/resources/extensions/workflow/persona-status.ts +109 -0
  423. package/src/resources/extensions/workflow/tests/auto-recovery.test.ts +34 -0
@@ -0,0 +1,171 @@
1
+ export type { SkippedKey } from './namespace-codec.js';
2
+ import type { SkippedKey } from './namespace-codec.js';
3
+ export interface RunRequest {
4
+ id: number;
5
+ type: 'run';
6
+ code: string;
7
+ }
8
+ export interface SnapshotRequest {
9
+ id: number;
10
+ type: 'snapshot';
11
+ }
12
+ export type KernelRequest = RunRequest | SnapshotRequest;
13
+ export interface ResultOk {
14
+ id: number;
15
+ type: 'result';
16
+ ok: true;
17
+ value: unknown;
18
+ stdout: string;
19
+ }
20
+ export interface ResultErr {
21
+ id: number;
22
+ type: 'result';
23
+ ok: false;
24
+ error: {
25
+ name: string;
26
+ message: string;
27
+ stack?: string;
28
+ };
29
+ }
30
+ export type ResultResponse = ResultOk | ResultErr;
31
+ export interface SnapshotResultOk {
32
+ id: number;
33
+ type: 'snapshot_result';
34
+ ok: true;
35
+ skipped: SkippedKey[];
36
+ snapshotted_at: string;
37
+ }
38
+ export interface SnapshotResultErr {
39
+ id: number;
40
+ type: 'snapshot_result';
41
+ ok: false;
42
+ error: {
43
+ name: string;
44
+ message: string;
45
+ stack?: string;
46
+ };
47
+ }
48
+ export type SnapshotResult = SnapshotResultOk | SnapshotResultErr;
49
+ export type RecoveryNote = {
50
+ kind: 'namespace-absent';
51
+ } | {
52
+ kind: 'namespace-corrupt';
53
+ message: string;
54
+ } | {
55
+ kind: 'cells-since-snapshot';
56
+ n: number;
57
+ } | {
58
+ kind: 'snapshot-failed';
59
+ message: string;
60
+ };
61
+ export interface DataLoadDrawer {
62
+ kind: 'data_load';
63
+ collector: string;
64
+ uri: string;
65
+ bytes: number | null;
66
+ rows_loaded: number | null;
67
+ loaded_at: string;
68
+ schema: null;
69
+ }
70
+ export interface ReadyEvent {
71
+ type: 'event';
72
+ event: 'ready';
73
+ recovery_notes?: RecoveryNote[];
74
+ }
75
+ export interface DataLoadEvent {
76
+ type: 'event';
77
+ event: 'data_load';
78
+ drawer: DataLoadDrawer;
79
+ }
80
+ export interface ProgressEvent {
81
+ type: 'event';
82
+ event: 'progress';
83
+ message?: string;
84
+ }
85
+ export interface StartupErrorEvent {
86
+ type: 'event';
87
+ event: 'startup_error';
88
+ kind: string;
89
+ error: {
90
+ name: string;
91
+ message: string;
92
+ stack?: string;
93
+ };
94
+ }
95
+ export interface ArtifactCreateDrawer {
96
+ kind: 'artifact';
97
+ slug: string;
98
+ artifact_kind: string;
99
+ uri: string;
100
+ primary_path: string;
101
+ created_at: string;
102
+ }
103
+ export interface ArtifactCreateRequest {
104
+ type: 'request';
105
+ request: 'artifact_create';
106
+ id: string;
107
+ kind: string;
108
+ name: string;
109
+ }
110
+ export interface ArtifactCreateResponseOk {
111
+ type: 'response';
112
+ request: 'artifact_create';
113
+ id: string;
114
+ ok: true;
115
+ slug: string;
116
+ uri: string;
117
+ primary_path: string;
118
+ }
119
+ export interface ArtifactCreateResponseErr {
120
+ type: 'response';
121
+ request: 'artifact_create';
122
+ id: string;
123
+ ok: false;
124
+ error: string;
125
+ }
126
+ export type ArtifactCreateResponse = ArtifactCreateResponseOk | ArtifactCreateResponseErr;
127
+ export interface ArtifactUpdateRequest {
128
+ type: 'request';
129
+ request: 'artifact_update';
130
+ id: string;
131
+ slug: string;
132
+ files: Array<{
133
+ path: string;
134
+ content: string;
135
+ }>;
136
+ }
137
+ export interface ArtifactUpdateResponseOk {
138
+ type: 'response';
139
+ request: 'artifact_update';
140
+ id: string;
141
+ ok: true;
142
+ files_touched: string[];
143
+ }
144
+ export interface ArtifactUpdateResponseErr {
145
+ type: 'response';
146
+ request: 'artifact_update';
147
+ id: string;
148
+ ok: false;
149
+ error: string;
150
+ }
151
+ export type ArtifactUpdateResponse = ArtifactUpdateResponseOk | ArtifactUpdateResponseErr;
152
+ export interface ArtifactCreateEvent {
153
+ type: 'event';
154
+ event: 'artifact_create';
155
+ drawer: ArtifactCreateDrawer;
156
+ }
157
+ export type KernelRpcRequest = ArtifactCreateRequest | ArtifactUpdateRequest;
158
+ export type KernelRpcResponse = ArtifactCreateResponse | ArtifactUpdateResponse;
159
+ export type KernelEvent = ReadyEvent | DataLoadEvent | ProgressEvent | StartupErrorEvent | ArtifactCreateEvent;
160
+ export type KernelFrame = ResultResponse | KernelEvent | SnapshotResult | KernelRpcRequest;
161
+ export declare function isDataLoadEvent(frame: KernelFrame): frame is DataLoadEvent;
162
+ export declare function isProgressEvent(frame: KernelFrame): frame is ProgressEvent;
163
+ export declare function isStartupErrorEvent(frame: KernelFrame): frame is StartupErrorEvent;
164
+ export declare function isSnapshotResult(frame: KernelFrame): frame is SnapshotResult;
165
+ export declare function isArtifactCreateEvent(frame: unknown): frame is ArtifactCreateEvent;
166
+ export declare function isArtifactCreateRequest(frame: unknown): frame is ArtifactCreateRequest;
167
+ export declare function isArtifactUpdateRequest(frame: unknown): frame is ArtifactUpdateRequest;
168
+ export declare function isArtifactCreateResponse(frame: unknown): frame is ArtifactCreateResponse;
169
+ export declare function isArtifactUpdateResponse(frame: unknown): frame is ArtifactUpdateResponse;
170
+ /** True for any `{type:'response'}` frame addressed to the kernel. */
171
+ export declare function isKernelRpcResponse(frame: unknown): frame is KernelRpcResponse;
@@ -0,0 +1,48 @@
1
+ // NDJSON wire protocol between the scratchpad parent runtime and the kernel child.
2
+ // One JSON object per line (\n terminated). See spec §2.4 + §6.3.
3
+ export function isDataLoadEvent(frame) {
4
+ return frame.type === 'event' && frame.event === 'data_load';
5
+ }
6
+ export function isProgressEvent(frame) {
7
+ return frame.type === 'event' && frame.event === 'progress';
8
+ }
9
+ export function isStartupErrorEvent(frame) {
10
+ return frame.type === 'event' && frame.event === 'startup_error';
11
+ }
12
+ export function isSnapshotResult(frame) {
13
+ return frame.type === 'snapshot_result';
14
+ }
15
+ export function isArtifactCreateEvent(frame) {
16
+ if (typeof frame !== 'object' || frame === null)
17
+ return false;
18
+ const f = frame;
19
+ return f.type === 'event' && f.event === 'artifact_create';
20
+ }
21
+ export function isArtifactCreateRequest(frame) {
22
+ if (typeof frame !== 'object' || frame === null)
23
+ return false;
24
+ const f = frame;
25
+ return f.type === 'request' && f.request === 'artifact_create';
26
+ }
27
+ export function isArtifactUpdateRequest(frame) {
28
+ if (typeof frame !== 'object' || frame === null)
29
+ return false;
30
+ const f = frame;
31
+ return f.type === 'request' && f.request === 'artifact_update';
32
+ }
33
+ export function isArtifactCreateResponse(frame) {
34
+ if (typeof frame !== 'object' || frame === null)
35
+ return false;
36
+ const f = frame;
37
+ return f.type === 'response' && f.request === 'artifact_create';
38
+ }
39
+ export function isArtifactUpdateResponse(frame) {
40
+ if (typeof frame !== 'object' || frame === null)
41
+ return false;
42
+ const f = frame;
43
+ return f.type === 'response' && f.request === 'artifact_update';
44
+ }
45
+ /** True for any `{type:'response'}` frame addressed to the kernel. */
46
+ export function isKernelRpcResponse(frame) {
47
+ return isArtifactCreateResponse(frame) || isArtifactUpdateResponse(frame);
48
+ }
@@ -0,0 +1,3 @@
1
+ export declare function filterEnv(source?: NodeJS.ProcessEnv): NodeJS.ProcessEnv;
2
+ export declare function kernelExecArgv(execArgv?: string[]): string[];
3
+ export declare function resolveKernelEntry(): string;
@@ -0,0 +1,54 @@
1
+ import { existsSync } from 'node:fs';
2
+ import { fileURLToPath } from 'node:url';
3
+ const ENV_ALLOW = new Set([
4
+ 'PATH', 'HOME', 'TERM', 'SHELL', 'TMPDIR', 'TMP', 'TEMP',
5
+ 'LANG', 'LANGUAGE', 'PWD', 'USER', 'LOGNAME',
6
+ ]);
7
+ const ENV_ALLOW_PREFIXES = ['LC_', 'XDG_', 'OTTO_', 'NODE_'];
8
+ const ENV_DENY = new Set([
9
+ 'LOOP24_GATEWAY_KEY', 'ANTHROPIC_API_KEY', 'OPENAI_API_KEY',
10
+ 'AWS_ACCESS_KEY_ID', 'AWS_SECRET_ACCESS_KEY', 'GITHUB_TOKEN',
11
+ ]);
12
+ export function filterEnv(source = process.env) {
13
+ const out = {};
14
+ for (const [key, value] of Object.entries(source)) {
15
+ if (value === undefined)
16
+ continue;
17
+ if (ENV_DENY.has(key))
18
+ continue; // denylist overrides any allow-rule
19
+ if (ENV_ALLOW.has(key) || ENV_ALLOW_PREFIXES.some((p) => key.startsWith(p))) {
20
+ out[key] = value;
21
+ }
22
+ }
23
+ return out;
24
+ }
25
+ const FORWARD_FLAGS_WITH_VALUE = new Set([
26
+ '--import', '--loader', '--experimental-loader', '--require', '-r', '--conditions',
27
+ ]);
28
+ const FORWARD_FLAGS_BOOLEAN = new Set([
29
+ '--experimental-strip-types', '--experimental-transform-types', '--no-warnings',
30
+ ]);
31
+ export function kernelExecArgv(execArgv = process.execArgv) {
32
+ const out = [];
33
+ for (let i = 0; i < execArgv.length; i++) {
34
+ const arg = execArgv[i];
35
+ const eq = arg.indexOf('=');
36
+ const flag = eq >= 0 ? arg.slice(0, eq) : arg;
37
+ if (FORWARD_FLAGS_WITH_VALUE.has(flag)) {
38
+ out.push(arg);
39
+ if (eq < 0 && i + 1 < execArgv.length)
40
+ out.push(execArgv[++i]);
41
+ }
42
+ else if (FORWARD_FLAGS_BOOLEAN.has(flag)) {
43
+ out.push(arg);
44
+ }
45
+ // Everything else (--test, --watch, --test-*, …) is dropped.
46
+ }
47
+ return out;
48
+ }
49
+ export function resolveKernelEntry() {
50
+ const js = fileURLToPath(new URL('./kernel-entry.js', import.meta.url));
51
+ if (existsSync(js))
52
+ return js;
53
+ return fileURLToPath(new URL('./kernel-entry.ts', import.meta.url));
54
+ }
@@ -0,0 +1,22 @@
1
+ export declare const NAMESPACE_SCHEMA_VERSION = 1;
2
+ export interface SkippedKey {
3
+ key: string;
4
+ ctor: string | null;
5
+ reason: string;
6
+ }
7
+ export interface NamespaceEnvelope {
8
+ schema_version: number;
9
+ snapshot_b64: string;
10
+ skipped: SkippedKey[];
11
+ ts: string;
12
+ }
13
+ export interface EncodeResult {
14
+ envelope: NamespaceEnvelope;
15
+ skipped: SkippedKey[];
16
+ }
17
+ export interface DecodeResult {
18
+ values: Record<string, unknown>;
19
+ skipped: SkippedKey[];
20
+ }
21
+ export declare function encodeNamespace(values: Record<string, unknown>, now: () => number): EncodeResult;
22
+ export declare function decodeNamespace(json: string): DecodeResult;
@@ -0,0 +1,61 @@
1
+ import { serialize, deserialize } from 'node:v8';
2
+ export const NAMESPACE_SCHEMA_VERSION = 1;
3
+ function ctorName(value) {
4
+ if (value === null || value === undefined)
5
+ return null;
6
+ const c = value.constructor;
7
+ return c?.name ?? null;
8
+ }
9
+ export function encodeNamespace(values, now) {
10
+ const survivors = {};
11
+ const skipped = [];
12
+ for (const key of Object.keys(values)) {
13
+ const value = values[key];
14
+ try {
15
+ // Probe by serializing a single-key wrapper. Cheaper than per-key buffers
16
+ // because the survivors map is re-serialized once below.
17
+ serialize({ [key]: value });
18
+ survivors[key] = value;
19
+ }
20
+ catch (err) {
21
+ skipped.push({
22
+ key,
23
+ ctor: ctorName(value),
24
+ reason: err.message,
25
+ });
26
+ }
27
+ }
28
+ let snapshot_b64;
29
+ try {
30
+ snapshot_b64 = serialize(survivors).toString('base64');
31
+ }
32
+ catch (err) {
33
+ // A value passed the per-key probe but threw on bulk serialize (e.g. a getter
34
+ // that throws on its second invocation). Demote every survivor to skipped so
35
+ // the caller still gets a usable envelope; the snapshot for this round is empty.
36
+ const reason = `bulk-serialize-failed: ${err.message}`;
37
+ for (const key of Object.keys(survivors)) {
38
+ skipped.push({ key, ctor: ctorName(survivors[key]), reason });
39
+ }
40
+ snapshot_b64 = serialize({}).toString('base64');
41
+ }
42
+ const envelope = {
43
+ schema_version: NAMESPACE_SCHEMA_VERSION,
44
+ snapshot_b64,
45
+ skipped,
46
+ ts: new Date(now()).toISOString(),
47
+ };
48
+ return { envelope, skipped };
49
+ }
50
+ export function decodeNamespace(json) {
51
+ const parsed = JSON.parse(json);
52
+ if (parsed.schema_version !== NAMESPACE_SCHEMA_VERSION) {
53
+ throw new Error(`namespace-codec: unsupported schema_version ${String(parsed.schema_version)} (expected ${NAMESPACE_SCHEMA_VERSION})`);
54
+ }
55
+ if (typeof parsed.snapshot_b64 !== 'string') {
56
+ throw new Error('namespace-codec: missing snapshot_b64');
57
+ }
58
+ const buf = Buffer.from(parsed.snapshot_b64, 'base64');
59
+ const values = deserialize(buf);
60
+ return { values, skipped: Array.isArray(parsed.skipped) ? parsed.skipped : [] };
61
+ }
@@ -0,0 +1,24 @@
1
+ export interface LockInfo {
2
+ pid: number;
3
+ host: string;
4
+ acquired_at: string;
5
+ takeover_from?: {
6
+ pid: number;
7
+ host: string;
8
+ reason: string;
9
+ };
10
+ }
11
+ export interface AcquireOptions {
12
+ forceTakeover?: boolean;
13
+ takeoverReason?: string;
14
+ now?: () => number;
15
+ }
16
+ export declare class ScratchpadBusyError extends Error {
17
+ readonly scratchpadName: string;
18
+ readonly holder: LockInfo;
19
+ constructor(scratchpadName: string, holder: LockInfo);
20
+ }
21
+ export declare function readLock(dir: string): LockInfo | null;
22
+ export declare function isStaleLock(holder: LockInfo): boolean;
23
+ export declare function acquireLock(dir: string, options?: AcquireOptions): LockInfo;
24
+ export declare function releaseLock(dir: string): void;
@@ -0,0 +1,86 @@
1
+ import { existsSync, mkdirSync, readFileSync, unlinkSync, writeFileSync } from 'node:fs';
2
+ import { basename, join } from 'node:path';
3
+ import { hostname } from 'node:os';
4
+ import process from 'node:process';
5
+ export class ScratchpadBusyError extends Error {
6
+ scratchpadName;
7
+ holder;
8
+ constructor(scratchpadName, holder) {
9
+ super(`scratchpad ${scratchpadName} is busy in another session`);
10
+ this.name = 'ScratchpadBusyError';
11
+ this.scratchpadName = scratchpadName;
12
+ this.holder = holder;
13
+ }
14
+ }
15
+ function lockPath(dir) {
16
+ return join(dir, 'lock.json');
17
+ }
18
+ export function readLock(dir) {
19
+ const path = lockPath(dir);
20
+ if (!existsSync(path))
21
+ return null;
22
+ try {
23
+ return JSON.parse(readFileSync(path, 'utf8'));
24
+ }
25
+ catch {
26
+ return null; // corrupt lock is treated as absent (clearable on acquire)
27
+ }
28
+ }
29
+ function holderIsAlive(holder) {
30
+ if (holder.host !== hostname())
31
+ return true; // can't verify a remote PID -> assume alive
32
+ try {
33
+ process.kill(holder.pid, 0);
34
+ return true; // exists and signalable
35
+ }
36
+ catch (err) {
37
+ return err.code !== 'ESRCH'; // ESRCH = no such process (dead); EPERM etc. = alive
38
+ }
39
+ }
40
+ export function isStaleLock(holder) {
41
+ return !holderIsAlive(holder);
42
+ }
43
+ export function acquireLock(dir, options = {}) {
44
+ const now = options.now ?? Date.now;
45
+ mkdirSync(dir, { recursive: true });
46
+ const path = lockPath(dir);
47
+ const self = { pid: process.pid, host: hostname(), acquired_at: new Date(now()).toISOString() };
48
+ try {
49
+ writeFileSync(path, JSON.stringify(self), { flag: 'wx' });
50
+ return self; // won the atomic create
51
+ }
52
+ catch (err) {
53
+ if (err.code !== 'EEXIST')
54
+ throw err;
55
+ }
56
+ const holder = readLock(dir);
57
+ if (holder === null || !holderIsAlive(holder)) {
58
+ // corrupt or stale -> clear and retake
59
+ unlinkSync(path);
60
+ writeFileSync(path, JSON.stringify(self), { flag: 'wx' });
61
+ return self;
62
+ }
63
+ if (options.forceTakeover) {
64
+ const taken = {
65
+ ...self,
66
+ takeover_from: { pid: holder.pid, host: holder.host, reason: options.takeoverReason ?? 'force-takeover' },
67
+ };
68
+ writeFileSync(path, JSON.stringify(taken)); // overwrite the live holder
69
+ return taken;
70
+ }
71
+ throw new ScratchpadBusyError(basename(dir), holder);
72
+ }
73
+ export function releaseLock(dir) {
74
+ const holder = readLock(dir);
75
+ if (holder === null)
76
+ return;
77
+ if (holder.pid === process.pid && holder.host === hostname()) {
78
+ try {
79
+ unlinkSync(lockPath(dir));
80
+ }
81
+ catch {
82
+ // already gone
83
+ }
84
+ }
85
+ // not ours (e.g. taken over) -> leave it
86
+ }
@@ -0,0 +1,193 @@
1
+ import type { CredentialInjector } from '@otto/coworker-vault';
2
+ import type { AuditLog } from '@otto/coworker-utils';
3
+ import type { ArtifactStore } from '@otto/coworker-artifacts';
4
+ import { ChildProcessRuntime, type ChildProcessRuntimeOptions } from './child-process-runtime.js';
5
+ import { type LockInfo } from './scratchpad-lock.js';
6
+ import { CellArchive } from './cell-archive.js';
7
+ import type { ArtifactCreateDrawer, DataLoadDrawer } from './kernel-protocol.js';
8
+ export declare class ForkKernelHangError extends Error {
9
+ readonly srcName: string;
10
+ readonly pid: number;
11
+ constructor(srcName: string, pid: number);
12
+ }
13
+ export interface ScratchpadManagerOptions {
14
+ workspace: string;
15
+ root?: string;
16
+ maxLiveKernels?: number;
17
+ idleMs?: number;
18
+ sweepIntervalMs?: number;
19
+ now?: () => number;
20
+ runtimeOptions?: Omit<ChildProcessRuntimeOptions, 'workspace'>;
21
+ sessionId?: string;
22
+ forkExitTimeoutMs?: number;
23
+ /**
24
+ * Phase 2 Task 13: optional vault credential injector. When provided, each
25
+ * spawned ChildProcessRuntime receives the injector + the scratchpad's
26
+ * meta.bindings list. Absent => runtime spawns with no OTTO_DS_* env vars.
27
+ */
28
+ injector?: CredentialInjector;
29
+ /**
30
+ * Phase 2 Task 14: optional audit sink for SecretScanner redactions on
31
+ * cell-output journal writes. When provided, every cell run's stdout is
32
+ * scanned BEFORE archive.append and emits one `producer: 'secret-scanner'`
33
+ * record per hit. Absent => redaction is a no-op (backward compat).
34
+ *
35
+ * Wiring contract: the caller is expected to pass the SAME AuditLog instance
36
+ * held by the CredentialInjector so secret-scanner records appear alongside
37
+ * vault inject/inject-skipped records in a single audit stream.
38
+ */
39
+ audit?: AuditLog;
40
+ /**
41
+ * Phase 3 Task 19: cross-pillar hook for the memory pillar's MemoryRecorder.
42
+ * Invoked once per `otto.collectors.open(...).load()` call inside a cell,
43
+ * with the kernel's `DataLoadDrawer` and the scratchpad name that produced it.
44
+ * The manager fans this through every spawn of every scratchpad (the callback
45
+ * is closure-bound to the name at spawn time, so multi-scratchpad sessions
46
+ * route loads to the correct room). Absent => data_load events are dropped.
47
+ */
48
+ onDataLoad?: (drawer: DataLoadDrawer, scratchpadName: string) => void;
49
+ /**
50
+ * Phase 4 Task 10: cross-pillar hook for the memory pillar's MemoryRecorder.
51
+ * Invoked once per `otto.artifact.create(...)` call inside a cell, with the
52
+ * kernel's `ArtifactCreateDrawer` and the scratchpad name that produced it.
53
+ * Closure-bound to the name at spawn time (same pattern as onDataLoad), so
54
+ * multi-scratchpad sessions route artifact events to the correct room.
55
+ * Absent => artifact_create events are dropped (memory stays silent).
56
+ */
57
+ onArtifactCreate?: (drawer: ArtifactCreateDrawer, scratchpadName: string) => void;
58
+ /**
59
+ * Phase 4 Task 10: lazy accessor for the ArtifactStore. The manager calls
60
+ * this each time it services an artifact RPC so the resolution sees the
61
+ * current extension activation state (callers can flip the store on/off as
62
+ * the artifacts extension activates/deactivates). When this returns null the
63
+ * RPC fails fast with "artifacts unavailable" — the kernel surfaces the
64
+ * error to the cell. Absent => RPC always fails (no artifact store wired).
65
+ */
66
+ getArtifactStore?: () => ArtifactStore | null;
67
+ }
68
+ export interface AttachOptions {
69
+ forceTakeover?: boolean;
70
+ takeoverReason?: string;
71
+ /**
72
+ * Phase 2 Task 12: optional list of binding ids (e.g. ['jira:prod']) to record
73
+ * in meta.json on first create. Subsequent meta writes preserve whatever's on
74
+ * disk via prevExtras — once persisted, bindings survive every other meta-write
75
+ * path. Ignored on re-attach if meta.json already has a bindings field.
76
+ */
77
+ bindings?: string[];
78
+ }
79
+ export interface ScratchpadInfo {
80
+ name: string;
81
+ live: boolean;
82
+ lastUsedAt: number;
83
+ hasActiveCell: boolean;
84
+ }
85
+ interface Entry {
86
+ runtime: ChildProcessRuntime | null;
87
+ lock: LockInfo;
88
+ lastUsedAt: number;
89
+ archive: CellArchive;
90
+ kernelAtCellId: number | null;
91
+ }
92
+ export declare class ScratchpadManager {
93
+ protected readonly entries: Map<string, Entry>;
94
+ protected readonly workspace: string;
95
+ protected readonly root: string;
96
+ protected readonly maxLive: number;
97
+ protected readonly idleMs: number;
98
+ protected readonly sessionId: string | undefined;
99
+ protected readonly now: () => number;
100
+ protected readonly runtimeOptions: Omit<ChildProcessRuntimeOptions, 'workspace'>;
101
+ protected readonly forkExitTimeoutMs: number;
102
+ protected readonly injector: CredentialInjector | undefined;
103
+ protected readonly audit: AuditLog | undefined;
104
+ protected readonly onDataLoad: ((drawer: DataLoadDrawer, scratchpadName: string) => void) | undefined;
105
+ protected readonly onArtifactCreate: ((drawer: ArtifactCreateDrawer, scratchpadName: string) => void) | undefined;
106
+ protected readonly getArtifactStore: (() => ArtifactStore | null) | undefined;
107
+ protected disposed: boolean;
108
+ private sweepTimer;
109
+ constructor(options: ScratchpadManagerOptions);
110
+ protected dirFor(name: string): string;
111
+ private metaPath;
112
+ private existsOnDisk;
113
+ private payloadSize;
114
+ private writeMetaAtomic;
115
+ private writeMeta;
116
+ private appendRecoveryNotes;
117
+ private applySnapshotToMeta;
118
+ private snapshotThenDispose;
119
+ private ingestRecoveryNotesOnAttach;
120
+ private restoreLeafOnAttach;
121
+ private restoreKernelAtCellIdOnAttach;
122
+ private warmCount;
123
+ /**
124
+ * Phase 2 Task 13: read meta.bindings from disk so each fresh spawn picks up
125
+ * the current binding set (bindings can change between attaches via /sp use).
126
+ * Returns [] if meta.json doesn't exist or doesn't have a v4 bindings array.
127
+ *
128
+ * Phase 2 Task 16: also surfaced as a public read for /sp list rendering and
129
+ * staleness-banner emission. Stays a thin read; callers that need to mutate
130
+ * use addBinding / removeBinding (which atomically RMW meta.json).
131
+ */
132
+ readBindings(name: string): string[];
133
+ /**
134
+ * Phase 2 Task 16: append a binding ref (e.g. 'jira:prod') to meta.bindings.
135
+ * Idempotent — adding a ref already in the list is a no-op (the meta.json
136
+ * write still happens so callers can detect "added" vs "noop" only via the
137
+ * returned tuple). Atomically rewrites meta.json via writeMetaAtomic, so
138
+ * concurrent writers cannot interleave. Caller is responsible for validating
139
+ * `ref` (sp-command uses LocalDataVault.parseRef before invoking).
140
+ */
141
+ addBinding(name: string, ref: string): Promise<{
142
+ added: boolean;
143
+ }>;
144
+ /**
145
+ * Phase 2 Task 16: remove a binding ref from meta.bindings. Returns whether
146
+ * a removal happened so callers can emit "no such binding" if needed.
147
+ */
148
+ removeBinding(name: string, ref: string): Promise<{
149
+ removed: boolean;
150
+ }>;
151
+ private spawnRuntime;
152
+ private evictLruIfNeeded;
153
+ create(name: string, opts?: AttachOptions): Promise<ChildProcessRuntime>;
154
+ getOrAttach(name: string, opts?: AttachOptions): Promise<ChildProcessRuntime>;
155
+ runCell(name: string, code: string, opts?: AttachOptions): Promise<{
156
+ value: unknown;
157
+ stdout: string;
158
+ }>;
159
+ /**
160
+ * Phase 2 Task 14: redact known-secret patterns from a cell-output string
161
+ * before journaling. No-op (pass-through) when no AuditLog is configured —
162
+ * the manager was constructed in test/legacy mode without vault wiring.
163
+ */
164
+ private redactStdout;
165
+ /**
166
+ * Task D: Release a warm kernel's process+memory while preserving on-disk state
167
+ * (kernel.db, namespace.json, cells.jsonl, meta.json, lock.json). Cold-restart
168
+ * happens on the next attach.
169
+ *
170
+ * Without --force: refuses if a cell is mid-execution. With --force: cancels the
171
+ * active cell via runtime.cancel() (SIGINT → SIGTERM → SIGKILL escalation handled
172
+ * internally by ChildProcessRuntime). Post-cancel the kernel is dead, so we skip
173
+ * the snapshot — the next attach replays from cells.jsonl.
174
+ */
175
+ evict(name: string, opts?: {
176
+ force?: boolean;
177
+ }): Promise<{
178
+ interrupted: boolean;
179
+ }>;
180
+ setLeaf(name: string, id: number): Promise<void>;
181
+ fork(srcName: string, dstName: string): Promise<void>;
182
+ clearHistory(name: string): Promise<void>;
183
+ save(name: string): Promise<void>;
184
+ detach(name: string, sessionId: string): Promise<void>;
185
+ markRecoveryNotesSeen(name: string): Promise<void>;
186
+ private attachUnmanaged;
187
+ list(): ScratchpadInfo[];
188
+ remove(name: string): Promise<void>;
189
+ evictIdle(): Promise<void>;
190
+ disposeAll(): Promise<void>;
191
+ protected assertNotDisposed(): void;
192
+ }
193
+ export {};