@cmetech/otto 1.1.1 → 1.2.5

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 (433) 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-artifacts/artifacts-command.js +31 -0
  7. package/dist/resources/extensions/coworker-artifacts/artifacts-singleton.js +17 -0
  8. package/dist/resources/extensions/coworker-artifacts/extension-manifest.json +13 -0
  9. package/dist/resources/extensions/coworker-artifacts/index.js +125 -0
  10. package/dist/resources/extensions/coworker-artifacts/list-tool.js +27 -0
  11. package/dist/resources/extensions/coworker-artifacts/open-tool.js +25 -0
  12. package/dist/resources/extensions/coworker-memory/extension-manifest.json +13 -0
  13. package/dist/resources/extensions/coworker-memory/index.js +219 -0
  14. package/dist/resources/extensions/coworker-memory/memorize-tool.js +10 -0
  15. package/dist/resources/extensions/coworker-memory/memory-command.js +157 -0
  16. package/dist/resources/extensions/coworker-memory/memory-singleton.js +55 -0
  17. package/dist/resources/extensions/coworker-memory/recall-tool.js +18 -0
  18. package/dist/resources/extensions/coworker-memory/session-hooks.js +45 -0
  19. package/dist/resources/extensions/coworker-scratchpad/attach-banners.js +53 -0
  20. package/dist/resources/extensions/coworker-scratchpad/extension-manifest.json +13 -0
  21. package/dist/resources/extensions/coworker-scratchpad/format-age.js +9 -0
  22. package/dist/resources/extensions/coworker-scratchpad/helpers.js +38 -0
  23. package/dist/resources/extensions/coworker-scratchpad/index.js +199 -0
  24. package/dist/resources/extensions/coworker-scratchpad/mime-bundle.js +20 -0
  25. package/dist/resources/extensions/coworker-scratchpad/scratchpad-tool.js +118 -0
  26. package/dist/resources/extensions/coworker-scratchpad/session-sidecar.js +60 -0
  27. package/dist/resources/extensions/coworker-scratchpad/sp-command.js +597 -0
  28. package/dist/resources/extensions/coworker-scratchpad/workspace-pointer.js +41 -0
  29. package/dist/resources/extensions/coworker-scratchpad/workspace-root.js +17 -0
  30. package/dist/resources/extensions/coworker-vault/audit-command.js +35 -0
  31. package/dist/resources/extensions/coworker-vault/connect-command.js +42 -0
  32. package/dist/resources/extensions/coworker-vault/datasource-command.js +50 -0
  33. package/dist/resources/extensions/coworker-vault/extension-manifest.json +12 -0
  34. package/dist/resources/extensions/coworker-vault/index.js +171 -0
  35. package/dist/resources/extensions/coworker-vault/test-helpers.js +86 -0
  36. package/dist/resources/extensions/coworker-vault/vault-singleton.js +24 -0
  37. package/dist/resources/extensions/otto/commands/release-notes/_data.js +83 -0
  38. package/dist/resources/extensions/otto/commands/release-notes/command.js +15 -4
  39. package/dist/resources/extensions/otto/index.js +31 -6
  40. package/dist/resources/extensions/shared/coworker-paths.js +8 -0
  41. package/dist/resources/extensions/slash-commands/{audit.js → audit-codebase.js} +4 -4
  42. package/dist/resources/extensions/slash-commands/extension-manifest.json +1 -1
  43. package/dist/resources/extensions/slash-commands/index.js +2 -2
  44. package/dist/resources/extensions/subagent/index.js +8 -1
  45. package/dist/resources/extensions/subagent/launch.js +37 -5
  46. package/dist/resources/extensions/subagent/run-store.js +1 -0
  47. package/dist/resources/extensions/workflow/bootstrap/register-extension.js +2 -0
  48. package/dist/resources/extensions/workflow/bootstrap/register-hooks.js +10 -0
  49. package/dist/resources/extensions/workflow/health-widget-core.js +1 -1
  50. package/dist/resources/extensions/workflow/persona-status.js +87 -0
  51. package/package.json +26 -10
  52. package/packages/contracts/package.json +1 -1
  53. package/packages/coworker-artifacts/dist/artifact-store.d.ts +25 -0
  54. package/packages/coworker-artifacts/dist/artifact-store.js +187 -0
  55. package/packages/coworker-artifacts/dist/dir-snapshot.d.ts +7 -0
  56. package/packages/coworker-artifacts/dist/dir-snapshot.js +54 -0
  57. package/packages/coworker-artifacts/dist/errors.d.ts +18 -0
  58. package/packages/coworker-artifacts/dist/errors.js +37 -0
  59. package/packages/coworker-artifacts/dist/index.d.ts +7 -0
  60. package/packages/coworker-artifacts/dist/index.js +7 -0
  61. package/packages/coworker-artifacts/dist/readme-renderer.d.ts +5 -0
  62. package/packages/coworker-artifacts/dist/readme-renderer.js +47 -0
  63. package/packages/coworker-artifacts/dist/resolve-uri.d.ts +3 -0
  64. package/packages/coworker-artifacts/dist/resolve-uri.js +29 -0
  65. package/packages/coworker-artifacts/dist/slug.d.ts +4 -0
  66. package/packages/coworker-artifacts/dist/slug.js +32 -0
  67. package/packages/coworker-artifacts/dist/types.d.ts +52 -0
  68. package/packages/coworker-artifacts/dist/types.js +1 -0
  69. package/packages/coworker-artifacts/package.json +20 -0
  70. package/packages/coworker-artifacts/src/artifact-store.test.ts +188 -0
  71. package/packages/coworker-artifacts/src/artifact-store.ts +206 -0
  72. package/packages/coworker-artifacts/src/artifacts-integration.test.ts +109 -0
  73. package/packages/coworker-artifacts/src/dir-snapshot.test.ts +71 -0
  74. package/packages/coworker-artifacts/src/dir-snapshot.ts +52 -0
  75. package/packages/coworker-artifacts/src/errors.test.ts +37 -0
  76. package/packages/coworker-artifacts/src/errors.ts +28 -0
  77. package/packages/coworker-artifacts/src/index.test.ts +22 -0
  78. package/packages/coworker-artifacts/src/index.ts +7 -0
  79. package/packages/coworker-artifacts/src/readme-renderer.test.ts +72 -0
  80. package/packages/coworker-artifacts/src/readme-renderer.ts +56 -0
  81. package/packages/coworker-artifacts/src/resolve-uri.test.ts +46 -0
  82. package/packages/coworker-artifacts/src/resolve-uri.ts +29 -0
  83. package/packages/coworker-artifacts/src/slug.test.ts +47 -0
  84. package/packages/coworker-artifacts/src/slug.ts +31 -0
  85. package/packages/coworker-artifacts/src/types.ts +61 -0
  86. package/packages/coworker-artifacts/tsconfig.json +15 -0
  87. package/packages/coworker-artifacts/tsconfig.publish.json +4 -0
  88. package/packages/coworker-memory/dist/context-injection.d.ts +9 -0
  89. package/packages/coworker-memory/dist/context-injection.js +41 -0
  90. package/packages/coworker-memory/dist/errors.d.ts +25 -0
  91. package/packages/coworker-memory/dist/errors.js +51 -0
  92. package/packages/coworker-memory/dist/index.d.ts +12 -0
  93. package/packages/coworker-memory/dist/index.js +12 -0
  94. package/packages/coworker-memory/dist/layer-a-store.d.ts +16 -0
  95. package/packages/coworker-memory/dist/layer-a-store.js +78 -0
  96. package/packages/coworker-memory/dist/local-sqlite-backend.d.ts +28 -0
  97. package/packages/coworker-memory/dist/local-sqlite-backend.js +167 -0
  98. package/packages/coworker-memory/dist/memory-backend.d.ts +14 -0
  99. package/packages/coworker-memory/dist/memory-backend.js +1 -0
  100. package/packages/coworker-memory/dist/memory-recorder.d.ts +50 -0
  101. package/packages/coworker-memory/dist/memory-recorder.js +69 -0
  102. package/packages/coworker-memory/dist/migrations/001-init.sql +38 -0
  103. package/packages/coworker-memory/dist/migrations/002-artifact-kind.sql +50 -0
  104. package/packages/coworker-memory/dist/paste-detector.d.ts +5 -0
  105. package/packages/coworker-memory/dist/paste-detector.js +14 -0
  106. package/packages/coworker-memory/dist/persona-seed.d.ts +10 -0
  107. package/packages/coworker-memory/dist/persona-seed.js +38 -0
  108. package/packages/coworker-memory/dist/recall-formatter.d.ts +2 -0
  109. package/packages/coworker-memory/dist/recall-formatter.js +14 -0
  110. package/packages/coworker-memory/dist/scope-resolver.d.ts +9 -0
  111. package/packages/coworker-memory/dist/scope-resolver.js +10 -0
  112. package/packages/coworker-memory/dist/types.d.ts +51 -0
  113. package/packages/coworker-memory/dist/types.js +2 -0
  114. package/packages/coworker-memory/dist/workspace-id.d.ts +3 -0
  115. package/packages/coworker-memory/dist/workspace-id.js +54 -0
  116. package/packages/coworker-memory/package.json +35 -0
  117. package/packages/coworker-memory/src/activator-integration.test.ts +141 -0
  118. package/packages/coworker-memory/src/context-injection.test.ts +72 -0
  119. package/packages/coworker-memory/src/context-injection.ts +57 -0
  120. package/packages/coworker-memory/src/errors.test.ts +45 -0
  121. package/packages/coworker-memory/src/errors.ts +42 -0
  122. package/packages/coworker-memory/src/index.test.ts +21 -0
  123. package/packages/coworker-memory/src/index.ts +12 -0
  124. package/packages/coworker-memory/src/layer-a-store.test.ts +85 -0
  125. package/packages/coworker-memory/src/layer-a-store.ts +88 -0
  126. package/packages/coworker-memory/src/local-sqlite-backend.test.ts +110 -0
  127. package/packages/coworker-memory/src/local-sqlite-backend.ts +185 -0
  128. package/packages/coworker-memory/src/memory-backend.ts +10 -0
  129. package/packages/coworker-memory/src/memory-integration.test.ts +89 -0
  130. package/packages/coworker-memory/src/memory-recorder.test.ts +101 -0
  131. package/packages/coworker-memory/src/memory-recorder.ts +95 -0
  132. package/packages/coworker-memory/src/migrations/001-init.sql +38 -0
  133. package/packages/coworker-memory/src/migrations/002-artifact-kind.sql +50 -0
  134. package/packages/coworker-memory/src/paste-detector.test.ts +23 -0
  135. package/packages/coworker-memory/src/paste-detector.ts +18 -0
  136. package/packages/coworker-memory/src/persona-seed.test.ts +57 -0
  137. package/packages/coworker-memory/src/persona-seed.ts +46 -0
  138. package/packages/coworker-memory/src/recall-formatter.test.ts +34 -0
  139. package/packages/coworker-memory/src/recall-formatter.ts +15 -0
  140. package/packages/coworker-memory/src/scope-resolver.test.ts +23 -0
  141. package/packages/coworker-memory/src/scope-resolver.ts +18 -0
  142. package/packages/coworker-memory/src/types.ts +61 -0
  143. package/packages/coworker-memory/src/workspace-id.test.ts +48 -0
  144. package/packages/coworker-memory/src/workspace-id.ts +56 -0
  145. package/packages/coworker-memory/tsconfig.json +15 -0
  146. package/packages/coworker-memory/tsconfig.publish.json +4 -0
  147. package/packages/coworker-persona/dist/commands.d.ts +7 -0
  148. package/packages/coworker-persona/dist/commands.js +35 -0
  149. package/packages/coworker-persona/dist/defaults/manifest.yaml +12 -0
  150. package/packages/coworker-persona/dist/defaults/steering/identity.md +3 -0
  151. package/packages/coworker-persona/dist/index.d.ts +3 -0
  152. package/packages/coworker-persona/dist/index.js +3 -0
  153. package/packages/coworker-persona/dist/manifest.d.ts +24 -0
  154. package/packages/coworker-persona/dist/manifest.js +21 -0
  155. package/packages/coworker-persona/dist/registry.d.ts +22 -0
  156. package/packages/coworker-persona/dist/registry.js +142 -0
  157. package/packages/coworker-persona/package.json +28 -0
  158. package/packages/coworker-persona/scripts/copy-defaults.cjs +17 -0
  159. package/packages/coworker-persona/src/commands.ts +47 -0
  160. package/packages/coworker-persona/src/defaults/manifest.yaml +12 -0
  161. package/packages/coworker-persona/src/defaults/steering/identity.md +3 -0
  162. package/packages/coworker-persona/src/index.ts +3 -0
  163. package/packages/coworker-persona/src/manifest.test.ts +67 -0
  164. package/packages/coworker-persona/src/manifest.ts +49 -0
  165. package/packages/coworker-persona/src/registry.test.ts +89 -0
  166. package/packages/coworker-persona/src/registry.ts +147 -0
  167. package/packages/coworker-persona/tsconfig.json +15 -0
  168. package/packages/coworker-persona/tsconfig.publish.json +4 -0
  169. package/packages/coworker-scratchpad/dist/cell-archive.d.ts +39 -0
  170. package/packages/coworker-scratchpad/dist/cell-archive.js +77 -0
  171. package/packages/coworker-scratchpad/dist/cell-tree.d.ts +14 -0
  172. package/packages/coworker-scratchpad/dist/cell-tree.js +72 -0
  173. package/packages/coworker-scratchpad/dist/child-process-runtime.d.ts +129 -0
  174. package/packages/coworker-scratchpad/dist/child-process-runtime.js +427 -0
  175. package/packages/coworker-scratchpad/dist/collector-registry.d.ts +12 -0
  176. package/packages/coworker-scratchpad/dist/collector-registry.js +29 -0
  177. package/packages/coworker-scratchpad/dist/detect-kind.d.ts +3 -0
  178. package/packages/coworker-scratchpad/dist/detect-kind.js +19 -0
  179. package/packages/coworker-scratchpad/dist/file-collector.d.ts +15 -0
  180. package/packages/coworker-scratchpad/dist/file-collector.js +99 -0
  181. package/packages/coworker-scratchpad/dist/index.d.ts +13 -0
  182. package/packages/coworker-scratchpad/dist/index.js +13 -0
  183. package/packages/coworker-scratchpad/dist/kernel-bindings.d.ts +49 -0
  184. package/packages/coworker-scratchpad/dist/kernel-bindings.js +220 -0
  185. package/packages/coworker-scratchpad/dist/kernel-entry.d.ts +1 -0
  186. package/packages/coworker-scratchpad/dist/kernel-entry.js +355 -0
  187. package/packages/coworker-scratchpad/dist/kernel-protocol.d.ts +171 -0
  188. package/packages/coworker-scratchpad/dist/kernel-protocol.js +48 -0
  189. package/packages/coworker-scratchpad/dist/kernel-spawn.d.ts +3 -0
  190. package/packages/coworker-scratchpad/dist/kernel-spawn.js +54 -0
  191. package/packages/coworker-scratchpad/dist/namespace-codec.d.ts +22 -0
  192. package/packages/coworker-scratchpad/dist/namespace-codec.js +61 -0
  193. package/packages/coworker-scratchpad/dist/scratchpad-lock.d.ts +24 -0
  194. package/packages/coworker-scratchpad/dist/scratchpad-lock.js +86 -0
  195. package/packages/coworker-scratchpad/dist/scratchpad-manager.d.ts +193 -0
  196. package/packages/coworker-scratchpad/dist/scratchpad-manager.js +866 -0
  197. package/packages/coworker-scratchpad/dist/staleness-banner.d.ts +12 -0
  198. package/packages/coworker-scratchpad/dist/staleness-banner.js +27 -0
  199. package/packages/coworker-scratchpad/package.json +31 -0
  200. package/packages/coworker-scratchpad/src/cell-archive.test.ts +150 -0
  201. package/packages/coworker-scratchpad/src/cell-archive.ts +97 -0
  202. package/packages/coworker-scratchpad/src/cell-tree.test.ts +105 -0
  203. package/packages/coworker-scratchpad/src/cell-tree.ts +90 -0
  204. package/packages/coworker-scratchpad/src/child-process-runtime.test.ts +413 -0
  205. package/packages/coworker-scratchpad/src/child-process-runtime.ts +493 -0
  206. package/packages/coworker-scratchpad/src/collector-registry.test.ts +69 -0
  207. package/packages/coworker-scratchpad/src/collector-registry.ts +33 -0
  208. package/packages/coworker-scratchpad/src/detect-kind.test.ts +33 -0
  209. package/packages/coworker-scratchpad/src/detect-kind.ts +22 -0
  210. package/packages/coworker-scratchpad/src/file-collector.test.ts +109 -0
  211. package/packages/coworker-scratchpad/src/file-collector.ts +114 -0
  212. package/packages/coworker-scratchpad/src/index.ts +74 -0
  213. package/packages/coworker-scratchpad/src/kernel-bindings.test.ts +188 -0
  214. package/packages/coworker-scratchpad/src/kernel-bindings.ts +279 -0
  215. package/packages/coworker-scratchpad/src/kernel-entry.test.ts +123 -0
  216. package/packages/coworker-scratchpad/src/kernel-entry.ts +390 -0
  217. package/packages/coworker-scratchpad/src/kernel-protocol.test.ts +105 -0
  218. package/packages/coworker-scratchpad/src/kernel-protocol.ts +230 -0
  219. package/packages/coworker-scratchpad/src/kernel-spawn.test.ts +60 -0
  220. package/packages/coworker-scratchpad/src/kernel-spawn.ts +54 -0
  221. package/packages/coworker-scratchpad/src/namespace-codec.test.ts +102 -0
  222. package/packages/coworker-scratchpad/src/namespace-codec.ts +90 -0
  223. package/packages/coworker-scratchpad/src/scratchpad-lock.test.ts +98 -0
  224. package/packages/coworker-scratchpad/src/scratchpad-lock.ts +102 -0
  225. package/packages/coworker-scratchpad/src/scratchpad-manager.test.ts +1343 -0
  226. package/packages/coworker-scratchpad/src/scratchpad-manager.ts +891 -0
  227. package/packages/coworker-scratchpad/src/staleness-banner.test.ts +53 -0
  228. package/packages/coworker-scratchpad/src/staleness-banner.ts +33 -0
  229. package/packages/coworker-scratchpad/src/vault-integration.test.ts +221 -0
  230. package/packages/coworker-scratchpad/tsconfig.json +15 -0
  231. package/packages/coworker-scratchpad/tsconfig.publish.json +4 -0
  232. package/packages/coworker-types/dist/artifacts.d.ts +31 -0
  233. package/packages/coworker-types/dist/artifacts.js +2 -0
  234. package/packages/coworker-types/dist/contracts.d.ts +32 -0
  235. package/packages/coworker-types/dist/contracts.js +1 -0
  236. package/packages/coworker-types/dist/index.d.ts +5 -0
  237. package/packages/coworker-types/dist/index.js +5 -0
  238. package/packages/coworker-types/dist/memory.d.ts +61 -0
  239. package/packages/coworker-types/dist/memory.js +3 -0
  240. package/packages/coworker-types/dist/scratchpad.d.ts +43 -0
  241. package/packages/coworker-types/dist/scratchpad.js +2 -0
  242. package/packages/coworker-types/dist/vault.d.ts +34 -0
  243. package/packages/coworker-types/dist/vault.js +2 -0
  244. package/packages/coworker-types/package.json +24 -0
  245. package/packages/coworker-types/src/artifacts.test.ts +52 -0
  246. package/packages/coworker-types/src/artifacts.ts +35 -0
  247. package/packages/coworker-types/src/contracts.test.ts +43 -0
  248. package/packages/coworker-types/src/contracts.ts +36 -0
  249. package/packages/coworker-types/src/index.ts +5 -0
  250. package/packages/coworker-types/src/memory.test.ts +50 -0
  251. package/packages/coworker-types/src/memory.ts +79 -0
  252. package/packages/coworker-types/src/scratchpad.test.ts +46 -0
  253. package/packages/coworker-types/src/scratchpad.ts +51 -0
  254. package/packages/coworker-types/src/smoke.test.ts +34 -0
  255. package/packages/coworker-types/src/vault.test.ts +49 -0
  256. package/packages/coworker-types/src/vault.ts +40 -0
  257. package/packages/coworker-types/tsconfig.json +15 -0
  258. package/packages/coworker-types/tsconfig.publish.json +4 -0
  259. package/packages/coworker-utils/dist/audit-log.d.ts +34 -0
  260. package/packages/coworker-utils/dist/audit-log.js +88 -0
  261. package/packages/coworker-utils/dist/index.d.ts +6 -0
  262. package/packages/coworker-utils/dist/index.js +6 -0
  263. package/packages/coworker-utils/dist/lease.d.ts +7 -0
  264. package/packages/coworker-utils/dist/lease.js +67 -0
  265. package/packages/coworker-utils/dist/logger.d.ts +13 -0
  266. package/packages/coworker-utils/dist/logger.js +26 -0
  267. package/packages/coworker-utils/dist/migration-runner.d.ts +7 -0
  268. package/packages/coworker-utils/dist/migration-runner.js +36 -0
  269. package/packages/coworker-utils/dist/ndjson-channel.d.ts +3 -0
  270. package/packages/coworker-utils/dist/ndjson-channel.js +38 -0
  271. package/packages/coworker-utils/dist/secret-scanner.d.ts +10 -0
  272. package/packages/coworker-utils/dist/secret-scanner.js +42 -0
  273. package/packages/coworker-utils/package.json +24 -0
  274. package/packages/coworker-utils/src/audit-log.test.ts +140 -0
  275. package/packages/coworker-utils/src/audit-log.ts +107 -0
  276. package/packages/coworker-utils/src/index.ts +6 -0
  277. package/packages/coworker-utils/src/lease.test.ts +64 -0
  278. package/packages/coworker-utils/src/lease.ts +76 -0
  279. package/packages/coworker-utils/src/logger.test.ts +50 -0
  280. package/packages/coworker-utils/src/logger.ts +45 -0
  281. package/packages/coworker-utils/src/migration-runner.test.ts +65 -0
  282. package/packages/coworker-utils/src/migration-runner.ts +50 -0
  283. package/packages/coworker-utils/src/ndjson-channel.test.ts +76 -0
  284. package/packages/coworker-utils/src/ndjson-channel.ts +41 -0
  285. package/packages/coworker-utils/src/secret-scanner.test.ts +61 -0
  286. package/packages/coworker-utils/src/secret-scanner.ts +56 -0
  287. package/packages/coworker-utils/tsconfig.json +15 -0
  288. package/packages/coworker-utils/tsconfig.publish.json +4 -0
  289. package/packages/coworker-vault/dist/data-vault.d.ts +41 -0
  290. package/packages/coworker-vault/dist/data-vault.js +223 -0
  291. package/packages/coworker-vault/dist/engine-registry.d.ts +34 -0
  292. package/packages/coworker-vault/dist/engine-registry.js +90 -0
  293. package/packages/coworker-vault/dist/engines/jira.yaml +17 -0
  294. package/packages/coworker-vault/dist/errors.d.ts +28 -0
  295. package/packages/coworker-vault/dist/errors.js +57 -0
  296. package/packages/coworker-vault/dist/index.d.ts +6 -0
  297. package/packages/coworker-vault/dist/index.js +6 -0
  298. package/packages/coworker-vault/dist/injector.d.ts +19 -0
  299. package/packages/coworker-vault/dist/injector.js +77 -0
  300. package/packages/coworker-vault/dist/types.d.ts +28 -0
  301. package/packages/coworker-vault/dist/types.js +1 -0
  302. package/packages/coworker-vault/dist/vault-keep.d.ts +4 -0
  303. package/packages/coworker-vault/dist/vault-keep.js +21 -0
  304. package/packages/coworker-vault/package.json +29 -0
  305. package/packages/coworker-vault/src/data-vault.test.ts +199 -0
  306. package/packages/coworker-vault/src/data-vault.ts +257 -0
  307. package/packages/coworker-vault/src/engine-registry.test.ts +120 -0
  308. package/packages/coworker-vault/src/engine-registry.ts +107 -0
  309. package/packages/coworker-vault/src/engines/jira.yaml +17 -0
  310. package/packages/coworker-vault/src/errors.test.ts +58 -0
  311. package/packages/coworker-vault/src/errors.ts +50 -0
  312. package/packages/coworker-vault/src/index.test.ts +24 -0
  313. package/packages/coworker-vault/src/index.ts +6 -0
  314. package/packages/coworker-vault/src/injector.test.ts +109 -0
  315. package/packages/coworker-vault/src/injector.ts +98 -0
  316. package/packages/coworker-vault/src/types.ts +33 -0
  317. package/packages/coworker-vault/src/vault-keep.test.ts +49 -0
  318. package/packages/coworker-vault/src/vault-keep.ts +31 -0
  319. package/packages/coworker-vault/tsconfig.json +15 -0
  320. package/packages/coworker-vault/tsconfig.publish.json +4 -0
  321. package/packages/daemon/package.json +3 -3
  322. package/packages/mcp-server/package.json +3 -3
  323. package/packages/mcp-server/tsconfig.tsbuildinfo +1 -1
  324. package/packages/native/package.json +1 -1
  325. package/packages/native/tsconfig.tsbuildinfo +1 -1
  326. package/packages/pi-agent-core/package.json +1 -1
  327. package/packages/pi-agent-core/tsconfig.tsbuildinfo +1 -1
  328. package/packages/pi-ai/package.json +1 -1
  329. package/packages/pi-ai/tsconfig.tsbuildinfo +1 -1
  330. package/packages/pi-coding-agent/dist/core/extensions/runner.d.ts +6 -1
  331. package/packages/pi-coding-agent/dist/core/extensions/runner.d.ts.map +1 -1
  332. package/packages/pi-coding-agent/dist/core/extensions/runner.js +22 -3
  333. package/packages/pi-coding-agent/dist/core/extensions/runner.js.map +1 -1
  334. package/packages/pi-coding-agent/dist/core/resolve-config-value.test.js +11 -0
  335. package/packages/pi-coding-agent/dist/core/resolve-config-value.test.js.map +1 -1
  336. package/packages/pi-coding-agent/dist/modes/rpc/raw-stdout.d.ts +47 -0
  337. package/packages/pi-coding-agent/dist/modes/rpc/raw-stdout.d.ts.map +1 -0
  338. package/packages/pi-coding-agent/dist/modes/rpc/raw-stdout.js +107 -0
  339. package/packages/pi-coding-agent/dist/modes/rpc/raw-stdout.js.map +1 -0
  340. package/packages/pi-coding-agent/dist/modes/rpc/raw-stdout.regression.test.d.ts +19 -0
  341. package/packages/pi-coding-agent/dist/modes/rpc/raw-stdout.regression.test.d.ts.map +1 -0
  342. package/packages/pi-coding-agent/dist/modes/rpc/raw-stdout.regression.test.js +121 -0
  343. package/packages/pi-coding-agent/dist/modes/rpc/raw-stdout.regression.test.js.map +1 -0
  344. package/packages/pi-coding-agent/dist/modes/rpc/rpc-mode.d.ts.map +1 -1
  345. package/packages/pi-coding-agent/dist/modes/rpc/rpc-mode.js +17 -1
  346. package/packages/pi-coding-agent/dist/modes/rpc/rpc-mode.js.map +1 -1
  347. package/packages/pi-coding-agent/package.json +2 -2
  348. package/packages/pi-coding-agent/src/core/extensions/runner.ts +22 -3
  349. package/packages/pi-coding-agent/src/core/resolve-config-value.test.ts +11 -0
  350. package/packages/pi-coding-agent/src/modes/rpc/raw-stdout.regression.test.ts +129 -0
  351. package/packages/pi-coding-agent/src/modes/rpc/raw-stdout.ts +117 -0
  352. package/packages/pi-coding-agent/src/modes/rpc/rpc-mode.ts +18 -1
  353. package/packages/pi-coding-agent/tsconfig.tsbuildinfo +1 -1
  354. package/packages/pi-tui/package.json +1 -1
  355. package/packages/pi-tui/tsconfig.tsbuildinfo +1 -1
  356. package/packages/rpc-client/package.json +2 -2
  357. package/packages/rpc-client/tsconfig.tsbuildinfo +1 -1
  358. package/pkg/package.json +1 -1
  359. package/scripts/install.js +6 -5
  360. package/src/resources/extensions/coworker-artifacts/artifacts-command.test.ts +54 -0
  361. package/src/resources/extensions/coworker-artifacts/artifacts-command.ts +43 -0
  362. package/src/resources/extensions/coworker-artifacts/artifacts-singleton.test.ts +25 -0
  363. package/src/resources/extensions/coworker-artifacts/artifacts-singleton.ts +29 -0
  364. package/src/resources/extensions/coworker-artifacts/extension-manifest.json +13 -0
  365. package/src/resources/extensions/coworker-artifacts/index.test.ts +46 -0
  366. package/src/resources/extensions/coworker-artifacts/index.ts +154 -0
  367. package/src/resources/extensions/coworker-artifacts/list-tool.test.ts +29 -0
  368. package/src/resources/extensions/coworker-artifacts/list-tool.ts +53 -0
  369. package/src/resources/extensions/coworker-artifacts/open-tool.test.ts +30 -0
  370. package/src/resources/extensions/coworker-artifacts/open-tool.ts +43 -0
  371. package/src/resources/extensions/coworker-memory/extension-manifest.json +13 -0
  372. package/src/resources/extensions/coworker-memory/index.test.ts +137 -0
  373. package/src/resources/extensions/coworker-memory/index.ts +257 -0
  374. package/src/resources/extensions/coworker-memory/memorize-tool.test.ts +41 -0
  375. package/src/resources/extensions/coworker-memory/memorize-tool.ts +20 -0
  376. package/src/resources/extensions/coworker-memory/memory-command.test.ts +134 -0
  377. package/src/resources/extensions/coworker-memory/memory-command.ts +131 -0
  378. package/src/resources/extensions/coworker-memory/memory-singleton.test.ts +41 -0
  379. package/src/resources/extensions/coworker-memory/memory-singleton.ts +89 -0
  380. package/src/resources/extensions/coworker-memory/recall-tool.test.ts +50 -0
  381. package/src/resources/extensions/coworker-memory/recall-tool.ts +35 -0
  382. package/src/resources/extensions/coworker-memory/session-hooks.test.ts +77 -0
  383. package/src/resources/extensions/coworker-memory/session-hooks.ts +61 -0
  384. package/src/resources/extensions/coworker-scratchpad/attach-banners.test.ts +124 -0
  385. package/src/resources/extensions/coworker-scratchpad/attach-banners.ts +67 -0
  386. package/src/resources/extensions/coworker-scratchpad/extension-manifest.json +13 -0
  387. package/src/resources/extensions/coworker-scratchpad/format-age.test.ts +30 -0
  388. package/src/resources/extensions/coworker-scratchpad/format-age.ts +6 -0
  389. package/src/resources/extensions/coworker-scratchpad/helpers.test.ts +93 -0
  390. package/src/resources/extensions/coworker-scratchpad/helpers.ts +42 -0
  391. package/src/resources/extensions/coworker-scratchpad/index.test.ts +514 -0
  392. package/src/resources/extensions/coworker-scratchpad/index.ts +207 -0
  393. package/src/resources/extensions/coworker-scratchpad/mime-bundle.test.ts +61 -0
  394. package/src/resources/extensions/coworker-scratchpad/mime-bundle.ts +23 -0
  395. package/src/resources/extensions/coworker-scratchpad/scratchpad-tool.test.ts +137 -0
  396. package/src/resources/extensions/coworker-scratchpad/scratchpad-tool.ts +165 -0
  397. package/src/resources/extensions/coworker-scratchpad/session-sidecar.test.ts +133 -0
  398. package/src/resources/extensions/coworker-scratchpad/session-sidecar.ts +68 -0
  399. package/src/resources/extensions/coworker-scratchpad/sp-command.test.ts +836 -0
  400. package/src/resources/extensions/coworker-scratchpad/sp-command.ts +602 -0
  401. package/src/resources/extensions/coworker-scratchpad/workspace-pointer.test.ts +74 -0
  402. package/src/resources/extensions/coworker-scratchpad/workspace-pointer.ts +55 -0
  403. package/src/resources/extensions/coworker-scratchpad/workspace-root.test.ts +51 -0
  404. package/src/resources/extensions/coworker-scratchpad/workspace-root.ts +16 -0
  405. package/src/resources/extensions/coworker-vault/audit-command.test.ts +109 -0
  406. package/src/resources/extensions/coworker-vault/audit-command.ts +56 -0
  407. package/src/resources/extensions/coworker-vault/connect-command.test.ts +103 -0
  408. package/src/resources/extensions/coworker-vault/connect-command.ts +69 -0
  409. package/src/resources/extensions/coworker-vault/datasource-command.test.ts +80 -0
  410. package/src/resources/extensions/coworker-vault/datasource-command.ts +81 -0
  411. package/src/resources/extensions/coworker-vault/extension-manifest.json +12 -0
  412. package/src/resources/extensions/coworker-vault/index.test.ts +82 -0
  413. package/src/resources/extensions/coworker-vault/index.ts +181 -0
  414. package/src/resources/extensions/coworker-vault/test-helpers.ts +120 -0
  415. package/src/resources/extensions/coworker-vault/vault-singleton.test.ts +27 -0
  416. package/src/resources/extensions/coworker-vault/vault-singleton.ts +40 -0
  417. package/src/resources/extensions/otto/commands/release-notes/_data.ts +97 -0
  418. package/src/resources/extensions/otto/commands/release-notes/command.ts +16 -3
  419. package/src/resources/extensions/otto/index.ts +29 -6
  420. package/src/resources/extensions/shared/coworker-paths.test.ts +40 -0
  421. package/src/resources/extensions/shared/coworker-paths.ts +10 -0
  422. package/src/resources/extensions/slash-commands/{audit.ts → audit-codebase.ts} +4 -4
  423. package/src/resources/extensions/slash-commands/extension-manifest.json +1 -1
  424. package/src/resources/extensions/slash-commands/index.ts +2 -2
  425. package/src/resources/extensions/subagent/index.ts +9 -0
  426. package/src/resources/extensions/subagent/launch.test.ts +97 -0
  427. package/src/resources/extensions/subagent/launch.ts +42 -5
  428. package/src/resources/extensions/subagent/run-store.ts +3 -1
  429. package/src/resources/extensions/workflow/bootstrap/register-extension.ts +2 -0
  430. package/src/resources/extensions/workflow/bootstrap/register-hooks.ts +10 -0
  431. package/src/resources/extensions/workflow/health-widget-core.ts +1 -1
  432. package/src/resources/extensions/workflow/persona-status.ts +109 -0
  433. package/src/resources/extensions/workflow/tests/auto-recovery.test.ts +34 -0
@@ -0,0 +1,78 @@
1
+ // packages/coworker-memory/src/layer-a-store.ts
2
+ import { chmodSync, existsSync, mkdirSync, readFileSync, renameSync, writeFileSync } from 'node:fs';
3
+ import { join } from 'node:path';
4
+ import { parse as parseYaml, stringify as stringifyYaml } from 'yaml';
5
+ import { LayerAWriteBlocked, MemoryEntryMalformed } from './errors.js';
6
+ const FILE_FOR = {
7
+ profile: 'profile.md',
8
+ rule: 'rules.md',
9
+ lesson: 'lessons.md',
10
+ };
11
+ const TITLE_FOR = {
12
+ profile: 'Profile',
13
+ rule: 'Rules',
14
+ lesson: 'Lessons',
15
+ };
16
+ export class LayerAStore {
17
+ opts;
18
+ constructor(opts) {
19
+ this.opts = opts;
20
+ }
21
+ async append(entry) {
22
+ const hits = this.opts.scanner.scan(entry.text);
23
+ if (hits.length > 0) {
24
+ this.opts.audit.append({
25
+ _schema: 1, ts: new Date().toISOString(), producer: 'memory', action: 'block', severity: 'warn',
26
+ detail: { scope: this.opts.scope, kind: entry.kind, reason: 'secret', secret_kind: hits[0].kind },
27
+ });
28
+ throw new LayerAWriteBlocked(hits[0].kind);
29
+ }
30
+ mkdirSync(this.opts.scopeDir, { recursive: true, mode: 0o700 });
31
+ const path = join(this.opts.scopeDir, FILE_FOR[entry.kind]);
32
+ const existing = existsSync(path) ? readFileSync(path, 'utf8') : null;
33
+ const { body } = existing ? this.split(existing, path) : { body: '' };
34
+ const addition = entry.kind === 'lesson'
35
+ ? `- (${entry.ts}) ${entry.text}\n`
36
+ : `## ${entry.ts}\n${entry.text}\n\n`;
37
+ const newBody = (body && !body.endsWith('\n') ? body + '\n' : body) + addition;
38
+ const newFile = this.composeFile(entry.kind, newBody, entry.ts, entry.source);
39
+ const tmp = `${path}.tmp`;
40
+ writeFileSync(tmp, newFile, { mode: 0o600 });
41
+ chmodSync(tmp, 0o600);
42
+ renameSync(tmp, path);
43
+ this.opts.audit.append({
44
+ _schema: 1, ts: new Date().toISOString(), producer: 'memory', action: 'write-layer-a',
45
+ detail: { scope: this.opts.scope, kind: entry.kind, source: entry.source, byte_count: Buffer.byteLength(entry.text, 'utf8') },
46
+ });
47
+ }
48
+ async read(kind) {
49
+ const path = join(this.opts.scopeDir, FILE_FOR[kind]);
50
+ if (!existsSync(path))
51
+ return '';
52
+ const raw = readFileSync(path, 'utf8');
53
+ const { body } = this.split(raw, path);
54
+ return body.trim();
55
+ }
56
+ split(raw, path) {
57
+ if (!raw.startsWith('---')) {
58
+ return { frontmatter: {}, body: raw };
59
+ }
60
+ const end = raw.indexOf('\n---\n', 4);
61
+ if (end < 0)
62
+ throw new MemoryEntryMalformed(path, 'unterminated frontmatter');
63
+ try {
64
+ const fm = parseYaml(raw.slice(4, end));
65
+ const body = raw.slice(end + 5);
66
+ return { frontmatter: fm ?? {}, body };
67
+ }
68
+ catch (err) {
69
+ throw new MemoryEntryMalformed(path, `frontmatter parse: ${err.message}`);
70
+ }
71
+ }
72
+ composeFile(kind, body, ts, source) {
73
+ const fm = { schema_version: 1, last_modified_at: ts, source };
74
+ const fmStr = stringifyYaml(fm).trimEnd();
75
+ const header = `---\n${fmStr}\n---\n\n# ${TITLE_FOR[kind]}\n\n`;
76
+ return header + body.replace(new RegExp(`^\\n?# ${TITLE_FOR[kind]}\\n\\n?`), '');
77
+ }
78
+ }
@@ -0,0 +1,28 @@
1
+ import type { MemoryBackend } from './memory-backend.js';
2
+ import type { Drawer, RecallQuery, RecallResult, BackendStatus, Wing, Room } from './types.js';
3
+ export interface LocalSqliteBackendOptions {
4
+ dbPath: string;
5
+ now?: () => string;
6
+ busyTimeoutMs?: number;
7
+ }
8
+ export declare class LocalSqliteBackend implements MemoryBackend {
9
+ private db;
10
+ private readonly path;
11
+ private readonly now;
12
+ private readonly busyTimeoutMs;
13
+ constructor(opts: LocalSqliteBackendOptions);
14
+ open(): Promise<void>;
15
+ close(): Promise<void>;
16
+ private requireDb;
17
+ retain(input: Omit<Drawer, 'id' | 'created_at'>): Promise<Drawer>;
18
+ recall(query: RecallQuery): Promise<RecallResult[]>;
19
+ listRooms(wing?: Wing): Promise<Room[]>;
20
+ listWings(): Promise<Wing[]>;
21
+ status(): Promise<BackendStatus>;
22
+ clear(args: {
23
+ wing?: Wing;
24
+ confirm: true;
25
+ }): Promise<{
26
+ deleted: number;
27
+ }>;
28
+ }
@@ -0,0 +1,167 @@
1
+ // packages/coworker-memory/src/local-sqlite-backend.ts
2
+ import Database from 'better-sqlite3';
3
+ import { readFileSync, mkdirSync } from 'node:fs';
4
+ import { dirname, join } from 'node:path';
5
+ import { fileURLToPath } from 'node:url';
6
+ import { v4 as uuid } from 'uuid';
7
+ import { RecallQueryMalformed, BackendUnavailable } from './errors.js';
8
+ function migrationDir() {
9
+ return join(dirname(fileURLToPath(import.meta.url)), 'migrations');
10
+ }
11
+ function escapeFts5(q) {
12
+ // Wrap each word containing special chars in double quotes; doubled internal quotes.
13
+ // Empty query → throw upstream.
14
+ const tokens = q.match(/\S+/g) ?? [];
15
+ return tokens.map(t => `"${t.replace(/"/g, '""')}"`).join(' OR ');
16
+ }
17
+ export class LocalSqliteBackend {
18
+ db = null;
19
+ path;
20
+ now;
21
+ busyTimeoutMs;
22
+ constructor(opts) {
23
+ this.path = opts.dbPath;
24
+ this.now = opts.now ?? (() => new Date().toISOString());
25
+ this.busyTimeoutMs = opts.busyTimeoutMs ?? 2000;
26
+ }
27
+ async open() {
28
+ if (this.db)
29
+ return;
30
+ mkdirSync(dirname(this.path), { recursive: true, mode: 0o700 });
31
+ try {
32
+ this.db = new Database(this.path);
33
+ this.db.pragma(`busy_timeout = ${this.busyTimeoutMs}`);
34
+ const dir = migrationDir();
35
+ const migrations = [
36
+ { version: 1, file: '001-init.sql' },
37
+ { version: 2, file: '002-artifact-kind.sql' },
38
+ ];
39
+ const userVersion = this.db.pragma('user_version', { simple: true });
40
+ for (const m of migrations) {
41
+ if (userVersion < m.version) {
42
+ const sql = readFileSync(join(dir, m.file), 'utf8');
43
+ this.db.exec(sql);
44
+ }
45
+ }
46
+ }
47
+ catch (err) {
48
+ throw new BackendUnavailable(`open failed: ${err.message}`);
49
+ }
50
+ }
51
+ async close() {
52
+ this.db?.close();
53
+ this.db = null;
54
+ }
55
+ requireDb() {
56
+ if (!this.db)
57
+ throw new BackendUnavailable('not opened');
58
+ return this.db;
59
+ }
60
+ async retain(input) {
61
+ const db = this.requireDb();
62
+ const id = uuid();
63
+ const created_at = this.now();
64
+ const stmt = db.prepare(`
65
+ INSERT INTO drawers (id, wing, room, kind, content, metadata_json, parent_id, redacted, created_at)
66
+ VALUES (@id, @wing, @room, @kind, @content, @metadata_json, @parent_id, @redacted, @created_at)
67
+ `);
68
+ stmt.run({
69
+ id, wing: input.wing, room: input.room, kind: input.kind, content: input.content,
70
+ metadata_json: JSON.stringify(input.metadata ?? {}),
71
+ parent_id: input.parent_id ?? null,
72
+ redacted: input.redacted ? 1 : 0,
73
+ created_at,
74
+ });
75
+ return { id, created_at, ...input };
76
+ }
77
+ async recall(query) {
78
+ if (!query.query || !query.query.trim())
79
+ throw new RecallQueryMalformed('empty query');
80
+ const db = this.requireDb();
81
+ const matchExpr = escapeFts5(query.query.trim());
82
+ const conditions = ['drawers_fts MATCH ?'];
83
+ const params = [matchExpr];
84
+ if (query.wing) {
85
+ if (Array.isArray(query.wing)) {
86
+ conditions.push(`d.wing IN (${query.wing.map(() => '?').join(',')})`);
87
+ params.push(...query.wing);
88
+ }
89
+ else {
90
+ conditions.push('d.wing = ?');
91
+ params.push(query.wing);
92
+ }
93
+ }
94
+ if (query.room) {
95
+ conditions.push('d.room = ?');
96
+ params.push(query.room);
97
+ }
98
+ if (query.kind) {
99
+ const kinds = Array.isArray(query.kind) ? query.kind : [query.kind];
100
+ conditions.push(`d.kind IN (${kinds.map(() => '?').join(',')})`);
101
+ params.push(...kinds);
102
+ }
103
+ if (query.days_back && query.days_back > 0) {
104
+ const cutoff = new Date(Date.now() - query.days_back * 86400_000).toISOString();
105
+ conditions.push('d.created_at >= ?');
106
+ params.push(cutoff);
107
+ }
108
+ const limit = Math.min(Math.max(query.max_results ?? 8, 1), 64);
109
+ params.push(limit);
110
+ const sql = `
111
+ SELECT d.id, d.wing, d.room, d.kind, d.content, d.metadata_json, d.parent_id, d.redacted, d.created_at,
112
+ bm25(drawers_fts) AS rank,
113
+ snippet(drawers_fts, 0, '<mark>', '</mark>', '...', 16) AS snippet
114
+ FROM drawers_fts
115
+ JOIN drawers d ON d.rowid = drawers_fts.rowid
116
+ WHERE ${conditions.join(' AND ')}
117
+ ORDER BY rank
118
+ LIMIT ?
119
+ `;
120
+ const rows = db.prepare(sql).all(...params);
121
+ return rows.map(r => ({
122
+ drawer: {
123
+ id: r.id, wing: r.wing, room: r.room, kind: r.kind, content: r.content,
124
+ metadata: JSON.parse(r.metadata_json),
125
+ parent_id: r.parent_id ?? undefined, redacted: r.redacted === 1,
126
+ created_at: r.created_at,
127
+ },
128
+ score: -r.rank, // BM25 lower=better in sqlite; invert for descending
129
+ snippet: r.snippet,
130
+ }));
131
+ }
132
+ async listRooms(wing) {
133
+ const db = this.requireDb();
134
+ const sql = wing
135
+ ? `SELECT DISTINCT room FROM drawers WHERE wing = ? ORDER BY room`
136
+ : `SELECT DISTINCT room FROM drawers ORDER BY room`;
137
+ const rows = wing ? db.prepare(sql).all(wing) : db.prepare(sql).all();
138
+ return rows.map(r => r.room);
139
+ }
140
+ async listWings() {
141
+ const db = this.requireDb();
142
+ const rows = db.prepare(`SELECT DISTINCT wing FROM drawers ORDER BY wing`).all();
143
+ return rows.map(r => r.wing);
144
+ }
145
+ async status() {
146
+ const db = this.requireDb();
147
+ const { c } = db.prepare(`SELECT COUNT(*) AS c FROM drawers`).get();
148
+ const { user_version } = db.prepare(`PRAGMA user_version`).get();
149
+ return {
150
+ ready: true,
151
+ workspace_wing: '', // caller (memory-singleton) overlays this from scope info
152
+ drawer_count: c,
153
+ layer_b_db_path: this.path,
154
+ schema_version: user_version,
155
+ };
156
+ }
157
+ async clear(args) {
158
+ if (args.confirm !== true)
159
+ throw new RecallQueryMalformed('confirm must be true');
160
+ const db = this.requireDb();
161
+ const stmt = args.wing
162
+ ? db.prepare(`DELETE FROM drawers WHERE wing = ?`)
163
+ : db.prepare(`DELETE FROM drawers`);
164
+ const result = args.wing ? stmt.run(args.wing) : stmt.run();
165
+ return { deleted: result.changes };
166
+ }
167
+ }
@@ -0,0 +1,14 @@
1
+ import type { Drawer, RecallQuery, RecallResult, BackendStatus, Wing, Room } from './types.js';
2
+ export interface MemoryBackend {
3
+ recall(query: RecallQuery): Promise<RecallResult[]>;
4
+ retain(input: Omit<Drawer, 'id' | 'created_at'>): Promise<Drawer>;
5
+ listRooms(wing?: Wing): Promise<Room[]>;
6
+ listWings(): Promise<Wing[]>;
7
+ status(): Promise<BackendStatus>;
8
+ clear(args: {
9
+ wing?: Wing;
10
+ confirm: true;
11
+ }): Promise<{
12
+ deleted: number;
13
+ }>;
14
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,50 @@
1
+ import { AuditLog, SecretScanner } from '@otto/coworker-utils';
2
+ import type { MemoryBackend } from './memory-backend.js';
3
+ import type { Wing, Room, Drawer } from './types.js';
4
+ export interface CurrentScratchpadProvider {
5
+ (sessionId: string): string | null;
6
+ }
7
+ export interface MemoryRecorderOptions {
8
+ backend: MemoryBackend;
9
+ scanner: SecretScanner;
10
+ audit: AuditLog;
11
+ writeWing: Wing;
12
+ currentScratchpadName: CurrentScratchpadProvider;
13
+ pasteOptions?: {
14
+ lengthThreshold?: number;
15
+ newlineThreshold?: number;
16
+ };
17
+ }
18
+ export declare class MemoryRecorder {
19
+ private readonly opts;
20
+ constructor(opts: MemoryRecorderOptions);
21
+ recordTurn(args: {
22
+ sessionId: string;
23
+ userText: string;
24
+ turnId: string;
25
+ room?: Room;
26
+ }): Promise<Drawer>;
27
+ recordPaste(args: {
28
+ sessionId: string;
29
+ content: string;
30
+ turnId: string;
31
+ room?: Room;
32
+ }): Promise<Drawer>;
33
+ recordFileLoad(args: {
34
+ scratchpadName: string;
35
+ collector: string;
36
+ uri: string;
37
+ bytes: number;
38
+ rows_loaded?: number;
39
+ schema?: object;
40
+ turnId: string;
41
+ }): Promise<Drawer>;
42
+ recordArtifact(args: {
43
+ scratchpadName: string;
44
+ slug: string;
45
+ kind: string;
46
+ uri: string;
47
+ turnId: string;
48
+ }): Promise<Drawer>;
49
+ private writeDrawer;
50
+ }
@@ -0,0 +1,69 @@
1
+ import { detectPaste } from './paste-detector.js';
2
+ export class MemoryRecorder {
3
+ opts;
4
+ constructor(opts) {
5
+ this.opts = opts;
6
+ }
7
+ async recordTurn(args) {
8
+ const kind = detectPaste(args.userText, this.opts.pasteOptions);
9
+ const room = args.room ?? this.opts.currentScratchpadName(args.sessionId) ?? 'inbox';
10
+ return this.writeDrawer({
11
+ wing: this.opts.writeWing, room, kind,
12
+ content: args.userText, metadata: { turn_id: args.turnId, session_id: args.sessionId },
13
+ });
14
+ }
15
+ async recordPaste(args) {
16
+ const room = args.room ?? this.opts.currentScratchpadName(args.sessionId) ?? 'inbox';
17
+ return this.writeDrawer({
18
+ wing: this.opts.writeWing, room, kind: 'paste',
19
+ content: args.content, metadata: { turn_id: args.turnId, session_id: args.sessionId },
20
+ });
21
+ }
22
+ async recordFileLoad(args) {
23
+ const content = JSON.stringify({
24
+ collector: args.collector, uri: args.uri, bytes: args.bytes,
25
+ rows_loaded: args.rows_loaded, schema: args.schema,
26
+ });
27
+ return this.writeDrawer({
28
+ wing: this.opts.writeWing, room: args.scratchpadName, kind: 'file_load',
29
+ content, metadata: { turn_id: args.turnId, scratchpad: args.scratchpadName },
30
+ });
31
+ }
32
+ async recordArtifact(args) {
33
+ const content = JSON.stringify({
34
+ slug: args.slug, kind: args.kind, uri: args.uri,
35
+ });
36
+ return this.writeDrawer({
37
+ wing: this.opts.writeWing, room: args.scratchpadName, kind: 'artifact',
38
+ content, metadata: { turn_id: args.turnId, scratchpad: args.scratchpadName },
39
+ });
40
+ }
41
+ async writeDrawer(input) {
42
+ const hits = this.opts.scanner.scan(input.content);
43
+ let content = input.content;
44
+ let redacted = false;
45
+ if (hits.length > 0) {
46
+ content = this.opts.scanner.redact(input.content);
47
+ redacted = true;
48
+ const ts = new Date().toISOString();
49
+ for (const h of hits) {
50
+ this.opts.audit.append({
51
+ _schema: 1, ts, producer: 'memory', action: 'redact', severity: 'warn',
52
+ detail: {
53
+ wing: input.wing, room: input.room, kind: input.kind,
54
+ secret_kind: h.kind, offset: h.start, length: h.end - h.start,
55
+ },
56
+ });
57
+ }
58
+ }
59
+ const drawer = await this.opts.backend.retain({ ...input, content, redacted });
60
+ this.opts.audit.append({
61
+ _schema: 1, ts: new Date().toISOString(), producer: 'memory', action: 'write-drawer',
62
+ detail: {
63
+ wing: drawer.wing, room: drawer.room, kind: drawer.kind,
64
+ byte_count: Buffer.byteLength(content, 'utf8'), redacted,
65
+ },
66
+ });
67
+ return drawer;
68
+ }
69
+ }
@@ -0,0 +1,38 @@
1
+ -- packages/coworker-memory/src/migrations/001-init.sql
2
+ PRAGMA journal_mode = WAL;
3
+ PRAGMA user_version = 1;
4
+ PRAGMA foreign_keys = ON;
5
+
6
+ CREATE TABLE IF NOT EXISTS drawers (
7
+ id TEXT PRIMARY KEY,
8
+ wing TEXT NOT NULL,
9
+ room TEXT NOT NULL,
10
+ kind TEXT NOT NULL CHECK (kind IN ('turn','paste','file_load','ticket','email','rca','note')),
11
+ content TEXT NOT NULL,
12
+ metadata_json TEXT NOT NULL DEFAULT '{}',
13
+ parent_id TEXT REFERENCES drawers(id) ON DELETE SET NULL,
14
+ redacted INTEGER NOT NULL DEFAULT 0,
15
+ created_at TEXT NOT NULL
16
+ );
17
+
18
+ CREATE INDEX IF NOT EXISTS idx_drawers_wing_room ON drawers (wing, room);
19
+ CREATE INDEX IF NOT EXISTS idx_drawers_kind ON drawers (kind);
20
+ CREATE INDEX IF NOT EXISTS idx_drawers_created_at ON drawers (created_at);
21
+
22
+ CREATE VIRTUAL TABLE IF NOT EXISTS drawers_fts USING fts5 (
23
+ content,
24
+ content='drawers',
25
+ content_rowid='rowid',
26
+ tokenize='unicode61 remove_diacritics 2'
27
+ );
28
+
29
+ CREATE TRIGGER IF NOT EXISTS drawers_ai AFTER INSERT ON drawers BEGIN
30
+ INSERT INTO drawers_fts (rowid, content) VALUES (new.rowid, new.content);
31
+ END;
32
+ CREATE TRIGGER IF NOT EXISTS drawers_ad AFTER DELETE ON drawers BEGIN
33
+ INSERT INTO drawers_fts (drawers_fts, rowid, content) VALUES ('delete', old.rowid, old.content);
34
+ END;
35
+ CREATE TRIGGER IF NOT EXISTS drawers_au AFTER UPDATE ON drawers BEGIN
36
+ INSERT INTO drawers_fts (drawers_fts, rowid, content) VALUES ('delete', old.rowid, old.content);
37
+ INSERT INTO drawers_fts (rowid, content) VALUES (new.rowid, new.content);
38
+ END;
@@ -0,0 +1,50 @@
1
+ -- packages/coworker-memory/src/migrations/002-artifact-kind.sql
2
+ -- Adds 'artifact' to the drawers.kind CHECK constraint. SQLite can't ALTER
3
+ -- constraints, so the table is rebuilt. Dropping the old table also drops
4
+ -- its triggers, so we recreate them. The FTS index is rebuilt from the
5
+ -- new drawers table to keep rowid alignment.
6
+
7
+ BEGIN;
8
+
9
+ CREATE TABLE drawers_new (
10
+ id TEXT PRIMARY KEY,
11
+ wing TEXT NOT NULL,
12
+ room TEXT NOT NULL,
13
+ kind TEXT NOT NULL CHECK (kind IN
14
+ ('turn','paste','file_load','ticket','email','rca','note','artifact')),
15
+ content TEXT NOT NULL,
16
+ metadata_json TEXT NOT NULL DEFAULT '{}',
17
+ parent_id TEXT REFERENCES drawers_new(id) ON DELETE SET NULL,
18
+ redacted INTEGER NOT NULL DEFAULT 0,
19
+ created_at TEXT NOT NULL
20
+ );
21
+
22
+ INSERT INTO drawers_new (id, wing, room, kind, content, metadata_json, parent_id, redacted, created_at)
23
+ SELECT id, wing, room, kind, content, metadata_json, parent_id, redacted, created_at FROM drawers;
24
+
25
+ DROP TABLE drawers;
26
+ ALTER TABLE drawers_new RENAME TO drawers;
27
+
28
+ -- Recreate indexes (the rename preserves rowids but not separately-named indexes).
29
+ CREATE INDEX IF NOT EXISTS idx_drawers_wing_room ON drawers (wing, room);
30
+ CREATE INDEX IF NOT EXISTS idx_drawers_kind ON drawers (kind);
31
+ CREATE INDEX IF NOT EXISTS idx_drawers_created_at ON drawers (created_at);
32
+
33
+ -- Recreate triggers (dropped when the old drawers table was dropped).
34
+ CREATE TRIGGER IF NOT EXISTS drawers_ai AFTER INSERT ON drawers BEGIN
35
+ INSERT INTO drawers_fts (rowid, content) VALUES (new.rowid, new.content);
36
+ END;
37
+ CREATE TRIGGER IF NOT EXISTS drawers_ad AFTER DELETE ON drawers BEGIN
38
+ INSERT INTO drawers_fts (drawers_fts, rowid, content) VALUES ('delete', old.rowid, old.content);
39
+ END;
40
+ CREATE TRIGGER IF NOT EXISTS drawers_au AFTER UPDATE ON drawers BEGIN
41
+ INSERT INTO drawers_fts (drawers_fts, rowid, content) VALUES ('delete', old.rowid, old.content);
42
+ INSERT INTO drawers_fts (rowid, content) VALUES (new.rowid, new.content);
43
+ END;
44
+
45
+ -- Rebuild FTS index so rowids align with the new drawers table.
46
+ INSERT INTO drawers_fts (drawers_fts) VALUES ('rebuild');
47
+
48
+ PRAGMA user_version = 2;
49
+
50
+ COMMIT;
@@ -0,0 +1,5 @@
1
+ export interface PasteDetectorOptions {
2
+ lengthThreshold?: number;
3
+ newlineThreshold?: number;
4
+ }
5
+ export declare function detectPaste(text: string, opts?: PasteDetectorOptions): 'turn' | 'paste';
@@ -0,0 +1,14 @@
1
+ const DEFAULT_LENGTH = 500;
2
+ const DEFAULT_NEWLINES = 10;
3
+ export function detectPaste(text, opts = {}) {
4
+ const lengthThreshold = opts.lengthThreshold ?? DEFAULT_LENGTH;
5
+ const newlineThreshold = opts.newlineThreshold ?? DEFAULT_NEWLINES;
6
+ if (/```/.test(text))
7
+ return 'paste';
8
+ if (text.length >= lengthThreshold)
9
+ return 'paste';
10
+ const newlines = (text.match(/\n/g) ?? []).length;
11
+ if (newlines > newlineThreshold)
12
+ return 'paste';
13
+ return 'turn';
14
+ }
@@ -0,0 +1,10 @@
1
+ import type { LayerAStore } from './layer-a-store.js';
2
+ export interface SeedResult {
3
+ copied: string[];
4
+ blocked: string[];
5
+ }
6
+ export declare function applyPersonaSeed(args: {
7
+ personaId: string;
8
+ personaDir: string;
9
+ store: LayerAStore;
10
+ }): Promise<SeedResult>;
@@ -0,0 +1,38 @@
1
+ // packages/coworker-memory/src/persona-seed.ts
2
+ import { existsSync, readFileSync } from 'node:fs';
3
+ import { join } from 'node:path';
4
+ import { LayerAWriteBlocked } from './errors.js';
5
+ const FILE_MAP = [
6
+ { name: 'profile.md', kind: 'profile' },
7
+ { name: 'rules.md', kind: 'rule' },
8
+ { name: 'lessons.md', kind: 'lesson' },
9
+ ];
10
+ export async function applyPersonaSeed(args) {
11
+ const seedDir = join(args.personaDir, 'memory-seed');
12
+ if (!existsSync(seedDir))
13
+ return { copied: [], blocked: [] };
14
+ const ts = new Date().toISOString();
15
+ const copied = [];
16
+ const blocked = [];
17
+ for (const entry of FILE_MAP) {
18
+ const path = join(seedDir, entry.name);
19
+ if (!existsSync(path))
20
+ continue;
21
+ const text = readFileSync(path, 'utf8').trim();
22
+ if (!text)
23
+ continue;
24
+ try {
25
+ await args.store.append({ kind: entry.kind, text, source: 'persona-seed', ts });
26
+ copied.push(entry.name);
27
+ }
28
+ catch (err) {
29
+ if (err instanceof LayerAWriteBlocked) {
30
+ blocked.push(entry.name);
31
+ }
32
+ else {
33
+ throw err;
34
+ }
35
+ }
36
+ }
37
+ return { copied, blocked };
38
+ }
@@ -0,0 +1,2 @@
1
+ import type { RecallResult } from './types.js';
2
+ export declare function formatRecall(results: RecallResult[]): string;
@@ -0,0 +1,14 @@
1
+ export function formatRecall(results) {
2
+ const header = `### Memory recall (${results.length} matches)\n`;
3
+ if (results.length === 0)
4
+ return header;
5
+ const lines = [header];
6
+ results.forEach((r, i) => {
7
+ const ts = r.drawer.created_at.replace('T', ' ').slice(0, 16);
8
+ const redacted = r.drawer.redacted ? ' (redacted)' : '';
9
+ lines.push(`\n${i + 1}. [${r.drawer.wing}/${r.drawer.room}/${r.drawer.kind} · ${ts}] (score ${r.score.toFixed(2)})${redacted}`);
10
+ lines.push(` > ${r.snippet}`);
11
+ lines.push(` drawer://${r.drawer.id}`);
12
+ });
13
+ return lines.join('\n');
14
+ }
@@ -0,0 +1,9 @@
1
+ import type { ScopeMode, Wing } from './types.js';
2
+ export interface ResolvedScope {
3
+ writeWing: Wing;
4
+ readWings: Wing[];
5
+ }
6
+ export declare function resolveScope(args: {
7
+ mode: ScopeMode;
8
+ workspaceId: Wing;
9
+ }): ResolvedScope;
@@ -0,0 +1,10 @@
1
+ export function resolveScope(args) {
2
+ switch (args.mode) {
3
+ case 'global':
4
+ return { writeWing: 'global', readWings: ['global'] };
5
+ case 'per-project':
6
+ return { writeWing: args.workspaceId, readWings: [args.workspaceId] };
7
+ case 'per-project-tagged':
8
+ return { writeWing: args.workspaceId, readWings: [args.workspaceId, 'global'] };
9
+ }
10
+ }
@@ -0,0 +1,51 @@
1
+ export type Wing = string;
2
+ export type Room = string;
3
+ export declare const DRAWER_KINDS: readonly ["turn", "paste", "file_load", "ticket", "email", "rca", "note", "artifact"];
4
+ export type DrawerKind = typeof DRAWER_KINDS[number];
5
+ export declare const LAYER_A_KINDS: readonly ["profile", "rule", "lesson"];
6
+ export type LayerAKind = typeof LAYER_A_KINDS[number];
7
+ export type ScopeMode = 'global' | 'per-project' | 'per-project-tagged';
8
+ export interface Drawer {
9
+ id: string;
10
+ wing: Wing;
11
+ room: Room;
12
+ kind: DrawerKind;
13
+ content: string;
14
+ metadata: Record<string, unknown>;
15
+ created_at: string;
16
+ parent_id?: string;
17
+ redacted: boolean;
18
+ }
19
+ export interface RecallQuery {
20
+ query: string;
21
+ wing?: Wing | Wing[];
22
+ room?: Room;
23
+ kind?: DrawerKind | DrawerKind[];
24
+ days_back?: number;
25
+ max_results?: number;
26
+ }
27
+ export interface RecallResult {
28
+ drawer: Drawer;
29
+ score: number;
30
+ snippet: string;
31
+ }
32
+ export interface BackendStatus {
33
+ ready: boolean;
34
+ workspace_wing: Wing;
35
+ drawer_count: number;
36
+ layer_b_db_path: string;
37
+ schema_version: number;
38
+ }
39
+ export interface LayerAEntry {
40
+ kind: LayerAKind;
41
+ text: string;
42
+ source: 'user' | 'persona-seed';
43
+ ts: string;
44
+ }
45
+ export interface WorkspaceIdRecord {
46
+ _schema: 1;
47
+ id: string;
48
+ created_at: string;
49
+ memory_seed_applied: boolean;
50
+ memory_seed_persona: string | null;
51
+ }
@@ -0,0 +1,2 @@
1
+ export const DRAWER_KINDS = ['turn', 'paste', 'file_load', 'ticket', 'email', 'rca', 'note', 'artifact'];
2
+ export const LAYER_A_KINDS = ['profile', 'rule', 'lesson'];