@rubytech/create-sitedesk-code 0.1.340

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 (2951) hide show
  1. package/dist/__tests__/account-id-env.test.js +48 -0
  2. package/dist/__tests__/apt-resolve.test.js +179 -0
  3. package/dist/__tests__/base-toolchain-deps.test.js +67 -0
  4. package/dist/__tests__/brand-fonts.test.js +102 -0
  5. package/dist/__tests__/brew-install.test.js +151 -0
  6. package/dist/__tests__/brew-resolve.test.js +138 -0
  7. package/dist/__tests__/bundler-rewrite-platform-lib.test.js +68 -0
  8. package/dist/__tests__/cdp-port-no-silent-fallback.test.js +53 -0
  9. package/dist/__tests__/claude-ptys-slice.test.js +25 -0
  10. package/dist/__tests__/cloudflared-slice.test.js +20 -0
  11. package/dist/__tests__/cloudflared-version-pin.test.js +24 -0
  12. package/dist/__tests__/entitlement-flag.test.js +43 -0
  13. package/dist/__tests__/init-logging.test.js +85 -0
  14. package/dist/__tests__/install-immutability.test.js +55 -0
  15. package/dist/__tests__/installer-settings-permissions.test.js +220 -0
  16. package/dist/__tests__/installer-specialist-registration.test.js +116 -0
  17. package/dist/__tests__/launchd-plist.test.js +195 -0
  18. package/dist/__tests__/macos-darwin-branch.test.js +83 -0
  19. package/dist/__tests__/macos-version.test.js +96 -0
  20. package/dist/__tests__/peer-brand-detect.test.js +103 -0
  21. package/dist/__tests__/platform-detect.test.js +50 -0
  22. package/dist/__tests__/platform-port-stamp.test.js +28 -0
  23. package/dist/__tests__/plugin-install.test.js +145 -0
  24. package/dist/__tests__/port-canonicalisation.test.js +200 -0
  25. package/dist/__tests__/preflight-port-classifier.test.js +330 -0
  26. package/dist/__tests__/premium-bundle-gate.test.js +59 -0
  27. package/dist/__tests__/premium-mcp-discover.test.js +127 -0
  28. package/dist/__tests__/samba-provision.test.js +294 -0
  29. package/dist/__tests__/snap-chromium.test.js +115 -0
  30. package/dist/__tests__/tier-flag.test.js +53 -0
  31. package/dist/__tests__/watchdog-deferred-arming.test.js +64 -0
  32. package/dist/apt-resolve.js +73 -0
  33. package/dist/brew-install.js +180 -0
  34. package/dist/brew-resolve.js +68 -0
  35. package/dist/bundler-rewrite-platform-lib.js +29 -0
  36. package/dist/index.js +4418 -0
  37. package/dist/init-logging.js +28 -0
  38. package/dist/install-immutability.js +59 -0
  39. package/dist/launchd-plist.js +68 -0
  40. package/dist/lib/plugin-install.js +126 -0
  41. package/dist/lib/premium-mcp-discover.js +41 -0
  42. package/dist/macos-version.js +53 -0
  43. package/dist/peer-brand-detect.js +39 -0
  44. package/dist/permissions-seed.js +147 -0
  45. package/dist/pinned-binaries.js +12 -0
  46. package/dist/platform-detect.js +36 -0
  47. package/dist/port-resolution.js +209 -0
  48. package/dist/preflight-port-classifier.js +222 -0
  49. package/dist/samba-provision.js +275 -0
  50. package/dist/snap-chromium.js +88 -0
  51. package/dist/specialist-registration.js +78 -0
  52. package/dist/tier-flag.js +85 -0
  53. package/dist/uninstall.js +952 -0
  54. package/package.json +35 -0
  55. package/payload/platform/.docs/search-surface-contract.md +58 -0
  56. package/payload/platform/config/brand-registry.json +28 -0
  57. package/payload/platform/config/brand.json +82 -0
  58. package/payload/platform/docs/superpowers/plans/2026-06-02-task-610-follower-202-retry.md +372 -0
  59. package/payload/platform/docs/superpowers/plans/2026-06-04-public-agent-knowledge-delivery.md +230 -0
  60. package/payload/platform/docs/superpowers/specs/2026-06-02-task-610-follower-202-retry-design.md +116 -0
  61. package/payload/platform/lib/account-enumeration/dist/__tests__/enumerate.test.d.ts +2 -0
  62. package/payload/platform/lib/account-enumeration/dist/__tests__/enumerate.test.d.ts.map +1 -0
  63. package/payload/platform/lib/account-enumeration/dist/__tests__/enumerate.test.js +88 -0
  64. package/payload/platform/lib/account-enumeration/dist/__tests__/enumerate.test.js.map +1 -0
  65. package/payload/platform/lib/account-enumeration/dist/__tests__/validate-env.test.d.ts +2 -0
  66. package/payload/platform/lib/account-enumeration/dist/__tests__/validate-env.test.d.ts.map +1 -0
  67. package/payload/platform/lib/account-enumeration/dist/__tests__/validate-env.test.js +55 -0
  68. package/payload/platform/lib/account-enumeration/dist/__tests__/validate-env.test.js.map +1 -0
  69. package/payload/platform/lib/account-enumeration/dist/index.d.ts +82 -0
  70. package/payload/platform/lib/account-enumeration/dist/index.d.ts.map +1 -0
  71. package/payload/platform/lib/account-enumeration/dist/index.js +185 -0
  72. package/payload/platform/lib/account-enumeration/dist/index.js.map +1 -0
  73. package/payload/platform/lib/account-enumeration/src/__tests__/enumerate.test.ts +94 -0
  74. package/payload/platform/lib/account-enumeration/src/__tests__/validate-env.test.ts +57 -0
  75. package/payload/platform/lib/account-enumeration/src/index.ts +218 -0
  76. package/payload/platform/lib/account-enumeration/tsconfig.json +8 -0
  77. package/payload/platform/lib/admin-access-password/__tests__/index.test.ts +142 -0
  78. package/payload/platform/lib/admin-access-password/dist/index.d.ts +49 -0
  79. package/payload/platform/lib/admin-access-password/dist/index.d.ts.map +1 -0
  80. package/payload/platform/lib/admin-access-password/dist/index.js +198 -0
  81. package/payload/platform/lib/admin-access-password/dist/index.js.map +1 -0
  82. package/payload/platform/lib/admin-access-password/src/index.ts +176 -0
  83. package/payload/platform/lib/admin-access-password/tsconfig.json +8 -0
  84. package/payload/platform/lib/admin-conversation-purge/dist/index.d.ts +54 -0
  85. package/payload/platform/lib/admin-conversation-purge/dist/index.d.ts.map +1 -0
  86. package/payload/platform/lib/admin-conversation-purge/dist/index.js +84 -0
  87. package/payload/platform/lib/admin-conversation-purge/dist/index.js.map +1 -0
  88. package/payload/platform/lib/admin-conversation-purge/src/index.ts +120 -0
  89. package/payload/platform/lib/admin-conversation-purge/tsconfig.json +8 -0
  90. package/payload/platform/lib/admins-write/dist/index.d.ts +86 -0
  91. package/payload/platform/lib/admins-write/dist/index.d.ts.map +1 -0
  92. package/payload/platform/lib/admins-write/dist/index.js +245 -0
  93. package/payload/platform/lib/admins-write/dist/index.js.map +1 -0
  94. package/payload/platform/lib/admins-write/src/index.ts +305 -0
  95. package/payload/platform/lib/admins-write/tsconfig.json +8 -0
  96. package/payload/platform/lib/aeo-llms-txt-writer/dist/index.d.ts +33 -0
  97. package/payload/platform/lib/aeo-llms-txt-writer/dist/index.d.ts.map +1 -0
  98. package/payload/platform/lib/aeo-llms-txt-writer/dist/index.js +119 -0
  99. package/payload/platform/lib/aeo-llms-txt-writer/dist/index.js.map +1 -0
  100. package/payload/platform/lib/aeo-llms-txt-writer/src/index.ts +172 -0
  101. package/payload/platform/lib/aeo-llms-txt-writer/tsconfig.json +8 -0
  102. package/payload/platform/lib/anthropic-key/dist/index.d.ts +22 -0
  103. package/payload/platform/lib/anthropic-key/dist/index.d.ts.map +1 -0
  104. package/payload/platform/lib/anthropic-key/dist/index.js +232 -0
  105. package/payload/platform/lib/anthropic-key/dist/index.js.map +1 -0
  106. package/payload/platform/lib/brand-templating/dist/index.d.ts +18 -0
  107. package/payload/platform/lib/brand-templating/dist/index.d.ts.map +1 -0
  108. package/payload/platform/lib/brand-templating/dist/index.js +69 -0
  109. package/payload/platform/lib/brand-templating/dist/index.js.map +1 -0
  110. package/payload/platform/lib/brand-templating/src/index.ts +76 -0
  111. package/payload/platform/lib/brand-templating/tsconfig.json +8 -0
  112. package/payload/platform/lib/device-url/dist/index.d.ts +44 -0
  113. package/payload/platform/lib/device-url/dist/index.d.ts.map +1 -0
  114. package/payload/platform/lib/device-url/dist/index.js +68 -0
  115. package/payload/platform/lib/device-url/dist/index.js.map +1 -0
  116. package/payload/platform/lib/device-url/src/index.ts +78 -0
  117. package/payload/platform/lib/device-url/tsconfig.json +8 -0
  118. package/payload/platform/lib/embed-client/dist/index.d.ts +6 -0
  119. package/payload/platform/lib/embed-client/dist/index.d.ts.map +1 -0
  120. package/payload/platform/lib/embed-client/dist/index.js +93 -0
  121. package/payload/platform/lib/embed-client/dist/index.js.map +1 -0
  122. package/payload/platform/lib/embed-client/src/index.ts +101 -0
  123. package/payload/platform/lib/embed-client/tsconfig.json +8 -0
  124. package/payload/platform/lib/entitlement/PUBKEY-HASH.txt +1 -0
  125. package/payload/platform/lib/entitlement/dist/canonicalize.d.ts +26 -0
  126. package/payload/platform/lib/entitlement/dist/canonicalize.d.ts.map +1 -0
  127. package/payload/platform/lib/entitlement/dist/canonicalize.js +54 -0
  128. package/payload/platform/lib/entitlement/dist/canonicalize.js.map +1 -0
  129. package/payload/platform/lib/entitlement/dist/index.d.ts +76 -0
  130. package/payload/platform/lib/entitlement/dist/index.d.ts.map +1 -0
  131. package/payload/platform/lib/entitlement/dist/index.js +293 -0
  132. package/payload/platform/lib/entitlement/dist/index.js.map +1 -0
  133. package/payload/platform/lib/entitlement/rubytech-pubkey.pem +3 -0
  134. package/payload/platform/lib/graph-mcp/dist/__tests__/cypher-validate-write.test.d.ts +2 -0
  135. package/payload/platform/lib/graph-mcp/dist/__tests__/cypher-validate-write.test.d.ts.map +1 -0
  136. package/payload/platform/lib/graph-mcp/dist/__tests__/cypher-validate-write.test.js +97 -0
  137. package/payload/platform/lib/graph-mcp/dist/__tests__/cypher-validate-write.test.js.map +1 -0
  138. package/payload/platform/lib/graph-mcp/dist/__tests__/cypher-validate.test.d.ts +2 -0
  139. package/payload/platform/lib/graph-mcp/dist/__tests__/cypher-validate.test.d.ts.map +1 -0
  140. package/payload/platform/lib/graph-mcp/dist/__tests__/cypher-validate.test.js +112 -0
  141. package/payload/platform/lib/graph-mcp/dist/__tests__/cypher-validate.test.js.map +1 -0
  142. package/payload/platform/lib/graph-mcp/dist/__tests__/schema-cache.test.d.ts +2 -0
  143. package/payload/platform/lib/graph-mcp/dist/__tests__/schema-cache.test.d.ts.map +1 -0
  144. package/payload/platform/lib/graph-mcp/dist/__tests__/schema-cache.test.js +163 -0
  145. package/payload/platform/lib/graph-mcp/dist/__tests__/schema-cache.test.js.map +1 -0
  146. package/payload/platform/lib/graph-mcp/dist/__tests__/schema-cypher-parser.test.d.ts +2 -0
  147. package/payload/platform/lib/graph-mcp/dist/__tests__/schema-cypher-parser.test.d.ts.map +1 -0
  148. package/payload/platform/lib/graph-mcp/dist/__tests__/schema-cypher-parser.test.js +89 -0
  149. package/payload/platform/lib/graph-mcp/dist/__tests__/schema-cypher-parser.test.js.map +1 -0
  150. package/payload/platform/lib/graph-mcp/dist/__tests__/warnings-envelope.test.d.ts +2 -0
  151. package/payload/platform/lib/graph-mcp/dist/__tests__/warnings-envelope.test.d.ts.map +1 -0
  152. package/payload/platform/lib/graph-mcp/dist/__tests__/warnings-envelope.test.js +140 -0
  153. package/payload/platform/lib/graph-mcp/dist/__tests__/warnings-envelope.test.js.map +1 -0
  154. package/payload/platform/lib/graph-mcp/dist/cypher-rewrite-stamp.d.ts +37 -0
  155. package/payload/platform/lib/graph-mcp/dist/cypher-rewrite-stamp.d.ts.map +1 -0
  156. package/payload/platform/lib/graph-mcp/dist/cypher-rewrite-stamp.js +333 -0
  157. package/payload/platform/lib/graph-mcp/dist/cypher-rewrite-stamp.js.map +1 -0
  158. package/payload/platform/lib/graph-mcp/dist/cypher-shim-read.d.ts +85 -0
  159. package/payload/platform/lib/graph-mcp/dist/cypher-shim-read.d.ts.map +1 -0
  160. package/payload/platform/lib/graph-mcp/dist/cypher-shim-read.js +93 -0
  161. package/payload/platform/lib/graph-mcp/dist/cypher-shim-read.js.map +1 -0
  162. package/payload/platform/lib/graph-mcp/dist/cypher-shim-write.d.ts +71 -0
  163. package/payload/platform/lib/graph-mcp/dist/cypher-shim-write.d.ts.map +1 -0
  164. package/payload/platform/lib/graph-mcp/dist/cypher-shim-write.js +168 -0
  165. package/payload/platform/lib/graph-mcp/dist/cypher-shim-write.js.map +1 -0
  166. package/payload/platform/lib/graph-mcp/dist/cypher-validate.d.ts +50 -0
  167. package/payload/platform/lib/graph-mcp/dist/cypher-validate.d.ts.map +1 -0
  168. package/payload/platform/lib/graph-mcp/dist/cypher-validate.js +197 -0
  169. package/payload/platform/lib/graph-mcp/dist/cypher-validate.js.map +1 -0
  170. package/payload/platform/lib/graph-mcp/dist/index.d.ts +26 -0
  171. package/payload/platform/lib/graph-mcp/dist/index.d.ts.map +1 -0
  172. package/payload/platform/lib/graph-mcp/dist/index.js +845 -0
  173. package/payload/platform/lib/graph-mcp/dist/index.js.map +1 -0
  174. package/payload/platform/lib/graph-mcp/dist/schema-cache.d.ts +76 -0
  175. package/payload/platform/lib/graph-mcp/dist/schema-cache.d.ts.map +1 -0
  176. package/payload/platform/lib/graph-mcp/dist/schema-cache.js +218 -0
  177. package/payload/platform/lib/graph-mcp/dist/schema-cache.js.map +1 -0
  178. package/payload/platform/lib/graph-mcp/dist/schema-cypher-parser.d.ts +42 -0
  179. package/payload/platform/lib/graph-mcp/dist/schema-cypher-parser.d.ts.map +1 -0
  180. package/payload/platform/lib/graph-mcp/dist/schema-cypher-parser.js +87 -0
  181. package/payload/platform/lib/graph-mcp/dist/schema-cypher-parser.js.map +1 -0
  182. package/payload/platform/lib/graph-mcp/src/__tests__/cypher-validate-write.test.ts +150 -0
  183. package/payload/platform/lib/graph-mcp/src/__tests__/cypher-validate.test.ts +141 -0
  184. package/payload/platform/lib/graph-mcp/src/__tests__/schema-cache.test.ts +169 -0
  185. package/payload/platform/lib/graph-mcp/src/__tests__/schema-cypher-parser.test.ts +99 -0
  186. package/payload/platform/lib/graph-mcp/src/__tests__/warnings-envelope.test.ts +151 -0
  187. package/payload/platform/lib/graph-mcp/src/cypher-rewrite-stamp.ts +349 -0
  188. package/payload/platform/lib/graph-mcp/src/cypher-shim-read.ts +141 -0
  189. package/payload/platform/lib/graph-mcp/src/cypher-shim-write.ts +240 -0
  190. package/payload/platform/lib/graph-mcp/src/cypher-validate.ts +249 -0
  191. package/payload/platform/lib/graph-mcp/src/index.ts +1074 -0
  192. package/payload/platform/lib/graph-mcp/src/schema-cache.ts +243 -0
  193. package/payload/platform/lib/graph-mcp/src/schema-cypher-parser.ts +84 -0
  194. package/payload/platform/lib/graph-mcp/tsconfig.json +8 -0
  195. package/payload/platform/lib/graph-search/dist/boosts.d.ts +39 -0
  196. package/payload/platform/lib/graph-search/dist/boosts.d.ts.map +1 -0
  197. package/payload/platform/lib/graph-search/dist/boosts.js +57 -0
  198. package/payload/platform/lib/graph-search/dist/boosts.js.map +1 -0
  199. package/payload/platform/lib/graph-search/dist/dedup.d.ts +29 -0
  200. package/payload/platform/lib/graph-search/dist/dedup.d.ts.map +1 -0
  201. package/payload/platform/lib/graph-search/dist/dedup.js +97 -0
  202. package/payload/platform/lib/graph-search/dist/dedup.js.map +1 -0
  203. package/payload/platform/lib/graph-search/dist/index.d.ts +342 -0
  204. package/payload/platform/lib/graph-search/dist/index.d.ts.map +1 -0
  205. package/payload/platform/lib/graph-search/dist/index.js +848 -0
  206. package/payload/platform/lib/graph-search/dist/index.js.map +1 -0
  207. package/payload/platform/lib/graph-search/dist/query-expansion.d.ts +37 -0
  208. package/payload/platform/lib/graph-search/dist/query-expansion.d.ts.map +1 -0
  209. package/payload/platform/lib/graph-search/dist/query-expansion.js +101 -0
  210. package/payload/platform/lib/graph-search/dist/query-expansion.js.map +1 -0
  211. package/payload/platform/lib/graph-search/dist/route.d.ts +29 -0
  212. package/payload/platform/lib/graph-search/dist/route.d.ts.map +1 -0
  213. package/payload/platform/lib/graph-search/dist/route.js +53 -0
  214. package/payload/platform/lib/graph-search/dist/route.js.map +1 -0
  215. package/payload/platform/lib/graph-search/dist/rrf-fusion.d.ts +31 -0
  216. package/payload/platform/lib/graph-search/dist/rrf-fusion.d.ts.map +1 -0
  217. package/payload/platform/lib/graph-search/dist/rrf-fusion.js +57 -0
  218. package/payload/platform/lib/graph-search/dist/rrf-fusion.js.map +1 -0
  219. package/payload/platform/lib/graph-search/src/__tests__/bm25-label-gate.test.ts +88 -0
  220. package/payload/platform/lib/graph-search/src/__tests__/bm25-only.test.ts +129 -0
  221. package/payload/platform/lib/graph-search/src/__tests__/bm25-strong-bypass-threshold.test.ts +126 -0
  222. package/payload/platform/lib/graph-search/src/__tests__/boosts.test.ts +59 -0
  223. package/payload/platform/lib/graph-search/src/__tests__/brochure-threshold.test.ts +136 -0
  224. package/payload/platform/lib/graph-search/src/__tests__/dedup.test.ts +83 -0
  225. package/payload/platform/lib/graph-search/src/__tests__/escape-and-normalise.test.ts +53 -0
  226. package/payload/platform/lib/graph-search/src/__tests__/expand-batch.test.ts +206 -0
  227. package/payload/platform/lib/graph-search/src/__tests__/fulltext-coverage.test.ts +348 -0
  228. package/payload/platform/lib/graph-search/src/__tests__/hybrid.test.ts +355 -0
  229. package/payload/platform/lib/graph-search/src/__tests__/route.test.ts +62 -0
  230. package/payload/platform/lib/graph-search/src/__tests__/rrf-fusion.test.ts +39 -0
  231. package/payload/platform/lib/graph-search/src/__tests__/vector-index-coverage.test.ts +198 -0
  232. package/payload/platform/lib/graph-search/src/__tests__/vector-threshold.test.ts +170 -0
  233. package/payload/platform/lib/graph-search/src/boosts.ts +61 -0
  234. package/payload/platform/lib/graph-search/src/dedup.ts +108 -0
  235. package/payload/platform/lib/graph-search/src/index.ts +1144 -0
  236. package/payload/platform/lib/graph-search/src/route.ts +70 -0
  237. package/payload/platform/lib/graph-search/src/rrf-fusion.ts +62 -0
  238. package/payload/platform/lib/graph-search/tsconfig.json +9 -0
  239. package/payload/platform/lib/graph-search/vitest.config.ts +9 -0
  240. package/payload/platform/lib/graph-style/dist/index.d.ts +84 -0
  241. package/payload/platform/lib/graph-style/dist/index.d.ts.map +1 -0
  242. package/payload/platform/lib/graph-style/dist/index.js +378 -0
  243. package/payload/platform/lib/graph-style/dist/index.js.map +1 -0
  244. package/payload/platform/lib/graph-style/src/__tests__/parity.test.ts +332 -0
  245. package/payload/platform/lib/graph-style/src/index.ts +382 -0
  246. package/payload/platform/lib/graph-style/tsconfig.json +9 -0
  247. package/payload/platform/lib/graph-style/vitest.config.ts +9 -0
  248. package/payload/platform/lib/graph-trash/dist/index.d.ts +106 -0
  249. package/payload/platform/lib/graph-trash/dist/index.d.ts.map +1 -0
  250. package/payload/platform/lib/graph-trash/dist/index.js +340 -0
  251. package/payload/platform/lib/graph-trash/dist/index.js.map +1 -0
  252. package/payload/platform/lib/graph-trash/package.json +7 -0
  253. package/payload/platform/lib/graph-trash/src/index.ts +493 -0
  254. package/payload/platform/lib/graph-trash/tsconfig.json +8 -0
  255. package/payload/platform/lib/graph-write/dist/__tests__/account-id-gate.test.d.ts +2 -0
  256. package/payload/platform/lib/graph-write/dist/__tests__/account-id-gate.test.d.ts.map +1 -0
  257. package/payload/platform/lib/graph-write/dist/__tests__/account-id-gate.test.js +165 -0
  258. package/payload/platform/lib/graph-write/dist/__tests__/account-id-gate.test.js.map +1 -0
  259. package/payload/platform/lib/graph-write/dist/__tests__/action-provenance-gate.test.d.ts +2 -0
  260. package/payload/platform/lib/graph-write/dist/__tests__/action-provenance-gate.test.d.ts.map +1 -0
  261. package/payload/platform/lib/graph-write/dist/__tests__/action-provenance-gate.test.js +263 -0
  262. package/payload/platform/lib/graph-write/dist/__tests__/action-provenance-gate.test.js.map +1 -0
  263. package/payload/platform/lib/graph-write/dist/__tests__/audit.test.d.ts +2 -0
  264. package/payload/platform/lib/graph-write/dist/__tests__/audit.test.d.ts.map +1 -0
  265. package/payload/platform/lib/graph-write/dist/__tests__/audit.test.js +147 -0
  266. package/payload/platform/lib/graph-write/dist/__tests__/audit.test.js.map +1 -0
  267. package/payload/platform/lib/graph-write/dist/audit.d.ts +84 -0
  268. package/payload/platform/lib/graph-write/dist/audit.d.ts.map +1 -0
  269. package/payload/platform/lib/graph-write/dist/audit.js +129 -0
  270. package/payload/platform/lib/graph-write/dist/audit.js.map +1 -0
  271. package/payload/platform/lib/graph-write/dist/conversation-provenance.d.ts +30 -0
  272. package/payload/platform/lib/graph-write/dist/conversation-provenance.d.ts.map +1 -0
  273. package/payload/platform/lib/graph-write/dist/conversation-provenance.js +88 -0
  274. package/payload/platform/lib/graph-write/dist/conversation-provenance.js.map +1 -0
  275. package/payload/platform/lib/graph-write/dist/index.d.ts +151 -0
  276. package/payload/platform/lib/graph-write/dist/index.d.ts.map +1 -0
  277. package/payload/platform/lib/graph-write/dist/index.js +380 -0
  278. package/payload/platform/lib/graph-write/dist/index.js.map +1 -0
  279. package/payload/platform/lib/graph-write/src/__tests__/account-id-gate.test.ts +189 -0
  280. package/payload/platform/lib/graph-write/src/__tests__/action-provenance-gate.test.ts +279 -0
  281. package/payload/platform/lib/graph-write/src/__tests__/audit.test.ts +162 -0
  282. package/payload/platform/lib/graph-write/src/audit.ts +182 -0
  283. package/payload/platform/lib/graph-write/src/conversation-provenance.ts +148 -0
  284. package/payload/platform/lib/graph-write/src/index.ts +494 -0
  285. package/payload/platform/lib/graph-write/tsconfig.json +8 -0
  286. package/payload/platform/lib/mcp-eager/dist/index.d.ts +41 -0
  287. package/payload/platform/lib/mcp-eager/dist/index.d.ts.map +1 -0
  288. package/payload/platform/lib/mcp-eager/dist/index.js +50 -0
  289. package/payload/platform/lib/mcp-eager/dist/index.js.map +1 -0
  290. package/payload/platform/lib/mcp-eager/package.json +7 -0
  291. package/payload/platform/lib/mcp-eager/src/index.ts +80 -0
  292. package/payload/platform/lib/mcp-eager/tsconfig.json +8 -0
  293. package/payload/platform/lib/mcp-lifeline/dist/index.d.ts +8 -0
  294. package/payload/platform/lib/mcp-lifeline/dist/index.d.ts.map +1 -0
  295. package/payload/platform/lib/mcp-lifeline/dist/index.js +71 -0
  296. package/payload/platform/lib/mcp-lifeline/dist/index.js.map +1 -0
  297. package/payload/platform/lib/mcp-lifeline/package.json +7 -0
  298. package/payload/platform/lib/mcp-lifeline/src/__tests__/lifeline.test.ts +146 -0
  299. package/payload/platform/lib/mcp-lifeline/src/index.ts +78 -0
  300. package/payload/platform/lib/mcp-lifeline/tsconfig.json +9 -0
  301. package/payload/platform/lib/mcp-lifeline/vitest.config.ts +9 -0
  302. package/payload/platform/lib/mcp-spawn-tee/dist/index.d.ts +41 -0
  303. package/payload/platform/lib/mcp-spawn-tee/dist/index.d.ts.map +1 -0
  304. package/payload/platform/lib/mcp-spawn-tee/dist/index.js +193 -0
  305. package/payload/platform/lib/mcp-spawn-tee/dist/index.js.map +1 -0
  306. package/payload/platform/lib/mcp-spawn-tee/src/__tests__/spawn-tee.test.ts +148 -0
  307. package/payload/platform/lib/mcp-spawn-tee/src/index.ts +198 -0
  308. package/payload/platform/lib/mcp-spawn-tee/tsconfig.json +9 -0
  309. package/payload/platform/lib/mcp-stderr-tee/dist/index.d.ts +51 -0
  310. package/payload/platform/lib/mcp-stderr-tee/dist/index.d.ts.map +1 -0
  311. package/payload/platform/lib/mcp-stderr-tee/dist/index.js +196 -0
  312. package/payload/platform/lib/mcp-stderr-tee/dist/index.js.map +1 -0
  313. package/payload/platform/lib/mcp-stderr-tee/package.json +7 -0
  314. package/payload/platform/lib/mcp-stderr-tee/src/index.ts +206 -0
  315. package/payload/platform/lib/mcp-stderr-tee/tsconfig.json +8 -0
  316. package/payload/platform/lib/models/dist/index.d.ts +58 -0
  317. package/payload/platform/lib/models/dist/index.d.ts.map +1 -0
  318. package/payload/platform/lib/models/dist/index.js +110 -0
  319. package/payload/platform/lib/models/dist/index.js.map +1 -0
  320. package/payload/platform/lib/models/src/index.ts +118 -0
  321. package/payload/platform/lib/models/tsconfig.json +8 -0
  322. package/payload/platform/lib/oauth-llm/dist/index.d.ts +116 -0
  323. package/payload/platform/lib/oauth-llm/dist/index.d.ts.map +1 -0
  324. package/payload/platform/lib/oauth-llm/dist/index.js +386 -0
  325. package/payload/platform/lib/oauth-llm/dist/index.js.map +1 -0
  326. package/payload/platform/lib/obsidian-parser/dist/index.d.ts +98 -0
  327. package/payload/platform/lib/obsidian-parser/dist/index.d.ts.map +1 -0
  328. package/payload/platform/lib/obsidian-parser/dist/index.js +480 -0
  329. package/payload/platform/lib/obsidian-parser/dist/index.js.map +1 -0
  330. package/payload/platform/lib/obsidian-parser/src/index.ts +572 -0
  331. package/payload/platform/lib/obsidian-parser/tsconfig.json +8 -0
  332. package/payload/platform/lib/persistent-components/dist/index.d.ts +20 -0
  333. package/payload/platform/lib/persistent-components/dist/index.d.ts.map +1 -0
  334. package/payload/platform/lib/persistent-components/dist/index.js +31 -0
  335. package/payload/platform/lib/persistent-components/dist/index.js.map +1 -0
  336. package/payload/platform/lib/persistent-components/src/index.ts +27 -0
  337. package/payload/platform/lib/persistent-components/tsconfig.json +8 -0
  338. package/payload/platform/lib/require-port-env/dist/index.d.ts +31 -0
  339. package/payload/platform/lib/require-port-env/dist/index.d.ts.map +1 -0
  340. package/payload/platform/lib/require-port-env/dist/index.js +52 -0
  341. package/payload/platform/lib/require-port-env/dist/index.js.map +1 -0
  342. package/payload/platform/lib/require-port-env/src/index.ts +56 -0
  343. package/payload/platform/lib/require-port-env/tsconfig.json +8 -0
  344. package/payload/platform/lib/screening-patterns/dist/index.d.ts +29 -0
  345. package/payload/platform/lib/screening-patterns/dist/index.d.ts.map +1 -0
  346. package/payload/platform/lib/screening-patterns/dist/index.js +48 -0
  347. package/payload/platform/lib/screening-patterns/dist/index.js.map +1 -0
  348. package/payload/platform/lib/task-secrets/dist/index.d.ts +40 -0
  349. package/payload/platform/lib/task-secrets/dist/index.d.ts.map +1 -0
  350. package/payload/platform/lib/task-secrets/dist/index.js +44 -0
  351. package/payload/platform/lib/task-secrets/dist/index.js.map +1 -0
  352. package/payload/platform/lib/task-secrets/src/__tests__/redact-secrets.test.ts +127 -0
  353. package/payload/platform/lib/task-secrets/src/index.ts +77 -0
  354. package/payload/platform/lib/task-secrets/tsconfig.json +9 -0
  355. package/payload/platform/lib/task-secrets/vitest.config.ts +9 -0
  356. package/payload/platform/neo4j/edge-annotations.json +158 -0
  357. package/payload/platform/neo4j/schema.cypher +2041 -0
  358. package/payload/platform/package-lock.json +4093 -0
  359. package/payload/platform/package.json +31 -0
  360. package/payload/platform/plugins/.claude-plugin/marketplace.json +163 -0
  361. package/payload/platform/plugins/admin/.claude-plugin/plugin.json +21 -0
  362. package/payload/platform/plugins/admin/PLUGIN.md +180 -0
  363. package/payload/platform/plugins/admin/hooks/__tests__/archive-ingest-surface-gate.test.sh +191 -0
  364. package/payload/platform/plugins/admin/hooks/__tests__/askuserquestion-investigate-gate.test.sh +176 -0
  365. package/payload/platform/plugins/admin/hooks/__tests__/hook-emit-stale-lock-ttl.test.sh +102 -0
  366. package/payload/platform/plugins/admin/hooks/__tests__/hook-emit.test.sh +75 -0
  367. package/payload/platform/plugins/admin/hooks/__tests__/post-tool-use-agent.test.sh +173 -0
  368. package/payload/platform/plugins/admin/hooks/__tests__/prompt-optimiser-compliance.test.sh +242 -0
  369. package/payload/platform/plugins/admin/hooks/__tests__/prompt-optimiser-directive.test.sh +191 -0
  370. package/payload/platform/plugins/admin/hooks/admin-authoring-observer.sh +155 -0
  371. package/payload/platform/plugins/admin/hooks/archive-ingest-surface-gate.sh +224 -0
  372. package/payload/platform/plugins/admin/hooks/askuserquestion-investigate-gate.sh +257 -0
  373. package/payload/platform/plugins/admin/hooks/lib/hook-emit.sh +143 -0
  374. package/payload/platform/plugins/admin/hooks/lib/maxy-mcp-plugins.txt +17 -0
  375. package/payload/platform/plugins/admin/hooks/mcp-tool-missing.sh +94 -0
  376. package/payload/platform/plugins/admin/hooks/post-tool-use-agent.sh +155 -0
  377. package/payload/platform/plugins/admin/hooks/prompt-optimiser-compliance.sh +213 -0
  378. package/payload/platform/plugins/admin/hooks/prompt-optimiser-directive.sh +166 -0
  379. package/payload/platform/plugins/admin/hooks/webfetch-preflight.mjs +363 -0
  380. package/payload/platform/plugins/admin/lib/mcp-spawn-tee/index.js +193 -0
  381. package/payload/platform/plugins/admin/lib/mcp-spawn-tee/package.json +3 -0
  382. package/payload/platform/plugins/admin/mcp/dist/__tests__/admin-authoring-skill-gate.test.d.ts +2 -0
  383. package/payload/platform/plugins/admin/mcp/dist/__tests__/admin-authoring-skill-gate.test.d.ts.map +1 -0
  384. package/payload/platform/plugins/admin/mcp/dist/__tests__/admin-authoring-skill-gate.test.js +86 -0
  385. package/payload/platform/plugins/admin/mcp/dist/__tests__/admin-authoring-skill-gate.test.js.map +1 -0
  386. package/payload/platform/plugins/admin/mcp/dist/__tests__/admin-identity-authenticate.test.d.ts +2 -0
  387. package/payload/platform/plugins/admin/mcp/dist/__tests__/admin-identity-authenticate.test.d.ts.map +1 -0
  388. package/payload/platform/plugins/admin/mcp/dist/__tests__/admin-identity-authenticate.test.js +34 -0
  389. package/payload/platform/plugins/admin/mcp/dist/__tests__/admin-identity-authenticate.test.js.map +1 -0
  390. package/payload/platform/plugins/admin/mcp/dist/__tests__/capabilities-here.test.d.ts +2 -0
  391. package/payload/platform/plugins/admin/mcp/dist/__tests__/capabilities-here.test.d.ts.map +1 -0
  392. package/payload/platform/plugins/admin/mcp/dist/__tests__/capabilities-here.test.js +171 -0
  393. package/payload/platform/plugins/admin/mcp/dist/__tests__/capabilities-here.test.js.map +1 -0
  394. package/payload/platform/plugins/admin/mcp/dist/__tests__/e-sign-discoverable.test.d.ts +2 -0
  395. package/payload/platform/plugins/admin/mcp/dist/__tests__/e-sign-discoverable.test.d.ts.map +1 -0
  396. package/payload/platform/plugins/admin/mcp/dist/__tests__/e-sign-discoverable.test.js +54 -0
  397. package/payload/platform/plugins/admin/mcp/dist/__tests__/e-sign-discoverable.test.js.map +1 -0
  398. package/payload/platform/plugins/admin/mcp/dist/__tests__/plugin-read-skill-resolution.test.d.ts +2 -0
  399. package/payload/platform/plugins/admin/mcp/dist/__tests__/plugin-read-skill-resolution.test.d.ts.map +1 -0
  400. package/payload/platform/plugins/admin/mcp/dist/__tests__/plugin-read-skill-resolution.test.js +91 -0
  401. package/payload/platform/plugins/admin/mcp/dist/__tests__/plugin-read-skill-resolution.test.js.map +1 -0
  402. package/payload/platform/plugins/admin/mcp/dist/__tests__/public-hostname.test.d.ts +2 -0
  403. package/payload/platform/plugins/admin/mcp/dist/__tests__/public-hostname.test.d.ts.map +1 -0
  404. package/payload/platform/plugins/admin/mcp/dist/__tests__/public-hostname.test.js +98 -0
  405. package/payload/platform/plugins/admin/mcp/dist/__tests__/public-hostname.test.js.map +1 -0
  406. package/payload/platform/plugins/admin/mcp/dist/__tests__/skill-load-required-inputs.test.d.ts +2 -0
  407. package/payload/platform/plugins/admin/mcp/dist/__tests__/skill-load-required-inputs.test.d.ts.map +1 -0
  408. package/payload/platform/plugins/admin/mcp/dist/__tests__/skill-load-required-inputs.test.js +141 -0
  409. package/payload/platform/plugins/admin/mcp/dist/__tests__/skill-load-required-inputs.test.js.map +1 -0
  410. package/payload/platform/plugins/admin/mcp/dist/__tests__/skill-load.test.d.ts +2 -0
  411. package/payload/platform/plugins/admin/mcp/dist/__tests__/skill-load.test.d.ts.map +1 -0
  412. package/payload/platform/plugins/admin/mcp/dist/__tests__/skill-load.test.js +88 -0
  413. package/payload/platform/plugins/admin/mcp/dist/__tests__/skill-load.test.js.map +1 -0
  414. package/payload/platform/plugins/admin/mcp/dist/__tests__/skill-no-prescribed-role.test.d.ts +2 -0
  415. package/payload/platform/plugins/admin/mcp/dist/__tests__/skill-no-prescribed-role.test.d.ts.map +1 -0
  416. package/payload/platform/plugins/admin/mcp/dist/__tests__/skill-no-prescribed-role.test.js +50 -0
  417. package/payload/platform/plugins/admin/mcp/dist/__tests__/skill-no-prescribed-role.test.js.map +1 -0
  418. package/payload/platform/plugins/admin/mcp/dist/__tests__/skill-search.test.d.ts +2 -0
  419. package/payload/platform/plugins/admin/mcp/dist/__tests__/skill-search.test.d.ts.map +1 -0
  420. package/payload/platform/plugins/admin/mcp/dist/__tests__/skill-search.test.js +106 -0
  421. package/payload/platform/plugins/admin/mcp/dist/__tests__/skill-search.test.js.map +1 -0
  422. package/payload/platform/plugins/admin/mcp/dist/content-producer-authoring-skills.d.ts +2 -0
  423. package/payload/platform/plugins/admin/mcp/dist/content-producer-authoring-skills.d.ts.map +1 -0
  424. package/payload/platform/plugins/admin/mcp/dist/content-producer-authoring-skills.js +41 -0
  425. package/payload/platform/plugins/admin/mcp/dist/content-producer-authoring-skills.js.map +1 -0
  426. package/payload/platform/plugins/admin/mcp/dist/index.d.ts +2 -0
  427. package/payload/platform/plugins/admin/mcp/dist/index.d.ts.map +1 -0
  428. package/payload/platform/plugins/admin/mcp/dist/index.js +3294 -0
  429. package/payload/platform/plugins/admin/mcp/dist/index.js.map +1 -0
  430. package/payload/platform/plugins/admin/mcp/dist/lib/catalogue-census.d.ts +14 -0
  431. package/payload/platform/plugins/admin/mcp/dist/lib/catalogue-census.d.ts.map +1 -0
  432. package/payload/platform/plugins/admin/mcp/dist/lib/catalogue-census.js +50 -0
  433. package/payload/platform/plugins/admin/mcp/dist/lib/catalogue-census.js.map +1 -0
  434. package/payload/platform/plugins/admin/mcp/dist/lib/neo4j.d.ts +5 -0
  435. package/payload/platform/plugins/admin/mcp/dist/lib/neo4j.d.ts.map +1 -0
  436. package/payload/platform/plugins/admin/mcp/dist/lib/neo4j.js +40 -0
  437. package/payload/platform/plugins/admin/mcp/dist/lib/neo4j.js.map +1 -0
  438. package/payload/platform/plugins/admin/mcp/dist/lib/onboarding.d.ts +39 -0
  439. package/payload/platform/plugins/admin/mcp/dist/lib/onboarding.d.ts.map +1 -0
  440. package/payload/platform/plugins/admin/mcp/dist/lib/onboarding.js +249 -0
  441. package/payload/platform/plugins/admin/mcp/dist/lib/onboarding.js.map +1 -0
  442. package/payload/platform/plugins/admin/mcp/dist/lib/public-hostname.d.ts +15 -0
  443. package/payload/platform/plugins/admin/mcp/dist/lib/public-hostname.d.ts.map +1 -0
  444. package/payload/platform/plugins/admin/mcp/dist/lib/public-hostname.js +73 -0
  445. package/payload/platform/plugins/admin/mcp/dist/lib/public-hostname.js.map +1 -0
  446. package/payload/platform/plugins/admin/mcp/dist/skill-resolution.d.ts +56 -0
  447. package/payload/platform/plugins/admin/mcp/dist/skill-resolution.d.ts.map +1 -0
  448. package/payload/platform/plugins/admin/mcp/dist/skill-resolution.js +358 -0
  449. package/payload/platform/plugins/admin/mcp/dist/skill-resolution.js.map +1 -0
  450. package/payload/platform/plugins/admin/mcp/dist/tools/__tests__/account-lifecycle.test.d.ts +2 -0
  451. package/payload/platform/plugins/admin/mcp/dist/tools/__tests__/account-lifecycle.test.d.ts.map +1 -0
  452. package/payload/platform/plugins/admin/mcp/dist/tools/__tests__/account-lifecycle.test.js +57 -0
  453. package/payload/platform/plugins/admin/mcp/dist/tools/__tests__/account-lifecycle.test.js.map +1 -0
  454. package/payload/platform/plugins/admin/mcp/dist/tools/account-lifecycle.d.ts +34 -0
  455. package/payload/platform/plugins/admin/mcp/dist/tools/account-lifecycle.d.ts.map +1 -0
  456. package/payload/platform/plugins/admin/mcp/dist/tools/account-lifecycle.js +78 -0
  457. package/payload/platform/plugins/admin/mcp/dist/tools/account-lifecycle.js.map +1 -0
  458. package/payload/platform/plugins/admin/mcp/dist/tools/admin-identity-authenticate.d.ts +6 -0
  459. package/payload/platform/plugins/admin/mcp/dist/tools/admin-identity-authenticate.d.ts.map +1 -0
  460. package/payload/platform/plugins/admin/mcp/dist/tools/admin-identity-authenticate.js +32 -0
  461. package/payload/platform/plugins/admin/mcp/dist/tools/admin-identity-authenticate.js.map +1 -0
  462. package/payload/platform/plugins/admin/mcp/dist/tools/capabilities-here.d.ts +28 -0
  463. package/payload/platform/plugins/admin/mcp/dist/tools/capabilities-here.d.ts.map +1 -0
  464. package/payload/platform/plugins/admin/mcp/dist/tools/capabilities-here.js +68 -0
  465. package/payload/platform/plugins/admin/mcp/dist/tools/capabilities-here.js.map +1 -0
  466. package/payload/platform/plugins/admin/mcp/dist/tools/publish-site.d.ts +34 -0
  467. package/payload/platform/plugins/admin/mcp/dist/tools/publish-site.d.ts.map +1 -0
  468. package/payload/platform/plugins/admin/mcp/dist/tools/publish-site.js +176 -0
  469. package/payload/platform/plugins/admin/mcp/dist/tools/publish-site.js.map +1 -0
  470. package/payload/platform/plugins/admin/mcp/package.json +23 -0
  471. package/payload/platform/plugins/admin/mcp/vitest.config.ts +9 -0
  472. package/payload/platform/plugins/admin/references/chat-ui-guide.md +31 -0
  473. package/payload/platform/plugins/admin/references/publish-site-routing.md +44 -0
  474. package/payload/platform/plugins/admin/skills/a4-print-documents/SKILL.md +243 -0
  475. package/payload/platform/plugins/admin/skills/access-manager/SKILL.md +33 -0
  476. package/payload/platform/plugins/admin/skills/access-manager/references/operations.md +176 -0
  477. package/payload/platform/plugins/admin/skills/admin-user-management/SKILL.md +57 -0
  478. package/payload/platform/plugins/admin/skills/business-profile/SKILL.md +55 -0
  479. package/payload/platform/plugins/admin/skills/capabilities-here/SKILL.md +33 -0
  480. package/payload/platform/plugins/admin/skills/datetime/SKILL.md +151 -0
  481. package/payload/platform/plugins/admin/skills/deck-pages/SKILL.md +412 -0
  482. package/payload/platform/plugins/admin/skills/file-presentation/SKILL.md +49 -0
  483. package/payload/platform/plugins/admin/skills/insight/SKILL.md +24 -0
  484. package/payload/platform/plugins/admin/skills/investigate/SKILL.md +320 -0
  485. package/payload/platform/plugins/admin/skills/plainly/SKILL.md +149 -0
  486. package/payload/platform/plugins/admin/skills/plainly/references/worked-examples.md +114 -0
  487. package/payload/platform/plugins/admin/skills/platform-architecture/SKILL.md +4181 -0
  488. package/payload/platform/plugins/admin/skills/plugin-management/SKILL.md +101 -0
  489. package/payload/platform/plugins/admin/skills/professional-document/SKILL.md +186 -0
  490. package/payload/platform/plugins/admin/skills/public-agent-manager/SKILL.md +258 -0
  491. package/payload/platform/plugins/admin/skills/publish-site/SKILL.md +42 -0
  492. package/payload/platform/plugins/admin/skills/qr-code/SKILL.md +38 -0
  493. package/payload/platform/plugins/admin/skills/qr-code/references/data-formats.md +113 -0
  494. package/payload/platform/plugins/admin/skills/session-management/SKILL.md +64 -0
  495. package/payload/platform/plugins/admin/skills/skill-builder/SKILL.md +115 -0
  496. package/payload/platform/plugins/admin/skills/skill-builder/references/lean-pattern.md +110 -0
  497. package/payload/platform/plugins/admin/skills/skill-builder/references/pdf-generation.md +30 -0
  498. package/payload/platform/plugins/admin/skills/specialist-management/SKILL.md +47 -0
  499. package/payload/platform/plugins/admin/skills/stream-log-review/SKILL.md +73 -0
  500. package/payload/platform/plugins/admin/skills/stream-log-review/references/analysis-patterns.md +193 -0
  501. package/payload/platform/plugins/admin/skills/superpowers-sprint/SKILL.md +363 -0
  502. package/payload/platform/plugins/admin/skills/task/SKILL.md +316 -0
  503. package/payload/platform/plugins/admin/skills/unzip-attachment/SKILL.md +84 -0
  504. package/payload/platform/plugins/admin/skills/unzip-attachment/__tests__/preflight.sh +148 -0
  505. package/payload/platform/plugins/admin/skills/unzip-attachment/references/safety.md +116 -0
  506. package/payload/platform/plugins/admin/skills/update-knowledge/SKILL.md +54 -0
  507. package/payload/platform/plugins/admin/skills/upgrade/SKILL.md +36 -0
  508. package/payload/platform/plugins/aeo/.claude-plugin/plugin.json +21 -0
  509. package/payload/platform/plugins/aeo/PLUGIN.md +80 -0
  510. package/payload/platform/plugins/aeo/lib/mcp-spawn-tee/index.js +193 -0
  511. package/payload/platform/plugins/aeo/lib/mcp-spawn-tee/package.json +3 -0
  512. package/payload/platform/plugins/aeo/mcp/dist/__tests__/audit-heuristics.test.d.ts +2 -0
  513. package/payload/platform/plugins/aeo/mcp/dist/__tests__/audit-heuristics.test.d.ts.map +1 -0
  514. package/payload/platform/plugins/aeo/mcp/dist/__tests__/audit-heuristics.test.js +121 -0
  515. package/payload/platform/plugins/aeo/mcp/dist/__tests__/audit-heuristics.test.js.map +1 -0
  516. package/payload/platform/plugins/aeo/mcp/dist/__tests__/schema-mapping.test.d.ts +2 -0
  517. package/payload/platform/plugins/aeo/mcp/dist/__tests__/schema-mapping.test.d.ts.map +1 -0
  518. package/payload/platform/plugins/aeo/mcp/dist/__tests__/schema-mapping.test.js +129 -0
  519. package/payload/platform/plugins/aeo/mcp/dist/__tests__/schema-mapping.test.js.map +1 -0
  520. package/payload/platform/plugins/aeo/mcp/dist/index.d.ts +2 -0
  521. package/payload/platform/plugins/aeo/mcp/dist/index.d.ts.map +1 -0
  522. package/payload/platform/plugins/aeo/mcp/dist/index.js +189 -0
  523. package/payload/platform/plugins/aeo/mcp/dist/index.js.map +1 -0
  524. package/payload/platform/plugins/aeo/mcp/dist/lib/audit-heuristics.d.ts +27 -0
  525. package/payload/platform/plugins/aeo/mcp/dist/lib/audit-heuristics.d.ts.map +1 -0
  526. package/payload/platform/plugins/aeo/mcp/dist/lib/audit-heuristics.js +274 -0
  527. package/payload/platform/plugins/aeo/mcp/dist/lib/audit-heuristics.js.map +1 -0
  528. package/payload/platform/plugins/aeo/mcp/dist/lib/neo4j.d.ts +5 -0
  529. package/payload/platform/plugins/aeo/mcp/dist/lib/neo4j.d.ts.map +1 -0
  530. package/payload/platform/plugins/aeo/mcp/dist/lib/neo4j.js +38 -0
  531. package/payload/platform/plugins/aeo/mcp/dist/lib/neo4j.js.map +1 -0
  532. package/payload/platform/plugins/aeo/mcp/dist/lib/schema-mapping.d.ts +48 -0
  533. package/payload/platform/plugins/aeo/mcp/dist/lib/schema-mapping.d.ts.map +1 -0
  534. package/payload/platform/plugins/aeo/mcp/dist/lib/schema-mapping.js +254 -0
  535. package/payload/platform/plugins/aeo/mcp/dist/lib/schema-mapping.js.map +1 -0
  536. package/payload/platform/plugins/aeo/mcp/dist/tools/aeo-audit-page.d.ts +25 -0
  537. package/payload/platform/plugins/aeo/mcp/dist/tools/aeo-audit-page.d.ts.map +1 -0
  538. package/payload/platform/plugins/aeo/mcp/dist/tools/aeo-audit-page.js +78 -0
  539. package/payload/platform/plugins/aeo/mcp/dist/tools/aeo-audit-page.js.map +1 -0
  540. package/payload/platform/plugins/aeo/mcp/dist/tools/aeo-emit-jsonld.d.ts +18 -0
  541. package/payload/platform/plugins/aeo/mcp/dist/tools/aeo-emit-jsonld.d.ts.map +1 -0
  542. package/payload/platform/plugins/aeo/mcp/dist/tools/aeo-emit-jsonld.js +56 -0
  543. package/payload/platform/plugins/aeo/mcp/dist/tools/aeo-emit-jsonld.js.map +1 -0
  544. package/payload/platform/plugins/aeo/mcp/dist/tools/aeo-write-llms-txt.d.ts +9 -0
  545. package/payload/platform/plugins/aeo/mcp/dist/tools/aeo-write-llms-txt.d.ts.map +1 -0
  546. package/payload/platform/plugins/aeo/mcp/dist/tools/aeo-write-llms-txt.js +11 -0
  547. package/payload/platform/plugins/aeo/mcp/dist/tools/aeo-write-llms-txt.js.map +1 -0
  548. package/payload/platform/plugins/aeo/mcp/package.json +22 -0
  549. package/payload/platform/plugins/aeo/mcp/vitest.config.ts +9 -0
  550. package/payload/platform/plugins/aeo/skills/structured-answer/SKILL.md +55 -0
  551. package/payload/platform/plugins/browser/.claude-plugin/plugin.json +21 -0
  552. package/payload/platform/plugins/browser/PLUGIN.md +114 -0
  553. package/payload/platform/plugins/browser/lib/mcp-spawn-tee/index.js +193 -0
  554. package/payload/platform/plugins/browser/lib/mcp-spawn-tee/package.json +3 -0
  555. package/payload/platform/plugins/browser/mcp/dist/index.d.ts +2 -0
  556. package/payload/platform/plugins/browser/mcp/dist/index.d.ts.map +1 -0
  557. package/payload/platform/plugins/browser/mcp/dist/index.js +165 -0
  558. package/payload/platform/plugins/browser/mcp/dist/index.js.map +1 -0
  559. package/payload/platform/plugins/browser/mcp/dist/lib/cdp-actions.d.ts +98 -0
  560. package/payload/platform/plugins/browser/mcp/dist/lib/cdp-actions.d.ts.map +1 -0
  561. package/payload/platform/plugins/browser/mcp/dist/lib/cdp-actions.js +455 -0
  562. package/payload/platform/plugins/browser/mcp/dist/lib/cdp-actions.js.map +1 -0
  563. package/payload/platform/plugins/browser/mcp/dist/lib/cdp-render.d.ts +44 -0
  564. package/payload/platform/plugins/browser/mcp/dist/lib/cdp-render.d.ts.map +1 -0
  565. package/payload/platform/plugins/browser/mcp/dist/lib/cdp-render.js +89 -0
  566. package/payload/platform/plugins/browser/mcp/dist/lib/cdp-render.js.map +1 -0
  567. package/payload/platform/plugins/browser/mcp/dist/lib/cdp-session.d.ts +153 -0
  568. package/payload/platform/plugins/browser/mcp/dist/lib/cdp-session.d.ts.map +1 -0
  569. package/payload/platform/plugins/browser/mcp/dist/lib/cdp-session.js +401 -0
  570. package/payload/platform/plugins/browser/mcp/dist/lib/cdp-session.js.map +1 -0
  571. package/payload/platform/plugins/browser/mcp/package.json +19 -0
  572. package/payload/platform/plugins/business-assistant/.claude-plugin/plugin.json +8 -0
  573. package/payload/platform/plugins/business-assistant/PLUGIN.md +66 -0
  574. package/payload/platform/plugins/business-assistant/references/crm.md +118 -0
  575. package/payload/platform/plugins/business-assistant/references/document-management.md +96 -0
  576. package/payload/platform/plugins/business-assistant/references/escalation.md +126 -0
  577. package/payload/platform/plugins/business-assistant/references/invoicing.md +163 -0
  578. package/payload/platform/plugins/business-assistant/references/profiling.md +50 -0
  579. package/payload/platform/plugins/business-assistant/references/scheduling.md +127 -0
  580. package/payload/platform/plugins/business-assistant/references/site-lead-intake.md +52 -0
  581. package/payload/platform/plugins/business-assistant/references/task-management.md +163 -0
  582. package/payload/platform/plugins/business-assistant/skills/e-sign/SKILL.md +680 -0
  583. package/payload/platform/plugins/cloudflare/.claude-plugin/plugin.json +8 -0
  584. package/payload/platform/plugins/cloudflare/PLUGIN.md +62 -0
  585. package/payload/platform/plugins/cloudflare/mcp/dist/index.d.ts +2 -0
  586. package/payload/platform/plugins/cloudflare/mcp/dist/index.d.ts.map +1 -0
  587. package/payload/platform/plugins/cloudflare/mcp/dist/index.js +24 -0
  588. package/payload/platform/plugins/cloudflare/mcp/dist/index.js.map +1 -0
  589. package/payload/platform/plugins/cloudflare/mcp/dist/lib/cloudflared.d.ts +283 -0
  590. package/payload/platform/plugins/cloudflare/mcp/dist/lib/cloudflared.d.ts.map +1 -0
  591. package/payload/platform/plugins/cloudflare/mcp/dist/lib/cloudflared.js +1155 -0
  592. package/payload/platform/plugins/cloudflare/mcp/dist/lib/cloudflared.js.map +1 -0
  593. package/payload/platform/plugins/cloudflare/mcp/dist/lib/setup-orchestrator.d.ts +90 -0
  594. package/payload/platform/plugins/cloudflare/mcp/dist/lib/setup-orchestrator.d.ts.map +1 -0
  595. package/payload/platform/plugins/cloudflare/mcp/dist/lib/setup-orchestrator.js +551 -0
  596. package/payload/platform/plugins/cloudflare/mcp/dist/lib/setup-orchestrator.js.map +1 -0
  597. package/payload/platform/plugins/cloudflare/mcp/package.json +18 -0
  598. package/payload/platform/plugins/cloudflare/mcp/vitest.config.ts +10 -0
  599. package/payload/platform/plugins/cloudflare/references/api.md +255 -0
  600. package/payload/platform/plugins/cloudflare/references/d1-data-capture.md +165 -0
  601. package/payload/platform/plugins/cloudflare/references/dashboard-guide.md +184 -0
  602. package/payload/platform/plugins/cloudflare/references/hosting-sites.md +68 -0
  603. package/payload/platform/plugins/cloudflare/references/manual-setup.md +710 -0
  604. package/payload/platform/plugins/cloudflare/references/reset-guide.md +137 -0
  605. package/payload/platform/plugins/cloudflare/references/serving-published-sites.md +73 -0
  606. package/payload/platform/plugins/cloudflare/references/web-analytics.md +64 -0
  607. package/payload/platform/plugins/cloudflare/skills/cloudflare/SKILL.md +91 -0
  608. package/payload/platform/plugins/contacts/.claude-plugin/plugin.json +21 -0
  609. package/payload/platform/plugins/contacts/PLUGIN.md +62 -0
  610. package/payload/platform/plugins/contacts/lib/mcp-spawn-tee/index.js +193 -0
  611. package/payload/platform/plugins/contacts/lib/mcp-spawn-tee/package.json +3 -0
  612. package/payload/platform/plugins/contacts/mcp/dist/index.d.ts +2 -0
  613. package/payload/platform/plugins/contacts/mcp/dist/index.d.ts.map +1 -0
  614. package/payload/platform/plugins/contacts/mcp/dist/index.js +467 -0
  615. package/payload/platform/plugins/contacts/mcp/dist/index.js.map +1 -0
  616. package/payload/platform/plugins/contacts/mcp/dist/lib/neo4j.d.ts +5 -0
  617. package/payload/platform/plugins/contacts/mcp/dist/lib/neo4j.d.ts.map +1 -0
  618. package/payload/platform/plugins/contacts/mcp/dist/lib/neo4j.js +40 -0
  619. package/payload/platform/plugins/contacts/mcp/dist/lib/neo4j.js.map +1 -0
  620. package/payload/platform/plugins/contacts/mcp/dist/lib/resolve-person.d.ts +33 -0
  621. package/payload/platform/plugins/contacts/mcp/dist/lib/resolve-person.d.ts.map +1 -0
  622. package/payload/platform/plugins/contacts/mcp/dist/lib/resolve-person.js +53 -0
  623. package/payload/platform/plugins/contacts/mcp/dist/lib/resolve-person.js.map +1 -0
  624. package/payload/platform/plugins/contacts/mcp/dist/tools/__tests__/contact-lookup.test.d.ts +2 -0
  625. package/payload/platform/plugins/contacts/mcp/dist/tools/__tests__/contact-lookup.test.d.ts.map +1 -0
  626. package/payload/platform/plugins/contacts/mcp/dist/tools/__tests__/contact-lookup.test.js +71 -0
  627. package/payload/platform/plugins/contacts/mcp/dist/tools/__tests__/contact-lookup.test.js.map +1 -0
  628. package/payload/platform/plugins/contacts/mcp/dist/tools/__tests__/group-create.test.d.ts +2 -0
  629. package/payload/platform/plugins/contacts/mcp/dist/tools/__tests__/group-create.test.d.ts.map +1 -0
  630. package/payload/platform/plugins/contacts/mcp/dist/tools/__tests__/group-create.test.js +112 -0
  631. package/payload/platform/plugins/contacts/mcp/dist/tools/__tests__/group-create.test.js.map +1 -0
  632. package/payload/platform/plugins/contacts/mcp/dist/tools/__tests__/group-manage.test.d.ts +2 -0
  633. package/payload/platform/plugins/contacts/mcp/dist/tools/__tests__/group-manage.test.d.ts.map +1 -0
  634. package/payload/platform/plugins/contacts/mcp/dist/tools/__tests__/group-manage.test.js +102 -0
  635. package/payload/platform/plugins/contacts/mcp/dist/tools/__tests__/group-manage.test.js.map +1 -0
  636. package/payload/platform/plugins/contacts/mcp/dist/tools/contact-create.d.ts +23 -0
  637. package/payload/platform/plugins/contacts/mcp/dist/tools/contact-create.d.ts.map +1 -0
  638. package/payload/platform/plugins/contacts/mcp/dist/tools/contact-create.js +123 -0
  639. package/payload/platform/plugins/contacts/mcp/dist/tools/contact-create.js.map +1 -0
  640. package/payload/platform/plugins/contacts/mcp/dist/tools/contact-delete.d.ts +28 -0
  641. package/payload/platform/plugins/contacts/mcp/dist/tools/contact-delete.d.ts.map +1 -0
  642. package/payload/platform/plugins/contacts/mcp/dist/tools/contact-delete.js +39 -0
  643. package/payload/platform/plugins/contacts/mcp/dist/tools/contact-delete.js.map +1 -0
  644. package/payload/platform/plugins/contacts/mcp/dist/tools/contact-erase.d.ts +52 -0
  645. package/payload/platform/plugins/contacts/mcp/dist/tools/contact-erase.d.ts.map +1 -0
  646. package/payload/platform/plugins/contacts/mcp/dist/tools/contact-erase.js +181 -0
  647. package/payload/platform/plugins/contacts/mcp/dist/tools/contact-erase.js.map +1 -0
  648. package/payload/platform/plugins/contacts/mcp/dist/tools/contact-export.d.ts +52 -0
  649. package/payload/platform/plugins/contacts/mcp/dist/tools/contact-export.d.ts.map +1 -0
  650. package/payload/platform/plugins/contacts/mcp/dist/tools/contact-export.js +122 -0
  651. package/payload/platform/plugins/contacts/mcp/dist/tools/contact-export.js.map +1 -0
  652. package/payload/platform/plugins/contacts/mcp/dist/tools/contact-list.d.ts +23 -0
  653. package/payload/platform/plugins/contacts/mcp/dist/tools/contact-list.d.ts.map +1 -0
  654. package/payload/platform/plugins/contacts/mcp/dist/tools/contact-list.js +49 -0
  655. package/payload/platform/plugins/contacts/mcp/dist/tools/contact-list.js.map +1 -0
  656. package/payload/platform/plugins/contacts/mcp/dist/tools/contact-lookup.d.ts +22 -0
  657. package/payload/platform/plugins/contacts/mcp/dist/tools/contact-lookup.d.ts.map +1 -0
  658. package/payload/platform/plugins/contacts/mcp/dist/tools/contact-lookup.js +77 -0
  659. package/payload/platform/plugins/contacts/mcp/dist/tools/contact-lookup.js.map +1 -0
  660. package/payload/platform/plugins/contacts/mcp/dist/tools/contact-update.d.ts +14 -0
  661. package/payload/platform/plugins/contacts/mcp/dist/tools/contact-update.d.ts.map +1 -0
  662. package/payload/platform/plugins/contacts/mcp/dist/tools/contact-update.js +43 -0
  663. package/payload/platform/plugins/contacts/mcp/dist/tools/contact-update.js.map +1 -0
  664. package/payload/platform/plugins/contacts/mcp/dist/tools/group-create.d.ts +18 -0
  665. package/payload/platform/plugins/contacts/mcp/dist/tools/group-create.d.ts.map +1 -0
  666. package/payload/platform/plugins/contacts/mcp/dist/tools/group-create.js +100 -0
  667. package/payload/platform/plugins/contacts/mcp/dist/tools/group-create.js.map +1 -0
  668. package/payload/platform/plugins/contacts/mcp/dist/tools/group-manage.d.ts +15 -0
  669. package/payload/platform/plugins/contacts/mcp/dist/tools/group-manage.d.ts.map +1 -0
  670. package/payload/platform/plugins/contacts/mcp/dist/tools/group-manage.js +73 -0
  671. package/payload/platform/plugins/contacts/mcp/dist/tools/group-manage.js.map +1 -0
  672. package/payload/platform/plugins/contacts/mcp/package.json +21 -0
  673. package/payload/platform/plugins/deep-research/.claude-plugin/plugin.json +8 -0
  674. package/payload/platform/plugins/deep-research/PLUGIN.md +19 -0
  675. package/payload/platform/plugins/deep-research/recipes/README.md +36 -0
  676. package/payload/platform/plugins/deep-research/skills/academic-verify/SKILL.md +77 -0
  677. package/payload/platform/plugins/deep-research/skills/book-mirror/SKILL.md +70 -0
  678. package/payload/platform/plugins/deep-research/skills/data-research/SKILL.md +110 -0
  679. package/payload/platform/plugins/deep-research/skills/deep-research/SKILL.md +48 -0
  680. package/payload/platform/plugins/deep-research/skills/deep-research/references/citation-styles.md +52 -0
  681. package/payload/platform/plugins/deep-research/skills/deep-research/references/research-modes.md +22 -0
  682. package/payload/platform/plugins/deep-research/skills/deep-research/references/search-strategy.md +24 -0
  683. package/payload/platform/plugins/deep-research/skills/strategic-reading/SKILL.md +71 -0
  684. package/payload/platform/plugins/docs/.claude-plugin/plugin.json +8 -0
  685. package/payload/platform/plugins/docs/PLUGIN.md +58 -0
  686. package/payload/platform/plugins/docs/references/access-control.md +84 -0
  687. package/payload/platform/plugins/docs/references/admin-identity-gate.md +77 -0
  688. package/payload/platform/plugins/docs/references/admin-session.md +181 -0
  689. package/payload/platform/plugins/docs/references/admin-ui.md +397 -0
  690. package/payload/platform/plugins/docs/references/aeo.md +87 -0
  691. package/payload/platform/plugins/docs/references/attachments.md +44 -0
  692. package/payload/platform/plugins/docs/references/cloudflare.md +102 -0
  693. package/payload/platform/plugins/docs/references/contacts-guide.md +94 -0
  694. package/payload/platform/plugins/docs/references/deployment.md +323 -0
  695. package/payload/platform/plugins/docs/references/getting-started.md +95 -0
  696. package/payload/platform/plugins/docs/references/graph.md +163 -0
  697. package/payload/platform/plugins/docs/references/internals.md +547 -0
  698. package/payload/platform/plugins/docs/references/investigate-and-task-skills.md +9 -0
  699. package/payload/platform/plugins/docs/references/linkedin-extension.md +49 -0
  700. package/payload/platform/plugins/docs/references/memory-guide.md +163 -0
  701. package/payload/platform/plugins/docs/references/neo4j.md +72 -0
  702. package/payload/platform/plugins/docs/references/outlook-guide.md +69 -0
  703. package/payload/platform/plugins/docs/references/platform.md +190 -0
  704. package/payload/platform/plugins/docs/references/plugins-guide.md +189 -0
  705. package/payload/platform/plugins/docs/references/projects-guide.md +94 -0
  706. package/payload/platform/plugins/docs/references/quickbooks.md +29 -0
  707. package/payload/platform/plugins/docs/references/samba.md +93 -0
  708. package/payload/platform/plugins/docs/references/session-retrospective.md +14 -0
  709. package/payload/platform/plugins/docs/references/settings.md +82 -0
  710. package/payload/platform/plugins/docs/references/slides.md +31 -0
  711. package/payload/platform/plugins/docs/references/telegram-guide.md +58 -0
  712. package/payload/platform/plugins/docs/references/troubleshooting.md +291 -0
  713. package/payload/platform/plugins/docs/references/visitor-graph.md +83 -0
  714. package/payload/platform/plugins/docs/references/voice-mirror-guide.md +72 -0
  715. package/payload/platform/plugins/docs/superpowers/plans/2026-06-01-memory-edge.md +589 -0
  716. package/payload/platform/plugins/email/.claude-plugin/plugin.json +21 -0
  717. package/payload/platform/plugins/email/PLUGIN.md +112 -0
  718. package/payload/platform/plugins/email/lib/mcp-spawn-tee/index.js +193 -0
  719. package/payload/platform/plugins/email/lib/mcp-spawn-tee/package.json +3 -0
  720. package/payload/platform/plugins/email/mcp/dist/__tests__/attachment-resolve.test.d.ts +2 -0
  721. package/payload/platform/plugins/email/mcp/dist/__tests__/attachment-resolve.test.d.ts.map +1 -0
  722. package/payload/platform/plugins/email/mcp/dist/__tests__/attachment-resolve.test.js +92 -0
  723. package/payload/platform/plugins/email/mcp/dist/__tests__/attachment-resolve.test.js.map +1 -0
  724. package/payload/platform/plugins/email/mcp/dist/__tests__/email-draft-edit.test.d.ts +2 -0
  725. package/payload/platform/plugins/email/mcp/dist/__tests__/email-draft-edit.test.d.ts.map +1 -0
  726. package/payload/platform/plugins/email/mcp/dist/__tests__/email-draft-edit.test.js +71 -0
  727. package/payload/platform/plugins/email/mcp/dist/__tests__/email-draft-edit.test.js.map +1 -0
  728. package/payload/platform/plugins/email/mcp/dist/__tests__/email-draft-send.test.d.ts +2 -0
  729. package/payload/platform/plugins/email/mcp/dist/__tests__/email-draft-send.test.d.ts.map +1 -0
  730. package/payload/platform/plugins/email/mcp/dist/__tests__/email-draft-send.test.js +95 -0
  731. package/payload/platform/plugins/email/mcp/dist/__tests__/email-draft-send.test.js.map +1 -0
  732. package/payload/platform/plugins/email/mcp/dist/__tests__/email-draft.test.d.ts +2 -0
  733. package/payload/platform/plugins/email/mcp/dist/__tests__/email-draft.test.d.ts.map +1 -0
  734. package/payload/platform/plugins/email/mcp/dist/__tests__/email-draft.test.js +129 -0
  735. package/payload/platform/plugins/email/mcp/dist/__tests__/email-draft.test.js.map +1 -0
  736. package/payload/platform/plugins/email/mcp/dist/__tests__/email-setup.test.d.ts +2 -0
  737. package/payload/platform/plugins/email/mcp/dist/__tests__/email-setup.test.d.ts.map +1 -0
  738. package/payload/platform/plugins/email/mcp/dist/__tests__/email-setup.test.js +113 -0
  739. package/payload/platform/plugins/email/mcp/dist/__tests__/email-setup.test.js.map +1 -0
  740. package/payload/platform/plugins/email/mcp/dist/__tests__/imap-drafts.test.d.ts +2 -0
  741. package/payload/platform/plugins/email/mcp/dist/__tests__/imap-drafts.test.d.ts.map +1 -0
  742. package/payload/platform/plugins/email/mcp/dist/__tests__/imap-drafts.test.js +165 -0
  743. package/payload/platform/plugins/email/mcp/dist/__tests__/imap-drafts.test.js.map +1 -0
  744. package/payload/platform/plugins/email/mcp/dist/__tests__/imap-probe.test.d.ts +2 -0
  745. package/payload/platform/plugins/email/mcp/dist/__tests__/imap-probe.test.d.ts.map +1 -0
  746. package/payload/platform/plugins/email/mcp/dist/__tests__/imap-probe.test.js +69 -0
  747. package/payload/platform/plugins/email/mcp/dist/__tests__/imap-probe.test.js.map +1 -0
  748. package/payload/platform/plugins/email/mcp/dist/__tests__/mail-options.test.d.ts +2 -0
  749. package/payload/platform/plugins/email/mcp/dist/__tests__/mail-options.test.d.ts.map +1 -0
  750. package/payload/platform/plugins/email/mcp/dist/__tests__/mail-options.test.js +46 -0
  751. package/payload/platform/plugins/email/mcp/dist/__tests__/mail-options.test.js.map +1 -0
  752. package/payload/platform/plugins/email/mcp/dist/__tests__/providers.test.d.ts +2 -0
  753. package/payload/platform/plugins/email/mcp/dist/__tests__/providers.test.d.ts.map +1 -0
  754. package/payload/platform/plugins/email/mcp/dist/__tests__/providers.test.js +110 -0
  755. package/payload/platform/plugins/email/mcp/dist/__tests__/providers.test.js.map +1 -0
  756. package/payload/platform/plugins/email/mcp/dist/__tests__/recipient-filter.test.d.ts +2 -0
  757. package/payload/platform/plugins/email/mcp/dist/__tests__/recipient-filter.test.d.ts.map +1 -0
  758. package/payload/platform/plugins/email/mcp/dist/__tests__/recipient-filter.test.js +57 -0
  759. package/payload/platform/plugins/email/mcp/dist/__tests__/recipient-filter.test.js.map +1 -0
  760. package/payload/platform/plugins/email/mcp/dist/__tests__/send-raw.test.d.ts +2 -0
  761. package/payload/platform/plugins/email/mcp/dist/__tests__/send-raw.test.d.ts.map +1 -0
  762. package/payload/platform/plugins/email/mcp/dist/__tests__/send-raw.test.js +38 -0
  763. package/payload/platform/plugins/email/mcp/dist/__tests__/send-raw.test.js.map +1 -0
  764. package/payload/platform/plugins/email/mcp/dist/__tests__/setup-probe.test.d.ts +2 -0
  765. package/payload/platform/plugins/email/mcp/dist/__tests__/setup-probe.test.d.ts.map +1 -0
  766. package/payload/platform/plugins/email/mcp/dist/__tests__/setup-probe.test.js +56 -0
  767. package/payload/platform/plugins/email/mcp/dist/__tests__/setup-probe.test.js.map +1 -0
  768. package/payload/platform/plugins/email/mcp/dist/__tests__/smtp-probe.test.d.ts +2 -0
  769. package/payload/platform/plugins/email/mcp/dist/__tests__/smtp-probe.test.d.ts.map +1 -0
  770. package/payload/platform/plugins/email/mcp/dist/__tests__/smtp-probe.test.js +46 -0
  771. package/payload/platform/plugins/email/mcp/dist/__tests__/smtp-probe.test.js.map +1 -0
  772. package/payload/platform/plugins/email/mcp/dist/index.d.ts +2 -0
  773. package/payload/platform/plugins/email/mcp/dist/index.d.ts.map +1 -0
  774. package/payload/platform/plugins/email/mcp/dist/index.js +522 -0
  775. package/payload/platform/plugins/email/mcp/dist/index.js.map +1 -0
  776. package/payload/platform/plugins/email/mcp/dist/lib/attachment-archive.d.ts +39 -0
  777. package/payload/platform/plugins/email/mcp/dist/lib/attachment-archive.d.ts.map +1 -0
  778. package/payload/platform/plugins/email/mcp/dist/lib/attachment-archive.js +0 -0
  779. package/payload/platform/plugins/email/mcp/dist/lib/attachment-archive.js.map +1 -0
  780. package/payload/platform/plugins/email/mcp/dist/lib/attachment-resolve.d.ts +31 -0
  781. package/payload/platform/plugins/email/mcp/dist/lib/attachment-resolve.d.ts.map +1 -0
  782. package/payload/platform/plugins/email/mcp/dist/lib/attachment-resolve.js +103 -0
  783. package/payload/platform/plugins/email/mcp/dist/lib/attachment-resolve.js.map +1 -0
  784. package/payload/platform/plugins/email/mcp/dist/lib/claude-bridge.d.ts +17 -0
  785. package/payload/platform/plugins/email/mcp/dist/lib/claude-bridge.d.ts.map +1 -0
  786. package/payload/platform/plugins/email/mcp/dist/lib/claude-bridge.js +186 -0
  787. package/payload/platform/plugins/email/mcp/dist/lib/claude-bridge.js.map +1 -0
  788. package/payload/platform/plugins/email/mcp/dist/lib/compose.d.ts +47 -0
  789. package/payload/platform/plugins/email/mcp/dist/lib/compose.d.ts.map +1 -0
  790. package/payload/platform/plugins/email/mcp/dist/lib/compose.js +75 -0
  791. package/payload/platform/plugins/email/mcp/dist/lib/compose.js.map +1 -0
  792. package/payload/platform/plugins/email/mcp/dist/lib/conversation-archive-dispatch.d.ts +30 -0
  793. package/payload/platform/plugins/email/mcp/dist/lib/conversation-archive-dispatch.d.ts.map +1 -0
  794. package/payload/platform/plugins/email/mcp/dist/lib/conversation-archive-dispatch.js +305 -0
  795. package/payload/platform/plugins/email/mcp/dist/lib/conversation-archive-dispatch.js.map +1 -0
  796. package/payload/platform/plugins/email/mcp/dist/lib/conversation-archive-lookup.d.ts +19 -0
  797. package/payload/platform/plugins/email/mcp/dist/lib/conversation-archive-lookup.d.ts.map +1 -0
  798. package/payload/platform/plugins/email/mcp/dist/lib/conversation-archive-lookup.js +51 -0
  799. package/payload/platform/plugins/email/mcp/dist/lib/conversation-archive-lookup.js.map +1 -0
  800. package/payload/platform/plugins/email/mcp/dist/lib/credentials.d.ts +89 -0
  801. package/payload/platform/plugins/email/mcp/dist/lib/credentials.d.ts.map +1 -0
  802. package/payload/platform/plugins/email/mcp/dist/lib/credentials.js +245 -0
  803. package/payload/platform/plugins/email/mcp/dist/lib/credentials.js.map +1 -0
  804. package/payload/platform/plugins/email/mcp/dist/lib/embedding.d.ts +2 -0
  805. package/payload/platform/plugins/email/mcp/dist/lib/embedding.d.ts.map +1 -0
  806. package/payload/platform/plugins/email/mcp/dist/lib/embedding.js +24 -0
  807. package/payload/platform/plugins/email/mcp/dist/lib/embedding.js.map +1 -0
  808. package/payload/platform/plugins/email/mcp/dist/lib/graph.d.ts +29 -0
  809. package/payload/platform/plugins/email/mcp/dist/lib/graph.d.ts.map +1 -0
  810. package/payload/platform/plugins/email/mcp/dist/lib/graph.js +18 -0
  811. package/payload/platform/plugins/email/mcp/dist/lib/graph.js.map +1 -0
  812. package/payload/platform/plugins/email/mcp/dist/lib/imap.d.ts +352 -0
  813. package/payload/platform/plugins/email/mcp/dist/lib/imap.d.ts.map +1 -0
  814. package/payload/platform/plugins/email/mcp/dist/lib/imap.js +1021 -0
  815. package/payload/platform/plugins/email/mcp/dist/lib/imap.js.map +1 -0
  816. package/payload/platform/plugins/email/mcp/dist/lib/ingest-batch.d.ts +31 -0
  817. package/payload/platform/plugins/email/mcp/dist/lib/ingest-batch.d.ts.map +1 -0
  818. package/payload/platform/plugins/email/mcp/dist/lib/ingest-batch.js +15 -0
  819. package/payload/platform/plugins/email/mcp/dist/lib/ingest-batch.js.map +1 -0
  820. package/payload/platform/plugins/email/mcp/dist/lib/neo4j.d.ts +5 -0
  821. package/payload/platform/plugins/email/mcp/dist/lib/neo4j.d.ts.map +1 -0
  822. package/payload/platform/plugins/email/mcp/dist/lib/neo4j.js +40 -0
  823. package/payload/platform/plugins/email/mcp/dist/lib/neo4j.js.map +1 -0
  824. package/payload/platform/plugins/email/mcp/dist/lib/providers.d.ts +71 -0
  825. package/payload/platform/plugins/email/mcp/dist/lib/providers.d.ts.map +1 -0
  826. package/payload/platform/plugins/email/mcp/dist/lib/providers.js +782 -0
  827. package/payload/platform/plugins/email/mcp/dist/lib/providers.js.map +1 -0
  828. package/payload/platform/plugins/email/mcp/dist/lib/screening.d.ts +29 -0
  829. package/payload/platform/plugins/email/mcp/dist/lib/screening.d.ts.map +1 -0
  830. package/payload/platform/plugins/email/mcp/dist/lib/screening.js +105 -0
  831. package/payload/platform/plugins/email/mcp/dist/lib/screening.js.map +1 -0
  832. package/payload/platform/plugins/email/mcp/dist/lib/setup-probe.d.ts +42 -0
  833. package/payload/platform/plugins/email/mcp/dist/lib/setup-probe.d.ts.map +1 -0
  834. package/payload/platform/plugins/email/mcp/dist/lib/setup-probe.js +72 -0
  835. package/payload/platform/plugins/email/mcp/dist/lib/setup-probe.js.map +1 -0
  836. package/payload/platform/plugins/email/mcp/dist/lib/smtp.d.ts +61 -0
  837. package/payload/platform/plugins/email/mcp/dist/lib/smtp.d.ts.map +1 -0
  838. package/payload/platform/plugins/email/mcp/dist/lib/smtp.js +140 -0
  839. package/payload/platform/plugins/email/mcp/dist/lib/smtp.js.map +1 -0
  840. package/payload/platform/plugins/email/mcp/dist/scripts/email-auto-respond.d.ts +38 -0
  841. package/payload/platform/plugins/email/mcp/dist/scripts/email-auto-respond.d.ts.map +1 -0
  842. package/payload/platform/plugins/email/mcp/dist/scripts/email-auto-respond.js +817 -0
  843. package/payload/platform/plugins/email/mcp/dist/scripts/email-auto-respond.js.map +1 -0
  844. package/payload/platform/plugins/email/mcp/dist/scripts/email-fetch.d.ts +30 -0
  845. package/payload/platform/plugins/email/mcp/dist/scripts/email-fetch.d.ts.map +1 -0
  846. package/payload/platform/plugins/email/mcp/dist/scripts/email-fetch.js +215 -0
  847. package/payload/platform/plugins/email/mcp/dist/scripts/email-fetch.js.map +1 -0
  848. package/payload/platform/plugins/email/mcp/dist/scripts/send-transactional.d.ts +2 -0
  849. package/payload/platform/plugins/email/mcp/dist/scripts/send-transactional.d.ts.map +1 -0
  850. package/payload/platform/plugins/email/mcp/dist/scripts/send-transactional.js +55 -0
  851. package/payload/platform/plugins/email/mcp/dist/scripts/send-transactional.js.map +1 -0
  852. package/payload/platform/plugins/email/mcp/dist/tools/email-auto-respond-config.d.ts +19 -0
  853. package/payload/platform/plugins/email/mcp/dist/tools/email-auto-respond-config.d.ts.map +1 -0
  854. package/payload/platform/plugins/email/mcp/dist/tools/email-auto-respond-config.js +151 -0
  855. package/payload/platform/plugins/email/mcp/dist/tools/email-auto-respond-config.js.map +1 -0
  856. package/payload/platform/plugins/email/mcp/dist/tools/email-classify.d.ts +6 -0
  857. package/payload/platform/plugins/email/mcp/dist/tools/email-classify.d.ts.map +1 -0
  858. package/payload/platform/plugins/email/mcp/dist/tools/email-classify.js +89 -0
  859. package/payload/platform/plugins/email/mcp/dist/tools/email-classify.js.map +1 -0
  860. package/payload/platform/plugins/email/mcp/dist/tools/email-draft-edit.d.ts +9 -0
  861. package/payload/platform/plugins/email/mcp/dist/tools/email-draft-edit.d.ts.map +1 -0
  862. package/payload/platform/plugins/email/mcp/dist/tools/email-draft-edit.js +23 -0
  863. package/payload/platform/plugins/email/mcp/dist/tools/email-draft-edit.js.map +1 -0
  864. package/payload/platform/plugins/email/mcp/dist/tools/email-draft-send.d.ts +8 -0
  865. package/payload/platform/plugins/email/mcp/dist/tools/email-draft-send.d.ts.map +1 -0
  866. package/payload/platform/plugins/email/mcp/dist/tools/email-draft-send.js +52 -0
  867. package/payload/platform/plugins/email/mcp/dist/tools/email-draft-send.js.map +1 -0
  868. package/payload/platform/plugins/email/mcp/dist/tools/email-draft.d.ts +7 -0
  869. package/payload/platform/plugins/email/mcp/dist/tools/email-draft.d.ts.map +1 -0
  870. package/payload/platform/plugins/email/mcp/dist/tools/email-draft.js +17 -0
  871. package/payload/platform/plugins/email/mcp/dist/tools/email-draft.js.map +1 -0
  872. package/payload/platform/plugins/email/mcp/dist/tools/email-fetch.d.ts +15 -0
  873. package/payload/platform/plugins/email/mcp/dist/tools/email-fetch.d.ts.map +1 -0
  874. package/payload/platform/plugins/email/mcp/dist/tools/email-fetch.js +54 -0
  875. package/payload/platform/plugins/email/mcp/dist/tools/email-fetch.js.map +1 -0
  876. package/payload/platform/plugins/email/mcp/dist/tools/email-graph-query.d.ts +24 -0
  877. package/payload/platform/plugins/email/mcp/dist/tools/email-graph-query.d.ts.map +1 -0
  878. package/payload/platform/plugins/email/mcp/dist/tools/email-graph-query.js +293 -0
  879. package/payload/platform/plugins/email/mcp/dist/tools/email-graph-query.js.map +1 -0
  880. package/payload/platform/plugins/email/mcp/dist/tools/email-ingest.d.ts +20 -0
  881. package/payload/platform/plugins/email/mcp/dist/tools/email-ingest.d.ts.map +1 -0
  882. package/payload/platform/plugins/email/mcp/dist/tools/email-ingest.js +195 -0
  883. package/payload/platform/plugins/email/mcp/dist/tools/email-ingest.js.map +1 -0
  884. package/payload/platform/plugins/email/mcp/dist/tools/email-otp-extract.d.ts +15 -0
  885. package/payload/platform/plugins/email/mcp/dist/tools/email-otp-extract.d.ts.map +1 -0
  886. package/payload/platform/plugins/email/mcp/dist/tools/email-otp-extract.js +144 -0
  887. package/payload/platform/plugins/email/mcp/dist/tools/email-otp-extract.js.map +1 -0
  888. package/payload/platform/plugins/email/mcp/dist/tools/email-read.d.ts +14 -0
  889. package/payload/platform/plugins/email/mcp/dist/tools/email-read.d.ts.map +1 -0
  890. package/payload/platform/plugins/email/mcp/dist/tools/email-read.js +94 -0
  891. package/payload/platform/plugins/email/mcp/dist/tools/email-read.js.map +1 -0
  892. package/payload/platform/plugins/email/mcp/dist/tools/email-reply.d.ts +13 -0
  893. package/payload/platform/plugins/email/mcp/dist/tools/email-reply.d.ts.map +1 -0
  894. package/payload/platform/plugins/email/mcp/dist/tools/email-reply.js +71 -0
  895. package/payload/platform/plugins/email/mcp/dist/tools/email-reply.js.map +1 -0
  896. package/payload/platform/plugins/email/mcp/dist/tools/email-search.d.ts +15 -0
  897. package/payload/platform/plugins/email/mcp/dist/tools/email-search.d.ts.map +1 -0
  898. package/payload/platform/plugins/email/mcp/dist/tools/email-search.js +77 -0
  899. package/payload/platform/plugins/email/mcp/dist/tools/email-search.js.map +1 -0
  900. package/payload/platform/plugins/email/mcp/dist/tools/email-send.d.ts +13 -0
  901. package/payload/platform/plugins/email/mcp/dist/tools/email-send.d.ts.map +1 -0
  902. package/payload/platform/plugins/email/mcp/dist/tools/email-send.js +36 -0
  903. package/payload/platform/plugins/email/mcp/dist/tools/email-send.js.map +1 -0
  904. package/payload/platform/plugins/email/mcp/dist/tools/email-setup.d.ts +22 -0
  905. package/payload/platform/plugins/email/mcp/dist/tools/email-setup.d.ts.map +1 -0
  906. package/payload/platform/plugins/email/mcp/dist/tools/email-setup.js +202 -0
  907. package/payload/platform/plugins/email/mcp/dist/tools/email-setup.js.map +1 -0
  908. package/payload/platform/plugins/email/mcp/dist/tools/email-status.d.ts +6 -0
  909. package/payload/platform/plugins/email/mcp/dist/tools/email-status.d.ts.map +1 -0
  910. package/payload/platform/plugins/email/mcp/dist/tools/email-status.js +43 -0
  911. package/payload/platform/plugins/email/mcp/dist/tools/email-status.js.map +1 -0
  912. package/payload/platform/plugins/email/mcp/package.json +24 -0
  913. package/payload/platform/plugins/email/mcp/vitest.config.ts +9 -0
  914. package/payload/platform/plugins/email/references/email-reference.md +181 -0
  915. package/payload/platform/plugins/email/skills/email-composition/SKILL.md +208 -0
  916. package/payload/platform/plugins/email/skills/email-ingest/SKILL.md +89 -0
  917. package/payload/platform/plugins/graph/.claude-plugin/plugin.json +8 -0
  918. package/payload/platform/plugins/graph/PLUGIN.md +39 -0
  919. package/payload/platform/plugins/graph-viewer/.claude-plugin/plugin.json +8 -0
  920. package/payload/platform/plugins/graph-viewer/PLUGIN.md +56 -0
  921. package/payload/platform/plugins/graph-viewer/mcp/dist/index.d.ts +7 -0
  922. package/payload/platform/plugins/graph-viewer/mcp/dist/index.d.ts.map +1 -0
  923. package/payload/platform/plugins/graph-viewer/mcp/dist/index.js +70 -0
  924. package/payload/platform/plugins/graph-viewer/mcp/dist/index.js.map +1 -0
  925. package/payload/platform/plugins/graph-viewer/mcp/dist/lib/neo4j.d.ts +5 -0
  926. package/payload/platform/plugins/graph-viewer/mcp/dist/lib/neo4j.d.ts.map +1 -0
  927. package/payload/platform/plugins/graph-viewer/mcp/dist/lib/neo4j.js +43 -0
  928. package/payload/platform/plugins/graph-viewer/mcp/dist/lib/neo4j.js.map +1 -0
  929. package/payload/platform/plugins/graph-viewer/mcp/dist/render/draw.d.ts +28 -0
  930. package/payload/platform/plugins/graph-viewer/mcp/dist/render/draw.d.ts.map +1 -0
  931. package/payload/platform/plugins/graph-viewer/mcp/dist/render/draw.js +73 -0
  932. package/payload/platform/plugins/graph-viewer/mcp/dist/render/draw.js.map +1 -0
  933. package/payload/platform/plugins/graph-viewer/mcp/dist/render/layout.d.ts +40 -0
  934. package/payload/platform/plugins/graph-viewer/mcp/dist/render/layout.d.ts.map +1 -0
  935. package/payload/platform/plugins/graph-viewer/mcp/dist/render/layout.js +117 -0
  936. package/payload/platform/plugins/graph-viewer/mcp/dist/render/layout.js.map +1 -0
  937. package/payload/platform/plugins/graph-viewer/mcp/dist/tools/graph-render.d.ts +45 -0
  938. package/payload/platform/plugins/graph-viewer/mcp/dist/tools/graph-render.d.ts.map +1 -0
  939. package/payload/platform/plugins/graph-viewer/mcp/dist/tools/graph-render.js +199 -0
  940. package/payload/platform/plugins/graph-viewer/mcp/dist/tools/graph-render.js.map +1 -0
  941. package/payload/platform/plugins/graph-viewer/mcp/package.json +25 -0
  942. package/payload/platform/plugins/graph-viewer/mcp/vitest.config.ts +8 -0
  943. package/payload/platform/plugins/graph-viewer/skills/render-graph/SKILL.md +43 -0
  944. package/payload/platform/plugins/linkedin-extension/.claude-plugin/plugin.json +8 -0
  945. package/payload/platform/plugins/linkedin-extension/PLUGIN.md +58 -0
  946. package/payload/platform/plugins/linkedin-extension/extension/README.md +44 -0
  947. package/payload/platform/plugins/linkedin-extension/extension/__tests__/fixtures/profile.html +34 -0
  948. package/payload/platform/plugins/linkedin-extension/extension/__tests__/fixtures/thread.html +36 -0
  949. package/payload/platform/plugins/linkedin-extension/extension/assets/pill.css +52 -0
  950. package/payload/platform/plugins/linkedin-extension/extension/background/sw.js +60 -0
  951. package/payload/platform/plugins/linkedin-extension/extension/content/extractors.js +127 -0
  952. package/payload/platform/plugins/linkedin-extension/extension/content/profile.js +82 -0
  953. package/payload/platform/plugins/linkedin-extension/extension/content/thread.js +84 -0
  954. package/payload/platform/plugins/linkedin-extension/extension/manifest.json +32 -0
  955. package/payload/platform/plugins/linkedin-extension/extension/options/options.html +33 -0
  956. package/payload/platform/plugins/linkedin-extension/extension/options/options.js +30 -0
  957. package/payload/platform/plugins/linkedin-extension/skills/linkedin-extension/SKILL.md +93 -0
  958. package/payload/platform/plugins/linkedin-import/.claude-plugin/plugin.json +8 -0
  959. package/payload/platform/plugins/linkedin-import/PLUGIN.md +27 -0
  960. package/payload/platform/plugins/linkedin-import/skills/linkedin-import/SKILL.md +119 -0
  961. package/payload/platform/plugins/linkedin-import/skills/linkedin-import/references/connections.md +135 -0
  962. package/payload/platform/plugins/linkedin-import/skills/linkedin-import/references/profile.md +94 -0
  963. package/payload/platform/plugins/memory/.claude-plugin/plugin.json +21 -0
  964. package/payload/platform/plugins/memory/PLUGIN.md +290 -0
  965. package/payload/platform/plugins/memory/bin/conversation-archive-ingest.mjs +616 -0
  966. package/payload/platform/plugins/memory/bin/conversation-archive-ingest.sh +106 -0
  967. package/payload/platform/plugins/memory/lib/mcp-spawn-tee/index.js +193 -0
  968. package/payload/platform/plugins/memory/lib/mcp-spawn-tee/package.json +3 -0
  969. package/payload/platform/plugins/memory/mcp/dist/index.d.ts +2 -0
  970. package/payload/platform/plugins/memory/mcp/dist/index.d.ts.map +1 -0
  971. package/payload/platform/plugins/memory/mcp/dist/index.js +2479 -0
  972. package/payload/platform/plugins/memory/mcp/dist/index.js.map +1 -0
  973. package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/compiled-truth-revision.test.d.ts +2 -0
  974. package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/compiled-truth-revision.test.d.ts.map +1 -0
  975. package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/compiled-truth-revision.test.js +68 -0
  976. package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/compiled-truth-revision.test.js.map +1 -0
  977. package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/compiled-truth-rewriter-operator-hint.test.d.ts +2 -0
  978. package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/compiled-truth-rewriter-operator-hint.test.d.ts.map +1 -0
  979. package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/compiled-truth-rewriter-operator-hint.test.js +90 -0
  980. package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/compiled-truth-rewriter-operator-hint.test.js.map +1 -0
  981. package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/document-sectioniser.test.d.ts +2 -0
  982. package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/document-sectioniser.test.d.ts.map +1 -0
  983. package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/document-sectioniser.test.js +41 -0
  984. package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/document-sectioniser.test.js.map +1 -0
  985. package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/graph-write-embed-net.test.d.ts +2 -0
  986. package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/graph-write-embed-net.test.d.ts.map +1 -0
  987. package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/graph-write-embed-net.test.js +90 -0
  988. package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/graph-write-embed-net.test.js.map +1 -0
  989. package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/graph-write-gate-label.test.d.ts +2 -0
  990. package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/graph-write-gate-label.test.d.ts.map +1 -0
  991. package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/graph-write-gate-label.test.js +30 -0
  992. package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/graph-write-gate-label.test.js.map +1 -0
  993. package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/graph-write-gate-property.test.d.ts +2 -0
  994. package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/graph-write-gate-property.test.d.ts.map +1 -0
  995. package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/graph-write-gate-property.test.js +25 -0
  996. package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/graph-write-gate-property.test.js.map +1 -0
  997. package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/label-delete-gate.test.d.ts +2 -0
  998. package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/label-delete-gate.test.d.ts.map +1 -0
  999. package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/label-delete-gate.test.js +62 -0
  1000. package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/label-delete-gate.test.js.map +1 -0
  1001. package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/label-origin-gate.test.d.ts +2 -0
  1002. package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/label-origin-gate.test.d.ts.map +1 -0
  1003. package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/label-origin-gate.test.js +50 -0
  1004. package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/label-origin-gate.test.js.map +1 -0
  1005. package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/live-schema-source.test.d.ts +2 -0
  1006. package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/live-schema-source.test.d.ts.map +1 -0
  1007. package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/live-schema-source.test.js +154 -0
  1008. package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/live-schema-source.test.js.map +1 -0
  1009. package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/llm-classifier.test.d.ts +2 -0
  1010. package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/llm-classifier.test.d.ts.map +1 -0
  1011. package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/llm-classifier.test.js +226 -0
  1012. package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/llm-classifier.test.js.map +1 -0
  1013. package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/neo4j-password-path.test.d.ts +2 -0
  1014. package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/neo4j-password-path.test.d.ts.map +1 -0
  1015. package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/neo4j-password-path.test.js +57 -0
  1016. package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/neo4j-password-path.test.js.map +1 -0
  1017. package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/phase-backlinks.test.d.ts +2 -0
  1018. package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/phase-backlinks.test.d.ts.map +1 -0
  1019. package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/phase-backlinks.test.js +24 -0
  1020. package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/phase-backlinks.test.js.map +1 -0
  1021. package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/phase-prune-revisions.test.d.ts +2 -0
  1022. package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/phase-prune-revisions.test.d.ts.map +1 -0
  1023. package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/phase-prune-revisions.test.js +51 -0
  1024. package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/phase-prune-revisions.test.js.map +1 -0
  1025. package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/phase-tag-normalisation.test.d.ts +2 -0
  1026. package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/phase-tag-normalisation.test.d.ts.map +1 -0
  1027. package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/phase-tag-normalisation.test.js +51 -0
  1028. package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/phase-tag-normalisation.test.js.map +1 -0
  1029. package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/relationship-patterns.test.d.ts +2 -0
  1030. package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/relationship-patterns.test.d.ts.map +1 -0
  1031. package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/relationship-patterns.test.js +146 -0
  1032. package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/relationship-patterns.test.js.map +1 -0
  1033. package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/relative-date.test.d.ts +2 -0
  1034. package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/relative-date.test.d.ts.map +1 -0
  1035. package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/relative-date.test.js +68 -0
  1036. package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/relative-date.test.js.map +1 -0
  1037. package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/resolve-active-vertical.test.d.ts +2 -0
  1038. package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/resolve-active-vertical.test.d.ts.map +1 -0
  1039. package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/resolve-active-vertical.test.js +116 -0
  1040. package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/resolve-active-vertical.test.js.map +1 -0
  1041. package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/schema-cypher-drift.test.d.ts +2 -0
  1042. package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/schema-cypher-drift.test.d.ts.map +1 -0
  1043. package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/schema-cypher-drift.test.js +71 -0
  1044. package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/schema-cypher-drift.test.js.map +1 -0
  1045. package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/schema-doc-contradictions.test.d.ts +2 -0
  1046. package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/schema-doc-contradictions.test.d.ts.map +1 -0
  1047. package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/schema-doc-contradictions.test.js +214 -0
  1048. package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/schema-doc-contradictions.test.js.map +1 -0
  1049. package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/schema-loader.test.d.ts +2 -0
  1050. package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/schema-loader.test.d.ts.map +1 -0
  1051. package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/schema-loader.test.js +245 -0
  1052. package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/schema-loader.test.js.map +1 -0
  1053. package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/schema-validator.test.d.ts +2 -0
  1054. package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/schema-validator.test.d.ts.map +1 -0
  1055. package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/schema-validator.test.js +642 -0
  1056. package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/schema-validator.test.js.map +1 -0
  1057. package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/schema-write-path-task802.test.d.ts +2 -0
  1058. package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/schema-write-path-task802.test.d.ts.map +1 -0
  1059. package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/schema-write-path-task802.test.js +113 -0
  1060. package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/schema-write-path-task802.test.js.map +1 -0
  1061. package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/timeline-extractor.test.d.ts +2 -0
  1062. package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/timeline-extractor.test.d.ts.map +1 -0
  1063. package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/timeline-extractor.test.js +111 -0
  1064. package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/timeline-extractor.test.js.map +1 -0
  1065. package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/typed-edge-schema.test.d.ts +2 -0
  1066. package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/typed-edge-schema.test.d.ts.map +1 -0
  1067. package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/typed-edge-schema.test.js +85 -0
  1068. package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/typed-edge-schema.test.js.map +1 -0
  1069. package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/vector-indexed-labels-drift.test.d.ts +2 -0
  1070. package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/vector-indexed-labels-drift.test.d.ts.map +1 -0
  1071. package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/vector-indexed-labels-drift.test.js +27 -0
  1072. package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/vector-indexed-labels-drift.test.js.map +1 -0
  1073. package/payload/platform/plugins/memory/mcp/dist/lib/attachments.d.ts +37 -0
  1074. package/payload/platform/plugins/memory/mcp/dist/lib/attachments.d.ts.map +1 -0
  1075. package/payload/platform/plugins/memory/mcp/dist/lib/attachments.js +69 -0
  1076. package/payload/platform/plugins/memory/mcp/dist/lib/attachments.js.map +1 -0
  1077. package/payload/platform/plugins/memory/mcp/dist/lib/compiled-truth-revision.d.ts +91 -0
  1078. package/payload/platform/plugins/memory/mcp/dist/lib/compiled-truth-revision.d.ts.map +1 -0
  1079. package/payload/platform/plugins/memory/mcp/dist/lib/compiled-truth-revision.js +39 -0
  1080. package/payload/platform/plugins/memory/mcp/dist/lib/compiled-truth-revision.js.map +1 -0
  1081. package/payload/platform/plugins/memory/mcp/dist/lib/compiled-truth-rewriter.d.ts +60 -0
  1082. package/payload/platform/plugins/memory/mcp/dist/lib/compiled-truth-rewriter.d.ts.map +1 -0
  1083. package/payload/platform/plugins/memory/mcp/dist/lib/compiled-truth-rewriter.js +169 -0
  1084. package/payload/platform/plugins/memory/mcp/dist/lib/compiled-truth-rewriter.js.map +1 -0
  1085. package/payload/platform/plugins/memory/mcp/dist/lib/conversation-normalisers/email.d.ts +3 -0
  1086. package/payload/platform/plugins/memory/mcp/dist/lib/conversation-normalisers/email.d.ts.map +1 -0
  1087. package/payload/platform/plugins/memory/mcp/dist/lib/conversation-normalisers/email.js +61 -0
  1088. package/payload/platform/plugins/memory/mcp/dist/lib/conversation-normalisers/email.js.map +1 -0
  1089. package/payload/platform/plugins/memory/mcp/dist/lib/conversation-normalisers/index.d.ts +7 -0
  1090. package/payload/platform/plugins/memory/mcp/dist/lib/conversation-normalisers/index.d.ts.map +1 -0
  1091. package/payload/platform/plugins/memory/mcp/dist/lib/conversation-normalisers/index.js +36 -0
  1092. package/payload/platform/plugins/memory/mcp/dist/lib/conversation-normalisers/index.js.map +1 -0
  1093. package/payload/platform/plugins/memory/mcp/dist/lib/conversation-normalisers/timestamp-scanner.d.ts +49 -0
  1094. package/payload/platform/plugins/memory/mcp/dist/lib/conversation-normalisers/timestamp-scanner.d.ts.map +1 -0
  1095. package/payload/platform/plugins/memory/mcp/dist/lib/conversation-normalisers/timestamp-scanner.js +35 -0
  1096. package/payload/platform/plugins/memory/mcp/dist/lib/conversation-normalisers/timestamp-scanner.js.map +1 -0
  1097. package/payload/platform/plugins/memory/mcp/dist/lib/conversation-normalisers/types.d.ts +47 -0
  1098. package/payload/platform/plugins/memory/mcp/dist/lib/conversation-normalisers/types.d.ts.map +1 -0
  1099. package/payload/platform/plugins/memory/mcp/dist/lib/conversation-normalisers/types.js +38 -0
  1100. package/payload/platform/plugins/memory/mcp/dist/lib/conversation-normalisers/types.js.map +1 -0
  1101. package/payload/platform/plugins/memory/mcp/dist/lib/conversation-normalisers/whatsapp-text.d.ts +3 -0
  1102. package/payload/platform/plugins/memory/mcp/dist/lib/conversation-normalisers/whatsapp-text.d.ts.map +1 -0
  1103. package/payload/platform/plugins/memory/mcp/dist/lib/conversation-normalisers/whatsapp-text.js +155 -0
  1104. package/payload/platform/plugins/memory/mcp/dist/lib/conversation-normalisers/whatsapp-text.js.map +1 -0
  1105. package/payload/platform/plugins/memory/mcp/dist/lib/conversation-normalisers/x-dm.d.ts +3 -0
  1106. package/payload/platform/plugins/memory/mcp/dist/lib/conversation-normalisers/x-dm.d.ts.map +1 -0
  1107. package/payload/platform/plugins/memory/mcp/dist/lib/conversation-normalisers/x-dm.js +101 -0
  1108. package/payload/platform/plugins/memory/mcp/dist/lib/conversation-normalisers/x-dm.js.map +1 -0
  1109. package/payload/platform/plugins/memory/mcp/dist/lib/conversation-pipeline/delta-cursor.d.ts +11 -0
  1110. package/payload/platform/plugins/memory/mcp/dist/lib/conversation-pipeline/delta-cursor.d.ts.map +1 -0
  1111. package/payload/platform/plugins/memory/mcp/dist/lib/conversation-pipeline/delta-cursor.js +20 -0
  1112. package/payload/platform/plugins/memory/mcp/dist/lib/conversation-pipeline/delta-cursor.js.map +1 -0
  1113. package/payload/platform/plugins/memory/mcp/dist/lib/conversation-pipeline/derive-keys.d.ts +16 -0
  1114. package/payload/platform/plugins/memory/mcp/dist/lib/conversation-pipeline/derive-keys.d.ts.map +1 -0
  1115. package/payload/platform/plugins/memory/mcp/dist/lib/conversation-pipeline/derive-keys.js +43 -0
  1116. package/payload/platform/plugins/memory/mcp/dist/lib/conversation-pipeline/derive-keys.js.map +1 -0
  1117. package/payload/platform/plugins/memory/mcp/dist/lib/conversation-pipeline/sender-bind.d.ts +16 -0
  1118. package/payload/platform/plugins/memory/mcp/dist/lib/conversation-pipeline/sender-bind.d.ts.map +1 -0
  1119. package/payload/platform/plugins/memory/mcp/dist/lib/conversation-pipeline/sender-bind.js +60 -0
  1120. package/payload/platform/plugins/memory/mcp/dist/lib/conversation-pipeline/sender-bind.js.map +1 -0
  1121. package/payload/platform/plugins/memory/mcp/dist/lib/conversation-pipeline/sessionize.d.ts +9 -0
  1122. package/payload/platform/plugins/memory/mcp/dist/lib/conversation-pipeline/sessionize.d.ts.map +1 -0
  1123. package/payload/platform/plugins/memory/mcp/dist/lib/conversation-pipeline/sessionize.js +32 -0
  1124. package/payload/platform/plugins/memory/mcp/dist/lib/conversation-pipeline/sessionize.js.map +1 -0
  1125. package/payload/platform/plugins/memory/mcp/dist/lib/conversation-pipeline/to-turn-text.d.ts +3 -0
  1126. package/payload/platform/plugins/memory/mcp/dist/lib/conversation-pipeline/to-turn-text.d.ts.map +1 -0
  1127. package/payload/platform/plugins/memory/mcp/dist/lib/conversation-pipeline/to-turn-text.js +29 -0
  1128. package/payload/platform/plugins/memory/mcp/dist/lib/conversation-pipeline/to-turn-text.js.map +1 -0
  1129. package/payload/platform/plugins/memory/mcp/dist/lib/conversation-pipeline/turn-text-cache-path.d.ts +8 -0
  1130. package/payload/platform/plugins/memory/mcp/dist/lib/conversation-pipeline/turn-text-cache-path.d.ts.map +1 -0
  1131. package/payload/platform/plugins/memory/mcp/dist/lib/conversation-pipeline/turn-text-cache-path.js +27 -0
  1132. package/payload/platform/plugins/memory/mcp/dist/lib/conversation-pipeline/turn-text-cache-path.js.map +1 -0
  1133. package/payload/platform/plugins/memory/mcp/dist/lib/document-chunker.d.ts +45 -0
  1134. package/payload/platform/plugins/memory/mcp/dist/lib/document-chunker.d.ts.map +1 -0
  1135. package/payload/platform/plugins/memory/mcp/dist/lib/document-chunker.js +125 -0
  1136. package/payload/platform/plugins/memory/mcp/dist/lib/document-chunker.js.map +1 -0
  1137. package/payload/platform/plugins/memory/mcp/dist/lib/document-hierarchy.d.ts +9 -0
  1138. package/payload/platform/plugins/memory/mcp/dist/lib/document-hierarchy.d.ts.map +1 -0
  1139. package/payload/platform/plugins/memory/mcp/dist/lib/document-hierarchy.js +61 -0
  1140. package/payload/platform/plugins/memory/mcp/dist/lib/document-hierarchy.js.map +1 -0
  1141. package/payload/platform/plugins/memory/mcp/dist/lib/document-sectioniser.d.ts +10 -0
  1142. package/payload/platform/plugins/memory/mcp/dist/lib/document-sectioniser.d.ts.map +1 -0
  1143. package/payload/platform/plugins/memory/mcp/dist/lib/document-sectioniser.js +47 -0
  1144. package/payload/platform/plugins/memory/mcp/dist/lib/document-sectioniser.js.map +1 -0
  1145. package/payload/platform/plugins/memory/mcp/dist/lib/dream-cycle/index.d.ts +44 -0
  1146. package/payload/platform/plugins/memory/mcp/dist/lib/dream-cycle/index.d.ts.map +1 -0
  1147. package/payload/platform/plugins/memory/mcp/dist/lib/dream-cycle/index.js +14 -0
  1148. package/payload/platform/plugins/memory/mcp/dist/lib/dream-cycle/index.js.map +1 -0
  1149. package/payload/platform/plugins/memory/mcp/dist/lib/dream-cycle/phase-backlinks.d.ts +15 -0
  1150. package/payload/platform/plugins/memory/mcp/dist/lib/dream-cycle/phase-backlinks.d.ts.map +1 -0
  1151. package/payload/platform/plugins/memory/mcp/dist/lib/dream-cycle/phase-backlinks.js +37 -0
  1152. package/payload/platform/plugins/memory/mcp/dist/lib/dream-cycle/phase-backlinks.js.map +1 -0
  1153. package/payload/platform/plugins/memory/mcp/dist/lib/dream-cycle/phase-citation-audit.d.ts +3 -0
  1154. package/payload/platform/plugins/memory/mcp/dist/lib/dream-cycle/phase-citation-audit.d.ts.map +1 -0
  1155. package/payload/platform/plugins/memory/mcp/dist/lib/dream-cycle/phase-citation-audit.js +16 -0
  1156. package/payload/platform/plugins/memory/mcp/dist/lib/dream-cycle/phase-citation-audit.js.map +1 -0
  1157. package/payload/platform/plugins/memory/mcp/dist/lib/dream-cycle/phase-dead-edges.d.ts +19 -0
  1158. package/payload/platform/plugins/memory/mcp/dist/lib/dream-cycle/phase-dead-edges.d.ts.map +1 -0
  1159. package/payload/platform/plugins/memory/mcp/dist/lib/dream-cycle/phase-dead-edges.js +39 -0
  1160. package/payload/platform/plugins/memory/mcp/dist/lib/dream-cycle/phase-dead-edges.js.map +1 -0
  1161. package/payload/platform/plugins/memory/mcp/dist/lib/dream-cycle/phase-orphans.d.ts +19 -0
  1162. package/payload/platform/plugins/memory/mcp/dist/lib/dream-cycle/phase-orphans.d.ts.map +1 -0
  1163. package/payload/platform/plugins/memory/mcp/dist/lib/dream-cycle/phase-orphans.js +42 -0
  1164. package/payload/platform/plugins/memory/mcp/dist/lib/dream-cycle/phase-orphans.js.map +1 -0
  1165. package/payload/platform/plugins/memory/mcp/dist/lib/dream-cycle/phase-prune-revisions.d.ts +21 -0
  1166. package/payload/platform/plugins/memory/mcp/dist/lib/dream-cycle/phase-prune-revisions.d.ts.map +1 -0
  1167. package/payload/platform/plugins/memory/mcp/dist/lib/dream-cycle/phase-prune-revisions.js +27 -0
  1168. package/payload/platform/plugins/memory/mcp/dist/lib/dream-cycle/phase-prune-revisions.js.map +1 -0
  1169. package/payload/platform/plugins/memory/mcp/dist/lib/dream-cycle/phase-stale-truth.d.ts +18 -0
  1170. package/payload/platform/plugins/memory/mcp/dist/lib/dream-cycle/phase-stale-truth.d.ts.map +1 -0
  1171. package/payload/platform/plugins/memory/mcp/dist/lib/dream-cycle/phase-stale-truth.js +60 -0
  1172. package/payload/platform/plugins/memory/mcp/dist/lib/dream-cycle/phase-stale-truth.js.map +1 -0
  1173. package/payload/platform/plugins/memory/mcp/dist/lib/dream-cycle/phase-tag-normalisation.d.ts +25 -0
  1174. package/payload/platform/plugins/memory/mcp/dist/lib/dream-cycle/phase-tag-normalisation.d.ts.map +1 -0
  1175. package/payload/platform/plugins/memory/mcp/dist/lib/dream-cycle/phase-tag-normalisation.js +90 -0
  1176. package/payload/platform/plugins/memory/mcp/dist/lib/dream-cycle/phase-tag-normalisation.js.map +1 -0
  1177. package/payload/platform/plugins/memory/mcp/dist/lib/embeddings.d.ts +2 -0
  1178. package/payload/platform/plugins/memory/mcp/dist/lib/embeddings.d.ts.map +1 -0
  1179. package/payload/platform/plugins/memory/mcp/dist/lib/embeddings.js +6 -0
  1180. package/payload/platform/plugins/memory/mcp/dist/lib/embeddings.js.map +1 -0
  1181. package/payload/platform/plugins/memory/mcp/dist/lib/filter-token.d.ts +36 -0
  1182. package/payload/platform/plugins/memory/mcp/dist/lib/filter-token.d.ts.map +1 -0
  1183. package/payload/platform/plugins/memory/mcp/dist/lib/filter-token.js +86 -0
  1184. package/payload/platform/plugins/memory/mcp/dist/lib/filter-token.js.map +1 -0
  1185. package/payload/platform/plugins/memory/mcp/dist/lib/graph-prune.d.ts +41 -0
  1186. package/payload/platform/plugins/memory/mcp/dist/lib/graph-prune.d.ts.map +1 -0
  1187. package/payload/platform/plugins/memory/mcp/dist/lib/graph-prune.js +113 -0
  1188. package/payload/platform/plugins/memory/mcp/dist/lib/graph-prune.js.map +1 -0
  1189. package/payload/platform/plugins/memory/mcp/dist/lib/graph-write-gate.d.ts +76 -0
  1190. package/payload/platform/plugins/memory/mcp/dist/lib/graph-write-gate.d.ts.map +1 -0
  1191. package/payload/platform/plugins/memory/mcp/dist/lib/graph-write-gate.js +148 -0
  1192. package/payload/platform/plugins/memory/mcp/dist/lib/graph-write-gate.js.map +1 -0
  1193. package/payload/platform/plugins/memory/mcp/dist/lib/kd-classify-gate.d.ts +41 -0
  1194. package/payload/platform/plugins/memory/mcp/dist/lib/kd-classify-gate.d.ts.map +1 -0
  1195. package/payload/platform/plugins/memory/mcp/dist/lib/kd-classify-gate.js +69 -0
  1196. package/payload/platform/plugins/memory/mcp/dist/lib/kd-classify-gate.js.map +1 -0
  1197. package/payload/platform/plugins/memory/mcp/dist/lib/label-delete-gate.d.ts +18 -0
  1198. package/payload/platform/plugins/memory/mcp/dist/lib/label-delete-gate.d.ts.map +1 -0
  1199. package/payload/platform/plugins/memory/mcp/dist/lib/label-delete-gate.js +31 -0
  1200. package/payload/platform/plugins/memory/mcp/dist/lib/label-delete-gate.js.map +1 -0
  1201. package/payload/platform/plugins/memory/mcp/dist/lib/label-origin-gate.d.ts +18 -0
  1202. package/payload/platform/plugins/memory/mcp/dist/lib/label-origin-gate.d.ts.map +1 -0
  1203. package/payload/platform/plugins/memory/mcp/dist/lib/label-origin-gate.js +35 -0
  1204. package/payload/platform/plugins/memory/mcp/dist/lib/label-origin-gate.js.map +1 -0
  1205. package/payload/platform/plugins/memory/mcp/dist/lib/live-schema-source.d.ts +119 -0
  1206. package/payload/platform/plugins/memory/mcp/dist/lib/live-schema-source.d.ts.map +1 -0
  1207. package/payload/platform/plugins/memory/mcp/dist/lib/live-schema-source.js +208 -0
  1208. package/payload/platform/plugins/memory/mcp/dist/lib/live-schema-source.js.map +1 -0
  1209. package/payload/platform/plugins/memory/mcp/dist/lib/llm-classifier.d.ts +248 -0
  1210. package/payload/platform/plugins/memory/mcp/dist/lib/llm-classifier.d.ts.map +1 -0
  1211. package/payload/platform/plugins/memory/mcp/dist/lib/llm-classifier.js +824 -0
  1212. package/payload/platform/plugins/memory/mcp/dist/lib/llm-classifier.js.map +1 -0
  1213. package/payload/platform/plugins/memory/mcp/dist/lib/llm-ranker.d.ts +63 -0
  1214. package/payload/platform/plugins/memory/mcp/dist/lib/llm-ranker.d.ts.map +1 -0
  1215. package/payload/platform/plugins/memory/mcp/dist/lib/llm-ranker.js +210 -0
  1216. package/payload/platform/plugins/memory/mcp/dist/lib/llm-ranker.js.map +1 -0
  1217. package/payload/platform/plugins/memory/mcp/dist/lib/log-ingest.d.ts +65 -0
  1218. package/payload/platform/plugins/memory/mcp/dist/lib/log-ingest.d.ts.map +1 -0
  1219. package/payload/platform/plugins/memory/mcp/dist/lib/log-ingest.js +182 -0
  1220. package/payload/platform/plugins/memory/mcp/dist/lib/log-ingest.js.map +1 -0
  1221. package/payload/platform/plugins/memory/mcp/dist/lib/neo4j.d.ts +19 -0
  1222. package/payload/platform/plugins/memory/mcp/dist/lib/neo4j.d.ts.map +1 -0
  1223. package/payload/platform/plugins/memory/mcp/dist/lib/neo4j.js +76 -0
  1224. package/payload/platform/plugins/memory/mcp/dist/lib/neo4j.js.map +1 -0
  1225. package/payload/platform/plugins/memory/mcp/dist/lib/relationship-patterns.d.ts +66 -0
  1226. package/payload/platform/plugins/memory/mcp/dist/lib/relationship-patterns.d.ts.map +1 -0
  1227. package/payload/platform/plugins/memory/mcp/dist/lib/relationship-patterns.js +102 -0
  1228. package/payload/platform/plugins/memory/mcp/dist/lib/relationship-patterns.js.map +1 -0
  1229. package/payload/platform/plugins/memory/mcp/dist/lib/relative-date.d.ts +13 -0
  1230. package/payload/platform/plugins/memory/mcp/dist/lib/relative-date.d.ts.map +1 -0
  1231. package/payload/platform/plugins/memory/mcp/dist/lib/relative-date.js +191 -0
  1232. package/payload/platform/plugins/memory/mcp/dist/lib/relative-date.js.map +1 -0
  1233. package/payload/platform/plugins/memory/mcp/dist/lib/resolve-active-vertical.d.ts +33 -0
  1234. package/payload/platform/plugins/memory/mcp/dist/lib/resolve-active-vertical.d.ts.map +1 -0
  1235. package/payload/platform/plugins/memory/mcp/dist/lib/resolve-active-vertical.js +44 -0
  1236. package/payload/platform/plugins/memory/mcp/dist/lib/resolve-active-vertical.js.map +1 -0
  1237. package/payload/platform/plugins/memory/mcp/dist/lib/schema-loader.d.ts +200 -0
  1238. package/payload/platform/plugins/memory/mcp/dist/lib/schema-loader.d.ts.map +1 -0
  1239. package/payload/platform/plugins/memory/mcp/dist/lib/schema-loader.js +607 -0
  1240. package/payload/platform/plugins/memory/mcp/dist/lib/schema-loader.js.map +1 -0
  1241. package/payload/platform/plugins/memory/mcp/dist/lib/schema-validator.d.ts +92 -0
  1242. package/payload/platform/plugins/memory/mcp/dist/lib/schema-validator.d.ts.map +1 -0
  1243. package/payload/platform/plugins/memory/mcp/dist/lib/schema-validator.js +243 -0
  1244. package/payload/platform/plugins/memory/mcp/dist/lib/schema-validator.js.map +1 -0
  1245. package/payload/platform/plugins/memory/mcp/dist/lib/section-types.d.ts +127 -0
  1246. package/payload/platform/plugins/memory/mcp/dist/lib/section-types.d.ts.map +1 -0
  1247. package/payload/platform/plugins/memory/mcp/dist/lib/section-types.js +56 -0
  1248. package/payload/platform/plugins/memory/mcp/dist/lib/section-types.js.map +1 -0
  1249. package/payload/platform/plugins/memory/mcp/dist/lib/timeline-extractor.d.ts +19 -0
  1250. package/payload/platform/plugins/memory/mcp/dist/lib/timeline-extractor.d.ts.map +1 -0
  1251. package/payload/platform/plugins/memory/mcp/dist/lib/timeline-extractor.js +179 -0
  1252. package/payload/platform/plugins/memory/mcp/dist/lib/timeline-extractor.js.map +1 -0
  1253. package/payload/platform/plugins/memory/mcp/dist/lib/typed-edge-pass.d.ts +35 -0
  1254. package/payload/platform/plugins/memory/mcp/dist/lib/typed-edge-pass.d.ts.map +1 -0
  1255. package/payload/platform/plugins/memory/mcp/dist/lib/typed-edge-pass.js +28 -0
  1256. package/payload/platform/plugins/memory/mcp/dist/lib/typed-edge-pass.js.map +1 -0
  1257. package/payload/platform/plugins/memory/mcp/dist/lib/typed-edge-schema.d.ts +29 -0
  1258. package/payload/platform/plugins/memory/mcp/dist/lib/typed-edge-schema.d.ts.map +1 -0
  1259. package/payload/platform/plugins/memory/mcp/dist/lib/typed-edge-schema.js +160 -0
  1260. package/payload/platform/plugins/memory/mcp/dist/lib/typed-edge-schema.js.map +1 -0
  1261. package/payload/platform/plugins/memory/mcp/dist/lib/uuid.d.ts +3 -0
  1262. package/payload/platform/plugins/memory/mcp/dist/lib/uuid.d.ts.map +1 -0
  1263. package/payload/platform/plugins/memory/mcp/dist/lib/uuid.js +12 -0
  1264. package/payload/platform/plugins/memory/mcp/dist/lib/uuid.js.map +1 -0
  1265. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/_helpers/emit-capture.d.ts +22 -0
  1266. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/_helpers/emit-capture.d.ts.map +1 -0
  1267. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/_helpers/emit-capture.js +44 -0
  1268. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/_helpers/emit-capture.js.map +1 -0
  1269. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/build-text-representation-bound.test.d.ts +2 -0
  1270. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/build-text-representation-bound.test.d.ts.map +1 -0
  1271. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/build-text-representation-bound.test.js +20 -0
  1272. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/build-text-representation-bound.test.js.map +1 -0
  1273. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/conversation-archive-derive-insights-emit.test.d.ts +2 -0
  1274. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/conversation-archive-derive-insights-emit.test.d.ts.map +1 -0
  1275. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/conversation-archive-derive-insights-emit.test.js +68 -0
  1276. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/conversation-archive-derive-insights-emit.test.js.map +1 -0
  1277. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/conversation-archive-derive-insights.test.d.ts +7 -0
  1278. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/conversation-archive-derive-insights.test.d.ts.map +1 -0
  1279. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/conversation-archive-derive-insights.test.js +298 -0
  1280. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/conversation-archive-derive-insights.test.js.map +1 -0
  1281. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/conversation-archive-enrich-rejection-emit.test.d.ts +2 -0
  1282. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/conversation-archive-enrich-rejection-emit.test.d.ts.map +1 -0
  1283. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/conversation-archive-enrich-rejection-emit.test.js +48 -0
  1284. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/conversation-archive-enrich-rejection-emit.test.js.map +1 -0
  1285. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/conversation-archive-enrich-rejection.test.d.ts +2 -0
  1286. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/conversation-archive-enrich-rejection.test.d.ts.map +1 -0
  1287. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/conversation-archive-enrich-rejection.test.js +184 -0
  1288. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/conversation-archive-enrich-rejection.test.js.map +1 -0
  1289. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/conversation-archive-preference-embed.test.d.ts +2 -0
  1290. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/conversation-archive-preference-embed.test.d.ts.map +1 -0
  1291. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/conversation-archive-preference-embed.test.js +67 -0
  1292. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/conversation-archive-preference-embed.test.js.map +1 -0
  1293. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/conversation-memory-expunge-emit.test.d.ts +2 -0
  1294. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/conversation-memory-expunge-emit.test.d.ts.map +1 -0
  1295. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/conversation-memory-expunge-emit.test.js +53 -0
  1296. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/conversation-memory-expunge-emit.test.js.map +1 -0
  1297. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/conversation-normalisers-source-agnosticism.test.d.ts +2 -0
  1298. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/conversation-normalisers-source-agnosticism.test.d.ts.map +1 -0
  1299. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/conversation-normalisers-source-agnosticism.test.js +75 -0
  1300. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/conversation-normalisers-source-agnosticism.test.js.map +1 -0
  1301. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/conversation-normalisers-whatsapp-text.test.d.ts +2 -0
  1302. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/conversation-normalisers-whatsapp-text.test.d.ts.map +1 -0
  1303. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/conversation-normalisers-whatsapp-text.test.js +109 -0
  1304. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/conversation-normalisers-whatsapp-text.test.js.map +1 -0
  1305. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/embeddings-cap.test.d.ts +2 -0
  1306. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/embeddings-cap.test.d.ts.map +1 -0
  1307. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/embeddings-cap.test.js +34 -0
  1308. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/embeddings-cap.test.js.map +1 -0
  1309. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/graph-prune-denylist-add-emit.test.d.ts +2 -0
  1310. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/graph-prune-denylist-add-emit.test.d.ts.map +1 -0
  1311. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/graph-prune-denylist-add-emit.test.js +40 -0
  1312. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/graph-prune-denylist-add-emit.test.js.map +1 -0
  1313. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/graph-prune-denylist-remove-emit.test.d.ts +2 -0
  1314. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/graph-prune-denylist-remove-emit.test.d.ts.map +1 -0
  1315. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/graph-prune-denylist-remove-emit.test.js +39 -0
  1316. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/graph-prune-denylist-remove-emit.test.js.map +1 -0
  1317. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/kd-classify-account-dir.test.d.ts +2 -0
  1318. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/kd-classify-account-dir.test.d.ts.map +1 -0
  1319. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/kd-classify-account-dir.test.js +31 -0
  1320. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/kd-classify-account-dir.test.js.map +1 -0
  1321. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/log-ingest.test.d.ts +2 -0
  1322. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/log-ingest.test.d.ts.map +1 -0
  1323. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/log-ingest.test.js +241 -0
  1324. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/log-ingest.test.js.map +1 -0
  1325. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-archive-section-writer.test.d.ts +2 -0
  1326. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-archive-section-writer.test.d.ts.map +1 -0
  1327. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-archive-section-writer.test.js +61 -0
  1328. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-archive-section-writer.test.js.map +1 -0
  1329. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-archive-write-emit.test.d.ts +2 -0
  1330. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-archive-write-emit.test.d.ts.map +1 -0
  1331. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-archive-write-emit.test.js +88 -0
  1332. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-archive-write-emit.test.js.map +1 -0
  1333. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-archive-write.test.d.ts +2 -0
  1334. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-archive-write.test.d.ts.map +1 -0
  1335. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-archive-write.test.js +106 -0
  1336. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-archive-write.test.js.map +1 -0
  1337. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-classify-emit.test.d.ts +2 -0
  1338. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-classify-emit.test.d.ts.map +1 -0
  1339. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-classify-emit.test.js +58 -0
  1340. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-classify-emit.test.js.map +1 -0
  1341. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-compiled-truth-history.test.d.ts +2 -0
  1342. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-compiled-truth-history.test.d.ts.map +1 -0
  1343. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-compiled-truth-history.test.js +129 -0
  1344. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-compiled-truth-history.test.js.map +1 -0
  1345. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-delete-emit.test.d.ts +2 -0
  1346. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-delete-emit.test.d.ts.map +1 -0
  1347. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-delete-emit.test.js +64 -0
  1348. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-delete-emit.test.js.map +1 -0
  1349. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-delete-reserved-label.test.d.ts +2 -0
  1350. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-delete-reserved-label.test.d.ts.map +1 -0
  1351. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-delete-reserved-label.test.js +141 -0
  1352. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-delete-reserved-label.test.js.map +1 -0
  1353. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-edge.test.d.ts +2 -0
  1354. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-edge.test.d.ts.map +1 -0
  1355. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-edge.test.js +164 -0
  1356. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-edge.test.js.map +1 -0
  1357. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-edit-attachment-emit.test.d.ts +2 -0
  1358. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-edit-attachment-emit.test.d.ts.map +1 -0
  1359. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-edit-attachment-emit.test.js +70 -0
  1360. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-edit-attachment-emit.test.js.map +1 -0
  1361. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-empty-trash-admin-conversation.test.d.ts +2 -0
  1362. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-empty-trash-admin-conversation.test.d.ts.map +1 -0
  1363. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-empty-trash-admin-conversation.test.js +168 -0
  1364. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-empty-trash-admin-conversation.test.js.map +1 -0
  1365. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-empty-trash-emit.test.d.ts +2 -0
  1366. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-empty-trash-emit.test.d.ts.map +1 -0
  1367. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-empty-trash-emit.test.js +48 -0
  1368. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-empty-trash-emit.test.js.map +1 -0
  1369. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-empty-trash-reserved-label.test.d.ts +2 -0
  1370. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-empty-trash-reserved-label.test.d.ts.map +1 -0
  1371. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-empty-trash-reserved-label.test.js +86 -0
  1372. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-empty-trash-reserved-label.test.js.map +1 -0
  1373. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-ingest-body-server-sliced.test.d.ts +2 -0
  1374. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-ingest-body-server-sliced.test.d.ts.map +1 -0
  1375. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-ingest-body-server-sliced.test.js +134 -0
  1376. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-ingest-body-server-sliced.test.js.map +1 -0
  1377. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-ingest-chat-body-server-sliced.test.d.ts +2 -0
  1378. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-ingest-chat-body-server-sliced.test.d.ts.map +1 -0
  1379. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-ingest-chat-body-server-sliced.test.js +124 -0
  1380. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-ingest-chat-body-server-sliced.test.js.map +1 -0
  1381. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-ingest-emit.test.d.ts +2 -0
  1382. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-ingest-emit.test.d.ts.map +1 -0
  1383. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-ingest-emit.test.js +74 -0
  1384. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-ingest-emit.test.js.map +1 -0
  1385. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-ingest-extract-emit.test.d.ts +2 -0
  1386. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-ingest-extract-emit.test.d.ts.map +1 -0
  1387. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-ingest-extract-emit.test.js +47 -0
  1388. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-ingest-extract-emit.test.js.map +1 -0
  1389. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-ingest-inline-rewrite.test.d.ts +2 -0
  1390. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-ingest-inline-rewrite.test.d.ts.map +1 -0
  1391. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-ingest-inline-rewrite.test.js +66 -0
  1392. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-ingest-inline-rewrite.test.js.map +1 -0
  1393. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-ingest-section-properties-strip.test.d.ts +2 -0
  1394. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-ingest-section-properties-strip.test.d.ts.map +1 -0
  1395. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-ingest-section-properties-strip.test.js +104 -0
  1396. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-ingest-section-properties-strip.test.js.map +1 -0
  1397. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-ingest-web-emit.test.d.ts +2 -0
  1398. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-ingest-web-emit.test.d.ts.map +1 -0
  1399. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-ingest-web-emit.test.js +65 -0
  1400. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-ingest-web-emit.test.js.map +1 -0
  1401. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-ingest.test.d.ts +2 -0
  1402. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-ingest.test.d.ts.map +1 -0
  1403. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-ingest.test.js +175 -0
  1404. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-ingest.test.js.map +1 -0
  1405. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-lookup-by-name.test.d.ts +2 -0
  1406. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-lookup-by-name.test.d.ts.map +1 -0
  1407. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-lookup-by-name.test.js +174 -0
  1408. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-lookup-by-name.test.js.map +1 -0
  1409. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-reindex-emit.test.d.ts +2 -0
  1410. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-reindex-emit.test.d.ts.map +1 -0
  1411. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-reindex-emit.test.js +43 -0
  1412. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-reindex-emit.test.js.map +1 -0
  1413. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-reindex.test.d.ts +2 -0
  1414. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-reindex.test.d.ts.map +1 -0
  1415. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-reindex.test.js +87 -0
  1416. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-reindex.test.js.map +1 -0
  1417. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-rename-attachment-emit.test.d.ts +2 -0
  1418. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-rename-attachment-emit.test.d.ts.map +1 -0
  1419. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-rename-attachment-emit.test.js +65 -0
  1420. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-rename-attachment-emit.test.js.map +1 -0
  1421. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-report-tools.test.d.ts +2 -0
  1422. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-report-tools.test.d.ts.map +1 -0
  1423. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-report-tools.test.js +115 -0
  1424. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-report-tools.test.js.map +1 -0
  1425. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-restore-emit.test.d.ts +2 -0
  1426. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-restore-emit.test.d.ts.map +1 -0
  1427. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-restore-emit.test.js +49 -0
  1428. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-restore-emit.test.js.map +1 -0
  1429. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-search-fields.test.d.ts +2 -0
  1430. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-search-fields.test.d.ts.map +1 -0
  1431. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-search-fields.test.js +128 -0
  1432. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-search-fields.test.js.map +1 -0
  1433. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-search-threshold.test.d.ts +2 -0
  1434. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-search-threshold.test.d.ts.map +1 -0
  1435. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-search-threshold.test.js +34 -0
  1436. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-search-threshold.test.js.map +1 -0
  1437. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-update-by-name.test.d.ts +2 -0
  1438. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-update-by-name.test.d.ts.map +1 -0
  1439. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-update-by-name.test.js +125 -0
  1440. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-update-by-name.test.js.map +1 -0
  1441. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-update-emit.test.d.ts +2 -0
  1442. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-update-emit.test.d.ts.map +1 -0
  1443. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-update-emit.test.js +79 -0
  1444. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-update-emit.test.js.map +1 -0
  1445. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-update-operator-hint.test.d.ts +2 -0
  1446. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-update-operator-hint.test.d.ts.map +1 -0
  1447. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-update-operator-hint.test.js +329 -0
  1448. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-update-operator-hint.test.js.map +1 -0
  1449. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-write-compiled-truth-rejection.test.d.ts +2 -0
  1450. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-write-compiled-truth-rejection.test.d.ts.map +1 -0
  1451. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-write-compiled-truth-rejection.test.js +39 -0
  1452. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-write-compiled-truth-rejection.test.js.map +1 -0
  1453. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-write-emit.test.d.ts +2 -0
  1454. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-write-emit.test.d.ts.map +1 -0
  1455. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-write-emit.test.js +81 -0
  1456. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-write-emit.test.js.map +1 -0
  1457. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-write-timeline-learned-at.test.d.ts +2 -0
  1458. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-write-timeline-learned-at.test.d.ts.map +1 -0
  1459. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-write-timeline-learned-at.test.js +30 -0
  1460. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-write-timeline-learned-at.test.js.map +1 -0
  1461. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/profile-delete-emit.test.d.ts +2 -0
  1462. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/profile-delete-emit.test.d.ts.map +1 -0
  1463. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/profile-delete-emit.test.js +62 -0
  1464. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/profile-delete-emit.test.js.map +1 -0
  1465. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/profile-update-emit.test.d.ts +2 -0
  1466. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/profile-update-emit.test.d.ts.map +1 -0
  1467. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/profile-update-emit.test.js +76 -0
  1468. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/profile-update-emit.test.js.map +1 -0
  1469. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/profile-update-not-applicable.test.d.ts +2 -0
  1470. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/profile-update-not-applicable.test.d.ts.map +1 -0
  1471. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/profile-update-not-applicable.test.js +88 -0
  1472. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/profile-update-not-applicable.test.js.map +1 -0
  1473. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/profile-update-personfields-open.test.d.ts +2 -0
  1474. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/profile-update-personfields-open.test.d.ts.map +1 -0
  1475. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/profile-update-personfields-open.test.js +151 -0
  1476. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/profile-update-personfields-open.test.js.map +1 -0
  1477. package/payload/platform/plugins/memory/mcp/dist/tools/conversation-archive-derive-insights.d.ts +114 -0
  1478. package/payload/platform/plugins/memory/mcp/dist/tools/conversation-archive-derive-insights.d.ts.map +1 -0
  1479. package/payload/platform/plugins/memory/mcp/dist/tools/conversation-archive-derive-insights.js +415 -0
  1480. package/payload/platform/plugins/memory/mcp/dist/tools/conversation-archive-derive-insights.js.map +1 -0
  1481. package/payload/platform/plugins/memory/mcp/dist/tools/conversation-archive-enrich-rejection.d.ts +41 -0
  1482. package/payload/platform/plugins/memory/mcp/dist/tools/conversation-archive-enrich-rejection.d.ts.map +1 -0
  1483. package/payload/platform/plugins/memory/mcp/dist/tools/conversation-archive-enrich-rejection.js +124 -0
  1484. package/payload/platform/plugins/memory/mcp/dist/tools/conversation-archive-enrich-rejection.js.map +1 -0
  1485. package/payload/platform/plugins/memory/mcp/dist/tools/conversation-archive-list-chunks.d.ts +43 -0
  1486. package/payload/platform/plugins/memory/mcp/dist/tools/conversation-archive-list-chunks.d.ts.map +1 -0
  1487. package/payload/platform/plugins/memory/mcp/dist/tools/conversation-archive-list-chunks.js +96 -0
  1488. package/payload/platform/plugins/memory/mcp/dist/tools/conversation-archive-list-chunks.js.map +1 -0
  1489. package/payload/platform/plugins/memory/mcp/dist/tools/conversation-memory-expunge.d.ts +8 -0
  1490. package/payload/platform/plugins/memory/mcp/dist/tools/conversation-memory-expunge.d.ts.map +1 -0
  1491. package/payload/platform/plugins/memory/mcp/dist/tools/conversation-memory-expunge.js +15 -0
  1492. package/payload/platform/plugins/memory/mcp/dist/tools/conversation-memory-expunge.js.map +1 -0
  1493. package/payload/platform/plugins/memory/mcp/dist/tools/graph-prune-denylist-add.d.ts +7 -0
  1494. package/payload/platform/plugins/memory/mcp/dist/tools/graph-prune-denylist-add.d.ts.map +1 -0
  1495. package/payload/platform/plugins/memory/mcp/dist/tools/graph-prune-denylist-add.js +32 -0
  1496. package/payload/platform/plugins/memory/mcp/dist/tools/graph-prune-denylist-add.js.map +1 -0
  1497. package/payload/platform/plugins/memory/mcp/dist/tools/graph-prune-denylist-list.d.ts +7 -0
  1498. package/payload/platform/plugins/memory/mcp/dist/tools/graph-prune-denylist-list.d.ts.map +1 -0
  1499. package/payload/platform/plugins/memory/mcp/dist/tools/graph-prune-denylist-list.js +7 -0
  1500. package/payload/platform/plugins/memory/mcp/dist/tools/graph-prune-denylist-list.js.map +1 -0
  1501. package/payload/platform/plugins/memory/mcp/dist/tools/graph-prune-denylist-remove.d.ts +7 -0
  1502. package/payload/platform/plugins/memory/mcp/dist/tools/graph-prune-denylist-remove.d.ts.map +1 -0
  1503. package/payload/platform/plugins/memory/mcp/dist/tools/graph-prune-denylist-remove.js +31 -0
  1504. package/payload/platform/plugins/memory/mcp/dist/tools/graph-prune-denylist-remove.js.map +1 -0
  1505. package/payload/platform/plugins/memory/mcp/dist/tools/image-fetch.d.ts +15 -0
  1506. package/payload/platform/plugins/memory/mcp/dist/tools/image-fetch.d.ts.map +1 -0
  1507. package/payload/platform/plugins/memory/mcp/dist/tools/image-fetch.js +64 -0
  1508. package/payload/platform/plugins/memory/mcp/dist/tools/image-fetch.js.map +1 -0
  1509. package/payload/platform/plugins/memory/mcp/dist/tools/kd-classify.d.ts +11 -0
  1510. package/payload/platform/plugins/memory/mcp/dist/tools/kd-classify.d.ts.map +1 -0
  1511. package/payload/platform/plugins/memory/mcp/dist/tools/kd-classify.js +92 -0
  1512. package/payload/platform/plugins/memory/mcp/dist/tools/kd-classify.js.map +1 -0
  1513. package/payload/platform/plugins/memory/mcp/dist/tools/memory-archive-write.d.ts +202 -0
  1514. package/payload/platform/plugins/memory/mcp/dist/tools/memory-archive-write.d.ts.map +1 -0
  1515. package/payload/platform/plugins/memory/mcp/dist/tools/memory-archive-write.js +1084 -0
  1516. package/payload/platform/plugins/memory/mcp/dist/tools/memory-archive-write.js.map +1 -0
  1517. package/payload/platform/plugins/memory/mcp/dist/tools/memory-brain-capture-recent.d.ts +35 -0
  1518. package/payload/platform/plugins/memory/mcp/dist/tools/memory-brain-capture-recent.d.ts.map +1 -0
  1519. package/payload/platform/plugins/memory/mcp/dist/tools/memory-brain-capture-recent.js +80 -0
  1520. package/payload/platform/plugins/memory/mcp/dist/tools/memory-brain-capture-recent.js.map +1 -0
  1521. package/payload/platform/plugins/memory/mcp/dist/tools/memory-classify.d.ts +34 -0
  1522. package/payload/platform/plugins/memory/mcp/dist/tools/memory-classify.d.ts.map +1 -0
  1523. package/payload/platform/plugins/memory/mcp/dist/tools/memory-classify.js +62 -0
  1524. package/payload/platform/plugins/memory/mcp/dist/tools/memory-classify.js.map +1 -0
  1525. package/payload/platform/plugins/memory/mcp/dist/tools/memory-compiled-truth-history.d.ts +41 -0
  1526. package/payload/platform/plugins/memory/mcp/dist/tools/memory-compiled-truth-history.d.ts.map +1 -0
  1527. package/payload/platform/plugins/memory/mcp/dist/tools/memory-compiled-truth-history.js +73 -0
  1528. package/payload/platform/plugins/memory/mcp/dist/tools/memory-compiled-truth-history.js.map +1 -0
  1529. package/payload/platform/plugins/memory/mcp/dist/tools/memory-delete.d.ts +65 -0
  1530. package/payload/platform/plugins/memory/mcp/dist/tools/memory-delete.d.ts.map +1 -0
  1531. package/payload/platform/plugins/memory/mcp/dist/tools/memory-delete.js +151 -0
  1532. package/payload/platform/plugins/memory/mcp/dist/tools/memory-delete.js.map +1 -0
  1533. package/payload/platform/plugins/memory/mcp/dist/tools/memory-dream-run.d.ts +48 -0
  1534. package/payload/platform/plugins/memory/mcp/dist/tools/memory-dream-run.d.ts.map +1 -0
  1535. package/payload/platform/plugins/memory/mcp/dist/tools/memory-dream-run.js +197 -0
  1536. package/payload/platform/plugins/memory/mcp/dist/tools/memory-dream-run.js.map +1 -0
  1537. package/payload/platform/plugins/memory/mcp/dist/tools/memory-edge.d.ts +30 -0
  1538. package/payload/platform/plugins/memory/mcp/dist/tools/memory-edge.d.ts.map +1 -0
  1539. package/payload/platform/plugins/memory/mcp/dist/tools/memory-edge.js +75 -0
  1540. package/payload/platform/plugins/memory/mcp/dist/tools/memory-edge.js.map +1 -0
  1541. package/payload/platform/plugins/memory/mcp/dist/tools/memory-edit-attachment.d.ts +16 -0
  1542. package/payload/platform/plugins/memory/mcp/dist/tools/memory-edit-attachment.d.ts.map +1 -0
  1543. package/payload/platform/plugins/memory/mcp/dist/tools/memory-edit-attachment.js +95 -0
  1544. package/payload/platform/plugins/memory/mcp/dist/tools/memory-edit-attachment.js.map +1 -0
  1545. package/payload/platform/plugins/memory/mcp/dist/tools/memory-empty-trash.d.ts +50 -0
  1546. package/payload/platform/plugins/memory/mcp/dist/tools/memory-empty-trash.d.ts.map +1 -0
  1547. package/payload/platform/plugins/memory/mcp/dist/tools/memory-empty-trash.js +104 -0
  1548. package/payload/platform/plugins/memory/mcp/dist/tools/memory-empty-trash.js.map +1 -0
  1549. package/payload/platform/plugins/memory/mcp/dist/tools/memory-find-candidates.d.ts +58 -0
  1550. package/payload/platform/plugins/memory/mcp/dist/tools/memory-find-candidates.d.ts.map +1 -0
  1551. package/payload/platform/plugins/memory/mcp/dist/tools/memory-find-candidates.js +125 -0
  1552. package/payload/platform/plugins/memory/mcp/dist/tools/memory-find-candidates.js.map +1 -0
  1553. package/payload/platform/plugins/memory/mcp/dist/tools/memory-ingest-extract.d.ts +37 -0
  1554. package/payload/platform/plugins/memory/mcp/dist/tools/memory-ingest-extract.d.ts.map +1 -0
  1555. package/payload/platform/plugins/memory/mcp/dist/tools/memory-ingest-extract.js +97 -0
  1556. package/payload/platform/plugins/memory/mcp/dist/tools/memory-ingest-extract.js.map +1 -0
  1557. package/payload/platform/plugins/memory/mcp/dist/tools/memory-ingest-web.d.ts +32 -0
  1558. package/payload/platform/plugins/memory/mcp/dist/tools/memory-ingest-web.d.ts.map +1 -0
  1559. package/payload/platform/plugins/memory/mcp/dist/tools/memory-ingest-web.js +116 -0
  1560. package/payload/platform/plugins/memory/mcp/dist/tools/memory-ingest-web.js.map +1 -0
  1561. package/payload/platform/plugins/memory/mcp/dist/tools/memory-ingest.d.ts +194 -0
  1562. package/payload/platform/plugins/memory/mcp/dist/tools/memory-ingest.d.ts.map +1 -0
  1563. package/payload/platform/plugins/memory/mcp/dist/tools/memory-ingest.js +1303 -0
  1564. package/payload/platform/plugins/memory/mcp/dist/tools/memory-ingest.js.map +1 -0
  1565. package/payload/platform/plugins/memory/mcp/dist/tools/memory-list-attachments.d.ts +19 -0
  1566. package/payload/platform/plugins/memory/mcp/dist/tools/memory-list-attachments.d.ts.map +1 -0
  1567. package/payload/platform/plugins/memory/mcp/dist/tools/memory-list-attachments.js +125 -0
  1568. package/payload/platform/plugins/memory/mcp/dist/tools/memory-list-attachments.js.map +1 -0
  1569. package/payload/platform/plugins/memory/mcp/dist/tools/memory-lookup-by-name.d.ts +16 -0
  1570. package/payload/platform/plugins/memory/mcp/dist/tools/memory-lookup-by-name.d.ts.map +1 -0
  1571. package/payload/platform/plugins/memory/mcp/dist/tools/memory-lookup-by-name.js +68 -0
  1572. package/payload/platform/plugins/memory/mcp/dist/tools/memory-lookup-by-name.js.map +1 -0
  1573. package/payload/platform/plugins/memory/mcp/dist/tools/memory-node-exists.d.ts +28 -0
  1574. package/payload/platform/plugins/memory/mcp/dist/tools/memory-node-exists.d.ts.map +1 -0
  1575. package/payload/platform/plugins/memory/mcp/dist/tools/memory-node-exists.js +46 -0
  1576. package/payload/platform/plugins/memory/mcp/dist/tools/memory-node-exists.js.map +1 -0
  1577. package/payload/platform/plugins/memory/mcp/dist/tools/memory-rank.d.ts +61 -0
  1578. package/payload/platform/plugins/memory/mcp/dist/tools/memory-rank.d.ts.map +1 -0
  1579. package/payload/platform/plugins/memory/mcp/dist/tools/memory-rank.js +102 -0
  1580. package/payload/platform/plugins/memory/mcp/dist/tools/memory-rank.js.map +1 -0
  1581. package/payload/platform/plugins/memory/mcp/dist/tools/memory-read-attachment.d.ts +12 -0
  1582. package/payload/platform/plugins/memory/mcp/dist/tools/memory-read-attachment.d.ts.map +1 -0
  1583. package/payload/platform/plugins/memory/mcp/dist/tools/memory-read-attachment.js +100 -0
  1584. package/payload/platform/plugins/memory/mcp/dist/tools/memory-read-attachment.js.map +1 -0
  1585. package/payload/platform/plugins/memory/mcp/dist/tools/memory-reindex.d.ts +9 -0
  1586. package/payload/platform/plugins/memory/mcp/dist/tools/memory-reindex.d.ts.map +1 -0
  1587. package/payload/platform/plugins/memory/mcp/dist/tools/memory-reindex.js +127 -0
  1588. package/payload/platform/plugins/memory/mcp/dist/tools/memory-reindex.js.map +1 -0
  1589. package/payload/platform/plugins/memory/mcp/dist/tools/memory-rename-attachment.d.ts +13 -0
  1590. package/payload/platform/plugins/memory/mcp/dist/tools/memory-rename-attachment.d.ts.map +1 -0
  1591. package/payload/platform/plugins/memory/mcp/dist/tools/memory-rename-attachment.js +67 -0
  1592. package/payload/platform/plugins/memory/mcp/dist/tools/memory-rename-attachment.js.map +1 -0
  1593. package/payload/platform/plugins/memory/mcp/dist/tools/memory-report-list.d.ts +28 -0
  1594. package/payload/platform/plugins/memory/mcp/dist/tools/memory-report-list.d.ts.map +1 -0
  1595. package/payload/platform/plugins/memory/mcp/dist/tools/memory-report-list.js +64 -0
  1596. package/payload/platform/plugins/memory/mcp/dist/tools/memory-report-list.js.map +1 -0
  1597. package/payload/platform/plugins/memory/mcp/dist/tools/memory-report-read-latest.d.ts +24 -0
  1598. package/payload/platform/plugins/memory/mcp/dist/tools/memory-report-read-latest.d.ts.map +1 -0
  1599. package/payload/platform/plugins/memory/mcp/dist/tools/memory-report-read-latest.js +49 -0
  1600. package/payload/platform/plugins/memory/mcp/dist/tools/memory-report-read-latest.js.map +1 -0
  1601. package/payload/platform/plugins/memory/mcp/dist/tools/memory-report-write.d.ts +34 -0
  1602. package/payload/platform/plugins/memory/mcp/dist/tools/memory-report-write.d.ts.map +1 -0
  1603. package/payload/platform/plugins/memory/mcp/dist/tools/memory-report-write.js +99 -0
  1604. package/payload/platform/plugins/memory/mcp/dist/tools/memory-report-write.js.map +1 -0
  1605. package/payload/platform/plugins/memory/mcp/dist/tools/memory-restore.d.ts +24 -0
  1606. package/payload/platform/plugins/memory/mcp/dist/tools/memory-restore.d.ts.map +1 -0
  1607. package/payload/platform/plugins/memory/mcp/dist/tools/memory-restore.js +47 -0
  1608. package/payload/platform/plugins/memory/mcp/dist/tools/memory-restore.js.map +1 -0
  1609. package/payload/platform/plugins/memory/mcp/dist/tools/memory-review-queue.d.ts +29 -0
  1610. package/payload/platform/plugins/memory/mcp/dist/tools/memory-review-queue.d.ts.map +1 -0
  1611. package/payload/platform/plugins/memory/mcp/dist/tools/memory-review-queue.js +67 -0
  1612. package/payload/platform/plugins/memory/mcp/dist/tools/memory-review-queue.js.map +1 -0
  1613. package/payload/platform/plugins/memory/mcp/dist/tools/memory-search.d.ts +7 -0
  1614. package/payload/platform/plugins/memory/mcp/dist/tools/memory-search.d.ts.map +1 -0
  1615. package/payload/platform/plugins/memory/mcp/dist/tools/memory-search.js +184 -0
  1616. package/payload/platform/plugins/memory/mcp/dist/tools/memory-search.js.map +1 -0
  1617. package/payload/platform/plugins/memory/mcp/dist/tools/memory-signals-recent.d.ts +35 -0
  1618. package/payload/platform/plugins/memory/mcp/dist/tools/memory-signals-recent.d.ts.map +1 -0
  1619. package/payload/platform/plugins/memory/mcp/dist/tools/memory-signals-recent.js +73 -0
  1620. package/payload/platform/plugins/memory/mcp/dist/tools/memory-signals-recent.js.map +1 -0
  1621. package/payload/platform/plugins/memory/mcp/dist/tools/memory-typed-edge-pass.d.ts +29 -0
  1622. package/payload/platform/plugins/memory/mcp/dist/tools/memory-typed-edge-pass.d.ts.map +1 -0
  1623. package/payload/platform/plugins/memory/mcp/dist/tools/memory-typed-edge-pass.js +22 -0
  1624. package/payload/platform/plugins/memory/mcp/dist/tools/memory-typed-edge-pass.js.map +1 -0
  1625. package/payload/platform/plugins/memory/mcp/dist/tools/memory-update-by-name.d.ts +15 -0
  1626. package/payload/platform/plugins/memory/mcp/dist/tools/memory-update-by-name.d.ts.map +1 -0
  1627. package/payload/platform/plugins/memory/mcp/dist/tools/memory-update-by-name.js +45 -0
  1628. package/payload/platform/plugins/memory/mcp/dist/tools/memory-update-by-name.js.map +1 -0
  1629. package/payload/platform/plugins/memory/mcp/dist/tools/memory-update.d.ts +16 -0
  1630. package/payload/platform/plugins/memory/mcp/dist/tools/memory-update.d.ts.map +1 -0
  1631. package/payload/platform/plugins/memory/mcp/dist/tools/memory-update.js +194 -0
  1632. package/payload/platform/plugins/memory/mcp/dist/tools/memory-update.js.map +1 -0
  1633. package/payload/platform/plugins/memory/mcp/dist/tools/memory-write.d.ts +47 -0
  1634. package/payload/platform/plugins/memory/mcp/dist/tools/memory-write.d.ts.map +1 -0
  1635. package/payload/platform/plugins/memory/mcp/dist/tools/memory-write.js +397 -0
  1636. package/payload/platform/plugins/memory/mcp/dist/tools/memory-write.js.map +1 -0
  1637. package/payload/platform/plugins/memory/mcp/dist/tools/obsidian-vault-import.d.ts +127 -0
  1638. package/payload/platform/plugins/memory/mcp/dist/tools/obsidian-vault-import.d.ts.map +1 -0
  1639. package/payload/platform/plugins/memory/mcp/dist/tools/obsidian-vault-import.js +477 -0
  1640. package/payload/platform/plugins/memory/mcp/dist/tools/obsidian-vault-import.js.map +1 -0
  1641. package/payload/platform/plugins/memory/mcp/dist/tools/profile-delete.d.ts +24 -0
  1642. package/payload/platform/plugins/memory/mcp/dist/tools/profile-delete.d.ts.map +1 -0
  1643. package/payload/platform/plugins/memory/mcp/dist/tools/profile-delete.js +35 -0
  1644. package/payload/platform/plugins/memory/mcp/dist/tools/profile-delete.js.map +1 -0
  1645. package/payload/platform/plugins/memory/mcp/dist/tools/profile-read.d.ts +46 -0
  1646. package/payload/platform/plugins/memory/mcp/dist/tools/profile-read.d.ts.map +1 -0
  1647. package/payload/platform/plugins/memory/mcp/dist/tools/profile-read.js +423 -0
  1648. package/payload/platform/plugins/memory/mcp/dist/tools/profile-read.js.map +1 -0
  1649. package/payload/platform/plugins/memory/mcp/dist/tools/profile-update.d.ts +65 -0
  1650. package/payload/platform/plugins/memory/mcp/dist/tools/profile-update.d.ts.map +1 -0
  1651. package/payload/platform/plugins/memory/mcp/dist/tools/profile-update.js +395 -0
  1652. package/payload/platform/plugins/memory/mcp/dist/tools/profile-update.js.map +1 -0
  1653. package/payload/platform/plugins/memory/mcp/dist/tools/session-retrospective-skip-rate.d.ts +30 -0
  1654. package/payload/platform/plugins/memory/mcp/dist/tools/session-retrospective-skip-rate.d.ts.map +1 -0
  1655. package/payload/platform/plugins/memory/mcp/dist/tools/session-retrospective-skip-rate.js +130 -0
  1656. package/payload/platform/plugins/memory/mcp/dist/tools/session-retrospective-skip-rate.js.map +1 -0
  1657. package/payload/platform/plugins/memory/mcp/package.json +23 -0
  1658. package/payload/platform/plugins/memory/mcp/scripts/boot-smoke.sh +69 -0
  1659. package/payload/platform/plugins/memory/mcp/scripts/generate-edge-docs.ts +75 -0
  1660. package/payload/platform/plugins/memory/mcp/scripts/graph/accept.sh +217 -0
  1661. package/payload/platform/plugins/memory/mcp/scripts/graph/fixture.cypher +59 -0
  1662. package/payload/platform/plugins/memory/mcp/vitest.config.ts +53 -0
  1663. package/payload/platform/plugins/memory/references/graph-primitives.md +394 -0
  1664. package/payload/platform/plugins/memory/references/schema-base.md +338 -0
  1665. package/payload/platform/plugins/memory/references/schema-construction.md +96 -0
  1666. package/payload/platform/plugins/memory/references/schema-creator.md +35 -0
  1667. package/payload/platform/plugins/memory/references/schema-estate-agent.md +154 -0
  1668. package/payload/platform/plugins/memory/references/schema-food-beverage.md +32 -0
  1669. package/payload/platform/plugins/memory/references/schema-hospitality.md +31 -0
  1670. package/payload/platform/plugins/memory/references/schema-knowledge-work.md +80 -0
  1671. package/payload/platform/plugins/memory/references/schema-logistics.md +30 -0
  1672. package/payload/platform/plugins/memory/references/schema-professional-services.md +33 -0
  1673. package/payload/platform/plugins/memory/references/schema-retail.md +33 -0
  1674. package/payload/platform/plugins/memory/references/schema-trades.md +36 -0
  1675. package/payload/platform/plugins/memory/references/transcript-formats/circleback.md +49 -0
  1676. package/payload/platform/plugins/memory/references/transcript-formats/granola.md +50 -0
  1677. package/payload/platform/plugins/memory/references/transcript-formats/otter.md +50 -0
  1678. package/payload/platform/plugins/memory/skills/archive-crawler/SKILL.md +69 -0
  1679. package/payload/platform/plugins/memory/skills/challenge/SKILL.md +54 -0
  1680. package/payload/platform/plugins/memory/skills/concept-synthesis/SKILL.md +81 -0
  1681. package/payload/platform/plugins/memory/skills/connect/SKILL.md +58 -0
  1682. package/payload/platform/plugins/memory/skills/conversation-archive/SKILL.md +193 -0
  1683. package/payload/platform/plugins/memory/skills/conversation-archive-enrich/SKILL.md +207 -0
  1684. package/payload/platform/plugins/memory/skills/conversation-archive-mcp/SKILL.md +170 -0
  1685. package/payload/platform/plugins/memory/skills/conversational-memory/SKILL.md +115 -0
  1686. package/payload/platform/plugins/memory/skills/document-ingest/SKILL.md +331 -0
  1687. package/payload/platform/plugins/memory/skills/emerge/SKILL.md +89 -0
  1688. package/payload/platform/plugins/notion-import/.claude-plugin/plugin.json +8 -0
  1689. package/payload/platform/plugins/notion-import/PLUGIN.md +27 -0
  1690. package/payload/platform/plugins/notion-import/skills/notion-import/SKILL.md +114 -0
  1691. package/payload/platform/plugins/notion-import/skills/notion-import/references/attachments.md +55 -0
  1692. package/payload/platform/plugins/notion-import/skills/notion-import/references/databases.md +83 -0
  1693. package/payload/platform/plugins/notion-import/skills/notion-import/references/page-tree.md +61 -0
  1694. package/payload/platform/plugins/notion-import/skills/notion-import/references/workspace-export.md +41 -0
  1695. package/payload/platform/plugins/obsidian-import/.claude-plugin/plugin.json +8 -0
  1696. package/payload/platform/plugins/obsidian-import/PLUGIN.md +39 -0
  1697. package/payload/platform/plugins/obsidian-import/skills/obsidian-import/SKILL.md +92 -0
  1698. package/payload/platform/plugins/obsidian-import/skills/obsidian-import/references/attachments.md +80 -0
  1699. package/payload/platform/plugins/obsidian-import/skills/obsidian-import/references/daily-notes.md +31 -0
  1700. package/payload/platform/plugins/obsidian-import/skills/obsidian-import/references/vault-structure.md +46 -0
  1701. package/payload/platform/plugins/obsidian-import/skills/obsidian-import/references/wikilinks.md +70 -0
  1702. package/payload/platform/plugins/outlook/.claude-plugin/plugin.json +21 -0
  1703. package/payload/platform/plugins/outlook/PLUGIN.md +74 -0
  1704. package/payload/platform/plugins/outlook/lib/mcp-spawn-tee/index.js +193 -0
  1705. package/payload/platform/plugins/outlook/lib/mcp-spawn-tee/package.json +3 -0
  1706. package/payload/platform/plugins/outlook/mcp/dist/__tests__/graph-client.test.d.ts +2 -0
  1707. package/payload/platform/plugins/outlook/mcp/dist/__tests__/graph-client.test.d.ts.map +1 -0
  1708. package/payload/platform/plugins/outlook/mcp/dist/__tests__/graph-client.test.js +94 -0
  1709. package/payload/platform/plugins/outlook/mcp/dist/__tests__/graph-client.test.js.map +1 -0
  1710. package/payload/platform/plugins/outlook/mcp/dist/__tests__/log.test.d.ts +2 -0
  1711. package/payload/platform/plugins/outlook/mcp/dist/__tests__/log.test.d.ts.map +1 -0
  1712. package/payload/platform/plugins/outlook/mcp/dist/__tests__/log.test.js +31 -0
  1713. package/payload/platform/plugins/outlook/mcp/dist/__tests__/log.test.js.map +1 -0
  1714. package/payload/platform/plugins/outlook/mcp/dist/__tests__/pkce-flow.test.d.ts +2 -0
  1715. package/payload/platform/plugins/outlook/mcp/dist/__tests__/pkce-flow.test.d.ts.map +1 -0
  1716. package/payload/platform/plugins/outlook/mcp/dist/__tests__/pkce-flow.test.js +213 -0
  1717. package/payload/platform/plugins/outlook/mcp/dist/__tests__/pkce-flow.test.js.map +1 -0
  1718. package/payload/platform/plugins/outlook/mcp/dist/__tests__/token-store.test.d.ts +2 -0
  1719. package/payload/platform/plugins/outlook/mcp/dist/__tests__/token-store.test.d.ts.map +1 -0
  1720. package/payload/platform/plugins/outlook/mcp/dist/__tests__/token-store.test.js +130 -0
  1721. package/payload/platform/plugins/outlook/mcp/dist/__tests__/token-store.test.js.map +1 -0
  1722. package/payload/platform/plugins/outlook/mcp/dist/auth/pkce-flow.d.ts +65 -0
  1723. package/payload/platform/plugins/outlook/mcp/dist/auth/pkce-flow.d.ts.map +1 -0
  1724. package/payload/platform/plugins/outlook/mcp/dist/auth/pkce-flow.js +261 -0
  1725. package/payload/platform/plugins/outlook/mcp/dist/auth/pkce-flow.js.map +1 -0
  1726. package/payload/platform/plugins/outlook/mcp/dist/auth/token-store.d.ts +61 -0
  1727. package/payload/platform/plugins/outlook/mcp/dist/auth/token-store.d.ts.map +1 -0
  1728. package/payload/platform/plugins/outlook/mcp/dist/auth/token-store.js +170 -0
  1729. package/payload/platform/plugins/outlook/mcp/dist/auth/token-store.js.map +1 -0
  1730. package/payload/platform/plugins/outlook/mcp/dist/index.d.ts +18 -0
  1731. package/payload/platform/plugins/outlook/mcp/dist/index.d.ts.map +1 -0
  1732. package/payload/platform/plugins/outlook/mcp/dist/index.js +184 -0
  1733. package/payload/platform/plugins/outlook/mcp/dist/index.js.map +1 -0
  1734. package/payload/platform/plugins/outlook/mcp/dist/lib/graph-client.d.ts +60 -0
  1735. package/payload/platform/plugins/outlook/mcp/dist/lib/graph-client.d.ts.map +1 -0
  1736. package/payload/platform/plugins/outlook/mcp/dist/lib/graph-client.js +189 -0
  1737. package/payload/platform/plugins/outlook/mcp/dist/lib/graph-client.js.map +1 -0
  1738. package/payload/platform/plugins/outlook/mcp/dist/lib/log.d.ts +23 -0
  1739. package/payload/platform/plugins/outlook/mcp/dist/lib/log.d.ts.map +1 -0
  1740. package/payload/platform/plugins/outlook/mcp/dist/lib/log.js +53 -0
  1741. package/payload/platform/plugins/outlook/mcp/dist/lib/log.js.map +1 -0
  1742. package/payload/platform/plugins/outlook/mcp/dist/tools/account-register.d.ts +26 -0
  1743. package/payload/platform/plugins/outlook/mcp/dist/tools/account-register.d.ts.map +1 -0
  1744. package/payload/platform/plugins/outlook/mcp/dist/tools/account-register.js +50 -0
  1745. package/payload/platform/plugins/outlook/mcp/dist/tools/account-register.js.map +1 -0
  1746. package/payload/platform/plugins/outlook/mcp/dist/tools/calendar-event.d.ts +12 -0
  1747. package/payload/platform/plugins/outlook/mcp/dist/tools/calendar-event.d.ts.map +1 -0
  1748. package/payload/platform/plugins/outlook/mcp/dist/tools/calendar-event.js +32 -0
  1749. package/payload/platform/plugins/outlook/mcp/dist/tools/calendar-event.js.map +1 -0
  1750. package/payload/platform/plugins/outlook/mcp/dist/tools/calendar-list.d.ts +59 -0
  1751. package/payload/platform/plugins/outlook/mcp/dist/tools/calendar-list.d.ts.map +1 -0
  1752. package/payload/platform/plugins/outlook/mcp/dist/tools/calendar-list.js +54 -0
  1753. package/payload/platform/plugins/outlook/mcp/dist/tools/calendar-list.js.map +1 -0
  1754. package/payload/platform/plugins/outlook/mcp/dist/tools/contacts-list.d.ts +14 -0
  1755. package/payload/platform/plugins/outlook/mcp/dist/tools/contacts-list.d.ts.map +1 -0
  1756. package/payload/platform/plugins/outlook/mcp/dist/tools/contacts-list.js +45 -0
  1757. package/payload/platform/plugins/outlook/mcp/dist/tools/contacts-list.js.map +1 -0
  1758. package/payload/platform/plugins/outlook/mcp/dist/tools/mail-list.d.ts +15 -0
  1759. package/payload/platform/plugins/outlook/mcp/dist/tools/mail-list.d.ts.map +1 -0
  1760. package/payload/platform/plugins/outlook/mcp/dist/tools/mail-list.js +48 -0
  1761. package/payload/platform/plugins/outlook/mcp/dist/tools/mail-list.js.map +1 -0
  1762. package/payload/platform/plugins/outlook/mcp/dist/tools/mail-search.d.ts +8 -0
  1763. package/payload/platform/plugins/outlook/mcp/dist/tools/mail-search.d.ts.map +1 -0
  1764. package/payload/platform/plugins/outlook/mcp/dist/tools/mail-search.js +49 -0
  1765. package/payload/platform/plugins/outlook/mcp/dist/tools/mail-search.js.map +1 -0
  1766. package/payload/platform/plugins/outlook/mcp/dist/tools/mailbox-info.d.ts +19 -0
  1767. package/payload/platform/plugins/outlook/mcp/dist/tools/mailbox-info.d.ts.map +1 -0
  1768. package/payload/platform/plugins/outlook/mcp/dist/tools/mailbox-info.js +58 -0
  1769. package/payload/platform/plugins/outlook/mcp/dist/tools/mailbox-info.js.map +1 -0
  1770. package/payload/platform/plugins/outlook/mcp/package.json +20 -0
  1771. package/payload/platform/plugins/outlook/mcp/scripts/verify-doc-impl.sh +109 -0
  1772. package/payload/platform/plugins/outlook/references/auth.md +118 -0
  1773. package/payload/platform/plugins/outlook/references/graph-surfaces.md +114 -0
  1774. package/payload/platform/plugins/outlook/skills/outlook/SKILL.md +67 -0
  1775. package/payload/platform/plugins/projects/.claude-plugin/plugin.json +8 -0
  1776. package/payload/platform/plugins/projects/PLUGIN.md +101 -0
  1777. package/payload/platform/plugins/projects/references/investigation.md +63 -0
  1778. package/payload/platform/plugins/projects/references/meeting-to-tasks.md +34 -0
  1779. package/payload/platform/plugins/projects/references/prioritization.md +43 -0
  1780. package/payload/platform/plugins/projects/references/retrospective.md +71 -0
  1781. package/payload/platform/plugins/projects/references/review.md +51 -0
  1782. package/payload/platform/plugins/projects/references/risk-premortem.md +34 -0
  1783. package/payload/platform/plugins/projects/references/sprint.md +172 -0
  1784. package/payload/platform/plugins/projects/references/stakeholder-map.md +43 -0
  1785. package/payload/platform/plugins/prompt-optimiser/.claude-plugin/plugin.json +8 -0
  1786. package/payload/platform/plugins/prompt-optimiser/PLUGIN.md +14 -0
  1787. package/payload/platform/plugins/prompt-optimiser/skills/prompt-optimiser/SKILL.md +321 -0
  1788. package/payload/platform/plugins/prompt-optimiser/skills/prompt-optimiser/__tests__/restatement-ladder.test.sh +21 -0
  1789. package/payload/platform/plugins/quickbooks/.claude-plugin/plugin.json +21 -0
  1790. package/payload/platform/plugins/quickbooks/PLUGIN.md +91 -0
  1791. package/payload/platform/plugins/quickbooks/lib/mcp-spawn-tee/index.js +193 -0
  1792. package/payload/platform/plugins/quickbooks/lib/mcp-spawn-tee/package.json +3 -0
  1793. package/payload/platform/plugins/quickbooks/mcp/dist/index.d.ts +2 -0
  1794. package/payload/platform/plugins/quickbooks/mcp/dist/index.d.ts.map +1 -0
  1795. package/payload/platform/plugins/quickbooks/mcp/dist/index.js +219 -0
  1796. package/payload/platform/plugins/quickbooks/mcp/dist/index.js.map +1 -0
  1797. package/payload/platform/plugins/quickbooks/mcp/dist/lib/oauth.d.ts +37 -0
  1798. package/payload/platform/plugins/quickbooks/mcp/dist/lib/oauth.d.ts.map +1 -0
  1799. package/payload/platform/plugins/quickbooks/mcp/dist/lib/oauth.js +75 -0
  1800. package/payload/platform/plugins/quickbooks/mcp/dist/lib/oauth.js.map +1 -0
  1801. package/payload/platform/plugins/quickbooks/mcp/dist/lib/qbo-client.d.ts +39 -0
  1802. package/payload/platform/plugins/quickbooks/mcp/dist/lib/qbo-client.d.ts.map +1 -0
  1803. package/payload/platform/plugins/quickbooks/mcp/dist/lib/qbo-client.js +178 -0
  1804. package/payload/platform/plugins/quickbooks/mcp/dist/lib/qbo-client.js.map +1 -0
  1805. package/payload/platform/plugins/quickbooks/mcp/dist/lib/secrets.d.ts +36 -0
  1806. package/payload/platform/plugins/quickbooks/mcp/dist/lib/secrets.d.ts.map +1 -0
  1807. package/payload/platform/plugins/quickbooks/mcp/dist/lib/secrets.js +107 -0
  1808. package/payload/platform/plugins/quickbooks/mcp/dist/lib/secrets.js.map +1 -0
  1809. package/payload/platform/plugins/quickbooks/mcp/package.json +19 -0
  1810. package/payload/platform/plugins/quickbooks/skills/quickbooks/SKILL.md +37 -0
  1811. package/payload/platform/plugins/replicate/.claude-plugin/plugin.json +21 -0
  1812. package/payload/platform/plugins/replicate/PLUGIN.md +49 -0
  1813. package/payload/platform/plugins/replicate/lib/mcp-spawn-tee/index.js +193 -0
  1814. package/payload/platform/plugins/replicate/lib/mcp-spawn-tee/package.json +3 -0
  1815. package/payload/platform/plugins/replicate/mcp/dist/index.d.ts +2 -0
  1816. package/payload/platform/plugins/replicate/mcp/dist/index.d.ts.map +1 -0
  1817. package/payload/platform/plugins/replicate/mcp/dist/index.js +126 -0
  1818. package/payload/platform/plugins/replicate/mcp/dist/index.js.map +1 -0
  1819. package/payload/platform/plugins/replicate/mcp/dist/lib/replicate-key.d.ts +15 -0
  1820. package/payload/platform/plugins/replicate/mcp/dist/lib/replicate-key.d.ts.map +1 -0
  1821. package/payload/platform/plugins/replicate/mcp/dist/lib/replicate-key.js +73 -0
  1822. package/payload/platform/plugins/replicate/mcp/dist/lib/replicate-key.js.map +1 -0
  1823. package/payload/platform/plugins/replicate/mcp/dist/tools/image-generate.d.ts +14 -0
  1824. package/payload/platform/plugins/replicate/mcp/dist/tools/image-generate.d.ts.map +1 -0
  1825. package/payload/platform/plugins/replicate/mcp/dist/tools/image-generate.js +201 -0
  1826. package/payload/platform/plugins/replicate/mcp/dist/tools/image-generate.js.map +1 -0
  1827. package/payload/platform/plugins/replicate/mcp/package.json +21 -0
  1828. package/payload/platform/plugins/sales/.claude-plugin/plugin.json +8 -0
  1829. package/payload/platform/plugins/sales/PLUGIN.md +106 -0
  1830. package/payload/platform/plugins/sales/references/close-tracking.md +69 -0
  1831. package/payload/platform/plugins/sales/references/comparisons.md +99 -0
  1832. package/payload/platform/plugins/sales/references/competitive-positioning.md +51 -0
  1833. package/payload/platform/plugins/sales/references/faq.md +73 -0
  1834. package/payload/platform/plugins/sales/references/objection-handling.md +157 -0
  1835. package/payload/platform/plugins/sales/references/pricing.md +101 -0
  1836. package/payload/platform/plugins/scheduling/.claude-plugin/plugin.json +21 -0
  1837. package/payload/platform/plugins/scheduling/PLUGIN.md +153 -0
  1838. package/payload/platform/plugins/scheduling/lib/mcp-spawn-tee/index.js +193 -0
  1839. package/payload/platform/plugins/scheduling/lib/mcp-spawn-tee/package.json +3 -0
  1840. package/payload/platform/plugins/scheduling/mcp/dist/__tests__/time-resolve-description.test.d.ts +2 -0
  1841. package/payload/platform/plugins/scheduling/mcp/dist/__tests__/time-resolve-description.test.d.ts.map +1 -0
  1842. package/payload/platform/plugins/scheduling/mcp/dist/__tests__/time-resolve-description.test.js +16 -0
  1843. package/payload/platform/plugins/scheduling/mcp/dist/__tests__/time-resolve-description.test.js.map +1 -0
  1844. package/payload/platform/plugins/scheduling/mcp/dist/index.d.ts +2 -0
  1845. package/payload/platform/plugins/scheduling/mcp/dist/index.d.ts.map +1 -0
  1846. package/payload/platform/plugins/scheduling/mcp/dist/index.js +440 -0
  1847. package/payload/platform/plugins/scheduling/mcp/dist/index.js.map +1 -0
  1848. package/payload/platform/plugins/scheduling/mcp/dist/lib/__tests__/getUserTimezone.test.d.ts +2 -0
  1849. package/payload/platform/plugins/scheduling/mcp/dist/lib/__tests__/getUserTimezone.test.d.ts.map +1 -0
  1850. package/payload/platform/plugins/scheduling/mcp/dist/lib/__tests__/getUserTimezone.test.js +119 -0
  1851. package/payload/platform/plugins/scheduling/mcp/dist/lib/__tests__/getUserTimezone.test.js.map +1 -0
  1852. package/payload/platform/plugins/scheduling/mcp/dist/lib/embedding.d.ts +2 -0
  1853. package/payload/platform/plugins/scheduling/mcp/dist/lib/embedding.d.ts.map +1 -0
  1854. package/payload/platform/plugins/scheduling/mcp/dist/lib/embedding.js +19 -0
  1855. package/payload/platform/plugins/scheduling/mcp/dist/lib/embedding.js.map +1 -0
  1856. package/payload/platform/plugins/scheduling/mcp/dist/lib/ics-graph-ingest.d.ts +80 -0
  1857. package/payload/platform/plugins/scheduling/mcp/dist/lib/ics-graph-ingest.d.ts.map +1 -0
  1858. package/payload/platform/plugins/scheduling/mcp/dist/lib/ics-graph-ingest.js +410 -0
  1859. package/payload/platform/plugins/scheduling/mcp/dist/lib/ics-graph-ingest.js.map +1 -0
  1860. package/payload/platform/plugins/scheduling/mcp/dist/lib/ics.d.ts +63 -0
  1861. package/payload/platform/plugins/scheduling/mcp/dist/lib/ics.d.ts.map +1 -0
  1862. package/payload/platform/plugins/scheduling/mcp/dist/lib/ics.js +471 -0
  1863. package/payload/platform/plugins/scheduling/mcp/dist/lib/ics.js.map +1 -0
  1864. package/payload/platform/plugins/scheduling/mcp/dist/lib/neo4j.d.ts +30 -0
  1865. package/payload/platform/plugins/scheduling/mcp/dist/lib/neo4j.d.ts.map +1 -0
  1866. package/payload/platform/plugins/scheduling/mcp/dist/lib/neo4j.js +89 -0
  1867. package/payload/platform/plugins/scheduling/mcp/dist/lib/neo4j.js.map +1 -0
  1868. package/payload/platform/plugins/scheduling/mcp/dist/lib/time-format.d.ts +48 -0
  1869. package/payload/platform/plugins/scheduling/mcp/dist/lib/time-format.d.ts.map +1 -0
  1870. package/payload/platform/plugins/scheduling/mcp/dist/lib/time-format.js +140 -0
  1871. package/payload/platform/plugins/scheduling/mcp/dist/lib/time-format.js.map +1 -0
  1872. package/payload/platform/plugins/scheduling/mcp/dist/scripts/check-due-events.d.ts +24 -0
  1873. package/payload/platform/plugins/scheduling/mcp/dist/scripts/check-due-events.d.ts.map +1 -0
  1874. package/payload/platform/plugins/scheduling/mcp/dist/scripts/check-due-events.js +572 -0
  1875. package/payload/platform/plugins/scheduling/mcp/dist/scripts/check-due-events.js.map +1 -0
  1876. package/payload/platform/plugins/scheduling/mcp/dist/tools/schedule-archive-ics.d.ts +20 -0
  1877. package/payload/platform/plugins/scheduling/mcp/dist/tools/schedule-archive-ics.d.ts.map +1 -0
  1878. package/payload/platform/plugins/scheduling/mcp/dist/tools/schedule-archive-ics.js +63 -0
  1879. package/payload/platform/plugins/scheduling/mcp/dist/tools/schedule-archive-ics.js.map +1 -0
  1880. package/payload/platform/plugins/scheduling/mcp/dist/tools/schedule-cancel.d.ts +7 -0
  1881. package/payload/platform/plugins/scheduling/mcp/dist/tools/schedule-cancel.d.ts.map +1 -0
  1882. package/payload/platform/plugins/scheduling/mcp/dist/tools/schedule-cancel.js +23 -0
  1883. package/payload/platform/plugins/scheduling/mcp/dist/tools/schedule-cancel.js.map +1 -0
  1884. package/payload/platform/plugins/scheduling/mcp/dist/tools/schedule-event.d.ts +25 -0
  1885. package/payload/platform/plugins/scheduling/mcp/dist/tools/schedule-event.d.ts.map +1 -0
  1886. package/payload/platform/plugins/scheduling/mcp/dist/tools/schedule-event.js +121 -0
  1887. package/payload/platform/plugins/scheduling/mcp/dist/tools/schedule-event.js.map +1 -0
  1888. package/payload/platform/plugins/scheduling/mcp/dist/tools/schedule-export-ics.d.ts +9 -0
  1889. package/payload/platform/plugins/scheduling/mcp/dist/tools/schedule-export-ics.d.ts.map +1 -0
  1890. package/payload/platform/plugins/scheduling/mcp/dist/tools/schedule-export-ics.js +77 -0
  1891. package/payload/platform/plugins/scheduling/mcp/dist/tools/schedule-export-ics.js.map +1 -0
  1892. package/payload/platform/plugins/scheduling/mcp/dist/tools/schedule-get.d.ts +25 -0
  1893. package/payload/platform/plugins/scheduling/mcp/dist/tools/schedule-get.d.ts.map +1 -0
  1894. package/payload/platform/plugins/scheduling/mcp/dist/tools/schedule-get.js +53 -0
  1895. package/payload/platform/plugins/scheduling/mcp/dist/tools/schedule-get.js.map +1 -0
  1896. package/payload/platform/plugins/scheduling/mcp/dist/tools/schedule-import-ics.d.ts +8 -0
  1897. package/payload/platform/plugins/scheduling/mcp/dist/tools/schedule-import-ics.d.ts.map +1 -0
  1898. package/payload/platform/plugins/scheduling/mcp/dist/tools/schedule-import-ics.js +48 -0
  1899. package/payload/platform/plugins/scheduling/mcp/dist/tools/schedule-import-ics.js.map +1 -0
  1900. package/payload/platform/plugins/scheduling/mcp/dist/tools/schedule-list.d.ts +20 -0
  1901. package/payload/platform/plugins/scheduling/mcp/dist/tools/schedule-list.d.ts.map +1 -0
  1902. package/payload/platform/plugins/scheduling/mcp/dist/tools/schedule-list.js +76 -0
  1903. package/payload/platform/plugins/scheduling/mcp/dist/tools/schedule-list.js.map +1 -0
  1904. package/payload/platform/plugins/scheduling/mcp/dist/tools/schedule-update.d.ts +18 -0
  1905. package/payload/platform/plugins/scheduling/mcp/dist/tools/schedule-update.d.ts.map +1 -0
  1906. package/payload/platform/plugins/scheduling/mcp/dist/tools/schedule-update.js +167 -0
  1907. package/payload/platform/plugins/scheduling/mcp/dist/tools/schedule-update.js.map +1 -0
  1908. package/payload/platform/plugins/scheduling/mcp/package.json +23 -0
  1909. package/payload/platform/plugins/scheduling/mcp/vitest.config.ts +9 -0
  1910. package/payload/platform/plugins/scheduling/skills/briefing/SKILL.md +88 -0
  1911. package/payload/platform/plugins/scheduling/skills/daily-prep/SKILL.md +63 -0
  1912. package/payload/platform/plugins/slides/.claude-plugin/plugin.json +8 -0
  1913. package/payload/platform/plugins/slides/LICENSE +21 -0
  1914. package/payload/platform/plugins/slides/PLUGIN.md +18 -0
  1915. package/payload/platform/plugins/slides/PROVENANCE.md +40 -0
  1916. package/payload/platform/plugins/slides/commands/add-slide.md +29 -0
  1917. package/payload/platform/plugins/slides/commands/slides-claus.md +39 -0
  1918. package/payload/platform/plugins/slides/commands/slides-new-component.md +39 -0
  1919. package/payload/platform/plugins/slides/commands/slides-outline.md +43 -0
  1920. package/payload/platform/plugins/slides/commands/slides-review.md +52 -0
  1921. package/payload/platform/plugins/slides/commands/slides-theme.md +64 -0
  1922. package/payload/platform/plugins/slides/commands/slides.md +59 -0
  1923. package/payload/platform/plugins/slides/skills/deck-system/REFERENCE.md +581 -0
  1924. package/payload/platform/plugins/slides/skills/deck-system/SKILL.md +611 -0
  1925. package/payload/platform/plugins/slides/skills/deck-system/STORYTELLING-board.md +426 -0
  1926. package/payload/platform/plugins/slides/skills/deck-system/STORYTELLING-claus.md +185 -0
  1927. package/payload/platform/plugins/slides/skills/deck-system/STORYTELLING-mbb.md +450 -0
  1928. package/payload/platform/plugins/slides/skills/deck-system/STORYTELLING-product-launch.md +579 -0
  1929. package/payload/platform/plugins/slides/skills/deck-system/STORYTELLING-sales.md +464 -0
  1930. package/payload/platform/plugins/slides/skills/deck-system/STORYTELLING-sequoia.md +489 -0
  1931. package/payload/platform/plugins/slides/skills/deck-system/STORYTELLING.md +273 -0
  1932. package/payload/platform/plugins/slides/skills/deck-system/deck-craft.html +1371 -0
  1933. package/payload/platform/plugins/slides/skills/deck-system/deck-solid.html +1667 -0
  1934. package/payload/platform/plugins/slides/skills/deck-system/deck.html +1359 -0
  1935. package/payload/platform/plugins/substack-import/.claude-plugin/plugin.json +8 -0
  1936. package/payload/platform/plugins/substack-import/PLUGIN.md +34 -0
  1937. package/payload/platform/plugins/substack-import/skills/substack-import/SKILL.md +183 -0
  1938. package/payload/platform/plugins/substack-import/skills/substack-import/references/archive-shape.md +68 -0
  1939. package/payload/platform/plugins/substack-import/skills/substack-import/references/attachments.md +72 -0
  1940. package/payload/platform/plugins/substack-import/skills/substack-import/references/engagement.md +61 -0
  1941. package/payload/platform/plugins/substack-import/skills/substack-import/references/posts.md +80 -0
  1942. package/payload/platform/plugins/substack-import/skills/substack-import/references/subscribers.md +74 -0
  1943. package/payload/platform/plugins/telegram/.claude-plugin/plugin.json +21 -0
  1944. package/payload/platform/plugins/telegram/PLUGIN.md +58 -0
  1945. package/payload/platform/plugins/telegram/lib/mcp-spawn-tee/index.js +193 -0
  1946. package/payload/platform/plugins/telegram/lib/mcp-spawn-tee/package.json +3 -0
  1947. package/payload/platform/plugins/telegram/mcp/dist/index.d.ts +2 -0
  1948. package/payload/platform/plugins/telegram/mcp/dist/index.d.ts.map +1 -0
  1949. package/payload/platform/plugins/telegram/mcp/dist/index.js +253 -0
  1950. package/payload/platform/plugins/telegram/mcp/dist/index.js.map +1 -0
  1951. package/payload/platform/plugins/telegram/mcp/dist/lib/account-token.d.ts +6 -0
  1952. package/payload/platform/plugins/telegram/mcp/dist/lib/account-token.d.ts.map +1 -0
  1953. package/payload/platform/plugins/telegram/mcp/dist/lib/account-token.js +20 -0
  1954. package/payload/platform/plugins/telegram/mcp/dist/lib/account-token.js.map +1 -0
  1955. package/payload/platform/plugins/telegram/mcp/dist/lib/account-write.d.ts +21 -0
  1956. package/payload/platform/plugins/telegram/mcp/dist/lib/account-write.d.ts.map +1 -0
  1957. package/payload/platform/plugins/telegram/mcp/dist/lib/account-write.js +52 -0
  1958. package/payload/platform/plugins/telegram/mcp/dist/lib/account-write.js.map +1 -0
  1959. package/payload/platform/plugins/telegram/mcp/dist/lib/telegram.d.ts +41 -0
  1960. package/payload/platform/plugins/telegram/mcp/dist/lib/telegram.d.ts.map +1 -0
  1961. package/payload/platform/plugins/telegram/mcp/dist/lib/telegram.js +70 -0
  1962. package/payload/platform/plugins/telegram/mcp/dist/lib/telegram.js.map +1 -0
  1963. package/payload/platform/plugins/telegram/mcp/dist/tools/message-history.d.ts +16 -0
  1964. package/payload/platform/plugins/telegram/mcp/dist/tools/message-history.d.ts.map +1 -0
  1965. package/payload/platform/plugins/telegram/mcp/dist/tools/message-history.js +68 -0
  1966. package/payload/platform/plugins/telegram/mcp/dist/tools/message-history.js.map +1 -0
  1967. package/payload/platform/plugins/telegram/mcp/dist/tools/message.d.ts +20 -0
  1968. package/payload/platform/plugins/telegram/mcp/dist/tools/message.d.ts.map +1 -0
  1969. package/payload/platform/plugins/telegram/mcp/dist/tools/message.js +37 -0
  1970. package/payload/platform/plugins/telegram/mcp/dist/tools/message.js.map +1 -0
  1971. package/payload/platform/plugins/telegram/mcp/package.json +19 -0
  1972. package/payload/platform/plugins/telegram/references/setup-guide.md +53 -0
  1973. package/payload/platform/plugins/telegram/skills/configure/SKILL.md +79 -0
  1974. package/payload/platform/plugins/url-get/.claude-plugin/plugin.json +21 -0
  1975. package/payload/platform/plugins/url-get/PLUGIN.md +91 -0
  1976. package/payload/platform/plugins/url-get/lib/mcp-spawn-tee/index.js +193 -0
  1977. package/payload/platform/plugins/url-get/lib/mcp-spawn-tee/package.json +3 -0
  1978. package/payload/platform/plugins/url-get/mcp/dist/index.d.ts +9 -0
  1979. package/payload/platform/plugins/url-get/mcp/dist/index.d.ts.map +1 -0
  1980. package/payload/platform/plugins/url-get/mcp/dist/index.js +53 -0
  1981. package/payload/platform/plugins/url-get/mcp/dist/index.js.map +1 -0
  1982. package/payload/platform/plugins/url-get/mcp/dist/lib/summarise.d.ts +8 -0
  1983. package/payload/platform/plugins/url-get/mcp/dist/lib/summarise.d.ts.map +1 -0
  1984. package/payload/platform/plugins/url-get/mcp/dist/lib/summarise.js +83 -0
  1985. package/payload/platform/plugins/url-get/mcp/dist/lib/summarise.js.map +1 -0
  1986. package/payload/platform/plugins/url-get/mcp/dist/tools/url-get.d.ts +21 -0
  1987. package/payload/platform/plugins/url-get/mcp/dist/tools/url-get.d.ts.map +1 -0
  1988. package/payload/platform/plugins/url-get/mcp/dist/tools/url-get.js +133 -0
  1989. package/payload/platform/plugins/url-get/mcp/dist/tools/url-get.js.map +1 -0
  1990. package/payload/platform/plugins/url-get/mcp/package.json +22 -0
  1991. package/payload/platform/plugins/whatsapp/.claude-plugin/plugin.json +21 -0
  1992. package/payload/platform/plugins/whatsapp/PLUGIN.md +112 -0
  1993. package/payload/platform/plugins/whatsapp/lib/mcp-spawn-tee/index.js +193 -0
  1994. package/payload/platform/plugins/whatsapp/lib/mcp-spawn-tee/package.json +3 -0
  1995. package/payload/platform/plugins/whatsapp/mcp/dist/__tests__/boot-without-env.test.d.ts +2 -0
  1996. package/payload/platform/plugins/whatsapp/mcp/dist/__tests__/boot-without-env.test.d.ts.map +1 -0
  1997. package/payload/platform/plugins/whatsapp/mcp/dist/__tests__/boot-without-env.test.js +58 -0
  1998. package/payload/platform/plugins/whatsapp/mcp/dist/__tests__/boot-without-env.test.js.map +1 -0
  1999. package/payload/platform/plugins/whatsapp/mcp/dist/__tests__/format-login-start.test.d.ts +2 -0
  2000. package/payload/platform/plugins/whatsapp/mcp/dist/__tests__/format-login-start.test.d.ts.map +1 -0
  2001. package/payload/platform/plugins/whatsapp/mcp/dist/__tests__/format-login-start.test.js +16 -0
  2002. package/payload/platform/plugins/whatsapp/mcp/dist/__tests__/format-login-start.test.js.map +1 -0
  2003. package/payload/platform/plugins/whatsapp/mcp/dist/call-api.d.ts +14 -0
  2004. package/payload/platform/plugins/whatsapp/mcp/dist/call-api.d.ts.map +1 -0
  2005. package/payload/platform/plugins/whatsapp/mcp/dist/call-api.js +42 -0
  2006. package/payload/platform/plugins/whatsapp/mcp/dist/call-api.js.map +1 -0
  2007. package/payload/platform/plugins/whatsapp/mcp/dist/format.d.ts +7 -0
  2008. package/payload/platform/plugins/whatsapp/mcp/dist/format.d.ts.map +1 -0
  2009. package/payload/platform/plugins/whatsapp/mcp/dist/format.js +21 -0
  2010. package/payload/platform/plugins/whatsapp/mcp/dist/format.js.map +1 -0
  2011. package/payload/platform/plugins/whatsapp/mcp/dist/index.d.ts +8 -0
  2012. package/payload/platform/plugins/whatsapp/mcp/dist/index.d.ts.map +1 -0
  2013. package/payload/platform/plugins/whatsapp/mcp/dist/index.js +436 -0
  2014. package/payload/platform/plugins/whatsapp/mcp/dist/index.js.map +1 -0
  2015. package/payload/platform/plugins/whatsapp/mcp/package.json +21 -0
  2016. package/payload/platform/plugins/whatsapp/mcp/vitest.config.ts +9 -0
  2017. package/payload/platform/plugins/whatsapp/references/channels-whatsapp.md +307 -0
  2018. package/payload/platform/plugins/whatsapp/skills/connect-whatsapp/SKILL.md +86 -0
  2019. package/payload/platform/plugins/whatsapp/skills/manage-whatsapp-config/SKILL.md +90 -0
  2020. package/payload/platform/plugins/work/.claude-plugin/plugin.json +21 -0
  2021. package/payload/platform/plugins/work/.mcp.json +13 -0
  2022. package/payload/platform/plugins/work/PLUGIN.md +124 -0
  2023. package/payload/platform/plugins/work/lib/mcp-spawn-tee/index.js +193 -0
  2024. package/payload/platform/plugins/work/lib/mcp-spawn-tee/package.json +3 -0
  2025. package/payload/platform/plugins/work/mcp/dist/cli/project-create-cli.d.ts +2 -0
  2026. package/payload/platform/plugins/work/mcp/dist/cli/project-create-cli.d.ts.map +1 -0
  2027. package/payload/platform/plugins/work/mcp/dist/cli/project-create-cli.js +78 -0
  2028. package/payload/platform/plugins/work/mcp/dist/cli/project-create-cli.js.map +1 -0
  2029. package/payload/platform/plugins/work/mcp/dist/index.d.ts +2 -0
  2030. package/payload/platform/plugins/work/mcp/dist/index.d.ts.map +1 -0
  2031. package/payload/platform/plugins/work/mcp/dist/index.js +547 -0
  2032. package/payload/platform/plugins/work/mcp/dist/index.js.map +1 -0
  2033. package/payload/platform/plugins/work/mcp/dist/lib/embeddings.d.ts +7 -0
  2034. package/payload/platform/plugins/work/mcp/dist/lib/embeddings.d.ts.map +1 -0
  2035. package/payload/platform/plugins/work/mcp/dist/lib/embeddings.js +24 -0
  2036. package/payload/platform/plugins/work/mcp/dist/lib/embeddings.js.map +1 -0
  2037. package/payload/platform/plugins/work/mcp/dist/lib/neo4j.d.ts +5 -0
  2038. package/payload/platform/plugins/work/mcp/dist/lib/neo4j.d.ts.map +1 -0
  2039. package/payload/platform/plugins/work/mcp/dist/lib/neo4j.js +40 -0
  2040. package/payload/platform/plugins/work/mcp/dist/lib/neo4j.js.map +1 -0
  2041. package/payload/platform/plugins/work/mcp/dist/tools/project-complete.d.ts +17 -0
  2042. package/payload/platform/plugins/work/mcp/dist/tools/project-complete.d.ts.map +1 -0
  2043. package/payload/platform/plugins/work/mcp/dist/tools/project-complete.js +76 -0
  2044. package/payload/platform/plugins/work/mcp/dist/tools/project-complete.js.map +1 -0
  2045. package/payload/platform/plugins/work/mcp/dist/tools/project-create.d.ts +29 -0
  2046. package/payload/platform/plugins/work/mcp/dist/tools/project-create.d.ts.map +1 -0
  2047. package/payload/platform/plugins/work/mcp/dist/tools/project-create.js +235 -0
  2048. package/payload/platform/plugins/work/mcp/dist/tools/project-create.js.map +1 -0
  2049. package/payload/platform/plugins/work/mcp/dist/tools/project-get.d.ts +40 -0
  2050. package/payload/platform/plugins/work/mcp/dist/tools/project-get.d.ts.map +1 -0
  2051. package/payload/platform/plugins/work/mcp/dist/tools/project-get.js +125 -0
  2052. package/payload/platform/plugins/work/mcp/dist/tools/project-get.js.map +1 -0
  2053. package/payload/platform/plugins/work/mcp/dist/tools/project-list.d.ts +26 -0
  2054. package/payload/platform/plugins/work/mcp/dist/tools/project-list.d.ts.map +1 -0
  2055. package/payload/platform/plugins/work/mcp/dist/tools/project-list.js +81 -0
  2056. package/payload/platform/plugins/work/mcp/dist/tools/project-list.js.map +1 -0
  2057. package/payload/platform/plugins/work/mcp/dist/tools/project-update.d.ts +19 -0
  2058. package/payload/platform/plugins/work/mcp/dist/tools/project-update.d.ts.map +1 -0
  2059. package/payload/platform/plugins/work/mcp/dist/tools/project-update.js +102 -0
  2060. package/payload/platform/plugins/work/mcp/dist/tools/project-update.js.map +1 -0
  2061. package/payload/platform/plugins/work/mcp/dist/tools/session-list.d.ts +20 -0
  2062. package/payload/platform/plugins/work/mcp/dist/tools/session-list.d.ts.map +1 -0
  2063. package/payload/platform/plugins/work/mcp/dist/tools/session-list.js +37 -0
  2064. package/payload/platform/plugins/work/mcp/dist/tools/session-list.js.map +1 -0
  2065. package/payload/platform/plugins/work/mcp/dist/tools/session-name.d.ts +12 -0
  2066. package/payload/platform/plugins/work/mcp/dist/tools/session-name.d.ts.map +1 -0
  2067. package/payload/platform/plugins/work/mcp/dist/tools/session-name.js +28 -0
  2068. package/payload/platform/plugins/work/mcp/dist/tools/session-name.js.map +1 -0
  2069. package/payload/platform/plugins/work/mcp/dist/tools/work-complete.d.ts +16 -0
  2070. package/payload/platform/plugins/work/mcp/dist/tools/work-complete.d.ts.map +1 -0
  2071. package/payload/platform/plugins/work/mcp/dist/tools/work-complete.js +33 -0
  2072. package/payload/platform/plugins/work/mcp/dist/tools/work-complete.js.map +1 -0
  2073. package/payload/platform/plugins/work/mcp/dist/tools/work-create.d.ts +63 -0
  2074. package/payload/platform/plugins/work/mcp/dist/tools/work-create.d.ts.map +1 -0
  2075. package/payload/platform/plugins/work/mcp/dist/tools/work-create.js +141 -0
  2076. package/payload/platform/plugins/work/mcp/dist/tools/work-create.js.map +1 -0
  2077. package/payload/platform/plugins/work/mcp/dist/tools/work-get.d.ts +19 -0
  2078. package/payload/platform/plugins/work/mcp/dist/tools/work-get.d.ts.map +1 -0
  2079. package/payload/platform/plugins/work/mcp/dist/tools/work-get.js +51 -0
  2080. package/payload/platform/plugins/work/mcp/dist/tools/work-get.js.map +1 -0
  2081. package/payload/platform/plugins/work/mcp/dist/tools/work-list.d.ts +18 -0
  2082. package/payload/platform/plugins/work/mcp/dist/tools/work-list.d.ts.map +1 -0
  2083. package/payload/platform/plugins/work/mcp/dist/tools/work-list.js +66 -0
  2084. package/payload/platform/plugins/work/mcp/dist/tools/work-list.js.map +1 -0
  2085. package/payload/platform/plugins/work/mcp/dist/tools/work-ready.d.ts +21 -0
  2086. package/payload/platform/plugins/work/mcp/dist/tools/work-ready.d.ts.map +1 -0
  2087. package/payload/platform/plugins/work/mcp/dist/tools/work-ready.js +54 -0
  2088. package/payload/platform/plugins/work/mcp/dist/tools/work-ready.js.map +1 -0
  2089. package/payload/platform/plugins/work/mcp/dist/tools/work-relate.d.ts +12 -0
  2090. package/payload/platform/plugins/work/mcp/dist/tools/work-relate.d.ts.map +1 -0
  2091. package/payload/platform/plugins/work/mcp/dist/tools/work-relate.js +59 -0
  2092. package/payload/platform/plugins/work/mcp/dist/tools/work-relate.js.map +1 -0
  2093. package/payload/platform/plugins/work/mcp/dist/tools/work-update.d.ts +32 -0
  2094. package/payload/platform/plugins/work/mcp/dist/tools/work-update.d.ts.map +1 -0
  2095. package/payload/platform/plugins/work/mcp/dist/tools/work-update.js +112 -0
  2096. package/payload/platform/plugins/work/mcp/dist/tools/work-update.js.map +1 -0
  2097. package/payload/platform/plugins/work/mcp/package.json +20 -0
  2098. package/payload/platform/plugins/work/skills/execute-task/SKILL.md +103 -0
  2099. package/payload/platform/plugins/workflows/.claude-plugin/plugin.json +21 -0
  2100. package/payload/platform/plugins/workflows/.mcp.json +12 -0
  2101. package/payload/platform/plugins/workflows/PLUGIN.md +160 -0
  2102. package/payload/platform/plugins/workflows/lib/mcp-spawn-tee/index.js +193 -0
  2103. package/payload/platform/plugins/workflows/lib/mcp-spawn-tee/package.json +3 -0
  2104. package/payload/platform/plugins/workflows/mcp/dist/index.d.ts +2 -0
  2105. package/payload/platform/plugins/workflows/mcp/dist/index.d.ts.map +1 -0
  2106. package/payload/platform/plugins/workflows/mcp/dist/index.js +440 -0
  2107. package/payload/platform/plugins/workflows/mcp/dist/index.js.map +1 -0
  2108. package/payload/platform/plugins/workflows/mcp/dist/lib/active-runs.d.ts +38 -0
  2109. package/payload/platform/plugins/workflows/mcp/dist/lib/active-runs.d.ts.map +1 -0
  2110. package/payload/platform/plugins/workflows/mcp/dist/lib/active-runs.js +83 -0
  2111. package/payload/platform/plugins/workflows/mcp/dist/lib/active-runs.js.map +1 -0
  2112. package/payload/platform/plugins/workflows/mcp/dist/lib/embeddings.d.ts +2 -0
  2113. package/payload/platform/plugins/workflows/mcp/dist/lib/embeddings.d.ts.map +1 -0
  2114. package/payload/platform/plugins/workflows/mcp/dist/lib/embeddings.js +19 -0
  2115. package/payload/platform/plugins/workflows/mcp/dist/lib/embeddings.js.map +1 -0
  2116. package/payload/platform/plugins/workflows/mcp/dist/lib/llm-call.d.ts +151 -0
  2117. package/payload/platform/plugins/workflows/mcp/dist/lib/llm-call.d.ts.map +1 -0
  2118. package/payload/platform/plugins/workflows/mcp/dist/lib/llm-call.js +299 -0
  2119. package/payload/platform/plugins/workflows/mcp/dist/lib/llm-call.js.map +1 -0
  2120. package/payload/platform/plugins/workflows/mcp/dist/lib/neo4j.d.ts +5 -0
  2121. package/payload/platform/plugins/workflows/mcp/dist/lib/neo4j.d.ts.map +1 -0
  2122. package/payload/platform/plugins/workflows/mcp/dist/lib/neo4j.js +40 -0
  2123. package/payload/platform/plugins/workflows/mcp/dist/lib/neo4j.js.map +1 -0
  2124. package/payload/platform/plugins/workflows/mcp/dist/lib/step-resolver.d.ts +66 -0
  2125. package/payload/platform/plugins/workflows/mcp/dist/lib/step-resolver.d.ts.map +1 -0
  2126. package/payload/platform/plugins/workflows/mcp/dist/lib/step-resolver.js +187 -0
  2127. package/payload/platform/plugins/workflows/mcp/dist/lib/step-resolver.js.map +1 -0
  2128. package/payload/platform/plugins/workflows/mcp/dist/lib/validate-capabilities.d.ts +25 -0
  2129. package/payload/platform/plugins/workflows/mcp/dist/lib/validate-capabilities.d.ts.map +1 -0
  2130. package/payload/platform/plugins/workflows/mcp/dist/lib/validate-capabilities.js +56 -0
  2131. package/payload/platform/plugins/workflows/mcp/dist/lib/validate-capabilities.js.map +1 -0
  2132. package/payload/platform/plugins/workflows/mcp/dist/tools/workflow-create.d.ts +33 -0
  2133. package/payload/platform/plugins/workflows/mcp/dist/tools/workflow-create.d.ts.map +1 -0
  2134. package/payload/platform/plugins/workflows/mcp/dist/tools/workflow-create.js +130 -0
  2135. package/payload/platform/plugins/workflows/mcp/dist/tools/workflow-create.js.map +1 -0
  2136. package/payload/platform/plugins/workflows/mcp/dist/tools/workflow-delete.d.ts +28 -0
  2137. package/payload/platform/plugins/workflows/mcp/dist/tools/workflow-delete.d.ts.map +1 -0
  2138. package/payload/platform/plugins/workflows/mcp/dist/tools/workflow-delete.js +57 -0
  2139. package/payload/platform/plugins/workflows/mcp/dist/tools/workflow-delete.js.map +1 -0
  2140. package/payload/platform/plugins/workflows/mcp/dist/tools/workflow-execute.d.ts +51 -0
  2141. package/payload/platform/plugins/workflows/mcp/dist/tools/workflow-execute.d.ts.map +1 -0
  2142. package/payload/platform/plugins/workflows/mcp/dist/tools/workflow-execute.js +382 -0
  2143. package/payload/platform/plugins/workflows/mcp/dist/tools/workflow-execute.js.map +1 -0
  2144. package/payload/platform/plugins/workflows/mcp/dist/tools/workflow-get.d.ts +24 -0
  2145. package/payload/platform/plugins/workflows/mcp/dist/tools/workflow-get.d.ts.map +1 -0
  2146. package/payload/platform/plugins/workflows/mcp/dist/tools/workflow-get.js +48 -0
  2147. package/payload/platform/plugins/workflows/mcp/dist/tools/workflow-get.js.map +1 -0
  2148. package/payload/platform/plugins/workflows/mcp/dist/tools/workflow-list.d.ts +16 -0
  2149. package/payload/platform/plugins/workflows/mcp/dist/tools/workflow-list.d.ts.map +1 -0
  2150. package/payload/platform/plugins/workflows/mcp/dist/tools/workflow-list.js +44 -0
  2151. package/payload/platform/plugins/workflows/mcp/dist/tools/workflow-list.js.map +1 -0
  2152. package/payload/platform/plugins/workflows/mcp/dist/tools/workflow-runs.d.ts +28 -0
  2153. package/payload/platform/plugins/workflows/mcp/dist/tools/workflow-runs.d.ts.map +1 -0
  2154. package/payload/platform/plugins/workflows/mcp/dist/tools/workflow-runs.js +71 -0
  2155. package/payload/platform/plugins/workflows/mcp/dist/tools/workflow-runs.js.map +1 -0
  2156. package/payload/platform/plugins/workflows/mcp/dist/tools/workflow-update.d.ts +11 -0
  2157. package/payload/platform/plugins/workflows/mcp/dist/tools/workflow-update.d.ts.map +1 -0
  2158. package/payload/platform/plugins/workflows/mcp/dist/tools/workflow-update.js +150 -0
  2159. package/payload/platform/plugins/workflows/mcp/dist/tools/workflow-update.js.map +1 -0
  2160. package/payload/platform/plugins/workflows/mcp/dist/tools/workflow-validate.d.ts +13 -0
  2161. package/payload/platform/plugins/workflows/mcp/dist/tools/workflow-validate.d.ts.map +1 -0
  2162. package/payload/platform/plugins/workflows/mcp/dist/tools/workflow-validate.js +53 -0
  2163. package/payload/platform/plugins/workflows/mcp/dist/tools/workflow-validate.js.map +1 -0
  2164. package/payload/platform/plugins/workflows/mcp/package.json +20 -0
  2165. package/payload/platform/plugins/workflows/mcp/test-runner.mjs +710 -0
  2166. package/payload/platform/plugins/workflows/mcp/test-workflows.sh +77 -0
  2167. package/payload/platform/plugins/workflows/skills/workflow-manager/SKILL.md +95 -0
  2168. package/payload/platform/plugins/x-import/.claude-plugin/plugin.json +8 -0
  2169. package/payload/platform/plugins/x-import/PLUGIN.md +33 -0
  2170. package/payload/platform/plugins/x-import/references/archive-shape.md +124 -0
  2171. package/payload/platform/plugins/x-import/references/transcript-shape.md +121 -0
  2172. package/payload/platform/plugins/x-import/skills/x-import/SKILL.md +123 -0
  2173. package/payload/platform/scripts/__tests__/agents-md-bootstrap.test.sh +111 -0
  2174. package/payload/platform/scripts/__tests__/check-no-raw-mcp-registrations.test.sh +57 -0
  2175. package/payload/platform/scripts/__tests__/check-no-task-id-leaks.test.sh +153 -0
  2176. package/payload/platform/scripts/__tests__/first-token-creates-stream-log.test.sh +37 -0
  2177. package/payload/platform/scripts/__tests__/logs-read-prefix.sh +237 -0
  2178. package/payload/platform/scripts/__tests__/prompt-optimiser-audit.test.sh +59 -0
  2179. package/payload/platform/scripts/__tests__/provision-role-stamp.test.sh +40 -0
  2180. package/payload/platform/scripts/__tests__/resume-tunnel.test.sh +641 -0
  2181. package/payload/platform/scripts/__tests__/sweep-durability.test.sh +103 -0
  2182. package/payload/platform/scripts/admin-conversation-recover.mjs +386 -0
  2183. package/payload/platform/scripts/admin-persist-audit.ts +211 -0
  2184. package/payload/platform/scripts/backfill-bypass-permissions.sh +58 -0
  2185. package/payload/platform/scripts/check-architecture-skill-no-drift.mjs +114 -0
  2186. package/payload/platform/scripts/check-canonical-tool-names.mjs +110 -0
  2187. package/payload/platform/scripts/check-cypher-int-params.mjs +277 -0
  2188. package/payload/platform/scripts/check-no-conversation-id-leaks.mjs +165 -0
  2189. package/payload/platform/scripts/check-no-direct-clipboard.mjs +54 -0
  2190. package/payload/platform/scripts/check-no-esm-require.mjs +164 -0
  2191. package/payload/platform/scripts/check-no-legacy-spawn-route.mjs +37 -0
  2192. package/payload/platform/scripts/check-no-raw-mcp-registrations.mjs +70 -0
  2193. package/payload/platform/scripts/check-no-task-id-leaks.mjs +201 -0
  2194. package/payload/platform/scripts/check-plugin-references.mjs +256 -0
  2195. package/payload/platform/scripts/check-plugin-tools-mcp-consistency.mjs +136 -0
  2196. package/payload/platform/scripts/check-roles-doc-completeness.mjs +96 -0
  2197. package/payload/platform/scripts/check-routing-prose-bash.mjs +134 -0
  2198. package/payload/platform/scripts/check-skill-frontmatter.mjs +142 -0
  2199. package/payload/platform/scripts/check-skill-load-coverage.mjs +100 -0
  2200. package/payload/platform/scripts/check-specialist-tool-surface.mjs +323 -0
  2201. package/payload/platform/scripts/conversation-id-allowlist.txt +142 -0
  2202. package/payload/platform/scripts/dedupe-userprofile-ghosts.sh +388 -0
  2203. package/payload/platform/scripts/generate-canonical-tool-names.mjs +63 -0
  2204. package/payload/platform/scripts/generate-entitlement-fixture.mjs +152 -0
  2205. package/payload/platform/scripts/identity-forbidden-token-check.mjs +87 -0
  2206. package/payload/platform/scripts/installer-device-verify.sh +358 -0
  2207. package/payload/platform/scripts/lib/__tests__/admin-skills-bootstrap.test.sh +64 -0
  2208. package/payload/platform/scripts/lib/admin-skills-bootstrap.sh +109 -0
  2209. package/payload/platform/scripts/lib/agents-md-bootstrap.sh +49 -0
  2210. package/payload/platform/scripts/lib/canonical-tool-names.mjs +88 -0
  2211. package/payload/platform/scripts/lib/provision-account-dir.sh +316 -0
  2212. package/payload/platform/scripts/lib/read-brand-json.sh +69 -0
  2213. package/payload/platform/scripts/lib/resolve-account-dir.sh +131 -0
  2214. package/payload/platform/scripts/log-adherence-check.sh +125 -0
  2215. package/payload/platform/scripts/logs-read-jsonl.test.sh +307 -0
  2216. package/payload/platform/scripts/logs-read.sh +980 -0
  2217. package/payload/platform/scripts/logs-read.test.sh +159 -0
  2218. package/payload/platform/scripts/prompt-optimiser-audit.sh +82 -0
  2219. package/payload/platform/scripts/redact-install-logs.sh +87 -0
  2220. package/payload/platform/scripts/resume-tunnel.sh +280 -0
  2221. package/payload/platform/scripts/rss-sampler.sh +58 -0
  2222. package/payload/platform/scripts/seed-neo4j.sh +211 -0
  2223. package/payload/platform/scripts/setup-account.sh +55 -0
  2224. package/payload/platform/scripts/smoke-boot-services.sh +413 -0
  2225. package/payload/platform/scripts/test-laptop-vnc-boot.sh +88 -0
  2226. package/payload/platform/scripts/verify-skill-tool-surface.sh +389 -0
  2227. package/payload/platform/scripts/vnc.sh +476 -0
  2228. package/payload/platform/scripts/wifi-provision-server/server.js +743 -0
  2229. package/payload/platform/scripts/wifi-provision.sh +492 -0
  2230. package/payload/platform/services/claude-session-manager/dist/admin-identity-audit.d.ts +39 -0
  2231. package/payload/platform/services/claude-session-manager/dist/admin-identity-audit.d.ts.map +1 -0
  2232. package/payload/platform/services/claude-session-manager/dist/admin-identity-audit.js +133 -0
  2233. package/payload/platform/services/claude-session-manager/dist/admin-identity-audit.js.map +1 -0
  2234. package/payload/platform/services/claude-session-manager/dist/agent-identity-locator.d.ts +23 -0
  2235. package/payload/platform/services/claude-session-manager/dist/agent-identity-locator.d.ts.map +1 -0
  2236. package/payload/platform/services/claude-session-manager/dist/agent-identity-locator.js +29 -0
  2237. package/payload/platform/services/claude-session-manager/dist/agent-identity-locator.js.map +1 -0
  2238. package/payload/platform/services/claude-session-manager/dist/auth-snapshot.d.ts +4 -0
  2239. package/payload/platform/services/claude-session-manager/dist/auth-snapshot.d.ts.map +1 -0
  2240. package/payload/platform/services/claude-session-manager/dist/auth-snapshot.js +50 -0
  2241. package/payload/platform/services/claude-session-manager/dist/auth-snapshot.js.map +1 -0
  2242. package/payload/platform/services/claude-session-manager/dist/brand-foreign-filter.d.ts +30 -0
  2243. package/payload/platform/services/claude-session-manager/dist/brand-foreign-filter.d.ts.map +1 -0
  2244. package/payload/platform/services/claude-session-manager/dist/brand-foreign-filter.js +86 -0
  2245. package/payload/platform/services/claude-session-manager/dist/brand-foreign-filter.js.map +1 -0
  2246. package/payload/platform/services/claude-session-manager/dist/canonical-tool-names.d.ts +7 -0
  2247. package/payload/platform/services/claude-session-manager/dist/canonical-tool-names.d.ts.map +1 -0
  2248. package/payload/platform/services/claude-session-manager/dist/canonical-tool-names.generated.d.ts +5 -0
  2249. package/payload/platform/services/claude-session-manager/dist/canonical-tool-names.generated.d.ts.map +1 -0
  2250. package/payload/platform/services/claude-session-manager/dist/canonical-tool-names.generated.js +226 -0
  2251. package/payload/platform/services/claude-session-manager/dist/canonical-tool-names.generated.js.map +1 -0
  2252. package/payload/platform/services/claude-session-manager/dist/canonical-tool-names.js +23 -0
  2253. package/payload/platform/services/claude-session-manager/dist/canonical-tool-names.js.map +1 -0
  2254. package/payload/platform/services/claude-session-manager/dist/channel-mcp.d.ts +15 -0
  2255. package/payload/platform/services/claude-session-manager/dist/channel-mcp.d.ts.map +1 -0
  2256. package/payload/platform/services/claude-session-manager/dist/channel-mcp.js +34 -0
  2257. package/payload/platform/services/claude-session-manager/dist/channel-mcp.js.map +1 -0
  2258. package/payload/platform/services/claude-session-manager/dist/channel-targets.d.ts +26 -0
  2259. package/payload/platform/services/claude-session-manager/dist/channel-targets.d.ts.map +1 -0
  2260. package/payload/platform/services/claude-session-manager/dist/channel-targets.js +19 -0
  2261. package/payload/platform/services/claude-session-manager/dist/channel-targets.js.map +1 -0
  2262. package/payload/platform/services/claude-session-manager/dist/config.d.ts +73 -0
  2263. package/payload/platform/services/claude-session-manager/dist/config.d.ts.map +1 -0
  2264. package/payload/platform/services/claude-session-manager/dist/config.js +290 -0
  2265. package/payload/platform/services/claude-session-manager/dist/config.js.map +1 -0
  2266. package/payload/platform/services/claude-session-manager/dist/fs-watcher.d.ts +150 -0
  2267. package/payload/platform/services/claude-session-manager/dist/fs-watcher.d.ts.map +1 -0
  2268. package/payload/platform/services/claude-session-manager/dist/fs-watcher.js +913 -0
  2269. package/payload/platform/services/claude-session-manager/dist/fs-watcher.js.map +1 -0
  2270. package/payload/platform/services/claude-session-manager/dist/hooks-discovery.d.ts +7 -0
  2271. package/payload/platform/services/claude-session-manager/dist/hooks-discovery.d.ts.map +1 -0
  2272. package/payload/platform/services/claude-session-manager/dist/hooks-discovery.js +90 -0
  2273. package/payload/platform/services/claude-session-manager/dist/hooks-discovery.js.map +1 -0
  2274. package/payload/platform/services/claude-session-manager/dist/http-server.d.ts +56 -0
  2275. package/payload/platform/services/claude-session-manager/dist/http-server.d.ts.map +1 -0
  2276. package/payload/platform/services/claude-session-manager/dist/http-server.js +2797 -0
  2277. package/payload/platform/services/claude-session-manager/dist/http-server.js.map +1 -0
  2278. package/payload/platform/services/claude-session-manager/dist/index.d.ts +2 -0
  2279. package/payload/platform/services/claude-session-manager/dist/index.d.ts.map +1 -0
  2280. package/payload/platform/services/claude-session-manager/dist/index.js +784 -0
  2281. package/payload/platform/services/claude-session-manager/dist/index.js.map +1 -0
  2282. package/payload/platform/services/claude-session-manager/dist/input-postcondition.d.ts +22 -0
  2283. package/payload/platform/services/claude-session-manager/dist/input-postcondition.d.ts.map +1 -0
  2284. package/payload/platform/services/claude-session-manager/dist/input-postcondition.js +50 -0
  2285. package/payload/platform/services/claude-session-manager/dist/input-postcondition.js.map +1 -0
  2286. package/payload/platform/services/claude-session-manager/dist/install-log-sink.d.ts +2 -0
  2287. package/payload/platform/services/claude-session-manager/dist/install-log-sink.d.ts.map +1 -0
  2288. package/payload/platform/services/claude-session-manager/dist/install-log-sink.js +6 -0
  2289. package/payload/platform/services/claude-session-manager/dist/install-log-sink.js.map +1 -0
  2290. package/payload/platform/services/claude-session-manager/dist/jsonl-enumerator.d.ts +49 -0
  2291. package/payload/platform/services/claude-session-manager/dist/jsonl-enumerator.d.ts.map +1 -0
  2292. package/payload/platform/services/claude-session-manager/dist/jsonl-enumerator.js +169 -0
  2293. package/payload/platform/services/claude-session-manager/dist/jsonl-enumerator.js.map +1 -0
  2294. package/payload/platform/services/claude-session-manager/dist/jsonl-observer.d.ts +30 -0
  2295. package/payload/platform/services/claude-session-manager/dist/jsonl-observer.d.ts.map +1 -0
  2296. package/payload/platform/services/claude-session-manager/dist/jsonl-observer.js +204 -0
  2297. package/payload/platform/services/claude-session-manager/dist/jsonl-observer.js.map +1 -0
  2298. package/payload/platform/services/claude-session-manager/dist/jsonl-path.d.ts +67 -0
  2299. package/payload/platform/services/claude-session-manager/dist/jsonl-path.d.ts.map +1 -0
  2300. package/payload/platform/services/claude-session-manager/dist/jsonl-path.js +141 -0
  2301. package/payload/platform/services/claude-session-manager/dist/jsonl-path.js.map +1 -0
  2302. package/payload/platform/services/claude-session-manager/dist/jsonl-tail.d.ts +81 -0
  2303. package/payload/platform/services/claude-session-manager/dist/jsonl-tail.d.ts.map +1 -0
  2304. package/payload/platform/services/claude-session-manager/dist/jsonl-tail.js +503 -0
  2305. package/payload/platform/services/claude-session-manager/dist/jsonl-tail.js.map +1 -0
  2306. package/payload/platform/services/claude-session-manager/dist/liveness-divergence.d.ts +19 -0
  2307. package/payload/platform/services/claude-session-manager/dist/liveness-divergence.d.ts.map +1 -0
  2308. package/payload/platform/services/claude-session-manager/dist/liveness-divergence.js +38 -0
  2309. package/payload/platform/services/claude-session-manager/dist/liveness-divergence.js.map +1 -0
  2310. package/payload/platform/services/claude-session-manager/dist/log-sink.d.ts +12 -0
  2311. package/payload/platform/services/claude-session-manager/dist/log-sink.d.ts.map +1 -0
  2312. package/payload/platform/services/claude-session-manager/dist/log-sink.js +48 -0
  2313. package/payload/platform/services/claude-session-manager/dist/log-sink.js.map +1 -0
  2314. package/payload/platform/services/claude-session-manager/dist/mcp-tools-probe.d.ts +38 -0
  2315. package/payload/platform/services/claude-session-manager/dist/mcp-tools-probe.d.ts.map +1 -0
  2316. package/payload/platform/services/claude-session-manager/dist/mcp-tools-probe.js +131 -0
  2317. package/payload/platform/services/claude-session-manager/dist/mcp-tools-probe.js.map +1 -0
  2318. package/payload/platform/services/claude-session-manager/dist/permission-mode-tail.d.ts +22 -0
  2319. package/payload/platform/services/claude-session-manager/dist/permission-mode-tail.d.ts.map +1 -0
  2320. package/payload/platform/services/claude-session-manager/dist/permission-mode-tail.js +71 -0
  2321. package/payload/platform/services/claude-session-manager/dist/permission-mode-tail.js.map +1 -0
  2322. package/payload/platform/services/claude-session-manager/dist/pty-census.d.ts +40 -0
  2323. package/payload/platform/services/claude-session-manager/dist/pty-census.d.ts.map +1 -0
  2324. package/payload/platform/services/claude-session-manager/dist/pty-census.js +125 -0
  2325. package/payload/platform/services/claude-session-manager/dist/pty-census.js.map +1 -0
  2326. package/payload/platform/services/claude-session-manager/dist/pty-spawner.d.ts +684 -0
  2327. package/payload/platform/services/claude-session-manager/dist/pty-spawner.d.ts.map +1 -0
  2328. package/payload/platform/services/claude-session-manager/dist/pty-spawner.js +2245 -0
  2329. package/payload/platform/services/claude-session-manager/dist/pty-spawner.js.map +1 -0
  2330. package/payload/platform/services/claude-session-manager/dist/public-agent-reachability.d.ts +40 -0
  2331. package/payload/platform/services/claude-session-manager/dist/public-agent-reachability.d.ts.map +1 -0
  2332. package/payload/platform/services/claude-session-manager/dist/public-agent-reachability.js +123 -0
  2333. package/payload/platform/services/claude-session-manager/dist/public-agent-reachability.js.map +1 -0
  2334. package/payload/platform/services/claude-session-manager/dist/public-tool-audit.d.ts +33 -0
  2335. package/payload/platform/services/claude-session-manager/dist/public-tool-audit.d.ts.map +1 -0
  2336. package/payload/platform/services/claude-session-manager/dist/public-tool-audit.js +149 -0
  2337. package/payload/platform/services/claude-session-manager/dist/public-tool-audit.js.map +1 -0
  2338. package/payload/platform/services/claude-session-manager/dist/rc-child-log.d.ts +13 -0
  2339. package/payload/platform/services/claude-session-manager/dist/rc-child-log.d.ts.map +1 -0
  2340. package/payload/platform/services/claude-session-manager/dist/rc-child-log.js +52 -0
  2341. package/payload/platform/services/claude-session-manager/dist/rc-child-log.js.map +1 -0
  2342. package/payload/platform/services/claude-session-manager/dist/rc-daemon.d.ts +175 -0
  2343. package/payload/platform/services/claude-session-manager/dist/rc-daemon.d.ts.map +1 -0
  2344. package/payload/platform/services/claude-session-manager/dist/rc-daemon.js +644 -0
  2345. package/payload/platform/services/claude-session-manager/dist/rc-daemon.js.map +1 -0
  2346. package/payload/platform/services/claude-session-manager/dist/rc-life.d.ts +4 -0
  2347. package/payload/platform/services/claude-session-manager/dist/rc-life.d.ts.map +1 -0
  2348. package/payload/platform/services/claude-session-manager/dist/rc-life.js +16 -0
  2349. package/payload/platform/services/claude-session-manager/dist/rc-life.js.map +1 -0
  2350. package/payload/platform/services/claude-session-manager/dist/rc-script-spawn.d.ts +80 -0
  2351. package/payload/platform/services/claude-session-manager/dist/rc-script-spawn.d.ts.map +1 -0
  2352. package/payload/platform/services/claude-session-manager/dist/rc-script-spawn.js +306 -0
  2353. package/payload/platform/services/claude-session-manager/dist/rc-script-spawn.js.map +1 -0
  2354. package/payload/platform/services/claude-session-manager/dist/reaper.d.ts +28 -0
  2355. package/payload/platform/services/claude-session-manager/dist/reaper.d.ts.map +1 -0
  2356. package/payload/platform/services/claude-session-manager/dist/reaper.js +118 -0
  2357. package/payload/platform/services/claude-session-manager/dist/reaper.js.map +1 -0
  2358. package/payload/platform/services/claude-session-manager/dist/reseat-ledger.d.ts +49 -0
  2359. package/payload/platform/services/claude-session-manager/dist/reseat-ledger.d.ts.map +1 -0
  2360. package/payload/platform/services/claude-session-manager/dist/reseat-ledger.js +148 -0
  2361. package/payload/platform/services/claude-session-manager/dist/reseat-ledger.js.map +1 -0
  2362. package/payload/platform/services/claude-session-manager/dist/scope-record.d.ts +11 -0
  2363. package/payload/platform/services/claude-session-manager/dist/scope-record.d.ts.map +1 -0
  2364. package/payload/platform/services/claude-session-manager/dist/scope-record.js +63 -0
  2365. package/payload/platform/services/claude-session-manager/dist/scope-record.js.map +1 -0
  2366. package/payload/platform/services/claude-session-manager/dist/session-sidecar.d.ts +130 -0
  2367. package/payload/platform/services/claude-session-manager/dist/session-sidecar.d.ts.map +1 -0
  2368. package/payload/platform/services/claude-session-manager/dist/session-sidecar.js +291 -0
  2369. package/payload/platform/services/claude-session-manager/dist/session-sidecar.js.map +1 -0
  2370. package/payload/platform/services/claude-session-manager/dist/session-store.d.ts +49 -0
  2371. package/payload/platform/services/claude-session-manager/dist/session-store.d.ts.map +1 -0
  2372. package/payload/platform/services/claude-session-manager/dist/session-store.js +52 -0
  2373. package/payload/platform/services/claude-session-manager/dist/session-store.js.map +1 -0
  2374. package/payload/platform/services/claude-session-manager/dist/settings-permission-mode.d.ts +12 -0
  2375. package/payload/platform/services/claude-session-manager/dist/settings-permission-mode.d.ts.map +1 -0
  2376. package/payload/platform/services/claude-session-manager/dist/settings-permission-mode.js +57 -0
  2377. package/payload/platform/services/claude-session-manager/dist/settings-permission-mode.js.map +1 -0
  2378. package/payload/platform/services/claude-session-manager/dist/sidecar-store.d.ts +45 -0
  2379. package/payload/platform/services/claude-session-manager/dist/sidecar-store.d.ts.map +1 -0
  2380. package/payload/platform/services/claude-session-manager/dist/sidecar-store.js +118 -0
  2381. package/payload/platform/services/claude-session-manager/dist/sidecar-store.js.map +1 -0
  2382. package/payload/platform/services/claude-session-manager/dist/spawn-rate-limiter.d.ts +28 -0
  2383. package/payload/platform/services/claude-session-manager/dist/spawn-rate-limiter.d.ts.map +1 -0
  2384. package/payload/platform/services/claude-session-manager/dist/spawn-rate-limiter.js +77 -0
  2385. package/payload/platform/services/claude-session-manager/dist/spawn-rate-limiter.js.map +1 -0
  2386. package/payload/platform/services/claude-session-manager/dist/specialist-drift.d.ts +60 -0
  2387. package/payload/platform/services/claude-session-manager/dist/specialist-drift.d.ts.map +1 -0
  2388. package/payload/platform/services/claude-session-manager/dist/specialist-drift.js +203 -0
  2389. package/payload/platform/services/claude-session-manager/dist/specialist-drift.js.map +1 -0
  2390. package/payload/platform/services/claude-session-manager/dist/stuck-turn.d.ts +70 -0
  2391. package/payload/platform/services/claude-session-manager/dist/stuck-turn.d.ts.map +1 -0
  2392. package/payload/platform/services/claude-session-manager/dist/stuck-turn.js +213 -0
  2393. package/payload/platform/services/claude-session-manager/dist/stuck-turn.js.map +1 -0
  2394. package/payload/platform/services/claude-session-manager/dist/system-prompt.d.ts +157 -0
  2395. package/payload/platform/services/claude-session-manager/dist/system-prompt.d.ts.map +1 -0
  2396. package/payload/platform/services/claude-session-manager/dist/system-prompt.js +482 -0
  2397. package/payload/platform/services/claude-session-manager/dist/system-prompt.js.map +1 -0
  2398. package/payload/platform/services/claude-session-manager/dist/systemd-scope.d.ts +164 -0
  2399. package/payload/platform/services/claude-session-manager/dist/systemd-scope.d.ts.map +1 -0
  2400. package/payload/platform/services/claude-session-manager/dist/systemd-scope.js +296 -0
  2401. package/payload/platform/services/claude-session-manager/dist/systemd-scope.js.map +1 -0
  2402. package/payload/platform/services/claude-session-manager/dist/systemd-spawn.d.ts +83 -0
  2403. package/payload/platform/services/claude-session-manager/dist/systemd-spawn.d.ts.map +1 -0
  2404. package/payload/platform/services/claude-session-manager/dist/systemd-spawn.js +345 -0
  2405. package/payload/platform/services/claude-session-manager/dist/systemd-spawn.js.map +1 -0
  2406. package/payload/platform/services/claude-session-manager/dist/tool-surface.d.ts +69 -0
  2407. package/payload/platform/services/claude-session-manager/dist/tool-surface.d.ts.map +1 -0
  2408. package/payload/platform/services/claude-session-manager/dist/tool-surface.js +373 -0
  2409. package/payload/platform/services/claude-session-manager/dist/tool-surface.js.map +1 -0
  2410. package/payload/platform/services/claude-session-manager/dist/types.d.ts +41 -0
  2411. package/payload/platform/services/claude-session-manager/dist/types.d.ts.map +1 -0
  2412. package/payload/platform/services/claude-session-manager/dist/types.js +2 -0
  2413. package/payload/platform/services/claude-session-manager/dist/types.js.map +1 -0
  2414. package/payload/platform/services/claude-session-manager/dist/url-capture.d.ts +12 -0
  2415. package/payload/platform/services/claude-session-manager/dist/url-capture.d.ts.map +1 -0
  2416. package/payload/platform/services/claude-session-manager/dist/url-capture.js +79 -0
  2417. package/payload/platform/services/claude-session-manager/dist/url-capture.js.map +1 -0
  2418. package/payload/platform/services/claude-session-manager/dist/user-title-store.d.ts +39 -0
  2419. package/payload/platform/services/claude-session-manager/dist/user-title-store.d.ts.map +1 -0
  2420. package/payload/platform/services/claude-session-manager/dist/user-title-store.js +138 -0
  2421. package/payload/platform/services/claude-session-manager/dist/user-title-store.js.map +1 -0
  2422. package/payload/platform/services/claude-session-manager/dist/wa-channel-mcp.d.ts +36 -0
  2423. package/payload/platform/services/claude-session-manager/dist/wa-channel-mcp.d.ts.map +1 -0
  2424. package/payload/platform/services/claude-session-manager/dist/wa-channel-mcp.js +63 -0
  2425. package/payload/platform/services/claude-session-manager/dist/wa-channel-mcp.js.map +1 -0
  2426. package/payload/platform/services/claude-session-manager/dist/wa-channel-store.d.ts +29 -0
  2427. package/payload/platform/services/claude-session-manager/dist/wa-channel-store.d.ts.map +1 -0
  2428. package/payload/platform/services/claude-session-manager/dist/wa-channel-store.js +124 -0
  2429. package/payload/platform/services/claude-session-manager/dist/wa-channel-store.js.map +1 -0
  2430. package/payload/platform/services/claude-session-manager/dist/webchat-channel-mcp.d.ts +35 -0
  2431. package/payload/platform/services/claude-session-manager/dist/webchat-channel-mcp.d.ts.map +1 -0
  2432. package/payload/platform/services/claude-session-manager/dist/webchat-channel-mcp.js +52 -0
  2433. package/payload/platform/services/claude-session-manager/dist/webchat-channel-mcp.js.map +1 -0
  2434. package/payload/platform/services/claude-session-manager/dist/webchat-channel-store.d.ts +29 -0
  2435. package/payload/platform/services/claude-session-manager/dist/webchat-channel-store.d.ts.map +1 -0
  2436. package/payload/platform/services/claude-session-manager/dist/webchat-channel-store.js +121 -0
  2437. package/payload/platform/services/claude-session-manager/dist/webchat-channel-store.js.map +1 -0
  2438. package/payload/platform/services/claude-session-manager/package.json +22 -0
  2439. package/payload/platform/services/claude-session-manager/scripts/stash-cleanup.sh +410 -0
  2440. package/payload/platform/services/claude-session-manager/vitest.config.ts +14 -0
  2441. package/payload/platform/services/webchat-channel/dist/instructions.d.ts +9 -0
  2442. package/payload/platform/services/webchat-channel/dist/instructions.d.ts.map +1 -0
  2443. package/payload/platform/services/webchat-channel/dist/instructions.js +106 -0
  2444. package/payload/platform/services/webchat-channel/dist/instructions.js.map +1 -0
  2445. package/payload/platform/services/webchat-channel/dist/notification.d.ts +89 -0
  2446. package/payload/platform/services/webchat-channel/dist/notification.d.ts.map +1 -0
  2447. package/payload/platform/services/webchat-channel/dist/notification.js +118 -0
  2448. package/payload/platform/services/webchat-channel/dist/notification.js.map +1 -0
  2449. package/payload/platform/services/webchat-channel/dist/permission.d.ts +46 -0
  2450. package/payload/platform/services/webchat-channel/dist/permission.d.ts.map +1 -0
  2451. package/payload/platform/services/webchat-channel/dist/permission.js +56 -0
  2452. package/payload/platform/services/webchat-channel/dist/permission.js.map +1 -0
  2453. package/payload/platform/services/webchat-channel/dist/server.d.ts +40 -0
  2454. package/payload/platform/services/webchat-channel/dist/server.d.ts.map +1 -0
  2455. package/payload/platform/services/webchat-channel/dist/server.js +329 -0
  2456. package/payload/platform/services/webchat-channel/dist/server.js.map +1 -0
  2457. package/payload/platform/services/webchat-channel/dist/turn-follow.d.ts +28 -0
  2458. package/payload/platform/services/webchat-channel/dist/turn-follow.d.ts.map +1 -0
  2459. package/payload/platform/services/webchat-channel/dist/turn-follow.js +188 -0
  2460. package/payload/platform/services/webchat-channel/dist/turn-follow.js.map +1 -0
  2461. package/payload/platform/services/webchat-channel/package.json +20 -0
  2462. package/payload/platform/services/whatsapp-channel/dist/jsonl-watch.d.ts +10 -0
  2463. package/payload/platform/services/whatsapp-channel/dist/jsonl-watch.d.ts.map +1 -0
  2464. package/payload/platform/services/whatsapp-channel/dist/jsonl-watch.js +70 -0
  2465. package/payload/platform/services/whatsapp-channel/dist/jsonl-watch.js.map +1 -0
  2466. package/payload/platform/services/whatsapp-channel/dist/notification.d.ts +194 -0
  2467. package/payload/platform/services/whatsapp-channel/dist/notification.d.ts.map +1 -0
  2468. package/payload/platform/services/whatsapp-channel/dist/notification.js +265 -0
  2469. package/payload/platform/services/whatsapp-channel/dist/notification.js.map +1 -0
  2470. package/payload/platform/services/whatsapp-channel/dist/server.d.ts +57 -0
  2471. package/payload/platform/services/whatsapp-channel/dist/server.d.ts.map +1 -0
  2472. package/payload/platform/services/whatsapp-channel/dist/server.js +625 -0
  2473. package/payload/platform/services/whatsapp-channel/dist/server.js.map +1 -0
  2474. package/payload/platform/services/whatsapp-channel/dist/targets.d.ts +100 -0
  2475. package/payload/platform/services/whatsapp-channel/dist/targets.d.ts.map +1 -0
  2476. package/payload/platform/services/whatsapp-channel/dist/targets.js +154 -0
  2477. package/payload/platform/services/whatsapp-channel/dist/targets.js.map +1 -0
  2478. package/payload/platform/services/whatsapp-channel/dist/turn-follow.d.ts +22 -0
  2479. package/payload/platform/services/whatsapp-channel/dist/turn-follow.d.ts.map +1 -0
  2480. package/payload/platform/services/whatsapp-channel/dist/turn-follow.js +163 -0
  2481. package/payload/platform/services/whatsapp-channel/dist/turn-follow.js.map +1 -0
  2482. package/payload/platform/services/whatsapp-channel/package.json +20 -0
  2483. package/payload/platform/templates/account.json +14 -0
  2484. package/payload/platform/templates/agents/admin/AGENTS.md +23 -0
  2485. package/payload/platform/templates/agents/admin/IDENTITY.md +65 -0
  2486. package/payload/platform/templates/agents/admin/LEARNINGS.md +3 -0
  2487. package/payload/platform/templates/agents/admin/SOUL.md +1 -0
  2488. package/payload/platform/templates/agents/public/IDENTITY.md +19 -0
  2489. package/payload/platform/templates/specialists/.claude-plugin/plugin.json +4 -0
  2490. package/payload/platform/templates/specialists/agents/citation-auditor.md +37 -0
  2491. package/payload/platform/templates/specialists/agents/coding-assistant.md +73 -0
  2492. package/payload/platform/templates/specialists/agents/compiled-truth-rewriter.md +42 -0
  2493. package/payload/platform/templates/specialists/agents/content-producer.md +65 -0
  2494. package/payload/platform/templates/specialists/agents/data-manager.md +29 -0
  2495. package/payload/platform/templates/specialists/agents/database-operator.md +25 -0
  2496. package/payload/platform/templates/specialists/agents/librarian.md +70 -0
  2497. package/payload/platform/templates/specialists/agents/personal-assistant.md +62 -0
  2498. package/payload/platform/templates/specialists/agents/project-manager.md +63 -0
  2499. package/payload/platform/templates/specialists/agents/public-session-reviewer.md +40 -0
  2500. package/payload/platform/templates/specialists/agents/research-assistant.md +73 -0
  2501. package/payload/platform/templates/specialists/agents/typed-edge-classifier.md +37 -0
  2502. package/payload/platform/templates/systemd/edge.service.template +38 -0
  2503. package/payload/platform/tsconfig.base.json +18 -0
  2504. package/payload/premium-plugins/.claude-plugin/marketplace.json +28 -0
  2505. package/payload/premium-plugins/sitedesk/.claude-plugin/plugin.json +8 -0
  2506. package/payload/premium-plugins/sitedesk/BUNDLE.md +35 -0
  2507. package/payload/premium-plugins/sitedesk/PLUGIN.md +18 -0
  2508. package/payload/premium-plugins/sitedesk/agents/sitedesk--site-manager.md +45 -0
  2509. package/payload/premium-plugins/sitedesk/agents/worker-checkin/IDENTITY.md +11 -0
  2510. package/payload/premium-plugins/sitedesk/agents/worker-checkin/SOUL.md +7 -0
  2511. package/payload/premium-plugins/sitedesk/agents/worker-checkin/template.json +9 -0
  2512. package/payload/premium-plugins/sitedesk/plugins/.claude-plugin/marketplace.json +18 -0
  2513. package/payload/premium-plugins/sitedesk/plugins/sitedesk-job/.claude-plugin/plugin.json +8 -0
  2514. package/payload/premium-plugins/sitedesk/plugins/sitedesk-job/PLUGIN.md +46 -0
  2515. package/payload/premium-plugins/sitedesk/plugins/sitedesk-job/skills/quotation/SKILL.md +79 -0
  2516. package/payload/premium-plugins/sitedesk/plugins/sitedesk-job/skills/quotation/references/learning-from-history.md +51 -0
  2517. package/payload/premium-plugins/sitedesk/plugins/sitedesk-job/skills/quotation/references/maintenance.md +32 -0
  2518. package/payload/premium-plugins/sitedesk/plugins/sitedesk-job/skills/quotation/references/manual-definition.md +42 -0
  2519. package/payload/premium-plugins/sitedesk/plugins/sitedesk-job/skills/quotation/references/quote-engine.md +122 -0
  2520. package/payload/premium-plugins/sitedesk/plugins/sitedesk-job/skills/quotation/references/quote-generation.md +110 -0
  2521. package/payload/premium-plugins/sitedesk/plugins/sitedesk-job/skills/quotation/references/quoting.md +86 -0
  2522. package/payload/premium-plugins/sitedesk/plugins/sitedesk-job/skills/quotation/references/verification.md +39 -0
  2523. package/payload/premium-plugins/sitedesk/plugins/sitedesk-job/skills/timesheet/SKILL.md +47 -0
  2524. package/payload/premium-plugins/sitedesk/plugins/sitedesk-job/skills/timesheet/references/checkin-contract.md +31 -0
  2525. package/payload/premium-plugins/sitedesk/plugins/sitedesk-job/skills/timesheet/references/documents.md +28 -0
  2526. package/payload/premium-plugins/sitedesk/plugins/sitedesk-job/skills/timesheet/references/roll-up.md +38 -0
  2527. package/payload/premium-plugins/sitedesk/plugins/sitedesk-job/skills/timesheet/references/setup.md +20 -0
  2528. package/payload/premium-plugins/sitedesk/plugins/sitedesk-job/skills/timesheet/rollup.mjs +90 -0
  2529. package/payload/premium-plugins/sitedesk/plugins/sitedesk-job/skills/timesheet/rollup.test.mjs +106 -0
  2530. package/payload/premium-plugins/sitedesk/plugins/sitedesk-job/skills/valuation/SKILL.md +108 -0
  2531. package/payload/premium-plugins/sitedesk/plugins/sitedesk-job/skills/valuation/references/contract-template.md +34 -0
  2532. package/payload/premium-plugins/sitedesk/plugins/sitedesk-job/skills/valuation/references/document-learning.md +63 -0
  2533. package/payload/premium-plugins/sitedesk/plugins/sitedesk-job/skills/valuation/references/document-verification.md +52 -0
  2534. package/payload/premium-plugins/sitedesk/plugins/sitedesk-job/skills/valuation/references/document.md +108 -0
  2535. package/payload/premium-plugins/sitedesk/plugins/sitedesk-job/skills/valuation/references/issue-flow.md +117 -0
  2536. package/payload/premium-plugins/sitedesk/plugins/sitedesk-job/skills/valuation/references/job-folder.md +91 -0
  2537. package/payload/premium-plugins/sitedesk/plugins/sitedesk-job/skills/valuation/references/roll-up.md +73 -0
  2538. package/payload/premium-plugins/sitedesk/plugins/sitedesk-job/skills/valuation/rollup.mjs +147 -0
  2539. package/payload/premium-plugins/sitedesk/plugins/sitedesk-media/.claude-plugin/plugin.json +8 -0
  2540. package/payload/premium-plugins/sitedesk/plugins/sitedesk-media/PLUGIN.md +49 -0
  2541. package/payload/premium-plugins/sitedesk/plugins/sitedesk-media/README.md +70 -0
  2542. package/payload/premium-plugins/sitedesk/plugins/sitedesk-media/commands/make-media.md +13 -0
  2543. package/payload/premium-plugins/sitedesk/plugins/sitedesk-media/skills/brand-extract/SKILL.md +86 -0
  2544. package/payload/premium-plugins/sitedesk/plugins/sitedesk-media/skills/make-media/SKILL.md +75 -0
  2545. package/payload/premium-plugins/sitedesk/plugins/sitedesk-media/skills/make-media/references/intake-and-questions.md +74 -0
  2546. package/payload/premium-plugins/sitedesk/plugins/sitedesk-media/skills/microsite/SKILL.md +88 -0
  2547. package/payload/premium-plugins/sitedesk/plugins/sitedesk-media/skills/microsite/references/placeholders.md +96 -0
  2548. package/payload/premium-plugins/sitedesk/plugins/sitedesk-media/skills/microsite/references/sections.md +48 -0
  2549. package/payload/premium-plugins/sitedesk/plugins/sitedesk-media/skills/microsite/templates/index.html +1004 -0
  2550. package/payload/premium-plugins/sitedesk/plugins/sitedesk-media/skills/microsite/templates/llms.txt +32 -0
  2551. package/payload/premium-plugins/sitedesk/plugins/sitedesk-media/skills/socials/SKILL.md +133 -0
  2552. package/payload/premium-plugins/sitedesk/plugins/sitedesk-media/skills/socials/references/pii-strip.md +64 -0
  2553. package/payload/premium-plugins/sitedesk/plugins/sitedesk-media/skills/socials/references/sources.md +96 -0
  2554. package/payload/premium-plugins/sitedesk/plugins/sitedesk-media/skills/socials/templates/og.html +92 -0
  2555. package/payload/premium-plugins/sitedesk/plugins/sitedesk-media/skills/socials/templates/social-posts.md +47 -0
  2556. package/payload/premium-plugins/sitedesk/plugins/sitedesk-media/skills/socials/templates/socials.html +87 -0
  2557. package/payload/premium-plugins/teaching/.claude-plugin/plugin.json +8 -0
  2558. package/payload/premium-plugins/teaching/PLUGIN.md +58 -0
  2559. package/payload/premium-plugins/teaching/skills/interactive-tutor/SKILL.md +59 -0
  2560. package/payload/premium-plugins/teaching/skills/interactive-tutor/references/assessment.md +70 -0
  2561. package/payload/premium-plugins/teaching/skills/interactive-tutor/references/classroom-conduct.md +43 -0
  2562. package/payload/premium-plugins/teaching/skills/interactive-tutor/references/teaching-modes.md +83 -0
  2563. package/payload/premium-plugins/teaching/skills/lesson-planner/SKILL.md +48 -0
  2564. package/payload/premium-plugins/teaching/skills/lesson-planner/references/context-gathering.md +41 -0
  2565. package/payload/premium-plugins/teaching/skills/lesson-planner/references/plan-structure.md +94 -0
  2566. package/payload/premium-plugins/teaching/skills/study-pack-builder/SKILL.md +52 -0
  2567. package/payload/premium-plugins/teaching/skills/study-pack-builder/references/disaggregation.md +49 -0
  2568. package/payload/premium-plugins/teaching/skills/study-pack-builder/references/materials.md +116 -0
  2569. package/payload/premium-plugins/venture-studio/.claude-plugin/plugin.json +8 -0
  2570. package/payload/premium-plugins/venture-studio/PLUGIN.md +128 -0
  2571. package/payload/premium-plugins/venture-studio/bin/scaffold.sh +116 -0
  2572. package/payload/premium-plugins/venture-studio/skills/brand-pack/SKILL.md +256 -0
  2573. package/payload/premium-plugins/venture-studio/skills/brand-pack/references/color-psychology.md +118 -0
  2574. package/payload/premium-plugins/venture-studio/skills/investor-data-room/SKILL.md +390 -0
  2575. package/payload/premium-plugins/venture-studio/skills/investor-data-room/references/business-plan-template.md +64 -0
  2576. package/payload/premium-plugins/venture-studio/skills/investor-data-room/references/competitive-battlecard.md +37 -0
  2577. package/payload/premium-plugins/venture-studio/skills/investor-data-room/references/competitor-analysis.md +32 -0
  2578. package/payload/premium-plugins/venture-studio/skills/investor-data-room/references/compliance-research-checklist.md +53 -0
  2579. package/payload/premium-plugins/venture-studio/skills/investor-data-room/references/data-room-structure.md +88 -0
  2580. package/payload/premium-plugins/venture-studio/skills/investor-data-room/references/deck-blueprint-template.md +39 -0
  2581. package/payload/premium-plugins/venture-studio/skills/investor-data-room/references/design-tokens-application.md +79 -0
  2582. package/payload/premium-plugins/venture-studio/skills/investor-data-room/references/html-pdf-pipeline.md +236 -0
  2583. package/payload/premium-plugins/venture-studio/skills/investor-data-room/references/internal-workings-scrub.md +33 -0
  2584. package/payload/premium-plugins/venture-studio/skills/investor-data-room/references/monetization-strategy.md +35 -0
  2585. package/payload/premium-plugins/venture-studio/skills/investor-data-room/references/pricing-strategy.md +37 -0
  2586. package/payload/premium-plugins/venture-studio/skills/investor-data-room/references/strategy-frameworks.md +46 -0
  2587. package/payload/premium-plugins/venture-studio/skills/investor-data-room/references/termsheet-template.md +88 -0
  2588. package/payload/premium-plugins/venture-studio/skills/investor-data-room/templates/prospectus/index.html +1565 -0
  2589. package/payload/premium-plugins/venture-studio/skills/investor-data-room/templates/prospectus/render-pdf.mjs +91 -0
  2590. package/payload/premium-plugins/venture-studio/skills/investor-data-room/templates/prospectus/term_sheet.html +715 -0
  2591. package/payload/premium-plugins/venture-studio/skills/legal-essentials/SKILL.md +65 -0
  2592. package/payload/premium-plugins/venture-studio/skills/office-hours/SKILL.md +587 -0
  2593. package/payload/premium-plugins/venture-studio/skills/prototype-host/SKILL.md +179 -0
  2594. package/payload/premium-plugins/venture-studio/skills/prototype-host/references/cloudflared-ingress-edit.md +81 -0
  2595. package/payload/premium-plugins/venture-studio/skills/prototype-host/references/scaffold-frameworks.md +60 -0
  2596. package/payload/premium-plugins/venture-studio/skills/prototype-host/references/systemd-user-service.md +104 -0
  2597. package/payload/premium-plugins/venture-studio/skills/zero-to-prototype/SKILL.md +342 -0
  2598. package/payload/premium-plugins/venture-studio/skills/zero-to-prototype/references/aarrr-metrics.md +275 -0
  2599. package/payload/premium-plugins/venture-studio/skills/zero-to-prototype/references/assumption-testing.md +93 -0
  2600. package/payload/premium-plugins/venture-studio/skills/zero-to-prototype/references/boolean-search.md +308 -0
  2601. package/payload/premium-plugins/venture-studio/skills/zero-to-prototype/references/build-measure-learn.md +262 -0
  2602. package/payload/premium-plugins/venture-studio/skills/zero-to-prototype/references/business-model-canvas.md +171 -0
  2603. package/payload/premium-plugins/venture-studio/skills/zero-to-prototype/references/commitment-signals.md +246 -0
  2604. package/payload/premium-plugins/venture-studio/skills/zero-to-prototype/references/design-thinking.md +183 -0
  2605. package/payload/premium-plugins/venture-studio/skills/zero-to-prototype/references/earlyvangelist.md +190 -0
  2606. package/payload/premium-plugins/venture-studio/skills/zero-to-prototype/references/first-principles.md +58 -0
  2607. package/payload/premium-plugins/venture-studio/skills/zero-to-prototype/references/fishbone.md +114 -0
  2608. package/payload/premium-plugins/venture-studio/skills/zero-to-prototype/references/five-whys.md +43 -0
  2609. package/payload/premium-plugins/venture-studio/skills/zero-to-prototype/references/ice-scoring.md +237 -0
  2610. package/payload/premium-plugins/venture-studio/skills/zero-to-prototype/references/innovation-accounting.md +290 -0
  2611. package/payload/premium-plugins/venture-studio/skills/zero-to-prototype/references/jtbd.md +105 -0
  2612. package/payload/premium-plugins/venture-studio/skills/zero-to-prototype/references/landing-page.md +361 -0
  2613. package/payload/premium-plugins/venture-studio/skills/zero-to-prototype/references/market-sizing.md +58 -0
  2614. package/payload/premium-plugins/venture-studio/skills/zero-to-prototype/references/market-type.md +167 -0
  2615. package/payload/premium-plugins/venture-studio/skills/zero-to-prototype/references/mom-test.md +193 -0
  2616. package/payload/premium-plugins/venture-studio/skills/zero-to-prototype/references/mvp-types.md +200 -0
  2617. package/payload/premium-plugins/venture-studio/skills/zero-to-prototype/references/og-images.md +239 -0
  2618. package/payload/premium-plugins/venture-studio/skills/zero-to-prototype/references/pareto.md +103 -0
  2619. package/payload/premium-plugins/venture-studio/skills/zero-to-prototype/references/persona-development.md +291 -0
  2620. package/payload/premium-plugins/venture-studio/skills/zero-to-prototype/references/pivot-types.md +225 -0
  2621. package/payload/premium-plugins/venture-studio/skills/zero-to-prototype/references/positioning-statement.md +179 -0
  2622. package/payload/premium-plugins/venture-studio/skills/zero-to-prototype/references/prd.md +363 -0
  2623. package/payload/premium-plugins/venture-studio/skills/zero-to-prototype/references/pre-mortem.md +74 -0
  2624. package/payload/premium-plugins/venture-studio/skills/zero-to-prototype/references/problem-validation.md +253 -0
  2625. package/payload/premium-plugins/venture-studio/skills/zero-to-prototype/references/product-market-fit.md +256 -0
  2626. package/payload/premium-plugins/venture-studio/skills/zero-to-prototype/references/research-synthesis.md +276 -0
  2627. package/payload/premium-plugins/venture-studio/skills/zero-to-prototype/references/strategy-red-team.md +41 -0
  2628. package/payload/premium-plugins/venture-studio/skills/zero-to-prototype/references/three-engines-of-growth.md +248 -0
  2629. package/payload/premium-plugins/venture-studio/skills/zero-to-prototype/references/validation-tests.md +89 -0
  2630. package/payload/premium-plugins/venture-studio/skills/zero-to-prototype/references/value-proposition-canvas.md +121 -0
  2631. package/payload/premium-plugins/venture-studio/skills/zero-to-prototype/references/win-loss-analysis.md +242 -0
  2632. package/payload/premium-plugins/venture-studio/skills/zero-to-prototype/references/workflow-mapping.md +271 -0
  2633. package/payload/premium-plugins/writer-craft/.claude-plugin/plugin.json +21 -0
  2634. package/payload/premium-plugins/writer-craft/PLUGIN.md +134 -0
  2635. package/payload/premium-plugins/writer-craft/agents/writer-craft--manuscript-reviewer.md +96 -0
  2636. package/payload/premium-plugins/writer-craft/lib/mcp-lifeline/dist/index.d.ts +8 -0
  2637. package/payload/premium-plugins/writer-craft/lib/mcp-lifeline/dist/index.d.ts.map +1 -0
  2638. package/payload/premium-plugins/writer-craft/lib/mcp-lifeline/dist/index.js +71 -0
  2639. package/payload/premium-plugins/writer-craft/lib/mcp-lifeline/dist/index.js.map +1 -0
  2640. package/payload/premium-plugins/writer-craft/lib/mcp-lifeline/package.json +7 -0
  2641. package/payload/premium-plugins/writer-craft/lib/mcp-spawn-tee/index.js +193 -0
  2642. package/payload/premium-plugins/writer-craft/lib/mcp-spawn-tee/package.json +3 -0
  2643. package/payload/premium-plugins/writer-craft/lib/mcp-stderr-tee/dist/index.d.ts +51 -0
  2644. package/payload/premium-plugins/writer-craft/lib/mcp-stderr-tee/dist/index.d.ts.map +1 -0
  2645. package/payload/premium-plugins/writer-craft/lib/mcp-stderr-tee/dist/index.js +196 -0
  2646. package/payload/premium-plugins/writer-craft/lib/mcp-stderr-tee/dist/index.js.map +1 -0
  2647. package/payload/premium-plugins/writer-craft/lib/mcp-stderr-tee/package.json +7 -0
  2648. package/payload/premium-plugins/writer-craft/mcp/dist/cli/ingest-session-text.d.ts +3 -0
  2649. package/payload/premium-plugins/writer-craft/mcp/dist/cli/ingest-session-text.d.ts.map +1 -0
  2650. package/payload/premium-plugins/writer-craft/mcp/dist/cli/ingest-session-text.js +58 -0
  2651. package/payload/premium-plugins/writer-craft/mcp/dist/cli/ingest-session-text.js.map +1 -0
  2652. package/payload/premium-plugins/writer-craft/mcp/dist/index.d.ts +3 -0
  2653. package/payload/premium-plugins/writer-craft/mcp/dist/index.d.ts.map +1 -0
  2654. package/payload/premium-plugins/writer-craft/mcp/dist/index.js +403 -0
  2655. package/payload/premium-plugins/writer-craft/mcp/dist/index.js.map +1 -0
  2656. package/payload/premium-plugins/writer-craft/mcp/dist/lib/neo4j.d.ts +14 -0
  2657. package/payload/premium-plugins/writer-craft/mcp/dist/lib/neo4j.d.ts.map +1 -0
  2658. package/payload/premium-plugins/writer-craft/mcp/dist/lib/neo4j.js +47 -0
  2659. package/payload/premium-plugins/writer-craft/mcp/dist/lib/neo4j.js.map +1 -0
  2660. package/payload/premium-plugins/writer-craft/mcp/dist/lib/voice-corpus.d.ts +117 -0
  2661. package/payload/premium-plugins/writer-craft/mcp/dist/lib/voice-corpus.d.ts.map +1 -0
  2662. package/payload/premium-plugins/writer-craft/mcp/dist/lib/voice-corpus.js +138 -0
  2663. package/payload/premium-plugins/writer-craft/mcp/dist/lib/voice-corpus.js.map +1 -0
  2664. package/payload/premium-plugins/writer-craft/mcp/dist/tools/voice-distil-profile.d.ts +90 -0
  2665. package/payload/premium-plugins/writer-craft/mcp/dist/tools/voice-distil-profile.d.ts.map +1 -0
  2666. package/payload/premium-plugins/writer-craft/mcp/dist/tools/voice-distil-profile.js +609 -0
  2667. package/payload/premium-plugins/writer-craft/mcp/dist/tools/voice-distil-profile.js.map +1 -0
  2668. package/payload/premium-plugins/writer-craft/mcp/dist/tools/voice-ingest-session-text.d.ts +19 -0
  2669. package/payload/premium-plugins/writer-craft/mcp/dist/tools/voice-ingest-session-text.d.ts.map +1 -0
  2670. package/payload/premium-plugins/writer-craft/mcp/dist/tools/voice-ingest-session-text.js +124 -0
  2671. package/payload/premium-plugins/writer-craft/mcp/dist/tools/voice-ingest-session-text.js.map +1 -0
  2672. package/payload/premium-plugins/writer-craft/mcp/dist/tools/voice-record-feedback.d.ts +38 -0
  2673. package/payload/premium-plugins/writer-craft/mcp/dist/tools/voice-record-feedback.d.ts.map +1 -0
  2674. package/payload/premium-plugins/writer-craft/mcp/dist/tools/voice-record-feedback.js +93 -0
  2675. package/payload/premium-plugins/writer-craft/mcp/dist/tools/voice-record-feedback.js.map +1 -0
  2676. package/payload/premium-plugins/writer-craft/mcp/dist/tools/voice-retrieve-conditioning.d.ts +61 -0
  2677. package/payload/premium-plugins/writer-craft/mcp/dist/tools/voice-retrieve-conditioning.d.ts.map +1 -0
  2678. package/payload/premium-plugins/writer-craft/mcp/dist/tools/voice-retrieve-conditioning.js +171 -0
  2679. package/payload/premium-plugins/writer-craft/mcp/dist/tools/voice-retrieve-conditioning.js.map +1 -0
  2680. package/payload/premium-plugins/writer-craft/mcp/dist/tools/voice-tag-content.d.ts +35 -0
  2681. package/payload/premium-plugins/writer-craft/mcp/dist/tools/voice-tag-content.d.ts.map +1 -0
  2682. package/payload/premium-plugins/writer-craft/mcp/dist/tools/voice-tag-content.js +127 -0
  2683. package/payload/premium-plugins/writer-craft/mcp/dist/tools/voice-tag-content.js.map +1 -0
  2684. package/payload/premium-plugins/writer-craft/mcp/package-lock.json +1327 -0
  2685. package/payload/premium-plugins/writer-craft/mcp/package.json +19 -0
  2686. package/payload/premium-plugins/writer-craft/mcp/scripts/smoke.mjs +420 -0
  2687. package/payload/premium-plugins/writer-craft/mcp/src/index.ts +457 -0
  2688. package/payload/premium-plugins/writer-craft/mcp/src/lib/neo4j.ts +56 -0
  2689. package/payload/premium-plugins/writer-craft/mcp/src/lib/voice-corpus.ts +154 -0
  2690. package/payload/premium-plugins/writer-craft/mcp/src/tools/voice-distil-profile.ts +833 -0
  2691. package/payload/premium-plugins/writer-craft/mcp/src/tools/voice-ingest-session-text.ts +153 -0
  2692. package/payload/premium-plugins/writer-craft/mcp/src/tools/voice-record-feedback.ts +148 -0
  2693. package/payload/premium-plugins/writer-craft/mcp/src/tools/voice-retrieve-conditioning.ts +270 -0
  2694. package/payload/premium-plugins/writer-craft/mcp/src/tools/voice-tag-content.ts +181 -0
  2695. package/payload/premium-plugins/writer-craft/mcp/tsconfig.json +8 -0
  2696. package/payload/premium-plugins/writer-craft/skills/citation-style/SKILL.md +94 -0
  2697. package/payload/premium-plugins/writer-craft/skills/citation-style/references/book-and-chapter-models.md +77 -0
  2698. package/payload/premium-plugins/writer-craft/skills/citation-style/references/citation-rules.md +103 -0
  2699. package/payload/premium-plugins/writer-craft/skills/citation-style/references/journal-article-models.md +74 -0
  2700. package/payload/premium-plugins/writer-craft/skills/citation-style/references/other-source-models.md +146 -0
  2701. package/payload/premium-plugins/writer-craft/skills/citation-style/references/reference-list-rules.md +70 -0
  2702. package/payload/premium-plugins/writer-craft/skills/editorial-practice/SKILL.md +108 -0
  2703. package/payload/premium-plugins/writer-craft/skills/editorial-practice/references/copyediting.md +73 -0
  2704. package/payload/premium-plugins/writer-craft/skills/editorial-practice/references/developmental-editing.md +85 -0
  2705. package/payload/premium-plugins/writer-craft/skills/editorial-practice/references/genre-specific-editing.md +78 -0
  2706. package/payload/premium-plugins/writer-craft/skills/editorial-practice/references/line-editing.md +55 -0
  2707. package/payload/premium-plugins/writer-craft/skills/editorial-practice/references/self-editing.md +89 -0
  2708. package/payload/premium-plugins/writer-craft/skills/persuasive-storytelling/SKILL.md +114 -0
  2709. package/payload/premium-plugins/writer-craft/skills/persuasive-storytelling/references/audience-analysis.md +73 -0
  2710. package/payload/premium-plugins/writer-craft/skills/persuasive-storytelling/references/crafting-persuasive-story.md +76 -0
  2711. package/payload/premium-plugins/writer-craft/skills/persuasive-storytelling/references/persuasion-case-studies.md +67 -0
  2712. package/payload/premium-plugins/writer-craft/skills/persuasive-storytelling/references/transformation-framework.md +86 -0
  2713. package/payload/premium-plugins/writer-craft/skills/point-of-view/SKILL.md +97 -0
  2714. package/payload/premium-plugins/writer-craft/skills/point-of-view/references/indirect-narration.md +72 -0
  2715. package/payload/premium-plugins/writer-craft/skills/point-of-view/references/pov-types-and-voice.md +91 -0
  2716. package/payload/premium-plugins/writer-craft/skills/point-of-view/references/protagonist-filter.md +71 -0
  2717. package/payload/premium-plugins/writer-craft/skills/point-of-view/references/tense-and-person.md +85 -0
  2718. package/payload/premium-plugins/writer-craft/skills/prose-craft/SKILL.md +100 -0
  2719. package/payload/premium-plugins/writer-craft/skills/prose-craft/references/punctuation-and-grammar.md +72 -0
  2720. package/payload/premium-plugins/writer-craft/skills/prose-craft/references/repetition.md +71 -0
  2721. package/payload/premium-plugins/writer-craft/skills/prose-craft/references/sound-and-rhythm.md +64 -0
  2722. package/payload/premium-plugins/writer-craft/skills/prose-craft/references/word-economy.md +93 -0
  2723. package/payload/premium-plugins/writer-craft/skills/reader-engagement/SKILL.md +100 -0
  2724. package/payload/premium-plugins/writer-craft/skills/reader-engagement/references/cause-effect-setup-payoff.md +79 -0
  2725. package/payload/premium-plugins/writer-craft/skills/reader-engagement/references/conflict-escalation.md +81 -0
  2726. package/payload/premium-plugins/writer-craft/skills/reader-engagement/references/hooking-readers.md +67 -0
  2727. package/payload/premium-plugins/writer-craft/skills/reader-engagement/references/neurochemistry-of-engagement.md +94 -0
  2728. package/payload/premium-plugins/writer-craft/skills/review-manuscript/SKILL.md +111 -0
  2729. package/payload/premium-plugins/writer-craft/skills/review-manuscript/references/review-manuscript-checklist.md +119 -0
  2730. package/payload/premium-plugins/writer-craft/skills/review-prose/SKILL.md +99 -0
  2731. package/payload/premium-plugins/writer-craft/skills/review-prose/references/prose-review-checklist.md +112 -0
  2732. package/payload/premium-plugins/writer-craft/skills/review-scene/SKILL.md +99 -0
  2733. package/payload/premium-plugins/writer-craft/skills/review-scene/references/scene-analysis-framework.md +95 -0
  2734. package/payload/premium-plugins/writer-craft/skills/story-architecture/SKILL.md +106 -0
  2735. package/payload/premium-plugins/writer-craft/skills/story-architecture/references/blueprinting-and-scene-cards.md +118 -0
  2736. package/payload/premium-plugins/writer-craft/skills/story-architecture/references/inner-issue-and-protagonist-goal.md +66 -0
  2737. package/payload/premium-plugins/writer-craft/skills/story-architecture/references/misbelief-desire-worldview.md +87 -0
  2738. package/payload/premium-plugins/writer-craft/skills/story-architecture/references/origin-scenes-and-escalation.md +82 -0
  2739. package/payload/premium-plugins/writer-craft/skills/story-blueprint/SKILL.md +133 -0
  2740. package/payload/premium-plugins/writer-craft/skills/story-blueprint/references/blueprinting-exercises.md +118 -0
  2741. package/payload/premium-plugins/writer-craft/skills/story-blueprint/references/blueprinting-process.md +128 -0
  2742. package/payload/premium-plugins/writer-craft/skills/voice-mirror/SKILL.md +241 -0
  2743. package/payload/server/adminuser-self-heal-LC7HZAC6.js +54 -0
  2744. package/payload/server/chunk-NE7G5GT7.js +5807 -0
  2745. package/payload/server/chunk-PFF6I7KP.js +31 -0
  2746. package/payload/server/maxy-edge.js +832 -0
  2747. package/payload/server/package.json +11 -0
  2748. package/payload/server/power-health.cjs +129 -0
  2749. package/payload/server/public/assets/AdminLoginScreens-CHTeh_Vu.js +1 -0
  2750. package/payload/server/public/assets/AdminLoginScreens-CWMpccrR.css +1 -0
  2751. package/payload/server/public/assets/AdminShell-DjoP7YoA.js +1 -0
  2752. package/payload/server/public/assets/Checkbox-D58GsKoQ.js +1 -0
  2753. package/payload/server/public/assets/OperatorConversations-CDdp2nVn.css +1 -0
  2754. package/payload/server/public/assets/OperatorConversations-RmqANYz8.js +9 -0
  2755. package/payload/server/public/assets/_baseFor-DVaNaTfF.js +1 -0
  2756. package/payload/server/public/assets/admin-LGICBqil.js +1 -0
  2757. package/payload/server/public/assets/admin-types-CJrGd46U.js +1 -0
  2758. package/payload/server/public/assets/arc-CxLB9WCE.js +1 -0
  2759. package/payload/server/public/assets/architecture-YZFGNWBL-DN-MYxff.js +1 -0
  2760. package/payload/server/public/assets/architectureDiagram-Q4EWVU46-D-EdJPSY.js +36 -0
  2761. package/payload/server/public/assets/array-8_H1156C.js +1 -0
  2762. package/payload/server/public/assets/blockDiagram-DXYQGD6D-CXx9RgCm.js +132 -0
  2763. package/payload/server/public/assets/browser-CRgweVtw.js +1 -0
  2764. package/payload/server/public/assets/c4Diagram-AHTNJAMY-RFBXEe0B.js +10 -0
  2765. package/payload/server/public/assets/channel-y27xl53N.js +1 -0
  2766. package/payload/server/public/assets/chat-CXPRTVW7.js +1 -0
  2767. package/payload/server/public/assets/chunk-2KRD3SAO-DBqAFwK9.js +1 -0
  2768. package/payload/server/public/assets/chunk-336JU56O-DdnFEz6R.js +2 -0
  2769. package/payload/server/public/assets/chunk-426QAEUC-D8Iwaegm.js +1 -0
  2770. package/payload/server/public/assets/chunk-4BX2VUAB-cnw-3Gbs.js +1 -0
  2771. package/payload/server/public/assets/chunk-4TB4RGXK-BnqJ0bDc.js +206 -0
  2772. package/payload/server/public/assets/chunk-55IACEB6-BwyHvvzo.js +1 -0
  2773. package/payload/server/public/assets/chunk-5FUZZQ4R-DXA9U02I.js +62 -0
  2774. package/payload/server/public/assets/chunk-5PVQY5BW-D78bZ_8D.js +2 -0
  2775. package/payload/server/public/assets/chunk-67CJDMHE-CtE_Mgv7.js +1 -0
  2776. package/payload/server/public/assets/chunk-7N4EOEYR-CUZDaySl.js +1 -0
  2777. package/payload/server/public/assets/chunk-AA7GKIK3-CYQ3jO4X.js +1 -0
  2778. package/payload/server/public/assets/chunk-BSJP7CBP-BbA_HyTR.js +1 -0
  2779. package/payload/server/public/assets/chunk-CIAEETIT-D7_YqRhG.js +1 -0
  2780. package/payload/server/public/assets/chunk-EDXVE4YY-B23LrtSw.js +1 -0
  2781. package/payload/server/public/assets/chunk-ENJZ2VHE-D3fTHYKN.js +10 -0
  2782. package/payload/server/public/assets/chunk-FMBD7UC4-DFAA2tyh.js +15 -0
  2783. package/payload/server/public/assets/chunk-FOC6F5B3-BF4IHvlI.js +1 -0
  2784. package/payload/server/public/assets/chunk-ICPOFSXX-DBUGemHy.js +122 -0
  2785. package/payload/server/public/assets/chunk-K5T4RW27-rMMs08Eh.js +94 -0
  2786. package/payload/server/public/assets/chunk-KGLVRYIC-BD2r8R2G.js +1 -0
  2787. package/payload/server/public/assets/chunk-LIHQZDEY-D4sYTTwM.js +1 -0
  2788. package/payload/server/public/assets/chunk-ORNJ4GCN-CAs_uFzb.js +1 -0
  2789. package/payload/server/public/assets/chunk-OYMX7WX6-Fkp-2ORc.js +231 -0
  2790. package/payload/server/public/assets/chunk-Pqm5yXtL.js +1 -0
  2791. package/payload/server/public/assets/chunk-QZHKN3VN-qHqDpwz3.js +1 -0
  2792. package/payload/server/public/assets/chunk-U2HBQHQK-D_pxZh25.js +70 -0
  2793. package/payload/server/public/assets/chunk-X2U36JSP-CeVmvvRf.js +1 -0
  2794. package/payload/server/public/assets/chunk-XPW4576I-iWP54fKp.js +32 -0
  2795. package/payload/server/public/assets/chunk-YZCP3GAM-CNtbWJNN.js +1 -0
  2796. package/payload/server/public/assets/chunk-ZZ45TVLE-BmlFjU_9.js +1 -0
  2797. package/payload/server/public/assets/classDiagram-6PBFFD2Q-DgVoYWhO.js +1 -0
  2798. package/payload/server/public/assets/classDiagram-v2-HSJHXN6E-C0WNP3uN.js +1 -0
  2799. package/payload/server/public/assets/clone-D50F_pvg.js +1 -0
  2800. package/payload/server/public/assets/cormorant-cyrillic-300-normal-CzPHYadL.woff +0 -0
  2801. package/payload/server/public/assets/cormorant-cyrillic-300-normal-DFUoTmrg.woff2 +0 -0
  2802. package/payload/server/public/assets/cormorant-cyrillic-400-normal-C8QS47vb.woff2 +0 -0
  2803. package/payload/server/public/assets/cormorant-cyrillic-400-normal-D3EsxgFc.woff +0 -0
  2804. package/payload/server/public/assets/cormorant-cyrillic-500-normal-B7dJQtg-.woff +0 -0
  2805. package/payload/server/public/assets/cormorant-cyrillic-500-normal-BLlg2W5x.woff2 +0 -0
  2806. package/payload/server/public/assets/cormorant-cyrillic-ext-300-normal-BXl3lXsi.woff2 +0 -0
  2807. package/payload/server/public/assets/cormorant-cyrillic-ext-300-normal-DmxSOTe3.woff +0 -0
  2808. package/payload/server/public/assets/cormorant-cyrillic-ext-400-normal-Bgrpe4p1.woff +0 -0
  2809. package/payload/server/public/assets/cormorant-cyrillic-ext-400-normal-BlcaxZtM.woff2 +0 -0
  2810. package/payload/server/public/assets/cormorant-cyrillic-ext-500-normal-CdQuyvtc.woff +0 -0
  2811. package/payload/server/public/assets/cormorant-cyrillic-ext-500-normal-pZw22qtS.woff2 +0 -0
  2812. package/payload/server/public/assets/cormorant-latin-300-normal-CJ5dfen0.woff2 +0 -0
  2813. package/payload/server/public/assets/cormorant-latin-300-normal-DQZObO_3.woff +0 -0
  2814. package/payload/server/public/assets/cormorant-latin-400-normal-BGH8Vunh.woff2 +0 -0
  2815. package/payload/server/public/assets/cormorant-latin-400-normal-C3_-2Ua-.woff +0 -0
  2816. package/payload/server/public/assets/cormorant-latin-500-normal-Dj3SQ6fR.woff +0 -0
  2817. package/payload/server/public/assets/cormorant-latin-500-normal-EBdSCOD3.woff2 +0 -0
  2818. package/payload/server/public/assets/cormorant-latin-ext-300-normal-CkiUx0UG.woff +0 -0
  2819. package/payload/server/public/assets/cormorant-latin-ext-300-normal-De3D72RL.woff2 +0 -0
  2820. package/payload/server/public/assets/cormorant-latin-ext-400-normal-DuQ88yz3.woff2 +0 -0
  2821. package/payload/server/public/assets/cormorant-latin-ext-400-normal-DuXFa1Dr.woff +0 -0
  2822. package/payload/server/public/assets/cormorant-latin-ext-500-normal-AH9qog1s.woff2 +0 -0
  2823. package/payload/server/public/assets/cormorant-latin-ext-500-normal-DAuUCO41.woff +0 -0
  2824. package/payload/server/public/assets/cormorant-vietnamese-300-normal-BVqIp_mg.woff2 +0 -0
  2825. package/payload/server/public/assets/cormorant-vietnamese-300-normal-CEMS9Pw-.woff +0 -0
  2826. package/payload/server/public/assets/cormorant-vietnamese-400-normal-C-RiYxEf.woff2 +0 -0
  2827. package/payload/server/public/assets/cormorant-vietnamese-400-normal-DmUuA7Y2.woff +0 -0
  2828. package/payload/server/public/assets/cormorant-vietnamese-500-normal-DsPuwQHi.woff2 +0 -0
  2829. package/payload/server/public/assets/cormorant-vietnamese-500-normal-tGBW_mI7.woff +0 -0
  2830. package/payload/server/public/assets/cose-bilkent-S5V4N54A-C7YmF1Pg.js +1 -0
  2831. package/payload/server/public/assets/cytoscape.esm-h10p_6j-.js +321 -0
  2832. package/payload/server/public/assets/dagre-BAmiDDtR.js +1 -0
  2833. package/payload/server/public/assets/dagre-KV5264BT-Ca3ESJhc.js +4 -0
  2834. package/payload/server/public/assets/data-CttrzhfL.js +1 -0
  2835. package/payload/server/public/assets/defaultLocale-pD7tFa1r.js +1 -0
  2836. package/payload/server/public/assets/diagram-5BDNPKRD-BgT1ORf2.js +10 -0
  2837. package/payload/server/public/assets/diagram-G4DWMVQ6-BTaUIiem.js +24 -0
  2838. package/payload/server/public/assets/diagram-MMDJMWI5-Bdb2g6Uo.js +43 -0
  2839. package/payload/server/public/assets/diagram-TYMM5635-CkLGC0zZ.js +24 -0
  2840. package/payload/server/public/assets/dist-Bkbhs3jw.js +1 -0
  2841. package/payload/server/public/assets/dm-sans-latin-400-normal-BwCSEQnW.woff +0 -0
  2842. package/payload/server/public/assets/dm-sans-latin-400-normal-CW0RaeGs.woff2 +0 -0
  2843. package/payload/server/public/assets/dm-sans-latin-500-normal-B9HHJjqV.woff2 +0 -0
  2844. package/payload/server/public/assets/dm-sans-latin-500-normal-Dr3UlScf.woff +0 -0
  2845. package/payload/server/public/assets/dm-sans-latin-ext-400-normal-BjWJ59Pq.woff +0 -0
  2846. package/payload/server/public/assets/dm-sans-latin-ext-400-normal-BtiwyxMk.woff2 +0 -0
  2847. package/payload/server/public/assets/dm-sans-latin-ext-500-normal-BJfUCQsA.woff2 +0 -0
  2848. package/payload/server/public/assets/dm-sans-latin-ext-500-normal-DR84L5F-.woff +0 -0
  2849. package/payload/server/public/assets/erDiagram-SMLLAGMA-D_sj4DMg.js +85 -0
  2850. package/payload/server/public/assets/flatten-E2Sr0FeD.js +1 -0
  2851. package/payload/server/public/assets/flowDiagram-DWJPFMVM-iLERoZTe.js +162 -0
  2852. package/payload/server/public/assets/ganttDiagram-T4ZO3ILL-D60hjMBy.js +292 -0
  2853. package/payload/server/public/assets/gitGraph-7Q5UKJZL-D-L2yzYf.js +1 -0
  2854. package/payload/server/public/assets/gitGraphDiagram-UUTBAWPF-Di0XM6fi.js +106 -0
  2855. package/payload/server/public/assets/graph-CIBba84R.js +51 -0
  2856. package/payload/server/public/assets/graph-labels-Bi0fu8Ns.js +1 -0
  2857. package/payload/server/public/assets/graphlib-C8fUP7uV.js +1 -0
  2858. package/payload/server/public/assets/info-OMHHGYJF-BQn6jndO.js +1 -0
  2859. package/payload/server/public/assets/infoDiagram-42DDH7IO-BwMdbiXg.js +2 -0
  2860. package/payload/server/public/assets/init-CwJ4b81e.js +1 -0
  2861. package/payload/server/public/assets/isEmpty-CLz-UprQ.js +1 -0
  2862. package/payload/server/public/assets/ishikawaDiagram-UXIWVN3A-CwgI4B5Z.js +70 -0
  2863. package/payload/server/public/assets/jetbrains-mono-cyrillic-400-normal-BEIGL1Tu.woff2 +0 -0
  2864. package/payload/server/public/assets/jetbrains-mono-cyrillic-400-normal-ugxPyKxw.woff +0 -0
  2865. package/payload/server/public/assets/jetbrains-mono-cyrillic-500-normal-DJqRU3vO.woff +0 -0
  2866. package/payload/server/public/assets/jetbrains-mono-cyrillic-500-normal-DmUKJPL_.woff2 +0 -0
  2867. package/payload/server/public/assets/jetbrains-mono-greek-400-normal-B9oWc5Lo.woff +0 -0
  2868. package/payload/server/public/assets/jetbrains-mono-greek-400-normal-C190GLew.woff2 +0 -0
  2869. package/payload/server/public/assets/jetbrains-mono-greek-500-normal-D7SFKleX.woff +0 -0
  2870. package/payload/server/public/assets/jetbrains-mono-greek-500-normal-JpySY46c.woff2 +0 -0
  2871. package/payload/server/public/assets/jetbrains-mono-latin-400-normal-6-qcROiO.woff +0 -0
  2872. package/payload/server/public/assets/jetbrains-mono-latin-400-normal-V6pRDFza.woff2 +0 -0
  2873. package/payload/server/public/assets/jetbrains-mono-latin-500-normal-BWZEU5yA.woff2 +0 -0
  2874. package/payload/server/public/assets/jetbrains-mono-latin-500-normal-CJOVTJB7.woff +0 -0
  2875. package/payload/server/public/assets/jetbrains-mono-latin-ext-400-normal-Bc8Ftmh3.woff2 +0 -0
  2876. package/payload/server/public/assets/jetbrains-mono-latin-ext-400-normal-fXTG6kC5.woff +0 -0
  2877. package/payload/server/public/assets/jetbrains-mono-latin-ext-500-normal-Cut-4mMH.woff2 +0 -0
  2878. package/payload/server/public/assets/jetbrains-mono-latin-ext-500-normal-ckzbgY84.woff +0 -0
  2879. package/payload/server/public/assets/jetbrains-mono-vietnamese-400-normal-CqNFfHCs.woff +0 -0
  2880. package/payload/server/public/assets/jetbrains-mono-vietnamese-500-normal-DNRqzVM1.woff +0 -0
  2881. package/payload/server/public/assets/journeyDiagram-VCZTEJTY-CxBu-tze.js +139 -0
  2882. package/payload/server/public/assets/kanban-definition-6JOO6SKY-D2qlheA5.js +89 -0
  2883. package/payload/server/public/assets/katex-DJPjIBAI.js +257 -0
  2884. package/payload/server/public/assets/line-Bdod7uzQ.js +1 -0
  2885. package/payload/server/public/assets/linear-BiVe6QzC.js +1 -0
  2886. package/payload/server/public/assets/mermaid-parser.core-xZN7hC6M.js +4 -0
  2887. package/payload/server/public/assets/mermaid.core-D0IylAac.js +11 -0
  2888. package/payload/server/public/assets/mindmap-definition-QFDTVHPH-J_Szhwf1.js +96 -0
  2889. package/payload/server/public/assets/operator-mwkYv8g5.js +1 -0
  2890. package/payload/server/public/assets/ordinal-5RtyPJVt.js +1 -0
  2891. package/payload/server/public/assets/packet-4T2RLAQJ-DmkQBx4h.js +1 -0
  2892. package/payload/server/public/assets/page-BpxHz1N-.js +30 -0
  2893. package/payload/server/public/assets/path-CK8wrAxY.js +1 -0
  2894. package/payload/server/public/assets/pie-ZZUOXDRM-DDnxYUBm.js +1 -0
  2895. package/payload/server/public/assets/pieDiagram-DEJITSTG-CV5DxUVx.js +30 -0
  2896. package/payload/server/public/assets/preload-helper-Bf_JiD2A.js +1 -0
  2897. package/payload/server/public/assets/public-CiUboUwu.js +1 -0
  2898. package/payload/server/public/assets/quadrantDiagram-34T5L4WZ-BsFMVizF.js +7 -0
  2899. package/payload/server/public/assets/radar-PYXPWWZC-7H4k0ChM.js +1 -0
  2900. package/payload/server/public/assets/reduce-B3Mw_0s1.js +1 -0
  2901. package/payload/server/public/assets/requirementDiagram-MS252O5E-C5eRRvGc.js +84 -0
  2902. package/payload/server/public/assets/rough.esm-Dwml_la6.js +1 -0
  2903. package/payload/server/public/assets/sankeyDiagram-XADWPNL6-CJYv5gpw.js +10 -0
  2904. package/payload/server/public/assets/sequenceDiagram-FGHM5R23-B25563_2.js +157 -0
  2905. package/payload/server/public/assets/src-BKOAoFQc.js +1 -0
  2906. package/payload/server/public/assets/stateDiagram-FHFEXIEX-BLyNJYOA.js +1 -0
  2907. package/payload/server/public/assets/stateDiagram-v2-QKLJ7IA2-BSVuxZxz.js +1 -0
  2908. package/payload/server/public/assets/timeline-definition-GMOUNBTQ-D-HgOM6Q.js +120 -0
  2909. package/payload/server/public/assets/treeView-SZITEDCU-BLXWTQtW.js +1 -0
  2910. package/payload/server/public/assets/treemap-W4RFUUIX-DiePDF5d.js +1 -0
  2911. package/payload/server/public/assets/vennDiagram-DHZGUBPP-Cw1JElYp.js +34 -0
  2912. package/payload/server/public/assets/wardley-RL74JXVD-OSUWK5LN.js +1 -0
  2913. package/payload/server/public/assets/wardleyDiagram-NUSXRM2D-BqMWzEko.js +20 -0
  2914. package/payload/server/public/assets/xychartDiagram-5P7HB3ND-DBp71TLT.js +7 -0
  2915. package/payload/server/public/brand/claude.png +0 -0
  2916. package/payload/server/public/brand/maxy-black.png +0 -0
  2917. package/payload/server/public/brand/maxy-monochrome.png +0 -0
  2918. package/payload/server/public/brand/maxy.png +0 -0
  2919. package/payload/server/public/brand/sitedesk-black.png +0 -0
  2920. package/payload/server/public/brand/sitedesk-favicon-180.png +0 -0
  2921. package/payload/server/public/brand/sitedesk-favicon-32.png +0 -0
  2922. package/payload/server/public/brand/sitedesk-favicon-512.png +0 -0
  2923. package/payload/server/public/brand/sitedesk-horizontal-dark.png +0 -0
  2924. package/payload/server/public/brand/sitedesk-horizontal.png +0 -0
  2925. package/payload/server/public/brand/sitedesk-icon.svg +8 -0
  2926. package/payload/server/public/brand/sitedesk-monochrome.png +0 -0
  2927. package/payload/server/public/brand/sitedesk-square.png +0 -0
  2928. package/payload/server/public/brand/sitedesk-stacked.png +0 -0
  2929. package/payload/server/public/brand/sitedesk-white.png +0 -0
  2930. package/payload/server/public/brand/star.png +0 -0
  2931. package/payload/server/public/brand-constants.json +8 -0
  2932. package/payload/server/public/brand-defaults.css +12 -0
  2933. package/payload/server/public/browser.html +17 -0
  2934. package/payload/server/public/chat.html +20 -0
  2935. package/payload/server/public/consent.css +97 -0
  2936. package/payload/server/public/consent.js +259 -0
  2937. package/payload/server/public/data.html +17 -0
  2938. package/payload/server/public/favicon.ico +0 -0
  2939. package/payload/server/public/graph.html +19 -0
  2940. package/payload/server/public/index.html +22 -0
  2941. package/payload/server/public/operator.html +23 -0
  2942. package/payload/server/public/privacy.html +129 -0
  2943. package/payload/server/public/public.html +21 -0
  2944. package/payload/server/public/robots.txt +5 -0
  2945. package/payload/server/public/sw.js +24 -0
  2946. package/payload/server/public/v.js +244 -0
  2947. package/payload/server/public/vnc-popout.html +63 -0
  2948. package/payload/server/public/whatsapp-wallpaper.webp +0 -0
  2949. package/payload/server/server-init-line-stamper.cjs +26 -0
  2950. package/payload/server/server-init.cjs +251 -0
  2951. package/payload/server/server.js +21647 -0
package/dist/index.js ADDED
@@ -0,0 +1,4418 @@
1
+ #!/usr/bin/env node
2
+ import { execFileSync, spawn, spawnSync } from "node:child_process";
3
+ import { existsSync, mkdirSync, writeFileSync, cpSync, readFileSync, rmSync, readdirSync, appendFileSync, openSync, closeSync, chmodSync, statSync, realpathSync } from "node:fs";
4
+ import { registerSpecialistAgentsAt, SpecialistSymlinkCollision } from "./specialist-registration.js";
5
+ import { seedBypassPermissionsSettings, assertBypassPermissionsSeed } from "./permissions-seed.js";
6
+ import { resolve, join, dirname } from "node:path";
7
+ import { randomBytes } from "node:crypto";
8
+ import { resolveInstallPortFromFs, buildMaxyUnitFile, buildClaudeSessionManagerUnitFile, buildClaudePtysSliceUnitFile, buildCloudflaredSliceUnitFile } from "./port-resolution.js";
9
+ import { validateTierFlag, validateEntitlementBase64, applyTierToAccountConfig, entitlementPath } from "./tier-flag.js";
10
+ import { parseOsRelease, isUbuntuLike as isUbuntuLikePure, parseAptCacheCandidate, decideAptResolution, } from "./apt-resolve.js";
11
+ import { findPeerBrandOnDefaultNeo4jPort } from "./peer-brand-detect.js";
12
+ import { runInitLogging } from "./init-logging.js";
13
+ import { requireSupportedPlatform, detectPlatform } from "./platform-detect.js";
14
+ import { protectCommands, unprotectCommands, lsattrShowsImmutable } from "./install-immutability.js";
15
+ import { renderPlist } from "./launchd-plist.js";
16
+ import { installAllBrewPackages } from "./brew-install.js";
17
+ import { parseSwVers, isSupportedMacosVersion } from "./macos-version.js";
18
+ import { decideChromiumAction, isSnapConfinedPath } from "./snap-chromium.js";
19
+ import { classifyPortHolder } from "./preflight-port-classifier.js";
20
+ import { parsePluginList, computeInstallActions, parseExternalPlugins, findUnregisteredResyncs, } from "./lib/plugin-install.js";
21
+ import { findPremiumMcpDirs } from "./lib/premium-mcp-discover.js";
22
+ import { pickBindDecision, mergeSmbConf, formatSambaMarker, SAMBA_ENABLE_UNITS, } from "./samba-provision.js";
23
+ import { networkInterfaces, userInfo, cpus } from "node:os";
24
+ const PAYLOAD_DIR = resolve(import.meta.dirname, "../payload");
25
+ // Brand manifest — read from payload to derive all brand-specific installation values.
26
+ // The bundler stamps brand.json into the payload at build time.
27
+ const BRAND_PATH = join(PAYLOAD_DIR, "platform", "config", "brand.json");
28
+ if (!existsSync(BRAND_PATH)) {
29
+ console.error("Setup failed: brand.json not found in payload (package may be corrupted)");
30
+ console.error("FATAL: brand.json not found in payload. Package may be corrupted.");
31
+ process.exit(1);
32
+ }
33
+ let BRAND;
34
+ try {
35
+ BRAND = JSON.parse(readFileSync(BRAND_PATH, "utf-8"));
36
+ }
37
+ catch (err) {
38
+ console.error(`Setup failed: failed to parse brand.json: ${err.message}`);
39
+ console.error(`FATAL: Failed to parse brand.json: ${err.message}`);
40
+ process.exit(1);
41
+ }
42
+ const INSTALL_DIR = resolve(process.env.HOME ?? "/root", BRAND.installDir);
43
+ const PERSIST_DIR = resolve(process.env.HOME ?? "/root", BRAND.configDir);
44
+ const LOG_DIR = join(PERSIST_DIR, "logs");
45
+ const LOG_FILE = join(LOG_DIR, `install-${new Date().toISOString().replace(/[:.]/g, "-")}.log`);
46
+ // every `claude plugin` shellout must read/write the per-brand
47
+ // CLAUDE_CONFIG_DIR that the systemd unit at port-resolution.ts:229,286 uses
48
+ // at runtime. Without this override, the installer writes marketplaces and
49
+ // enabledPlugins to $HOME/.claude/settings.json (user-default), and the
50
+ // PTY spawned by the session-manager sees an empty config dir — plugins
51
+ // the operator turned on are invisible to the agent.
52
+ const CLAUDE_CONFIG_DIR = join(PERSIST_DIR, ".claude");
53
+ function claudePluginEnv() {
54
+ return { ...process.env, CLAUDE_CONFIG_DIR };
55
+ }
56
+ /** Known brand hostnames in the Maxy ecosystem. Each brand ships a main unit
57
+ * (`<hostname>.service`) and a per-brand edge unit
58
+ * (`<hostname>-edge.service`). Peer-brand detection matches only these
59
+ * filenames — stale units,
60
+ * gnome-keyring disable markers, and unrelated user services are not peer
61
+ * evidence. When a third brand is added under `brands/`, append its hostname
62
+ * here AND in the matching constant in `uninstall.ts` (intentional duplication
63
+ * per `uninstall.ts:` "Shell helpers (duplicated from index.ts ...)" policy). */
64
+ const KNOWN_BRAND_HOSTNAMES = ["maxy", "maxy-code", "realagent", "realagent-code", "maxy-2", "maxy-3", "maxy-4"];
65
+ // The device's actual hostname — may differ from BRAND.hostname if the user customized it.
66
+ // Updated by installSystemDeps() after hostname setup; used for user-facing URLs.
67
+ let DEVICE_HOSTNAME = BRAND.hostname;
68
+ // absolute path to the non-snap Chromium binary chosen during
69
+ // installSystemDeps(). Defaults to /usr/bin/chromium so non-Linux installs
70
+ // (which never call ensureNonSnapChromium) and the systemd unit's
71
+ // PLAYWRIGHT_CHROMIUM_EXECUTABLE_PATH still see a sensible value. On Linux,
72
+ // installSystemDeps() always overwrites this — either /usr/bin/chromium (Pi
73
+ // Bookworm: real .deb) or /usr/bin/google-chrome-stable (Ubuntu Noble laptop:
74
+ // snap-confined chromium replaced). Read by writeChromiumBinaryPathFile()
75
+ // and threaded into buildMaxyUnitFile() so the chromium-binary.path config
76
+ // file, the systemd unit's PLAYWRIGHT env var, and vnc.sh's runtime resolver
77
+ // all agree on one absolute path.
78
+ let RESOLVED_CHROMIUM_BIN = "/usr/bin/chromium";
79
+ // npm flags tuned for Raspberry Pi — reduce parallelism, increase patience
80
+ const NPM_NET_FLAGS = [
81
+ "--fetch-retries=5",
82
+ "--fetch-retry-mintimeout=30000",
83
+ "--fetch-retry-maxtimeout=120000",
84
+ "--maxsockets=3",
85
+ ];
86
+ // ---------------------------------------------------------------------------
87
+ // Logging — timestamped to console AND persistent log file
88
+ // ---------------------------------------------------------------------------
89
+ function initLogging() {
90
+ runInitLogging({
91
+ logDir: LOG_DIR,
92
+ logFile: LOG_FILE,
93
+ persistDir: PERSIST_DIR,
94
+ headerLines: [
95
+ "",
96
+ "=".repeat(64),
97
+ ` ${BRAND.productName} Install Log — ${new Date().toISOString()}`,
98
+ ` Node ${process.version} | ${process.platform} ${process.arch}`,
99
+ "=".repeat(64),
100
+ "",
101
+ ],
102
+ });
103
+ }
104
+ function logFile(msg) {
105
+ try {
106
+ appendFileSync(LOG_FILE, `[${new Date().toISOString()}] ${msg}\n`);
107
+ }
108
+ catch { /* fs full */ }
109
+ }
110
+ // Mirror all console output into the log file
111
+ const _log = console.log;
112
+ const _err = console.error;
113
+ console.log = (...args) => { _log(...args); logFile(args.map(String).join(" ")); };
114
+ console.error = (...args) => { _err(...args); logFile(`[ERROR] ${args.map(String).join(" ")}`); };
115
+ // ---------------------------------------------------------------------------
116
+ // Diagnostics — system state snapshot for post-mortem analysis
117
+ // ---------------------------------------------------------------------------
118
+ function logDiagnostics(label) {
119
+ logFile(`\n--- Diagnostics: ${label} ---`);
120
+ if (!isLinux()) {
121
+ logFile(" (not Linux — limited diagnostics)");
122
+ return;
123
+ }
124
+ const run = (cmd, args) => {
125
+ const r = spawnSync(cmd, args, { encoding: "utf-8", stdio: "pipe", timeout: 10_000 });
126
+ return (r.stdout || r.stderr || "").trim();
127
+ };
128
+ logFile(`Disk:\n${run("df", ["-h", "/", "/tmp"])}`);
129
+ logFile(`Memory:\n${run("free", ["-h"])}`);
130
+ logFile(`Uptime: ${run("uptime", [])}`);
131
+ for (const host of ["registry.npmjs.org", "github.com"]) {
132
+ const dns = spawnSync("host", ["-W", "5", host], { encoding: "utf-8", stdio: "pipe", timeout: 10_000 });
133
+ logFile(`DNS ${host}: ${dns.status === 0 ? "OK" : "FAIL"} — ${(dns.stdout || dns.stderr || "").trim().split("\n")[0]}`);
134
+ }
135
+ const curl = spawnSync("curl", [
136
+ "-sf", "-o", "/dev/null",
137
+ "-w", "HTTP %{http_code} in %{time_total}s (dns: %{time_namelookup}s, connect: %{time_connect}s)",
138
+ "--connect-timeout", "10",
139
+ "https://registry.npmjs.org/",
140
+ ], { encoding: "utf-8", stdio: "pipe", timeout: 15_000 });
141
+ logFile(`Registry HTTP: ${curl.stdout?.trim() || `FAIL — ${curl.stderr?.trim()}`}`);
142
+ logFile(`--- End Diagnostics ---\n`);
143
+ }
144
+ /** Append the most recent npm debug log into our install log for post-mortem. */
145
+ function captureNpmDebugLog() {
146
+ const logsDir = resolve(process.env.HOME ?? "/root", ".npm/_logs");
147
+ if (!existsSync(logsDir))
148
+ return;
149
+ try {
150
+ const files = readdirSync(logsDir).filter(f => f.endsWith("-debug-0.log")).sort().reverse();
151
+ if (files[0]) {
152
+ const content = readFileSync(join(logsDir, files[0]), "utf-8");
153
+ logFile(`\n--- npm debug log: ${files[0]} (last 200 lines) ---`);
154
+ const lines = content.split("\n");
155
+ logFile(lines.slice(Math.max(0, lines.length - 200)).join("\n"));
156
+ logFile(`--- end npm debug log ---\n`);
157
+ }
158
+ }
159
+ catch { /* ignore */ }
160
+ }
161
+ // ---------------------------------------------------------------------------
162
+ // Helpers
163
+ // ---------------------------------------------------------------------------
164
+ function log(step, total, message) {
165
+ console.log(`[${step}/${total}] ${message}`);
166
+ }
167
+ function shell(command, args, options) {
168
+ const cmd = options?.sudo ? "sudo" : command;
169
+ const cmdArgs = options?.sudo ? [command, ...args] : args;
170
+ const start = Date.now();
171
+ // Redaction: callers handling secrets pass redact: true so the
172
+ // wrapper records the command name only, not the secret-bearing args. The
173
+ // child process still receives the real args via spawnSync below; only the
174
+ // install log line is sanitised. The grep-able audit shape stays:
175
+ // > sudo neo4j-admin dbms set-initial-password [REDACTED]
176
+ const loggedArgs = options?.redact
177
+ ? `${cmdArgs.slice(0, options?.sudo ? 4 : 3).join(" ")} [REDACTED]`
178
+ : cmdArgs.join(" ");
179
+ logFile(`> ${cmd} ${loggedArgs}${options?.cwd ? ` [cwd: ${options.cwd}]` : ""}`);
180
+ const result = spawnSync(cmd, cmdArgs, {
181
+ stdio: "inherit",
182
+ timeout: options?.timeout ?? 300_000,
183
+ cwd: options?.cwd,
184
+ env: options?.env,
185
+ });
186
+ const dur = ((Date.now() - start) / 1000).toFixed(1);
187
+ // bestEffort: tear-down ops on units/state that may or may not
188
+ // exist (stop/disable a system service we may never have started, reset-failed
189
+ // a freshly-created unit) log the non-zero exit but do not throw. Reserved
190
+ // for the "may not exist" pattern only — never use for ops that must succeed.
191
+ if (result.signal) {
192
+ logFile(` KILLED (${result.signal}) after ${dur}s`);
193
+ if (options?.bestEffort)
194
+ return;
195
+ throw new Error(`Command killed (${result.signal}) after ${dur}s: ${cmd} ${cmdArgs.join(" ")}`);
196
+ }
197
+ if (result.status !== 0) {
198
+ logFile(` ${options?.bestEffort ? "best-effort non-zero" : "FAILED"} (exit ${result.status}) after ${dur}s`);
199
+ if (options?.bestEffort)
200
+ return;
201
+ throw new Error(`Command failed (exit ${result.status}) after ${dur}s: ${cmd} ${cmdArgs.join(" ")}`);
202
+ }
203
+ logFile(` OK in ${dur}s`);
204
+ }
205
+ /** Wait until DNS resolves for a host. Returns true if recovered. */
206
+ function waitForDns(host, maxSec = 60) {
207
+ for (let elapsed = 0; elapsed < maxSec; elapsed += 5) {
208
+ const r = spawnSync("host", ["-W", "3", host], { stdio: "pipe", timeout: 5_000 });
209
+ if (r.status === 0) {
210
+ logFile(` DNS ${host}: recovered after ${elapsed}s`);
211
+ return true;
212
+ }
213
+ console.log(` DNS ${host} not resolving — waiting (${elapsed}s/${maxSec}s)...`);
214
+ spawnSync("sleep", ["5"]);
215
+ }
216
+ return false;
217
+ }
218
+ /** Retry a shell command with exponential backoff. Runs network diagnostics between attempts. */
219
+ function shellRetry(command, args, options, maxAttempts = 3, backoffSec = 20) {
220
+ for (let attempt = 1; attempt <= maxAttempts; attempt++) {
221
+ try {
222
+ shell(command, args, options);
223
+ return;
224
+ }
225
+ catch (err) {
226
+ const msg = err instanceof Error ? err.message : String(err);
227
+ logFile(` Attempt ${attempt}/${maxAttempts} error: ${msg}`);
228
+ if (attempt === maxAttempts) {
229
+ console.error(` All ${maxAttempts} attempts failed.`);
230
+ logDiagnostics(`final failure — ${command}`);
231
+ if (command === "npm")
232
+ captureNpmDebugLog();
233
+ throw err;
234
+ }
235
+ const wait = backoffSec * attempt;
236
+ console.log(` Attempt ${attempt}/${maxAttempts} failed. Retrying in ${wait}s...`);
237
+ // On network errors, diagnose and wait for DNS recovery before retrying
238
+ if (/ETIMEDOUT|EAI_AGAIN|ECONNRESET|ENOTFOUND|ENETUNREACH/.test(msg)) {
239
+ console.log(" Network error — running diagnostics...");
240
+ logDiagnostics(`network failure — attempt ${attempt}`);
241
+ waitForDns("registry.npmjs.org");
242
+ }
243
+ if (command === "npm")
244
+ captureNpmDebugLog();
245
+ spawnSync("sleep", [String(wait)]);
246
+ }
247
+ }
248
+ }
249
+ function commandExists(cmd) {
250
+ try {
251
+ execFileSync("which", [cmd], { stdio: "pipe" });
252
+ return true;
253
+ }
254
+ catch {
255
+ return false;
256
+ }
257
+ }
258
+ function nodeVersion() {
259
+ try {
260
+ const v = execFileSync("node", ["-v"], { encoding: "utf-8" }).trim();
261
+ return parseInt(v.replace("v", "").split(".")[0], 10);
262
+ }
263
+ catch {
264
+ return 0;
265
+ }
266
+ }
267
+ function isLinux() {
268
+ return process.platform === "linux";
269
+ }
270
+ function isArm64() {
271
+ return process.arch === "arm64";
272
+ }
273
+ /** Check whether non-interactive sudo is available (passwordless or cached credentials). */
274
+ function canSudo() {
275
+ const result = spawnSync("sudo", ["-n", "true"], { stdio: "pipe", timeout: 5_000 });
276
+ return result.status === 0;
277
+ }
278
+ // verified-not-asserted apt-dep reconciliation.
279
+ // resolve package-name aliases before probing dpkg, so the
280
+ // post-install check no longer false-negatives when apt resolves a virtual
281
+ // name (e.g. Noble's `chromium` → `chromium-browser`).
282
+ // UBUNTU_ALIASES, parseOsRelease, isUbuntuLike, and decideAptResolution moved
283
+ // to./apt-resolve.ts. The pure logic lives there so a unit test
284
+ // can hit every branch without spawning real apt/dpkg or reading
285
+ // /etc/os-release. The thin wrappers below feed real spawn + fs results into
286
+ // that pure decision.
287
+ function readOsRelease() {
288
+ try {
289
+ return parseOsRelease(readFileSync("/etc/os-release", "utf-8"));
290
+ }
291
+ catch {
292
+ return {};
293
+ }
294
+ }
295
+ /** Summarise `apt-cache policy` output for diagnostics — one token per package. */
296
+ function aptCachePolicySummary(pkg) {
297
+ const r = spawnSync("apt-cache", ["policy", pkg], { stdio: "pipe", encoding: "utf-8", timeout: 5_000 });
298
+ if (r.status !== 0)
299
+ return "policy-spawn-failed";
300
+ const cand = parseAptCacheCandidate(r.stdout ?? "");
301
+ if (cand === null)
302
+ return "no-candidate-line";
303
+ return cand === "(none)" ? "candidate-none" : `candidate=${cand}`;
304
+ }
305
+ /**
306
+ * map an apt-level package name to the concrete name dpkg will
307
+ * record after install. Resolution order:
308
+ * 1. `dpkg -s pkg` exits 0 → name is concrete and installed; return pkg.
309
+ * 2. `apt-cache policy pkg` reports a real Candidate → concrete-but-missing;
310
+ * return pkg (apt-get install + post-check will use the same name).
311
+ * 3. `apt-cache policy pkg` reports `Candidate: (none)` and `pkg` is in
312
+ * UBUNTU_ALIASES on an Ubuntu-like host → return the alias. Log the
313
+ * resolution so the install log answers "what did apt resolve this to?".
314
+ * 4. Otherwise return pkg unchanged — the post-check will throw loudly,
315
+ * preserving the fail-loud contract for genuinely missing packages.
316
+ */
317
+ function resolveAptName(pkg) {
318
+ const dpkg = spawnSync("dpkg", ["-s", pkg], { stdio: "pipe", timeout: 5_000 });
319
+ const dpkgInstalled = dpkg.status === 0;
320
+ // Short-circuit: when dpkg already records the name as installed, skip the
321
+ // apt-cache + os-release work — `decideAptResolution` returns pkg unchanged
322
+ // anyway and the extra spawn would burn ~10 ms per already-installed
323
+ // package across every `pkgsMissing` pass.
324
+ if (dpkgInstalled)
325
+ return pkg;
326
+ const policy = spawnSync("apt-cache", ["policy", pkg], {
327
+ stdio: "pipe", encoding: "utf-8", timeout: 5_000,
328
+ });
329
+ const aptCandidate = policy.status === 0
330
+ ? parseAptCacheCandidate(policy.stdout ?? "")
331
+ : null;
332
+ const os = readOsRelease();
333
+ const decision = decideAptResolution({
334
+ pkg,
335
+ dpkgInstalled,
336
+ aptCandidate,
337
+ ubuntuLike: isUbuntuLikePure(os),
338
+ distro: `${os.ID ?? "unknown"}-${os.VERSION_CODENAME ?? "unknown"}`,
339
+ });
340
+ if (decision.log)
341
+ logFile(decision.log);
342
+ return decision.resolved;
343
+ }
344
+ /** Probe runtime binary presence on PATH (independent of dpkg-recorded state). */
345
+ function commandVPath(pkg) {
346
+ const r = spawnSync("which", [pkg], { stdio: "pipe", encoding: "utf-8", timeout: 5_000 });
347
+ return r.status === 0 ? (r.stdout ?? "").trim() || "missing" : "missing";
348
+ }
349
+ /** Probe snap-recorded state for a name (snap lives outside dpkg). */
350
+ function snapStatus(pkg) {
351
+ const r = spawnSync("snap", ["list", pkg], { stdio: "pipe", encoding: "utf-8", timeout: 5_000 });
352
+ if (r.status !== 0)
353
+ return "none";
354
+ const line = (r.stdout ?? "").split("\n").find((l) => l.startsWith(pkg));
355
+ return line ? line.split(/\s+/).slice(0, 2).join(" ") : "none";
356
+ }
357
+ /**
358
+ * Returns the subset of `pkgs` that are not currently installed, after
359
+ * alias resolution. Uses `dpkg -s <resolved>` per package (exit 0 = installed,
360
+ * any non-zero = missing) so we never parse dpkg's prose output for control
361
+ * flow (feedback_no_stdout_parsing_for_control_flow.md). The operator-facing
362
+ * name stays the original `pkg` — the resolution is logged but not renamed
363
+ * in the returned list, so diagnostics match what the installer declared.
364
+ */
365
+ function pkgsMissing(pkgs) {
366
+ return pkgs.filter((p) => {
367
+ const resolved = resolveAptName(p);
368
+ const r = spawnSync("dpkg", ["-s", resolved], { stdio: "pipe", timeout: 5_000 });
369
+ return r.status !== 0;
370
+ });
371
+ }
372
+ /**
373
+ * Install a logical group of apt packages, then verify each one landed in
374
+ * dpkg's installed state. The post-install `dpkg -s` probe catches the
375
+ * partial-failure class where `apt-get install` returns 0 but a package did
376
+ * not actually install — silent regressions that would otherwise only
377
+ * surface at runtime when the binary is missing.
378
+ *
379
+ * Resolves each package through `resolveAptName` before both the install
380
+ * command and the post-check, so alias packages pass through
381
+ * cleanly on distros where the apt-level name differs from the dpkg-recorded
382
+ * name (e.g. Noble's chromium → chromium-browser). Resolution is computed
383
+ * once per package and reused across install, post-check, and error
384
+ * diagnostics — three spawnSync chains per package, not nine on failure.
385
+ */
386
+ function installAptGroup(label, pkgs) {
387
+ const pairs = pkgs.map((original) => ({ original, resolved: resolveAptName(original) }));
388
+ logFile(` apt install (${label}): ${pairs.map((x) => x.resolved).join(" ")}`);
389
+ console.log(" [privileged] apt-get install");
390
+ shell("apt-get", ["install", "-y", ...pairs.map((x) => x.resolved)], { sudo: true });
391
+ const stillMissing = pairs.filter(({ resolved }) => {
392
+ const r = spawnSync("dpkg", ["-s", resolved], { stdio: "pipe", timeout: 5_000 });
393
+ return r.status !== 0;
394
+ });
395
+ if (stillMissing.length > 0) {
396
+ const diag = stillMissing.map(({ original, resolved }) => `${original} (resolved-name=${resolved}, apt-cache-policy=${aptCachePolicySummary(original)}, command-v=${commandVPath(original)}, snap-status=${snapStatus(resolved)})`).join("; ");
397
+ throw new Error(`apt-get install (${label}) returned 0 but packages are still not installed per dpkg -s: ${diag}`);
398
+ }
399
+ }
400
+ // ---------------------------------------------------------------------------
401
+ // Installation steps
402
+ // ---------------------------------------------------------------------------
403
+ const TOTAL = "11";
404
+ /**
405
+ * set macOS hostname via scutil. Three sequential `sudo scutil
406
+ * --set` calls (HostName, LocalHostName, ComputerName) — `hostnamectl` is
407
+ * Linux-only and `--hostname <h>` silently no-ops on darwin. All-or-nothing
408
+ * rollback within the 3-call batch: if any call fails, we restore the
409
+ * pre-batch values for the keys we already changed and re-throw. Full
410
+ * system-state rollback (avahi, /etc/hosts) is out of scope per the brief.
411
+ */
412
+ function setMacosHostnameViaScutil(hostname) {
413
+ const keys = ["HostName", "LocalHostName", "ComputerName"];
414
+ // Capture pre-batch values for rollback. Empty string is a legitimate
415
+ // scutil --get value (the key was never set) — preserve that as "" so
416
+ // rollback writes empty back rather than failing.
417
+ const previous = {};
418
+ for (const k of keys) {
419
+ const r = spawnSync("scutil", ["--get", k], { encoding: "utf-8", stdio: "pipe", timeout: 5_000 });
420
+ previous[k] = (r.stdout ?? "").trim();
421
+ }
422
+ const applied = [];
423
+ for (const k of keys) {
424
+ const r = spawnSync("sudo", ["scutil", "--set", k, hostname], { encoding: "utf-8", stdio: "inherit", timeout: 30_000 });
425
+ if (r.status !== 0) {
426
+ // Roll back any keys we already changed within this batch.
427
+ for (const done of applied) {
428
+ spawnSync("sudo", ["scutil", "--set", done, previous[done] ?? ""], { stdio: "inherit", timeout: 30_000 });
429
+ }
430
+ const stderr = r.stderr ? `: ${r.stderr.toString().trim()}` : "";
431
+ console.error(` [scutil] ${k} failed${stderr}`);
432
+ throw new Error(`scutil --set ${k} ${hostname} exited ${r.status}`);
433
+ }
434
+ applied.push(k);
435
+ }
436
+ console.log(` [scutil] HostName=${hostname} LocalHostName=${hostname} ComputerName=${hostname} set ok`);
437
+ }
438
+ /**
439
+ * detect snap-confined Chromium on Linux and install Google Chrome
440
+ * stable as the non-snap replacement. Runs after `installAptGroup("VNC stack")`
441
+ * inside `installSystemDeps`. Resolution rules live in `snap-chromium.ts`
442
+ * (pure decision); this wrapper does the spawnSync + apt-repo writes + post-
443
+ * install gate. Skipped on darwin (Maxy uses Playwright-managed Chromium per
444
+ * brew-install.ts) — RESOLVED_CHROMIUM_BIN keeps its `/usr/bin/chromium`
445
+ * default which is unused on darwin (no systemd unit).
446
+ *
447
+ * Detection: `command -v chromium` + `realpath`; an extra probe for
448
+ * `google-chrome-stable` covers re-run installs where a previous run already
449
+ * landed Chrome. Snap detection is the literal `snap` segment in the realpath
450
+ * (see isSnapConfinedPath in snap-chromium.ts) — covers the three real-world
451
+ * shapes (`/snap/bin/chromium`, `/snap/<rev>/usr/...`, `/usr/bin/snap` which
452
+ * is the snap launcher binary that `readlink -f` terminates at on Noble).
453
+ *
454
+ * Replacement: Google's signed apt repo (cryptographic verification via
455
+ * `signed-by=` GPG key) — the canonical pinned-deterministic source for
456
+ * Chrome stable. Pinning a specific Chrome version would require an out-of-
457
+ * band SHA-bump cadence and contradicts the apt-repo trust model.
458
+ *
459
+ * Post-install gate: spawn the resolved binary headless against a throwaway
460
+ * profile dir under persistDir, assert exit 0. The AppArmor denial that
461
+ * triggered the original denial was on SingletonLock writes which `--headless=new` still
462
+ * attempts, so the headless probe fires the same EACCES path that production
463
+ * VNC headed launches do — closing the post-fix-sibling-audit-skipped gap.
464
+ */
465
+ function ensureNonSnapChromium() {
466
+ if (process.platform !== "linux") {
467
+ logFile(` ensureNonSnapChromium skipped: platform=${process.platform}`);
468
+ return;
469
+ }
470
+ const which = (cmd) => {
471
+ const r = spawnSync("command", ["-v", cmd], { stdio: "pipe", encoding: "utf-8", shell: "/bin/bash", timeout: 5_000 });
472
+ if (r.status !== 0)
473
+ return null;
474
+ const out = (r.stdout ?? "").trim();
475
+ return out || null;
476
+ };
477
+ const realpath = (path) => {
478
+ if (!path)
479
+ return null;
480
+ try {
481
+ return realpathSync(path);
482
+ }
483
+ catch {
484
+ return null;
485
+ }
486
+ };
487
+ const whichChromium = which("chromium");
488
+ const whichGoogleChrome = which("google-chrome-stable");
489
+ const decision = decideChromiumAction({
490
+ platform: "linux",
491
+ whichChromium,
492
+ realpathChromium: realpath(whichChromium),
493
+ whichGoogleChrome,
494
+ realpathGoogleChrome: realpath(whichGoogleChrome),
495
+ });
496
+ logFile(` [snap-chromium] decision: ${decision.action} reason="${decision.reason}"`);
497
+ if (decision.action === "fail") {
498
+ throw new Error(`ensureNonSnapChromium: ${decision.reason}. apt install of \`chromium\` ran in installAptGroup(VNC stack) above; if its post-check passed but no chromium binary is on PATH, the system PATH is misconfigured.`);
499
+ }
500
+ if (decision.action === "install-google-chrome") {
501
+ console.log(" Detected snap-confined Chromium — installing Google Chrome stable...");
502
+ logFile(` [snap-chromium] installing google-chrome-stable from Google's signed apt repo`);
503
+ // Fetch + dearmor the signing key, write to /etc/apt/trusted.gpg.d/. Pipe
504
+ // composition runs through bash -c so the curl|gpg pipeline is one
505
+ // privileged command rather than two separate sudo escalations.
506
+ console.log(" [privileged] curl + gpg --dearmor (Google Chrome signing key)");
507
+ shell("bash", ["-c",
508
+ "set -euo pipefail; " +
509
+ "curl -fsSL https://dl.google.com/linux/linux_signing_key.pub | " +
510
+ "gpg --dearmor --yes -o /etc/apt/trusted.gpg.d/google-chrome.gpg",
511
+ ], { sudo: true });
512
+ // Add the apt source list with `signed-by=` scoping so the key only
513
+ // verifies google-chrome-* packages, not arbitrary repo overrides. arch
514
+ // pinned to amd64 — Google does not ship arm64 Chrome for Linux.
515
+ console.log(" [privileged] tee /etc/apt/sources.list.d/google-chrome.list");
516
+ shell("bash", ["-c",
517
+ "echo 'deb [arch=amd64 signed-by=/etc/apt/trusted.gpg.d/google-chrome.gpg] " +
518
+ "http://dl.google.com/linux/chrome/deb/ stable main' " +
519
+ "> /etc/apt/sources.list.d/google-chrome.list",
520
+ ], { sudo: true });
521
+ console.log(" [privileged] apt-get update");
522
+ shell("apt-get", ["update"], { sudo: true });
523
+ installAptGroup("Google Chrome stable", ["google-chrome-stable"]);
524
+ // Re-resolve after install to capture the now-installed absolute path.
525
+ const postInstallWhich = which("google-chrome-stable");
526
+ if (!postInstallWhich) {
527
+ throw new Error("ensureNonSnapChromium: apt install of google-chrome-stable returned 0 and dpkg -s passed, but `command -v google-chrome-stable` is empty — PATH is broken.");
528
+ }
529
+ RESOLVED_CHROMIUM_BIN = postInstallWhich;
530
+ }
531
+ else {
532
+ // action === "use" — decision.resolvedPath is the existing non-snap binary
533
+ // (chromium or google-chrome-stable already installed).
534
+ if (!decision.resolvedPath) {
535
+ throw new Error(`ensureNonSnapChromium: action=use returned without resolvedPath — bug in snap-chromium.ts (input: chromium=${whichChromium} google-chrome=${whichGoogleChrome})`);
536
+ }
537
+ RESOLVED_CHROMIUM_BIN = decision.resolvedPath;
538
+ }
539
+ // Defensive: never persist a snap-confined path. If realpath of the resolved
540
+ // binary still lands under /snap/ (e.g. apt landed a snap package by mistake
541
+ // on a misconfigured device), throw before writeChromiumBinaryPathFile sees
542
+ // it — the runtime gate in vnc.sh would refuse anyway, but failing here
543
+ // surfaces the contract breach with the install context still in scope.
544
+ const finalRealpath = realpath(RESOLVED_CHROMIUM_BIN);
545
+ if (isSnapConfinedPath(finalRealpath)) {
546
+ throw new Error(`ensureNonSnapChromium: resolved Chromium binary ${RESOLVED_CHROMIUM_BIN} realpaths to ${finalRealpath} which is under /snap/ — refusing to persist.`);
547
+ }
548
+ console.log(` Chromium binary: ${RESOLVED_CHROMIUM_BIN} (realpath=${finalRealpath ?? "?"})`);
549
+ logFile(` [snap-chromium] resolved bin=${RESOLVED_CHROMIUM_BIN} realpath=${finalRealpath ?? "null"}`);
550
+ runChromiumPostInstallGate(RESOLVED_CHROMIUM_BIN);
551
+ }
552
+ /**
553
+ * post-install gate. Spawns the resolved Chromium binary headless
554
+ * against a throwaway profile dir under persistDir (`~/.{brand}/chromium-
555
+ * gate-profile/`). The AppArmor denial that triggered the task was on
556
+ * SingletonLock writes which `--headless=new` still attempts, so this probe
557
+ * fires the same EACCES path the headed VNC stack would. Cleans up the gate
558
+ * profile afterward — the live profile (`chromium-profile/`) is owned by
559
+ * vnc.sh's start_chrome and not touched here.
560
+ */
561
+ function runChromiumPostInstallGate(chromiumBin) {
562
+ const persistDir = resolve(process.env.HOME ?? "/root", BRAND.configDir);
563
+ const gateProfileDir = join(persistDir, "chromium-gate-profile");
564
+ mkdirSync(gateProfileDir, { recursive: true });
565
+ console.log(` Verifying ${chromiumBin} can write to ${gateProfileDir} (post-install gate)...`);
566
+ const r = spawnSync(chromiumBin, [
567
+ `--user-data-dir=${gateProfileDir}`,
568
+ "--headless=new",
569
+ "--disable-gpu",
570
+ "--no-sandbox",
571
+ "--disable-dev-shm-usage",
572
+ "--dump-dom",
573
+ "about:blank",
574
+ ], { stdio: "pipe", encoding: "utf-8", timeout: 30_000 });
575
+ // Cleanup before throwing on failure so successive runs start clean.
576
+ try {
577
+ rmSync(gateProfileDir, { recursive: true, force: true });
578
+ }
579
+ catch { /* best-effort */ }
580
+ if (r.status !== 0) {
581
+ const stderr = (r.stderr ?? "").slice(-2000);
582
+ const eaccesHit = /Permission denied/i.test(stderr) || /EACCES/i.test(stderr);
583
+ const taskRef = eaccesHit
584
+ ? "chromium-profile not writable (likely AppArmor denial on snap-confined binary). "
585
+ : "";
586
+ throw new Error(`${taskRef}Chromium post-install gate failed: ${chromiumBin} exited ${r.status} signal=${r.signal ?? "none"}. stderr:\n${stderr}`);
587
+ }
588
+ console.log(" Chromium post-install gate passed.");
589
+ logFile(` [snap-chromium] post-install gate ok: ${chromiumBin} exit=0`);
590
+ }
591
+ /**
592
+ * write the resolved Chromium absolute path to
593
+ * `<INSTALL_DIR>/platform/config/chromium-binary.path` so vnc.sh and
594
+ * writeChromiumWrapper read the same value. Called
595
+ * after deployPayload so the platform/config/ directory exists. Idempotent:
596
+ * re-running the installer with the same RESOLVED_CHROMIUM_BIN is a no-op
597
+ * write (writeFileSync overwrites in place).
598
+ */
599
+ function writeChromiumBinaryPathFile() {
600
+ if (process.platform !== "linux") {
601
+ logFile(` writeChromiumBinaryPathFile skipped: platform=${process.platform}`);
602
+ return;
603
+ }
604
+ const configDir = resolve(INSTALL_DIR, "platform/config");
605
+ mkdirSync(configDir, { recursive: true });
606
+ const target = join(configDir, "chromium-binary.path");
607
+ writeFileSync(target, RESOLVED_CHROMIUM_BIN + "\n", { mode: 0o644 });
608
+ console.log(` Wrote ${target} → ${RESOLVED_CHROMIUM_BIN}`);
609
+ logFile(` [snap-chromium] wrote ${target} contents=${RESOLVED_CHROMIUM_BIN}`);
610
+ }
611
+ // Scrub any hardware-watchdog drop-in this installer (or an earlier version)
612
+ // left on the box, then daemon-reexec so the live RuntimeWatchdogUSec returns
613
+ // to systemd's default (0 = off). The hardware-watchdog feature is retired:
614
+ // a RuntimeWatchdogSec=20s timer (inert above the ~15s BCM2835 kernel cap, so
615
+ // it cannot be loosened) reboot-looped constrained Pis — mid-install when armed
616
+ // early, and again at the post-install load peak when armed at install end. It
617
+ // bit both muvin and beacons. configureHardwareWatchdog() no longer arms
618
+ // anything; see its comment for the full rationale. Kernel-freeze recovery is
619
+ // left to the brand service's software watchdog (Type=notify WATCHDOG_USEC),
620
+ // which restarts the UI process rather than resetting the whole SoC.
621
+ //
622
+ // Runs unconditionally at install start. Idempotent: if no drop-in is on
623
+ // disk, this is a no-op.
624
+ function disableHardwareWatchdogForInstall() {
625
+ try {
626
+ if (!isLinux()) {
627
+ logFile(" hardware watchdog: scrub-on-install skipped (not Linux)");
628
+ return;
629
+ }
630
+ const dropinPath = "/etc/systemd/system.conf.d/10-maxy-watchdog.conf";
631
+ if (!existsSync(dropinPath)) {
632
+ logFile(` hardware watchdog: no prior drop-in to scrub (${dropinPath})`);
633
+ return;
634
+ }
635
+ console.log(` [privileged] remove prior hardware-watchdog drop-in (${dropinPath}) — feature retired`);
636
+ shell("rm", ["-f", dropinPath], { sudo: true });
637
+ spawnSync("sudo", ["systemctl", "daemon-reexec"], { stdio: "inherit" });
638
+ logFile(` hardware watchdog: drop-in removed; daemon-reexec applied — RuntimeWatchdogUSec back to default`);
639
+ }
640
+ catch (err) {
641
+ console.error(` WARNING: failed to scrub hardware-watchdog drop-in: ${err instanceof Error ? err.message : String(err)}`);
642
+ }
643
+ }
644
+ function configureHardwareWatchdog() {
645
+ // The hardware-watchdog drop-in was hostile to constrained Pis. Task 997
646
+ // deferred the arm to install end so a tight 20s timer would not reboot the
647
+ // box mid-build. But arming via daemon-reexec at install end lands the live
648
+ // timer at the very peak of post-install load (services initialising,
649
+ // chattr +i sweep just finished, neo4j seeding). PID1 cannot feed
650
+ // /dev/watchdog fast enough — the SoC resets, next boot starts the same
651
+ // services under the same load, resets again. Beacons reboot-looped on
652
+ // every install after the previous fix until the operator deleted the
653
+ // drop-in by hand.
654
+ //
655
+ // Raising RuntimeWatchdogSec is inert above the kernel watchdog cap
656
+ // (~15s on BCM2835), so the timer cannot simply be loosened. Until a
657
+ // version of this feature actually survives a constrained-Pi install
658
+ // unattended, it is removed. The disable-at-install-start path
659
+ // (disableHardwareWatchdogForInstall) stays — it scrubs any prior
660
+ // drop-in off devices that had it from earlier installer versions, so the
661
+ // hostile timer is cleared from the fleet on first run of this installer
662
+ // version. Kernel-freeze recovery is deferred to the in-server software
663
+ // watchdog (Type=notify WATCHDOG_USEC, already shipped on the brand
664
+ // service) which restarts the UI process, not the whole SoC.
665
+ try {
666
+ if (!isLinux()) {
667
+ logFile(" hardware watchdog: skipped (not Linux)");
668
+ return;
669
+ }
670
+ const dropinPath = "/etc/systemd/system.conf.d/10-maxy-watchdog.conf";
671
+ if (existsSync(dropinPath)) {
672
+ // Defence in depth — disableHardwareWatchdogForInstall() already runs
673
+ // at install start, but log here too so the install summary makes the
674
+ // policy explicit even if step 0 was skipped.
675
+ logFile(` hardware watchdog: drop-in present at ${dropinPath} but feature is disabled (see disableHardwareWatchdogForInstall)`);
676
+ return;
677
+ }
678
+ logFile(" hardware watchdog: feature disabled (constrained-Pi reboot loops)");
679
+ }
680
+ catch (err) {
681
+ console.error(` WARNING: hardware watchdog post-install probe failed: ${err instanceof Error ? err.message : String(err)}`);
682
+ }
683
+ }
684
+ function installSystemDeps() {
685
+ log("1", TOTAL, "System dependencies and network...");
686
+ const platform = requireSupportedPlatform(process.platform);
687
+ if (platform === "darwin") {
688
+ // darwin hostname via scutil when --hostname is supplied,
689
+ // otherwise preserve the existing system hostname.
690
+ if (HOSTNAME_FLAG) {
691
+ console.log(` Hostname: ${HOSTNAME_FLAG} (from --hostname flag)`);
692
+ logFile(` [create-maxy] darwin-hostname-mode=scutil-set value=${HOSTNAME_FLAG}`);
693
+ try {
694
+ setMacosHostnameViaScutil(HOSTNAME_FLAG);
695
+ DEVICE_HOSTNAME = HOSTNAME_FLAG;
696
+ }
697
+ catch (err) {
698
+ console.error(` WARNING: Failed to set hostname to '${HOSTNAME_FLAG}': ${err instanceof Error ? err.message : String(err)}`);
699
+ }
700
+ }
701
+ else {
702
+ // No flag — read the live LocalHostName so the printed URL matches mDNS
703
+ // resolution (`<LocalHostName>.local`). The `hostname` command on darwin
704
+ // returns the fully-qualified `<name>.local`, which would render the
705
+ // completion URL with a double `.local` suffix; scutil --get returns the
706
+ // bare token. No sudo, no system mutation.
707
+ const scutilGet = spawnSync("scutil", ["--get", "LocalHostName"], { encoding: "utf-8", stdio: "pipe", timeout: 5_000 });
708
+ const scutilName = ((scutilGet.stdout ?? "").trim());
709
+ if (scutilGet.status === 0 && scutilName.length > 0) {
710
+ DEVICE_HOSTNAME = scutilName;
711
+ console.log(` Hostname: ${DEVICE_HOSTNAME} (from scutil --get LocalHostName — no --hostname flag)`);
712
+ logFile(` [create-maxy] darwin-hostname-mode=scutil-get value=${DEVICE_HOSTNAME}`);
713
+ }
714
+ else {
715
+ // scutil failed or returned empty — fall back to BRAND.hostname so the
716
+ // completion URL at least matches the brand's documented .local name.
717
+ DEVICE_HOSTNAME = BRAND.hostname;
718
+ console.log(` Hostname: ${DEVICE_HOSTNAME} (brand fallback — scutil --get LocalHostName empty)`);
719
+ logFile(` [create-maxy] darwin-hostname-mode=brand-fallback value=${DEVICE_HOSTNAME} scutil-status=${scutilGet.status}`);
720
+ }
721
+ }
722
+ // macOS has no apt analogue for the VNC/WiFi-AP stacks
723
+ // (kiosk display + hostapd/dnsmasq are Pi-specific's
724
+ // out-of-scope note). mDNS is provided by the OS, so avahi-* drop out.
725
+ // Translate the remaining apt names through decideBrewResolution and
726
+ // let installAllBrewPackages handle the install + verify pattern.
727
+ const DARWIN_BASE_DEPS = ["curl", "git", "unzip", "jq", "poppler", "ffmpeg", "tesseract", "ocrmypdf"];
728
+ installAllBrewPackages(DARWIN_BASE_DEPS, logFile);
729
+ return;
730
+ }
731
+ // python3-pip, file, and python-is-python3 cover a toolchain gap: python3
732
+ // arrives transitively (python3-websockify in VNC_DEPS) but pip, the
733
+ // unversioned `python` alias, and `file` were absent, so account-side jobs
734
+ // that shell out to `python`/`pip`/`file` hit exit 127. All three are
735
+ // concrete .deb names on Debian bookworm and Ubuntu noble — no apt-resolve
736
+ // alias needed.
737
+ const BASE_DEPS = ["curl", "git", "unzip", "jq", "avahi-daemon", "avahi-utils", "poppler-utils", "ffmpeg", "bind9-dnsutils", "tesseract-ocr", "ocrmypdf", "python3-pip", "file", "python-is-python3"];
738
+ // xterm is the *preferred* terminal-emulator binary for the VNC-rendered
739
+ // Terminal surface
740
+ // delegates window creation to the session's gnome-terminal-server,
741
+ // opening windows on the wrong display; xterm has no IPC layer and
742
+ // honours DISPLAY directly). Kept in the apt list unconditionally so
743
+ // vnc.sh's resolve_terminal_bin has a display-safe binary on every
744
+ // supported distro (Ubuntu 24.04 noble/universe, Debian 12 bookworm/main
745
+ // verified). xdotool backs the post-spawn display-membership
746
+ // assertion in vnc.sh check_window_on_display, closing the silent-fail
747
+ // class where PID is alive but no window is mapped on the target display.
748
+ const VNC_DEPS = ["tigervnc-standalone-server", "python3-websockify", "novnc", "xdg-utils", "chromium", "xterm", "xdotool"];
749
+ // retired the ttyd/tmux admin terminal stack — upgrades run via
750
+ // the action runner (systemd-run --user transient units) and no longer
751
+ // need a shared tmux session. `tmux` was only required by the retired
752
+ // byte-stream terminal; removing it shrinks the apt footprint.
753
+ const WIFI_DEPS = ["hostapd", "dnsmasq"];
754
+ const ALL_APT_DEPS = [...BASE_DEPS, ...VNC_DEPS, ...WIFI_DEPS];
755
+ // verify the "deps are present" assumption with `dpkg -s` instead
756
+ // of asserting it (feedback_loud_failures.md). The previous silent-skip
757
+ // branch was benign added xdotool (the first new apt dep
758
+ // since the skip path became load-bearing on user-password-sudo devices).
759
+ const missing = pkgsMissing(ALL_APT_DEPS);
760
+ if (missing.length === 0) {
761
+ logFile(` all system deps present per dpkg -s (${ALL_APT_DEPS.length} packages) — skipping apt install`);
762
+ console.log(` All ${ALL_APT_DEPS.length} system deps already installed — skipping apt install.`);
763
+ }
764
+ else {
765
+ const canEscalate = canSudo() || process.stdout.isTTY === true;
766
+ if (!canEscalate) {
767
+ const repair = `sudo apt-get install -y ${missing.join(" ")}`;
768
+ console.error(` MISSING ${missing.length} system deps per dpkg -s: ${missing.join(" ")}`);
769
+ console.error(` Non-interactive sudo is unavailable; cannot prompt for password from a non-TTY shell.`);
770
+ console.error(` Re-run this installer from an interactive shell, or repair manually:`);
771
+ console.error(` ${repair}`);
772
+ logFile(` FAIL: missing apt deps without interactive sudo: ${missing.join(",")}`);
773
+ throw new Error(`installSystemDeps: missing packages (${missing.join(", ")}) and sudo is unavailable non-interactively — repair with: ${repair}`);
774
+ }
775
+ console.log(` Missing apt deps (${missing.length}): ${missing.join(", ")}`);
776
+ console.log(` Installing via sudo apt-get — sudo may prompt for your password...`);
777
+ console.log(" [privileged] apt-get update");
778
+ shell("apt-get", ["update"], { sudo: true });
779
+ installAptGroup("base utilities", BASE_DEPS);
780
+ installAptGroup("VNC stack", VNC_DEPS);
781
+ installAptGroup("WiFi AP", WIFI_DEPS);
782
+ }
783
+ // replace snap-confined Chromium with Google Chrome stable on
784
+ // Linux laptops (Ubuntu Noble) where `/usr/bin/chromium` realpaths to the
785
+ // snap launcher. The snap AppArmor profile denies writes to hidden top-level
786
+ // paths under $HOME, so any write to `~/.{brand}/chromium-profile/SingletonLock`
787
+ // hits EACCES and Chromium never starts the CDP listener. Always sets
788
+ // RESOLVED_CHROMIUM_BIN even on Pi Bookworm (where the path is unchanged),
789
+ // so deployPayload's writeChromiumBinaryPathFile and installService's
790
+ // buildMaxyUnitFile both have a real absolute path to thread through.
791
+ ensureNonSnapChromium();
792
+ // Task 600 — provision swap so the OOM-killer has a buffer to work in
793
+ // instead of silently freezing the box. dphys-swapfile is the standard
794
+ // Raspberry Pi OS swap manager. CONF_MAXSWAP raised to 4096 so the
795
+ // operator can manually grow the swap file without reinstalling.
796
+ // Best-effort: a failure here warns but does not abort the install.
797
+ try {
798
+ console.log(" [privileged] apt-get install dphys-swapfile");
799
+ shell("apt-get", ["install", "-y", "dphys-swapfile"], { sudo: true, bestEffort: true });
800
+ const desiredSwapConf = "CONF_SWAPSIZE=2048\nCONF_MAXSWAP=4096\n";
801
+ const swapConfPath = "/etc/dphys-swapfile";
802
+ let swapCurrent = "";
803
+ if (existsSync(swapConfPath)) {
804
+ try {
805
+ swapCurrent = readFileSync(swapConfPath, "utf-8");
806
+ }
807
+ catch {
808
+ swapCurrent = "";
809
+ }
810
+ }
811
+ if (swapCurrent === desiredSwapConf) {
812
+ logFile(" swap: already configured (CONF_SWAPSIZE=2048 CONF_MAXSWAP=4096)");
813
+ }
814
+ else {
815
+ const swapTmpPath = `/tmp/dphys-swapfile.${process.pid}`;
816
+ writeFileSync(swapTmpPath, desiredSwapConf);
817
+ console.log(" [privileged] install /etc/dphys-swapfile (CONF_SWAPSIZE=2048 CONF_MAXSWAP=4096)");
818
+ shell("cp", [swapTmpPath, swapConfPath], { sudo: true });
819
+ spawnSync("rm", ["-f", swapTmpPath]);
820
+ console.log(" [privileged] systemctl restart dphys-swapfile");
821
+ shell("systemctl", ["restart", "dphys-swapfile"], { sudo: true, bestEffort: true });
822
+ logFile(" swap: configured CONF_SWAPSIZE=2048 CONF_MAXSWAP=4096 and restarted dphys-swapfile");
823
+ }
824
+ }
825
+ catch (err) {
826
+ console.error(` WARNING: failed to provision swap: ${err instanceof Error ? err.message : String(err)}`);
827
+ }
828
+ // Hostname resolution — four sources, in priority order:
829
+ // 1. --hostname flag (unconditional — the caller is the authority)
830
+ // 2. OS detection on same-brand upgrade (service exists → keep whatever is currently set)
831
+ // 3. OS preservation on multi-brand device (another brand's service detected → keep hostname)
832
+ // 4. BRAND.hostname on fresh install (brand default)
833
+ if (HOSTNAME_FLAG) {
834
+ // --hostname flag: set unconditionally, no detection, no preservation logic.
835
+ console.log(` Hostname: ${HOSTNAME_FLAG} (from --hostname flag)`);
836
+ try {
837
+ console.log(" [privileged] hostnamectl set-hostname");
838
+ shell("hostnamectl", ["set-hostname", HOSTNAME_FLAG], { sudo: true });
839
+ console.log(" [privileged] sed -i");
840
+ shell("sed", ["-i", `s/127\\.0\\.1\\.1.*$/127.0.1.1\\t${HOSTNAME_FLAG}/`, "/etc/hosts"], { sudo: true });
841
+ try {
842
+ console.log(" [privileged] sed -i");
843
+ shell("sed", ["-i", `s/^[#]*host-name=.*/host-name=${HOSTNAME_FLAG}/`, "/etc/avahi/avahi-daemon.conf"], { sudo: true });
844
+ console.log(` Avahi host-name: ${HOSTNAME_FLAG} (updated avahi-daemon.conf)`);
845
+ }
846
+ catch { /* avahi-daemon.conf may not exist — non-critical */ }
847
+ // Restart avahi-daemon so the new hostname takes effect immediately
848
+ // and any stale "maxytest-2" auto-renamed records from a previous
849
+ // boot's hostname-conflict cycle are withdrawn. Without this,
850
+ // avahi-resolve -n <hostname>.local times out from the device itself
851
+ // because the daemon is still advertising the previous identity.
852
+ try {
853
+ console.log(" [privileged] systemctl restart avahi-daemon");
854
+ shell("systemctl", ["restart", "avahi-daemon"], { sudo: true });
855
+ }
856
+ catch (err) {
857
+ console.error(` WARNING: avahi-daemon restart failed: ${err instanceof Error ? err.message : String(err)}`);
858
+ }
859
+ }
860
+ catch (err) {
861
+ console.error(` WARNING: Failed to set hostname to '${HOSTNAME_FLAG}': ${err instanceof Error ? err.message : String(err)}`);
862
+ }
863
+ DEVICE_HOSTNAME = HOSTNAME_FLAG;
864
+ }
865
+ else {
866
+ // No flag — fall back to detection (upgrade) or brand default (fresh install).
867
+ // Check for this brand's service (same-brand upgrade) and any other brand's service
868
+ // (multi-brand device). On a multi-brand device, hostname is a device-level concern
869
+ // set by the user or the first installer — subsequent brands must not overwrite it.
870
+ const systemdUserDir = resolve(process.env.HOME ?? "/root", ".config/systemd/user");
871
+ const serviceExists = existsSync(join(systemdUserDir, BRAND.serviceName));
872
+ // narrow peer detection to KNOWN_BRAND_HOSTNAMES. The previous
873
+ // predicate ("any *.service that isn't ours") matched stray user units
874
+ // such as a `gnome-keyring-daemon.service -> /dev/null` disable marker,
875
+ // silently flipping single-brand fresh installs into the "preserve hostname"
876
+ // branch. Mirrors the `peerBrandPresent` allowlist in `uninstall.ts`.
877
+ let otherBrandService = false;
878
+ if (!serviceExists) {
879
+ const peerUnits = KNOWN_BRAND_HOSTNAMES
880
+ .filter((h) => h !== BRAND.hostname)
881
+ .flatMap((h) => [`${h}.service`, `${h}-edge.service`]);
882
+ try {
883
+ const files = new Set(readdirSync(systemdUserDir));
884
+ otherBrandService = peerUnits.some((unit) => files.has(unit));
885
+ }
886
+ catch { /* directory may not exist on a fresh device — not an error */ }
887
+ }
888
+ // "raspberrypi" is the Pi factory default — it means "never configured,"
889
+ // not "the admin chose this hostname." Treat it the same as a fresh install.
890
+ const FACTORY_HOSTNAMES = ["raspberrypi", "localhost"];
891
+ let hostnameSetAttempted = false;
892
+ try {
893
+ const currentHostname = execFileSync("hostname", [], { encoding: "utf-8" }).trim();
894
+ const isFactory = FACTORY_HOSTNAMES.includes(currentHostname);
895
+ if (currentHostname === BRAND.hostname) {
896
+ console.log(` Hostname: ${currentHostname} (detected from OS)`);
897
+ }
898
+ else if (serviceExists && !isFactory) {
899
+ // Upgrade: admin-chosen hostname — preserve it.
900
+ console.log(` Hostname: ${currentHostname} (detected from OS — differs from brand '${BRAND.hostname}')`);
901
+ }
902
+ else if (otherBrandService && !isFactory) {
903
+ // Multi-brand: another brand set the hostname — preserve it.
904
+ console.log(` Hostname preserved: ${currentHostname} (another brand service detected)`);
905
+ }
906
+ else {
907
+ // Fresh install, OR a factory default that was never changed.
908
+ const reason = isFactory && serviceExists
909
+ ? `factory default '${currentHostname}' was never changed`
910
+ : `brand default — fresh install, was '${currentHostname}'`;
911
+ console.log(` Hostname: ${BRAND.hostname} (${reason})`);
912
+ hostnameSetAttempted = true;
913
+ try {
914
+ console.log(" [privileged] hostnamectl set-hostname");
915
+ shell("hostnamectl", ["set-hostname", BRAND.hostname], { sudo: true });
916
+ console.log(" [privileged] sed -i");
917
+ shell("sed", ["-i", `s/127\\.0\\.1\\.1.*$/127.0.1.1\\t${BRAND.hostname}/`, "/etc/hosts"], { sudo: true });
918
+ try {
919
+ console.log(" [privileged] sed -i");
920
+ shell("sed", ["-i", `s/^[#]*host-name=.*/host-name=${BRAND.hostname}/`, "/etc/avahi/avahi-daemon.conf"], { sudo: true });
921
+ console.log(` Avahi host-name: ${BRAND.hostname} (updated avahi-daemon.conf)`);
922
+ }
923
+ catch { /* avahi-daemon.conf may not exist — non-critical */ }
924
+ }
925
+ catch (err) {
926
+ console.error(` WARNING: Could not set hostname to '${BRAND.hostname}': ${err instanceof Error ? err.message : String(err)}`);
927
+ console.error(` After install, run: sudo hostnamectl set-hostname ${BRAND.hostname}`);
928
+ }
929
+ }
930
+ }
931
+ catch (err) {
932
+ console.error(` WARNING: Could not detect hostname: ${err instanceof Error ? err.message : String(err)}`);
933
+ }
934
+ // Read the actual hostname after any changes — used for user-facing URLs.
935
+ try {
936
+ DEVICE_HOSTNAME = execFileSync("hostname", [], { encoding: "utf-8" }).trim();
937
+ }
938
+ catch { /* fallback to brand — set at declaration */ }
939
+ // If we attempted to set the hostname but it didn't take, use the brand
940
+ // hostname for the completion URL. The user needs the URL that will work
941
+ // after a reboot or manual hostname fix — not the stale factory default.
942
+ if (hostnameSetAttempted && DEVICE_HOSTNAME !== BRAND.hostname) {
943
+ console.error(` WARNING: Hostname is still '${DEVICE_HOSTNAME}' — using '${BRAND.hostname}' for the completion URL.`);
944
+ DEVICE_HOSTNAME = BRAND.hostname;
945
+ }
946
+ }
947
+ // Avahi service file for LAN discovery
948
+ const avahiService = `<?xml version="1.0" standalone='no'?>
949
+ <!DOCTYPE service-group SYSTEM "avahi-service.dtd">
950
+ <service-group>
951
+ <name replace-wildcards="yes">${BRAND.productName} on %h</name>
952
+ <service>
953
+ <type>_http._tcp</type>
954
+ <port>${PORT}</port>
955
+ <txt-record>role=${BRAND.hostname}</txt-record>
956
+ </service>
957
+ </service-group>`;
958
+ const avahiTmpPath = `/tmp/${BRAND.hostname}-avahi.service`;
959
+ const avahiDestPath = `/etc/avahi/services/${BRAND.hostname}.service`;
960
+ try {
961
+ writeFileSync(avahiTmpPath, avahiService);
962
+ console.log(" [privileged] cp");
963
+ shell("cp", [avahiTmpPath, avahiDestPath], { sudo: true });
964
+ console.log(" [privileged] systemctl enable");
965
+ shell("systemctl", ["enable", "avahi-daemon"], { sudo: true });
966
+ console.log(" [privileged] systemctl restart");
967
+ shell("systemctl", ["restart", "avahi-daemon"], { sudo: true });
968
+ }
969
+ catch { /* not critical */ }
970
+ // Hostname collision detection: check if another device already claims this hostname.
971
+ // Avahi appends -2 on collision, which causes the agent to construct URLs to the wrong device.
972
+ try {
973
+ const resolveResult = spawnSync("avahi-resolve", ["-n", `${BRAND.hostname}.local`], {
974
+ encoding: "utf-8", timeout: 5000, stdio: ["pipe", "pipe", "pipe"],
975
+ });
976
+ if (resolveResult.status === 0 && resolveResult.stdout.trim()) {
977
+ const resolvedIp = resolveResult.stdout.trim().split(/\s+/)[1];
978
+ // Get this device's IP addresses to compare
979
+ const hostnameResult = spawnSync("hostname", ["-I"], { encoding: "utf-8", timeout: 3000 });
980
+ const localIps = hostnameResult.stdout?.trim().split(/\s+/) ?? [];
981
+ if (resolvedIp && !localIps.includes(resolvedIp)) {
982
+ console.log(` WARNING: ${BRAND.hostname}.local already resolves to ${resolvedIp} — this device may get ${BRAND.hostname}-2.local`);
983
+ logFile(` WARNING: hostname collision detected — ${BRAND.hostname}.local resolves to ${resolvedIp}, local IPs: ${localIps.join(", ")}`);
984
+ }
985
+ }
986
+ }
987
+ catch { /* non-critical — avahi-resolve may not be ready yet */ }
988
+ // Disable WiFi power management — the Pi's WiFi driver aggressively sleeps
989
+ // the radio between transmissions, causing dropped DNS/mDNS packets and
990
+ // intermittent connection resets on LAN.
991
+ try {
992
+ const nmConfDir = "/etc/NetworkManager/conf.d";
993
+ const nmConfFile = join(nmConfDir, `${BRAND.hostname}-no-powersave.conf`);
994
+ if (existsSync("/usr/bin/nmcli") && !existsSync(nmConfFile)) {
995
+ console.log(" Disabling WiFi power save...");
996
+ writeFileSync(`/tmp/${BRAND.hostname}-no-powersave.conf`, "[connection]\nwifi.powersave = 2\n");
997
+ console.log(" [privileged] cp");
998
+ shell("cp", [`/tmp/${BRAND.hostname}-no-powersave.conf`, nmConfFile], { sudo: true });
999
+ spawnSync("sudo", ["systemctl", "restart", "NetworkManager"], { stdio: "pipe" });
1000
+ }
1001
+ }
1002
+ catch { /* not critical — wired connections unaffected */ }
1003
+ console.log(` Device reachable at http://${DEVICE_HOSTNAME}.local:${PORT}`);
1004
+ }
1005
+ function installNodejs() {
1006
+ if (commandExists("node") && nodeVersion() >= 20) {
1007
+ log("2", TOTAL, `Node.js v${nodeVersion()} already installed.`);
1008
+ return;
1009
+ }
1010
+ log("2", TOTAL, "Installing Node.js...");
1011
+ const platform = requireSupportedPlatform(process.platform);
1012
+ if (platform === "darwin") {
1013
+ // Pass the apt-side `nodejs` name; decideBrewResolution maps it to
1014
+ // `node@22` per DARWIN_ALIASES so the cellar formula matches Maxy's
1015
+ // pinned-binaries floor.
1016
+ installAllBrewPackages(["nodejs"], logFile);
1017
+ return;
1018
+ }
1019
+ spawnSync("bash", ["-c", "curl -fsSL https://deb.nodesource.com/setup_22.x | sudo -E bash -"], { stdio: "inherit" });
1020
+ console.log(" [privileged] apt-get install");
1021
+ shell("apt-get", ["install", "-y", "nodejs"], { sudo: true });
1022
+ }
1023
+ function installClaudeCode() {
1024
+ let needsInstall = true;
1025
+ if (commandExists("claude")) {
1026
+ try {
1027
+ // `claude --version` prints "2.1.114 (Claude Code)" — extract the semver so
1028
+ // the equality check against `npm view` (which returns bare "2.1.114") works.
1029
+ const rawVersion = execFileSync("claude", ["--version"], { encoding: "utf-8", timeout: 10_000 }).trim();
1030
+ const installed = rawVersion.match(/^(\d+\.\d+\.\d+(?:[-+][0-9A-Za-z.-]+)?)/)?.[1] ?? rawVersion;
1031
+ let latest = null;
1032
+ try {
1033
+ latest = execFileSync("npm", ["view", "@anthropic-ai/claude-code", "version"], { encoding: "utf-8", timeout: 30_000 }).trim();
1034
+ }
1035
+ catch {
1036
+ logFile(" Could not check latest version — will attempt install anyway");
1037
+ }
1038
+ if (latest && installed === latest) {
1039
+ log("3", TOTAL, `Claude Code v${installed} already up to date.`);
1040
+ needsInstall = false;
1041
+ }
1042
+ else {
1043
+ log("3", TOTAL, `Upgrading Claude Code (${installed}${latest ? ` → ${latest}` : ""})...`);
1044
+ }
1045
+ }
1046
+ catch {
1047
+ log("3", TOTAL, "Claude Code found but version check failed. Reinstalling...");
1048
+ }
1049
+ }
1050
+ else {
1051
+ log("3", TOTAL, "Installing Claude Code...");
1052
+ }
1053
+ if (needsInstall) {
1054
+ // `npm install -g` needs write access to the global prefix, which on Linux is
1055
+ // root-owned by default — so we run it under sudo. When sudo requires a password
1056
+ // and the installer is running non-interactively (e.g. systemd-run --scope on
1057
+ // upgrade), sudo fails instantly. Skip the upgrade in that case; the running
1058
+ // installation is assumed adequate. Matches the apt-get skip in step 1.
1059
+ if (isLinux() && !canSudo()) {
1060
+ console.log(" Skipping Claude Code upgrade (sudo unavailable non-interactively — keeping installed version)");
1061
+ }
1062
+ else {
1063
+ console.log(" This may take 15–30 minutes on Raspberry Pi...");
1064
+ console.log(" [privileged] npm install -g @anthropic-ai/claude-code@latest");
1065
+ shellRetry("npm", ["install", "-g", ...NPM_NET_FLAGS, "--loglevel", "verbose", "@anthropic-ai/claude-code@latest"], { sudo: true, timeout: 2_400_000 }, // 40 min — Pi downloads can take 25+ min
1066
+ 3, 30);
1067
+ }
1068
+ }
1069
+ console.log(" Registering Claude plugin marketplaces...");
1070
+ // pre-create the per-brand CLAUDE_CONFIG_DIR so the first
1071
+ // `claude plugin marketplace add` has a directory to write into.
1072
+ mkdirSync(CLAUDE_CONFIG_DIR, { recursive: true });
1073
+ // Task 583 — seed the brand-scoped permissions block so claude.ai/code
1074
+ // sessions short-circuit Stage 1 of the local matcher and never fall
1075
+ // through to the Anthropic remote auto-classifier (which routes Agent
1076
+ // dispatch to `ask` and surfaces a prompt no unattended operator clicks).
1077
+ const permissionsSeed = seedBypassPermissionsSettings(CLAUDE_CONFIG_DIR);
1078
+ logFile(`[install-permissions] action=${permissionsSeed.action} autoMode=${permissionsSeed.autoMode} path=${permissionsSeed.path}`);
1079
+ const marketplaceList = spawnSync("claude", ["plugin", "marketplace", "list"], { stdio: "pipe", encoding: "utf-8", env: claudePluginEnv() });
1080
+ if (marketplaceList.stderr)
1081
+ process.stderr.write(marketplaceList.stderr);
1082
+ const listed = marketplaceList.stdout ?? "";
1083
+ // register three Anthropic marketplaces uniformly with
1084
+ // [plugin-marketplace] observability. Each slug is grep-checked against
1085
+ // `marketplace list` for idempotence; failures log exit + first stderr
1086
+ // line but do not abort the installer (one marketplace's outage must not
1087
+ // block the others).
1088
+ // `slug` is the GitHub repo path passed to `marketplace add`. `marketplaceName`
1089
+ // is the marketplace's declared `name` from its .claude-plugin/marketplace.json —
1090
+ // what `marketplace list` prints and what `<plugin>@<marketplace>` resolves on
1091
+ // install. For FSI the two diverge: repo `anthropics/financial-services`,
1092
+ // marketplace name `claude-for-financial-services`. The idempotence check
1093
+ // greps the declared name to avoid substring false-positives.
1094
+ const MARKETPLACES = [
1095
+ { slug: "anthropics/claude-plugins-official", marketplaceName: "claude-plugins-official" },
1096
+ { slug: "anthropics/knowledge-work-plugins", marketplaceName: "knowledge-work-plugins" },
1097
+ { slug: "anthropics/financial-services", marketplaceName: "claude-for-financial-services" },
1098
+ ];
1099
+ for (const { slug, marketplaceName } of MARKETPLACES) {
1100
+ if (listed.includes(marketplaceName)) {
1101
+ logFile(`[plugin-marketplace] added ${slug} idempotent=true CLAUDE_CONFIG_DIR=${CLAUDE_CONFIG_DIR}`);
1102
+ continue;
1103
+ }
1104
+ const add = spawnSync("claude", ["plugin", "marketplace", "add", slug], { stdio: "pipe", encoding: "utf-8", timeout: 60_000, env: claudePluginEnv() });
1105
+ if (add.status === 0) {
1106
+ logFile(`[plugin-marketplace] added ${slug} idempotent=false CLAUDE_CONFIG_DIR=${CLAUDE_CONFIG_DIR}`);
1107
+ }
1108
+ else {
1109
+ const stderrShort = (add.stderr ?? "").split("\n")[0]?.slice(0, 200) ?? "";
1110
+ logFile(`[plugin-marketplace] ERROR add ${slug} exit=${add.status} stderr=${JSON.stringify(stderrShort)} CLAUDE_CONFIG_DIR=${CLAUDE_CONFIG_DIR}`);
1111
+ }
1112
+ }
1113
+ console.log(" Configuring git to use HTTPS for GitHub (plugin install support)...");
1114
+ shell("git", ["config", "--global", "url.https://github.com/.insteadOf", "git@github.com:"]);
1115
+ // Remove the Playwright plugin if previously installed. The programmatic MCP
1116
+ // server in claude-agent.ts (with --cdp-endpoint) is the single correct path.
1117
+ // The plugin creates a shadow server that intermittently handles tool calls
1118
+ // without --cdp-endpoint, causing Chrome launch failures on ARM64.
1119
+ const pluginList = spawnSync("claude", ["plugin", "list"], { stdio: "pipe", encoding: "utf-8", env: claudePluginEnv() });
1120
+ if (pluginList.stdout?.includes("playwright")) {
1121
+ console.log(" Removing Playwright plugin (replaced by programmatic CDP server)...");
1122
+ spawnSync("claude", ["plugin", "uninstall", "playwright"], { stdio: "inherit", env: claudePluginEnv() });
1123
+ }
1124
+ // Ensure @playwright/mcp and all its dependencies (including playwright-core)
1125
+ // are cached. Wipe any stale npx cache for it first — killed installs on Pi
1126
+ // leave corrupt temp dirs that block subsequent npm operations.
1127
+ console.log(" Pre-caching Playwright MCP server...");
1128
+ const npxDir = resolve(process.env.HOME ?? "/root", ".npm/_npx");
1129
+ const findResult = spawnSync("find", [npxDir, "-path", "*/@playwright/mcp/package.json", "-print", "-quit"], {
1130
+ encoding: "utf-8", stdio: "pipe",
1131
+ });
1132
+ const existingCache = findResult.stdout?.trim();
1133
+ if (existingCache) {
1134
+ // Nuke the entire npx cache entry to avoid ENOTEMPTY errors
1135
+ const cacheEntry = resolve(existingCache, "../../..");
1136
+ spawnSync("rm", ["-rf", cacheEntry], { stdio: "pipe" });
1137
+ }
1138
+ // Fresh install — npx creates a clean cache with all deps
1139
+ const npxResult = spawnSync("npx", ["-y", "@playwright/mcp@latest", "--version"], {
1140
+ stdio: "pipe",
1141
+ timeout: 180000,
1142
+ encoding: "utf-8",
1143
+ });
1144
+ // Verify playwright-core landed
1145
+ const verifyResult = spawnSync("find", [npxDir, "-path", "*/playwright-core/package.json", "-print", "-quit"], {
1146
+ encoding: "utf-8", stdio: "pipe",
1147
+ });
1148
+ if (verifyResult.stdout?.trim()) {
1149
+ console.log(" Playwright MCP server cached with all dependencies.");
1150
+ }
1151
+ else {
1152
+ console.log(` Warning: Playwright MCP cache may be incomplete (browser automation may not work).${npxResult.stderr ? ` npx stderr: ${npxResult.stderr.slice(0, 200)}` : ""}`);
1153
+ }
1154
+ }
1155
+ function resetNeo4jAuth(port = DEFAULT_NEO4J_PORT, dataDir = "/var/lib/neo4j") {
1156
+ const password = randomBytes(24).toString("base64url");
1157
+ const dedicated = port !== DEFAULT_NEO4J_PORT;
1158
+ const serviceName = dedicated ? `neo4j-${BRAND.hostname}` : "neo4j";
1159
+ console.log(` Resetting Neo4j auth with fresh password (${serviceName})...`);
1160
+ spawnSync("sudo", ["systemctl", "stop", serviceName], { stdio: "inherit" });
1161
+ // Clear the system database (stores auth/roles) and dbms auth config.
1162
+ // The neo4j user database (graph data) is preserved.
1163
+ // set-initial-password only works before the system DB's first start,
1164
+ // so we must delete it to make Neo4j treat the next start as initial.
1165
+ spawnSync("sudo", ["rm", "-rf",
1166
+ `${dataDir}/data/dbms`,
1167
+ `${dataDir}/data/databases/system`,
1168
+ `${dataDir}/data/transactions/system`,
1169
+ ], { stdio: "inherit" });
1170
+ if (dedicated) {
1171
+ const confDir = `/etc/neo4j-${BRAND.hostname}`;
1172
+ // sudo env VAR=val passes the variable through sudo's env_reset
1173
+ spawnSync("sudo", ["env", `NEO4J_CONF=${confDir}`, "neo4j-admin", "dbms", "set-initial-password", "--", password], {
1174
+ stdio: "inherit",
1175
+ });
1176
+ }
1177
+ else {
1178
+ console.log(" [privileged] neo4j-admin dbms");
1179
+ shell("neo4j-admin", ["dbms", "set-initial-password", "--", password], { sudo: true, redact: true });
1180
+ }
1181
+ console.log(" [privileged] systemctl start");
1182
+ shell("systemctl", ["start", serviceName], { sudo: true });
1183
+ console.log(" Waiting for Neo4j to start...");
1184
+ for (let i = 0; i < 15; i++) {
1185
+ const check = spawnSync("cypher-shell", [
1186
+ "-u", "neo4j", "-p", password,
1187
+ "-a", `bolt://localhost:${port}`,
1188
+ "RETURN 1",
1189
+ ], { stdio: "pipe", timeout: 5000 });
1190
+ if (check.status === 0)
1191
+ break;
1192
+ spawnSync("sleep", ["2"]);
1193
+ }
1194
+ return password;
1195
+ }
1196
+ /**
1197
+ * scrub plaintext neo4j passwords from pre-fix install-*.log files.
1198
+ * Calls platform/scripts/redact-install-logs.sh against the installer's LOG_DIR.
1199
+ * The script is idempotent; re-running on clean logs is a no-op. Failures here
1200
+ * are non-fatal — credential redaction is best-effort cleanup, not a blocker
1201
+ * for installation.
1202
+ */
1203
+ function redactInstallLogs() {
1204
+ const script = resolve(INSTALL_DIR, "platform/scripts/redact-install-logs.sh");
1205
+ if (!existsSync(script)) {
1206
+ logFile("[redact-install-logs] script not found at " + script + " — skipping");
1207
+ return;
1208
+ }
1209
+ const r = spawnSync("bash", [script, "--dir", LOG_DIR], {
1210
+ stdio: "pipe",
1211
+ encoding: "utf-8",
1212
+ timeout: 30_000,
1213
+ });
1214
+ if (r.stdout)
1215
+ logFile(r.stdout.trim());
1216
+ if (r.status !== 0 && r.stderr)
1217
+ logFile("[redact-install-logs] WARN " + r.stderr.trim());
1218
+ }
1219
+ /** Check Neo4j has a working password. Called AFTER deploy so config is in place. */
1220
+ function ensureNeo4jPassword() {
1221
+ const passwordFile = join(INSTALL_DIR, "platform/config/.neo4j-password");
1222
+ const configDir = resolve(INSTALL_DIR, "platform/config");
1223
+ mkdirSync(configDir, { recursive: true });
1224
+ const persistDir = resolve(process.env.HOME ?? "/root", BRAND.configDir);
1225
+ const persistentPasswordFile = join(persistDir, ".neo4j-password");
1226
+ // Dedicated instances have their own auth database — password checks and resets
1227
+ // must target the dedicated port and data directory, not the shared instance.
1228
+ const dataDir = NEO4J_DEDICATED ? `/var/lib/neo4j-${BRAND.hostname}` : "/var/lib/neo4j";
1229
+ // 1. Same-brand check: if our own password file exists and works, done (upgrade path).
1230
+ if (existsSync(passwordFile)) {
1231
+ const existingPassword = readFileSync(passwordFile, "utf-8").trim();
1232
+ if (neo4jPasswordWorks(existingPassword, NEO4J_PORT)) {
1233
+ logFile(` Neo4j password: already configured (port ${NEO4J_PORT})`);
1234
+ return;
1235
+ }
1236
+ if (NEO4J_DEDICATED) {
1237
+ console.log(" Stored password doesn't match dedicated Neo4j instance.");
1238
+ }
1239
+ else {
1240
+ console.log(" Stored password doesn't match Neo4j. Resetting auth.");
1241
+ }
1242
+ }
1243
+ // 2. Fresh install or recovery: no working same-brand password. Generate and set a new one.
1244
+ // Brand isolation: never read another brand's.neo4j-password.
1245
+ if (!existsSync(passwordFile)) {
1246
+ console.log(" No Neo4j password file found. Setting initial password...");
1247
+ }
1248
+ // Reset auth and set a new password. Graph data is preserved —
1249
+ // only the auth config ({dataDir}/data/dbms/) is cleared.
1250
+ const hasData = existsSync(`${dataDir}/data/databases/neo4j`);
1251
+ if (hasData) {
1252
+ console.log(" Neo4j has existing data. Resetting auth only (data preserved)...");
1253
+ logFile(` Neo4j auth reset — clearing dbms auth in ${dataDir}, preserving databases + transactions`);
1254
+ }
1255
+ const password = resetNeo4jAuth(NEO4J_PORT, dataDir);
1256
+ writeFileSync(passwordFile, password, { mode: 0o600 });
1257
+ mkdirSync(persistDir, { recursive: true });
1258
+ writeFileSync(persistentPasswordFile, password, { mode: 0o600 });
1259
+ logFile(" Neo4j password: generated new");
1260
+ }
1261
+ /** Test a Neo4j password against the running instance on the given port. */
1262
+ function neo4jPasswordWorks(password, port = DEFAULT_NEO4J_PORT) {
1263
+ const check = spawnSync("cypher-shell", [
1264
+ "-u", "neo4j", "-p", password,
1265
+ "-a", `bolt://localhost:${port}`,
1266
+ "RETURN 1",
1267
+ ], { stdio: "pipe", timeout: 10000 });
1268
+ return check.status === 0;
1269
+ }
1270
+ function installNeo4j() {
1271
+ if (commandExists("neo4j")) {
1272
+ log("4", TOTAL, "Neo4j already installed.");
1273
+ return;
1274
+ }
1275
+ log("4", TOTAL, "Installing Neo4j Community Edition 5...");
1276
+ const platform = requireSupportedPlatform(process.platform);
1277
+ if (platform === "darwin") {
1278
+ // Homebrew's neo4j formula declares openjdk as a runtime dependency, so
1279
+ // Java is pulled in transitively — no separate openjdk install step.
1280
+ // Process supervision (launchd LaunchAgent) is owned; this
1281
+ // step ends after `brew install neo4j` + initial-password seeding so the
1282
+ // payload deploy step finds the shared password file.
1283
+ installAllBrewPackages(["neo4j"], logFile);
1284
+ // Generate strong random password — stored in persistent location (~/{configDir}/)
1285
+ const password = randomBytes(24).toString("base64url");
1286
+ const persistDir = resolve(process.env.HOME ?? "/root", BRAND.configDir);
1287
+ mkdirSync(persistDir, { recursive: true });
1288
+ writeFileSync(join(persistDir, ".neo4j-password"), password, { mode: 0o600 });
1289
+ const configDir = resolve(INSTALL_DIR, "platform/config");
1290
+ mkdirSync(configDir, { recursive: true });
1291
+ writeFileSync(join(configDir, ".neo4j-password"), password, { mode: 0o600 });
1292
+ // Persist Neo4j data under ~/.maxy/neo4j-data/ per the task brief, so a
1293
+ // brew uninstall (which removes the cellar) does not destroy the graph.
1294
+ const neo4jDataDir = resolve(process.env.HOME ?? "/root", BRAND.configDir, "neo4j-data");
1295
+ mkdirSync(neo4jDataDir, { recursive: true });
1296
+ shell("neo4j-admin", ["dbms", "set-initial-password", "--", password], { redact: true });
1297
+ // Start Neo4j under brew's launchd supervision. Linux path starts the
1298
+ // service via systemd a few lines below; without this start the darwin
1299
+ // brand server binds successfully but every Cypher write fails with
1300
+ // "Failed to connect to server" because nothing is listening on 7687.
1301
+ // `brew services start` is idempotent — if already running it no-ops,
1302
+ // and the LaunchAgent persists across reboots.
1303
+ const brewStart = spawnSync("brew", ["services", "start", "neo4j"], { stdio: "inherit" });
1304
+ if (brewStart.status !== 0) {
1305
+ throw new Error(`brew services start neo4j failed (exit ${brewStart.status}) — Neo4j must be running before the brand server starts or all graph writes will fail`);
1306
+ }
1307
+ console.log(" Neo4j installed and started via Homebrew launchd. Password stored securely.");
1308
+ return;
1309
+ }
1310
+ // Neo4j 5.x supports Java 17 and 21. Debian Bookworm ships 17, Trixie ships 21.
1311
+ // apt-cache policy shows "Candidate: (none)" when no installable version exists.
1312
+ const policyResult = spawnSync("apt-cache", ["policy", "openjdk-17-jre-headless"], { stdio: "pipe" });
1313
+ const policyOutput = policyResult.stdout?.toString() ?? "";
1314
+ const has17 = policyResult.status === 0 && !policyOutput.includes("Candidate: (none)");
1315
+ const javaPackage = has17 ? "openjdk-17-jre-headless" : "openjdk-21-jre-headless";
1316
+ console.log(` Installing Java (${javaPackage})...`);
1317
+ console.log(" [privileged] apt-get install");
1318
+ shell("apt-get", ["install", "-y", javaPackage], { sudo: true });
1319
+ spawnSync("bash", ["-c", "curl -fsSL https://debian.neo4j.com/neotechnology.gpg.key | sudo gpg --yes --dearmor -o /usr/share/keyrings/neo4j.gpg 2>/dev/null"], { stdio: "inherit" });
1320
+ spawnSync("bash", ["-c", 'echo "deb [signed-by=/usr/share/keyrings/neo4j.gpg] https://debian.neo4j.com stable 5" | sudo tee /etc/apt/sources.list.d/neo4j.list'], { stdio: "inherit" });
1321
+ console.log(" [privileged] apt-get update");
1322
+ shell("apt-get", ["update"], { sudo: true });
1323
+ console.log(" [privileged] apt-get install");
1324
+ shell("apt-get", ["install", "-y", "neo4j"], { sudo: true });
1325
+ console.log(" [privileged] sed -i");
1326
+ shell("sed", ["-i", "s/#server.default_listen_address=0.0.0.0/server.default_listen_address=127.0.0.1/", "/etc/neo4j/neo4j.conf"], { sudo: true });
1327
+ // Generate strong random password — stored in persistent location (~/{configDir}/)
1328
+ const password = randomBytes(24).toString("base64url");
1329
+ const persistDir = resolve(process.env.HOME ?? "/root", BRAND.configDir);
1330
+ mkdirSync(persistDir, { recursive: true });
1331
+ writeFileSync(join(persistDir, ".neo4j-password"), password, { mode: 0o600 });
1332
+ // Also write to install dir (will be there when deploy step runs)
1333
+ const configDir = resolve(INSTALL_DIR, "platform/config");
1334
+ mkdirSync(configDir, { recursive: true });
1335
+ writeFileSync(join(configDir, ".neo4j-password"), password, { mode: 0o600 });
1336
+ console.log(" [privileged] neo4j-admin dbms");
1337
+ shell("neo4j-admin", ["dbms", "set-initial-password", "--", password], { sudo: true, redact: true });
1338
+ console.log(" [privileged] systemctl enable");
1339
+ shell("systemctl", ["enable", "neo4j"], { sudo: true });
1340
+ console.log(" [privileged] systemctl start");
1341
+ shell("systemctl", ["start", "neo4j"], { sudo: true });
1342
+ console.log(" Neo4j started. Password stored securely.");
1343
+ }
1344
+ /**
1345
+ * does any peer brand on this host pin `NEO4J_URI=bolt://localhost:<default>`
1346
+ * in its `.env`? If yes, the apt-installed `neo4j.service` is its database and the
1347
+ * dedicated-unit installer must NOT stop+disable it. Returns the first matching
1348
+ * peer's hostname, or `null` when no peer pins the default port.
1349
+ *
1350
+ * Wraps the pure decision in `peer-brand-detect.ts` with the fs reads of
1351
+ * `~/.<peer>/.env`. Bias on read errors: if `.env` exists but is unreadable
1352
+ * (permissions, transient I/O), the wrapper treats that peer as a *potential*
1353
+ * dependency and short-circuits to the kept-active path. Disabling the system
1354
+ * unit on faulty evidence would silently kill the peer's database (the exact
1355
+ * failure mode the kept-active path prevents); a conservatively-skipped disable is recoverable
1356
+ * because the dedicated-unit bind check at the end of `setupDedicatedNeo4j`
1357
+ * fails loud if the system unit is actually free.
1358
+ */
1359
+ function peerBrandUsingSystemUnit() {
1360
+ const home = process.env.HOME ?? "/root";
1361
+ const peerEnvContents = [];
1362
+ for (const hostname of KNOWN_BRAND_HOSTNAMES) {
1363
+ if (hostname === BRAND.hostname) {
1364
+ peerEnvContents.push([hostname, null]);
1365
+ continue;
1366
+ }
1367
+ const envPath = resolve(home, `.${hostname}`, ".env");
1368
+ if (!existsSync(envPath)) {
1369
+ peerEnvContents.push([hostname, null]);
1370
+ continue;
1371
+ }
1372
+ try {
1373
+ peerEnvContents.push([hostname, readFileSync(envPath, "utf-8")]);
1374
+ }
1375
+ catch (err) {
1376
+ console.error(` WARNING: unable to read peer brand .env at ${envPath} — treating as potential dependency to avoid data loss: ${err instanceof Error ? err.message : String(err)}`);
1377
+ return hostname;
1378
+ }
1379
+ }
1380
+ return findPeerBrandOnDefaultNeo4jPort({
1381
+ currentBrandHostname: BRAND.hostname,
1382
+ defaultNeo4jPort: DEFAULT_NEO4J_PORT,
1383
+ peerEnvContents,
1384
+ });
1385
+ }
1386
+ /**
1387
+ * Create a dedicated Neo4j instance for this brand when NEO4J_DEDICATED is true.
1388
+ * Produces: separate config dir, data dir, log dir, systemd service, and password.
1389
+ * On upgrade (config already exists), skips conf creation — but always runs the
1390
+ * state-remediation block (stop/disable system unit, reset-failed
1391
+ * dedicated, start, verify) so a half-installed Pi recovers in-place without
1392
+ * manual systemctl. ensureNeo4jPassword() handles password verification on the
1393
+ * recovery path.
1394
+ *
1395
+ * on multi-brand hosts where a peer brand still depends on the apt
1396
+ * `neo4j.service` (port 7687), the stop+disable step is skipped — disabling
1397
+ * the system unit would kill the peer's database.
1398
+ */
1399
+ function setupDedicatedNeo4j() {
1400
+ if (!NEO4J_DEDICATED)
1401
+ return;
1402
+ const brandSuffix = BRAND.hostname; // e.g., "realagent"
1403
+ const confDir = `/etc/neo4j-${brandSuffix}`;
1404
+ const dataDir = `/var/lib/neo4j-${brandSuffix}`;
1405
+ const logDir = `/var/log/neo4j-${brandSuffix}`;
1406
+ const serviceName = `neo4j-${brandSuffix}`;
1407
+ const httpPort = NEO4J_PORT - 213; // Preserve standard 7687/7474 offset
1408
+ // Per-brand state (sed, mkdir, chown, unit-write) is idempotent and runs on
1409
+ // every install. Only the base-config copy and initial-password rotation are
1410
+ // gated to first install established that state remediation must
1411
+ // run every install extended the same principle to the conf and
1412
+ // unit emission so a half-installed host (broken unit missing NEO4J_HOME)
1413
+ // recovers on retry without an out-of-band manual reset.
1414
+ const confExists = spawnSync("test", ["-f", `${confDir}/neo4j.conf`], { stdio: "pipe" }).status === 0;
1415
+ if (confExists) {
1416
+ console.log(` Dedicated Neo4j instance for ${BRAND.productName} already configured at ${confDir} — re-applying per-brand state`);
1417
+ logFile(` Neo4j dedicated: existing config at ${confDir}, re-applying sed/mkdir/chown/unit on every install`);
1418
+ }
1419
+ else {
1420
+ console.log(` Setting up dedicated Neo4j instance for ${BRAND.productName} on bolt://localhost:${NEO4J_PORT}...`);
1421
+ // Pre-check: neo4j user must exist (created by the apt package)
1422
+ const neo4jUserCheck = spawnSync("id", ["neo4j"], { stdio: "pipe" });
1423
+ if (neo4jUserCheck.status !== 0) {
1424
+ throw new Error("Neo4j system user 'neo4j' not found. Is Neo4j installed via apt?");
1425
+ }
1426
+ // Pre-check: source config must exist
1427
+ if (!existsSync("/etc/neo4j/neo4j.conf")) {
1428
+ throw new Error("/etc/neo4j/neo4j.conf not found. Cannot create dedicated instance without base config.");
1429
+ }
1430
+ // Copy base config (first install only — sed runs unconditionally below)
1431
+ console.log(" [privileged] cp -r");
1432
+ shell("cp", ["-r", "/etc/neo4j", confDir], { sudo: true });
1433
+ }
1434
+ // Idempotent per-brand state — runs on every install.
1435
+ // Older Neo4j 5.x templates ship a SECOND commented occurrence of these
1436
+ // keys in the "Other Neo4j system properties" section. An in-place
1437
+ // `sed s|^#?key=.*|key=value|` matches both and writes duplicate active
1438
+ // lines; the 5.26.26 parser turns that into a fatal startup error.
1439
+ // Delete-all-then-append guarantees exactly one active line per key
1440
+ // regardless of how many commented occurrences the template ships.
1441
+ const confPath = `${confDir}/neo4j.conf`;
1442
+ const confKeys = [
1443
+ ["server.bolt.listen_address", `:${NEO4J_PORT}`],
1444
+ ["server.http.listen_address", `:${httpPort}`],
1445
+ ["server.directories.data", `${dataDir}/data`],
1446
+ ["server.directories.logs", logDir],
1447
+ ["server.directories.plugins", `${dataDir}/plugins`],
1448
+ ["server.directories.import", `${dataDir}/import`],
1449
+ ];
1450
+ for (const [key, value] of confKeys) {
1451
+ const keyRe = key.replace(/\./g, "\\.");
1452
+ console.log(" [privileged] sed -i (delete)");
1453
+ shell("sed", ["-i", `/^#\\?${keyRe}=/d`, confPath], { sudo: true });
1454
+ console.log(" [privileged] echo >>");
1455
+ shell("sh", ["-c", `echo '${key}=${value}' >> ${confPath}`], { sudo: true });
1456
+ }
1457
+ // Verify exactly one active line per key. Any n>1 aborts the install
1458
+ // BEFORE the systemd unit is written. n==0 means the append failed.
1459
+ const activeCounts = [];
1460
+ for (const [key] of confKeys) {
1461
+ const r = spawnSync("sudo", ["grep", "-c", `^${key}=`, confPath], { stdio: "pipe" });
1462
+ const n = parseInt((r.stdout?.toString() ?? "0").trim(), 10) || 0;
1463
+ activeCounts.push(`${key}:${n}`);
1464
+ if (n !== 1) {
1465
+ const msg = `[neo4j-conf] FATAL ${key} active_count=${n}`;
1466
+ console.error(` ${msg}`);
1467
+ logFile(` ${msg}`);
1468
+ throw new Error(msg);
1469
+ }
1470
+ }
1471
+ const summary = `[neo4j-conf] keys_active=${activeCounts.join(",")}`;
1472
+ console.log(` ${summary}`);
1473
+ logFile(` ${summary}`);
1474
+ console.log(" [privileged] mkdir -p");
1475
+ shell("mkdir", ["-p", `${dataDir}/data`, `${dataDir}/plugins`, `${dataDir}/import`, logDir], { sudo: true });
1476
+ console.log(" [privileged] chown -R");
1477
+ shell("chown", ["-R", "neo4j:neo4j", dataDir, logDir, confDir], { sudo: true });
1478
+ const serviceContent = `[Unit]
1479
+ Description=Neo4j Graph Database (${BRAND.productName})
1480
+ After=network-online.target
1481
+ Wants=network-online.target
1482
+
1483
+ [Service]
1484
+ ExecStart=/usr/bin/neo4j console
1485
+ Restart=on-failure
1486
+ User=neo4j
1487
+ Group=neo4j
1488
+ Environment="NEO4J_CONF=${confDir}" "NEO4J_HOME=${dataDir}"
1489
+ LimitNOFILE=60000
1490
+
1491
+ [Install]
1492
+ WantedBy=multi-user.target
1493
+ `;
1494
+ const tmpServicePath = `/tmp/${serviceName}.service`;
1495
+ writeFileSync(tmpServicePath, serviceContent);
1496
+ console.log(" [privileged] cp");
1497
+ shell("cp", [tmpServicePath, `/etc/systemd/system/${serviceName}.service`], { sudo: true });
1498
+ spawnSync("rm", ["-f", tmpServicePath]);
1499
+ logFile(` [neo4j] dedicated unit env: NEO4J_CONF=${confDir} NEO4J_HOME=${dataDir}`);
1500
+ if (!confExists) {
1501
+ // Set initial password before first start (first install only — rotation
1502
+ // on retry would brick an existing DB whose password is already stored).
1503
+ const password = randomBytes(24).toString("base64url");
1504
+ const persistDir = resolve(process.env.HOME ?? "/root", BRAND.configDir);
1505
+ mkdirSync(persistDir, { recursive: true });
1506
+ writeFileSync(join(persistDir, ".neo4j-password"), password, { mode: 0o600 });
1507
+ const configDir = resolve(INSTALL_DIR, "platform/config");
1508
+ mkdirSync(configDir, { recursive: true });
1509
+ writeFileSync(join(configDir, ".neo4j-password"), password, { mode: 0o600 });
1510
+ // sudo env VAR=val passes NEO4J_CONF through sudo's env_reset policy
1511
+ spawnSync("sudo", ["env", `NEO4J_CONF=${confDir}`, "neo4j-admin", "dbms", "set-initial-password", "--", password], {
1512
+ stdio: "inherit",
1513
+ });
1514
+ }
1515
+ // ============================================================================
1516
+ // unified state remediation + start + verify.
1517
+ //
1518
+ // Runs on both fresh and recovery paths. The dedicated unit and the apt
1519
+ // package's system unit both exec /usr/bin/neo4j console without overriding
1520
+ // NEO4J_HOME, so server.directories.run resolves to /var/lib/neo4j/run for
1521
+ // both — the launcher refuses with "Neo4j is already running (pid:N)" if
1522
+ // the system unit holds the PID file. Stopping the system unit first frees
1523
+ // the run-state; disabling prevents it returning at next boot. reset-failed
1524
+ // clears any prior start-limit-hit from a half-installed Pi.
1525
+ // ============================================================================
1526
+ spawnSync("sudo", ["systemctl", "daemon-reload"], { stdio: "inherit" });
1527
+ console.log(" [privileged] systemctl enable");
1528
+ shell("systemctl", ["enable", serviceName], { sudo: true });
1529
+ // Tear down a legacy-package dedicated Neo4j unit pinning the same port.
1530
+ // The `-code` rewrite packages (`create-<brand>-code`) replace the legacy
1531
+ // `create-<brand>` packages. When migrating a device from legacy to -code,
1532
+ // both packages' dedicated Neo4j units exist (`neo4j-<brand>.service` and
1533
+ // `neo4j-<brand>-code.service`) and both try to bind the same dedicated
1534
+ // bolt port. The legacy unit wins the race (it boots first because it's
1535
+ // alphabetically earlier in systemd's load order), the new unit silently
1536
+ // fails with `bind failed -98 Address already in use`, and the seed step
1537
+ // talks to the legacy instance with the wrong password — auth fails with
1538
+ // a misleading "client is unauthorized" (observed on beacons).
1539
+ if (brandSuffix.endsWith("-code")) {
1540
+ const legacyBrand = brandSuffix.slice(0, -"-code".length);
1541
+ const legacyUnit = `neo4j-${legacyBrand}.service`;
1542
+ const legacyUnitFile = `/etc/systemd/system/${legacyUnit}`;
1543
+ if (existsSync(legacyUnitFile)) {
1544
+ const legacyMsg = ` [neo4j] legacy unit detected (${legacyUnit}) — stopping + disabling so the -code unit owns port ${NEO4J_PORT}`;
1545
+ console.log(legacyMsg);
1546
+ logFile(legacyMsg);
1547
+ shell("systemctl", ["stop", legacyUnit], { sudo: true, bestEffort: true });
1548
+ shell("systemctl", ["disable", legacyUnit], { sudo: true, bestEffort: true });
1549
+ }
1550
+ }
1551
+ // skip stop+disable when a peer brand on this host still depends
1552
+ // on the apt `neo4j.service` (port 7687). Disabling it would kill the peer's
1553
+ // database reproducer on Neo's laptop. The kept-active path is
1554
+ // mutually exclusive with the disable path: exactly one log line per install.
1555
+ const peerOnSystemUnit = peerBrandUsingSystemUnit();
1556
+ if (peerOnSystemUnit !== null) {
1557
+ const keptActiveMsg = ` [neo4j] system unit kept active — peer brand ${peerOnSystemUnit} depends on port ${DEFAULT_NEO4J_PORT}`;
1558
+ console.log(keptActiveMsg);
1559
+ logFile(keptActiveMsg);
1560
+ }
1561
+ else {
1562
+ console.log(` [neo4j] disabling system unit (brand-dedicated active on port ${NEO4J_PORT})`);
1563
+ logFile(` [neo4j] disabling system unit (brand-dedicated active on port ${NEO4J_PORT})`);
1564
+ shell("systemctl", ["stop", "neo4j"], { sudo: true });
1565
+ shell("systemctl", ["disable", "neo4j"], { sudo: true });
1566
+ }
1567
+ console.log(` [neo4j] reset-failed ${serviceName} before start`);
1568
+ logFile(` [neo4j] reset-failed ${serviceName} before start`);
1569
+ shell("systemctl", ["reset-failed", serviceName], { sudo: true, bestEffort: true });
1570
+ console.log(" [privileged] systemctl start");
1571
+ shell("systemctl", ["start", serviceName], { sudo: true });
1572
+ // Verify the dedicated unit bound its port. Password verification is
1573
+ // ensureNeo4jPassword()'s job (called next in the install pipeline) — that
1574
+ // function tests the stored password against this port and resets auth if
1575
+ // the password no longer matches the running instance.
1576
+ console.log(` Waiting for dedicated Neo4j instance on port ${NEO4J_PORT}...`);
1577
+ let listening = false;
1578
+ const portMatch = new RegExp(`:${NEO4J_PORT}\\b`);
1579
+ for (let i = 0; i < 15; i++) {
1580
+ const portCheck = spawnSync("ss", ["-tln"], { stdio: "pipe", timeout: 5000 });
1581
+ if (portMatch.test(portCheck.stdout?.toString() ?? "")) {
1582
+ listening = true;
1583
+ break;
1584
+ }
1585
+ spawnSync("sleep", ["2"]);
1586
+ }
1587
+ if (!listening) {
1588
+ // Loud failure — no silent fallback to the system instance.
1589
+ const portCheck = spawnSync("ss", ["-tlnp"], { stdio: "pipe", timeout: 5000 });
1590
+ const portLines = (portCheck.stdout?.toString() ?? "").split("\n").filter((l) => l.includes(String(NEO4J_PORT)));
1591
+ const diagnostic = portLines.length > 0 ? portLines.join("; ") : "nothing listening on port";
1592
+ const journal = spawnSync("journalctl", ["-u", serviceName, "--since", "5 min ago"], { stdio: "pipe", timeout: 5000 });
1593
+ const journalTail = (journal.stdout?.toString() ?? "").split("\n").slice(-20).join("\n");
1594
+ logFile(` Neo4j dedicated: failed to bind port ${NEO4J_PORT} — ${diagnostic}`);
1595
+ throw new Error(`Dedicated Neo4j instance ${serviceName} did not bind bolt://localhost:${NEO4J_PORT} within 30s.\n` +
1596
+ `Port ${NEO4J_PORT}: ${diagnostic}\n` +
1597
+ `journalctl -u ${serviceName} --since "5 min ago" | tail -20:\n${journalTail}`);
1598
+ }
1599
+ logFile(` Neo4j dedicated: config=${confDir} data=${dataDir} service=${serviceName} bolt=:${NEO4J_PORT} http=:${httpPort}`);
1600
+ console.log(` Dedicated Neo4j instance ready on bolt://localhost:${NEO4J_PORT}`);
1601
+ }
1602
+ function ensureOllamaServing() {
1603
+ const check = () => spawnSync("curl", ["-sf", "http://localhost:11434/api/tags"], {
1604
+ stdio: "pipe", timeout: 5_000,
1605
+ });
1606
+ if (check().status === 0)
1607
+ return;
1608
+ // Log which ollama binary we're using and its version
1609
+ const which = spawnSync("which", ["ollama"], { stdio: "pipe" });
1610
+ const ollamaPath = which.stdout?.toString().trim() || "not found";
1611
+ logFile(` Ollama binary: ${ollamaPath}`);
1612
+ const version = spawnSync("ollama", ["--version"], { stdio: "pipe", timeout: 5_000 });
1613
+ logFile(` Ollama version: ${version.stdout?.toString().trim() || version.stderr?.toString().trim() || `exit ${version.status}`}`);
1614
+ // Check if systemd service exists
1615
+ const svcCheck = spawnSync("systemctl", ["cat", "ollama"], { stdio: "pipe", timeout: 5_000 });
1616
+ logFile(` Ollama systemd service: ${svcCheck.status === 0 ? "exists" : "not found"}`);
1617
+ // Check if port 11434 is already in use by something else
1618
+ const portCheck = spawnSync("ss", ["-tlnp"], { stdio: "pipe", timeout: 5_000 });
1619
+ const portLines = portCheck.stdout?.toString().split("\n").filter((l) => l.includes("11434")) || [];
1620
+ if (portLines.length > 0)
1621
+ logFile(` Port 11434 in use: ${portLines.join("; ")}`);
1622
+ console.log(" Starting Ollama server...");
1623
+ logFile(" Ollama server not responding — starting ollama serve");
1624
+ // Capture ollama serve output to a log file for diagnostics
1625
+ const ollamaLog = join(LOG_DIR, "ollama-serve.log");
1626
+ const logFd = openSync(ollamaLog, "a");
1627
+ const child = spawn("ollama", ["serve"], {
1628
+ stdio: ["ignore", logFd, logFd], detached: true,
1629
+ });
1630
+ child.unref();
1631
+ closeSync(logFd);
1632
+ logFile(` Spawned ollama serve (PID ${child.pid}), log: ${ollamaLog}`);
1633
+ for (let elapsed = 0; elapsed < 30; elapsed += 3) {
1634
+ spawnSync("sleep", ["3"]);
1635
+ // Check if process is still alive
1636
+ const alive = child.pid && spawnSync("kill", ["-0", String(child.pid)], { stdio: "pipe" }).status === 0;
1637
+ logFile(` Poll ${elapsed + 3}s: pid ${child.pid} alive=${alive}`);
1638
+ if (check().status === 0) {
1639
+ logFile(` Ollama server ready after ${elapsed + 3}s`);
1640
+ return;
1641
+ }
1642
+ if (!alive) {
1643
+ // Process died — read the log to find out why
1644
+ const serveLog = readFileSync(ollamaLog, "utf-8").slice(-2000);
1645
+ logFile(` Ollama serve exited. Log tail:\n${serveLog}`);
1646
+ console.error(` Ollama serve exited unexpectedly. Log: ${ollamaLog}`);
1647
+ throw new Error(`Ollama serve failed to start. Log: ${ollamaLog}\n${serveLog}`);
1648
+ }
1649
+ }
1650
+ // Timed out — include diagnostics
1651
+ const serveLog = readFileSync(ollamaLog, "utf-8").slice(-2000);
1652
+ logFile(` Ollama serve timed out after 30s. Log tail:\n${serveLog}`);
1653
+ throw new Error(`Ollama server did not respond within 30s. Log: ${ollamaLog}\n${serveLog}`);
1654
+ }
1655
+ // Cap ollama's CPU so an embedding burst cannot thermally hard-reset a
1656
+ // passively-cooled Pi. The platform embeds a document's summary plus every
1657
+ // section body via one `/api/embed` POST; ollama's llama-server then runs
1658
+ // flat-out across every core for the whole batch with no idle gaps, and on a
1659
+ // passively-cooled Pi 5 the SoC climbs past its soft-temp limit until the board
1660
+ // reaches its thermal ceiling and hard-resets. A systemd `CPUQuota` drop-in on
1661
+ // `ollama.service` bounds llama-server to a fraction of the cores so peak
1662
+ // temperature plateaus below the limit regardless of batch shape or which
1663
+ // platform path issues the embeds — the caller-agnostic fix, inherited by every
1664
+ // install. Quota is one core (100%): an embedding burst then draws roughly a
1665
+ // quarter of a 4-core Pi's compute current instead of half, which both keeps
1666
+ // peak SoC temperature down and shaves the current spike that browns out a
1667
+ // marginal PSU. Ingest is slower in exchange. Applied only when the ollama
1668
+ // system service exists (the normal Linux path, where ollama's install.sh
1669
+ // registers `ollama.service`); a detached `ollama serve` has no unit to cap.
1670
+ // ollama is one shared host service across co-resident brands, so the drop-in is
1671
+ // host-wide with a neutral filename — idempotent across brands and reinstalls,
1672
+ // and ollama restarts only when the drop-in content actually changes. Best-
1673
+ // effort: a failure warns, never aborts the install.
1674
+ function capOllamaServiceCpu() {
1675
+ try {
1676
+ const svcCheck = spawnSync("systemctl", ["cat", "ollama"], { stdio: "pipe", timeout: 5_000 });
1677
+ if (svcCheck.status !== 0) {
1678
+ logFile(" ollama CPU cap: skipped (no ollama system service to cap)");
1679
+ return;
1680
+ }
1681
+ const coreCount = Math.max(1, cpus().length);
1682
+ const quotaCores = 1;
1683
+ const quotaPct = quotaCores * 100;
1684
+ const desired = `[Service]\nCPUQuota=${quotaPct}%\n`;
1685
+ const dropinDir = "/etc/systemd/system/ollama.service.d";
1686
+ const dropinPath = `${dropinDir}/10-maxy-cpuquota.conf`;
1687
+ let current = "";
1688
+ if (existsSync(dropinPath)) {
1689
+ try {
1690
+ current = readFileSync(dropinPath, "utf-8");
1691
+ }
1692
+ catch {
1693
+ // Unreadable existing drop-in — treat as changed so we rewrite + restart.
1694
+ current = "";
1695
+ }
1696
+ }
1697
+ if (current === desired) {
1698
+ logFile(` ollama CPU cap: already active (${dropinPath} matches CPUQuota=${quotaPct}%)`);
1699
+ return;
1700
+ }
1701
+ const tmpPath = "/tmp/10-maxy-ollama-cpuquota.conf";
1702
+ writeFileSync(tmpPath, desired);
1703
+ console.log(` [privileged] install ollama CPUQuota=${quotaPct}% drop-in (${quotaCores}/${coreCount} cores)`);
1704
+ shell("mkdir", ["-p", dropinDir], { sudo: true });
1705
+ shell("cp", [tmpPath, dropinPath], { sudo: true });
1706
+ spawnSync("rm", ["-f", tmpPath]);
1707
+ spawnSync("sudo", ["systemctl", "daemon-reload"], { stdio: "inherit" });
1708
+ console.log(" [privileged] systemctl restart ollama");
1709
+ spawnSync("sudo", ["systemctl", "restart", "ollama"], { stdio: "inherit", timeout: 30_000 });
1710
+ // The restart briefly drops the API. Wait for ollama to serve again before
1711
+ // returning so the immediately-following ensureOllamaServing() probe finds
1712
+ // it up and does not race the restart by spawning a second detached
1713
+ // `ollama serve` that would contend for port 11434. Bounded poll; the drop-in
1714
+ // is already on disk either way, so a timeout still applies the cap on the
1715
+ // next ollama start.
1716
+ let served = false;
1717
+ for (let elapsed = 0; elapsed < 15; elapsed += 3) {
1718
+ if (spawnSync("curl", ["-sf", "http://localhost:11434/api/tags"], { stdio: "pipe", timeout: 5_000 }).status === 0) {
1719
+ served = true;
1720
+ break;
1721
+ }
1722
+ spawnSync("sleep", ["3"]);
1723
+ }
1724
+ if (served) {
1725
+ logFile(` ollama CPU cap: enabled (wrote ${dropinPath} CPUQuota=${quotaPct}%, ollama serving again under the cap)`);
1726
+ }
1727
+ else {
1728
+ logFile(` ollama CPU cap: drop-in written (${dropinPath} CPUQuota=${quotaPct}%); ollama not serving yet after restart — cap applies on its next start`);
1729
+ }
1730
+ }
1731
+ catch (err) {
1732
+ console.error(` WARNING: failed to cap ollama CPU: ${err instanceof Error ? err.message : String(err)}`);
1733
+ }
1734
+ }
1735
+ function installOllama(embedModel) {
1736
+ if (!commandExists("ollama")) {
1737
+ log("5", TOTAL, "Installing Ollama...");
1738
+ spawnSync("bash", ["-c", "curl -fsSL https://ollama.ai/install.sh | sh"], { stdio: "inherit" });
1739
+ }
1740
+ else {
1741
+ log("5", TOTAL, "Ollama already installed.");
1742
+ }
1743
+ // Bound ollama's CPU before bringing the service up so the capped unit is what
1744
+ // serves embeds (and the restart below lands the new quota).
1745
+ capOllamaServiceCpu();
1746
+ ensureOllamaServing();
1747
+ console.log(` Pulling ${embedModel} embedding model...`);
1748
+ logFile(` Pulling embedding model: ${embedModel}`);
1749
+ shellRetry("ollama", ["pull", embedModel], { timeout: 600_000 }, 3, 15);
1750
+ }
1751
+ // uv/uvx bootstrap. Required by the `graph` MCP server which
1752
+ // spawns `uvx mcp-neo4j-cypher@0.6.0 --transport stdio`. Idempotent: when
1753
+ // uvx is already on PATH (or under $HOME/.local/bin) we skip. Non-fatal on
1754
+ // failure — the installer continues; the graph server will loudly fail
1755
+ // at session start with a clear "uvx not found" error, which is retriable
1756
+ // via a second installer run with network access.
1757
+ function installUv() {
1758
+ if (commandExists("uvx")) {
1759
+ logFile(" uv: already installed");
1760
+ console.log(" uv/uvx already installed.");
1761
+ return;
1762
+ }
1763
+ console.log(" Installing uv (Python tool runner — required by Neo4j MCP server)...");
1764
+ logFile(" uv: installing via astral.sh installer");
1765
+ // astral.sh installer auto-confirms when stdin is not a TTY (our case under
1766
+ // systemd-run). Historically we passed `-y`, which the script rejects with
1767
+ // "unknown option -y" and causes uv to never install on upgrade.
1768
+ const result = spawnSync("bash", ["-c", "curl -LsSf https://astral.sh/uv/install.sh | sh"], { stdio: "inherit" });
1769
+ if (result.status !== 0) {
1770
+ console.error(` WARNING: uv install exited ${result.status} — graph MCP server will fail at session start until this is retried`);
1771
+ logFile(` WARNING: uv install failed with status ${result.status}`);
1772
+ return;
1773
+ }
1774
+ // The installer writes uvx to $HOME/.local/bin — add it to PATH for the
1775
+ // remainder of this install so commandExists("uvx") works downstream.
1776
+ const localBin = `${process.env.HOME}/.local/bin`;
1777
+ if (process.env.PATH && !process.env.PATH.includes(localBin)) {
1778
+ process.env.PATH = `${localBin}:${process.env.PATH}`;
1779
+ }
1780
+ if (commandExists("uvx")) {
1781
+ logFile(" uv: install succeeded; uvx on PATH");
1782
+ }
1783
+ else {
1784
+ console.error(" WARNING: uv installed but uvx not on PATH — check $HOME/.local/bin");
1785
+ }
1786
+ }
1787
+ // Task 757 — cloudflared version is installer-owned and pinned. The connector
1788
+ // runs with --no-autoupdate (resume-tunnel.sh), so it never self-replaces; the
1789
+ // only way the binary version moves is bumping this pin and republishing the
1790
+ // installer. Fetching `latest` (the prior behaviour) let the binary drift at
1791
+ // install time and, combined with the connector's own auto-update, caused the
1792
+ // 2026-06-10 realagent-code tunnel outage.
1793
+ const CLOUDFLARED_VERSION = "2026.6.0";
1794
+ function installCloudflared() {
1795
+ if (commandExists("cloudflared")) {
1796
+ log("6", TOTAL, "Cloudflared already installed.");
1797
+ return;
1798
+ }
1799
+ log("6", TOTAL, "Installing cloudflared...");
1800
+ const platform = requireSupportedPlatform(process.platform);
1801
+ if (platform === "darwin") {
1802
+ // Homebrew's `cloudflared` formula tracks the Cloudflare release stream;
1803
+ // tunnel-login flow stays unchanged (`feedback_no_api_token_route.md`).
1804
+ // `cloudflared service install` and `cloudflared tunnel route dns` are not
1805
+ // invoked by the installer on darwin — public reach is operator-driven
1806
+ // post-install (`cloudflared tunnel login` + follow-up tooling). The brew
1807
+ // install puts the binary on PATH so the operator can opt in later.
1808
+ logFile(` [create-maxy] darwin-cloudflare-skip=true reason="Mac laptop — no public hostname provisioned at install time"`);
1809
+ installAllBrewPackages(["cloudflared"], logFile);
1810
+ return;
1811
+ }
1812
+ const arch = isArm64() ? "arm64" : "amd64";
1813
+ const debPath = "/tmp/cloudflared.deb";
1814
+ shellRetry("curl", ["-fSL", "--progress-bar", `https://github.com/cloudflare/cloudflared/releases/download/${CLOUDFLARED_VERSION}/cloudflared-linux-${arch}.deb`, "-o", debPath], { timeout: 120_000 }, 3, 10);
1815
+ console.log(" [privileged] dpkg -i");
1816
+ shell("dpkg", ["-i", debPath], { sudo: true });
1817
+ spawnSync("rm", ["-f", debPath]);
1818
+ }
1819
+ function installWhisperCpp() {
1820
+ const WHISPER_DIR = "/opt/whisper.cpp";
1821
+ const WHISPER_BINARY = join(WHISPER_DIR, "build/bin/whisper-cli");
1822
+ const WHISPER_MODEL = join(WHISPER_DIR, "models", "ggml-base.bin");
1823
+ if (existsSync(WHISPER_BINARY) && existsSync(WHISPER_MODEL)) {
1824
+ log("7", TOTAL, "whisper.cpp already installed.");
1825
+ return;
1826
+ }
1827
+ log("7", TOTAL, "Installing whisper.cpp (speech-to-text)...");
1828
+ if (!isLinux()) {
1829
+ console.log(" Skipping — install manually for your platform.");
1830
+ return;
1831
+ }
1832
+ // Build dependencies — cmake is required since whisper.cpp migrated from plain make
1833
+ console.log(" [privileged] apt-get install");
1834
+ shell("apt-get", ["install", "-y", "build-essential", "cmake"], { sudo: true });
1835
+ // Clone or update the repository
1836
+ if (!existsSync(WHISPER_DIR)) {
1837
+ console.log(" Cloning whisper.cpp...");
1838
+ console.log(" [privileged] git clone");
1839
+ shell("git", ["clone", "--depth", "1", "https://github.com/ggerganov/whisper.cpp.git", WHISPER_DIR], { sudo: true });
1840
+ }
1841
+ // Compile via cmake (whisper.cpp's Makefile is a thin cmake wrapper)
1842
+ console.log(" Compiling whisper.cpp (this takes a few minutes on Pi)...");
1843
+ console.log(" [privileged] cmake -B");
1844
+ shell("cmake", ["-B", "build"], { cwd: WHISPER_DIR, sudo: true, timeout: 120_000 });
1845
+ console.log(" [privileged] cmake --build");
1846
+ shell("cmake", ["--build", "build", "--config", "Release", "-j2"], { cwd: WHISPER_DIR, sudo: true, timeout: 600_000 });
1847
+ // Download the base model (~150MB)
1848
+ if (!existsSync(WHISPER_MODEL)) {
1849
+ console.log(" Downloading ggml-base model (~150MB)...");
1850
+ console.log(" [privileged] bash -c");
1851
+ shellRetry("bash", ["-c", `cd ${WHISPER_DIR} && bash models/download-ggml-model.sh base`], { sudo: true, timeout: 300_000 }, 3, 15);
1852
+ }
1853
+ console.log(" whisper.cpp installed successfully.");
1854
+ }
1855
+ /**
1856
+ * Provision the shared HMAC secret used to sign remote-session cookies
1857
+ *. Both `maxy-edge` and `maxy-ui` read this file; without it
1858
+ * they independently mint ephemeral secrets on first use and the
1859
+ * cross-process session namespace silently diverges again.
1860
+ *
1861
+ * First install: create the file (0600, 32-byte hex).
1862
+ * Upgrade: leave the existing file untouched — invalidating it here
1863
+ * would log every operator out on every upgrade.
1864
+ */
1865
+ function provisionRemoteSessionSecret() {
1866
+ const persistDir = resolve(process.env.HOME ?? "/root", BRAND.configDir);
1867
+ const credentialsDir = join(persistDir, "credentials");
1868
+ const secretFile = join(credentialsDir, "remote-session-secret");
1869
+ if (existsSync(secretFile)) {
1870
+ console.log(` [install] remote-session-secret exists — preserved`);
1871
+ return;
1872
+ }
1873
+ mkdirSync(credentialsDir, { recursive: true, mode: 0o700 });
1874
+ writeFileSync(secretFile, randomBytes(32).toString("hex"), { mode: 0o600 });
1875
+ console.log(` [install] remote-session-secret provisioned path=${secretFile}`);
1876
+ }
1877
+ // install-time admin-auth invariant. Walks every account.json
1878
+ // under accountsDir and compares its admins[] to the persistent users.json,
1879
+ // emitting one [install-invariant] line per divergence and one summary line.
1880
+ // Log-only (no install abort); future sprint can promote to refuse-or-degrade
1881
+ // once the deployed fleet is audited clean. Mirror of
1882
+ // checkAdminAuthInvariant() in platform/lib/admins-write/src/index.ts.
1883
+ function runInstallInvariantCheck(usersFile, accountsDir) {
1884
+ const TAG = "[install-invariant]";
1885
+ const usersUserIds = new Set();
1886
+ if (existsSync(usersFile)) {
1887
+ try {
1888
+ const raw = readFileSync(usersFile, "utf-8").trim();
1889
+ if (raw) {
1890
+ const users = JSON.parse(raw);
1891
+ for (const u of users) {
1892
+ if (typeof u.userId === "string")
1893
+ usersUserIds.add(u.userId);
1894
+ }
1895
+ }
1896
+ }
1897
+ catch (err) {
1898
+ const msg = err instanceof Error ? err.message : String(err);
1899
+ console.log(` ${TAG} users.json unreadable usersFile=${usersFile} error=${msg}`);
1900
+ }
1901
+ }
1902
+ const accountUserIds = new Set();
1903
+ let divergences = 0;
1904
+ if (existsSync(accountsDir)) {
1905
+ let entries = [];
1906
+ try {
1907
+ entries = readdirSync(accountsDir);
1908
+ }
1909
+ catch (err) {
1910
+ const msg = err instanceof Error ? err.message : String(err);
1911
+ console.log(` ${TAG} accounts-dir unreadable accountsDir=${accountsDir} error=${msg}`);
1912
+ console.log(` ${TAG} check complete divergences=0 (accounts-dir unreadable)`);
1913
+ return;
1914
+ }
1915
+ for (const entry of entries) {
1916
+ if (entry.startsWith("."))
1917
+ continue;
1918
+ const accountDir = join(accountsDir, entry);
1919
+ try {
1920
+ if (!statSync(accountDir).isDirectory())
1921
+ continue;
1922
+ }
1923
+ catch {
1924
+ continue;
1925
+ }
1926
+ const accountJsonPath = join(accountDir, "account.json");
1927
+ if (!existsSync(accountJsonPath))
1928
+ continue;
1929
+ let admins = [];
1930
+ try {
1931
+ const config = JSON.parse(readFileSync(accountJsonPath, "utf-8"));
1932
+ admins = (config.admins ?? []);
1933
+ }
1934
+ catch (err) {
1935
+ const msg = err instanceof Error ? err.message : String(err);
1936
+ console.log(` ${TAG} account.json unreadable source=${accountJsonPath} error=${msg}`);
1937
+ continue;
1938
+ }
1939
+ for (const a of admins) {
1940
+ if (typeof a.userId !== "string")
1941
+ continue;
1942
+ accountUserIds.add(a.userId);
1943
+ if (!usersUserIds.has(a.userId)) {
1944
+ const userIdShort = a.userId.slice(0, 8);
1945
+ console.log(` ${TAG} direction=account-without-users userId=${userIdShort} source=${accountJsonPath}`);
1946
+ divergences += 1;
1947
+ }
1948
+ }
1949
+ }
1950
+ }
1951
+ for (const uid of usersUserIds) {
1952
+ if (!accountUserIds.has(uid)) {
1953
+ const userIdShort = uid.slice(0, 8);
1954
+ console.log(` ${TAG} direction=users-without-account userId=${userIdShort} source=${usersFile}`);
1955
+ divergences += 1;
1956
+ }
1957
+ }
1958
+ console.log(` ${TAG} check complete divergences=${divergences}`);
1959
+ }
1960
+ function deployPayload() {
1961
+ log("8", TOTAL, `Deploying ${BRAND.productName}...`);
1962
+ if (!existsSync(PAYLOAD_DIR)) {
1963
+ throw new Error(`Payload not found at ${PAYLOAD_DIR}. Package may be corrupted.`);
1964
+ }
1965
+ // Persistent config lives at ~/{configDir}/ — survives rm -rf ~/{installDir}
1966
+ const persistentDir = resolve(process.env.HOME ?? "/root", BRAND.configDir);
1967
+ const persistentPasswordFile = join(persistentDir, ".neo4j-password");
1968
+ // users.json lives at <persistentDir>/users.json. Writers (paths.ts,
1969
+ // admin-add, set-pin, seed-neo4j.sh) target the persistent file directly —
1970
+ // see comment in platform/ui/app/lib/paths.ts.
1971
+ const persistentUsersFile = join(persistentDir, "users.json");
1972
+ // Claude Code OAuth credentials live at
1973
+ // `${persistDir}/.claude/.credentials.json`. The brand main service's
1974
+ // `claude` SDK subprocess and admin server read from there via the
1975
+ // Environment=CLAUDE_CONFIG_DIR= block in port-resolution.ts. Fresh
1976
+ // installs prompt the operator to run `claude /login`.
1977
+ const persistentClaudeDir = join(persistentDir, ".claude");
1978
+ mkdirSync(persistentClaudeDir, { recursive: true });
1979
+ // pre-populate the brand `.claude.json` so the manager's
1980
+ // PTY-spawned `claude --verbose --remote-control` boots straight into the
1981
+ // session URL without stopping at the first-run theme picker or the
1982
+ // workspace-trust dialog. Both prompts ate the manager's 30 s url-capture
1983
+ // window on 0.1.6 / 0.1.8 installs (Pi 192.168.88.16 verified). The two
1984
+ // markers required are:
1985
+ // - hasCompletedOnboarding: true (suppresses theme picker)
1986
+ // - projects[$HOME].hasTrustDialogAccepted: true
1987
+ // Existing fields (firstStartTime, oauthAccount, migrationVersion, …) are
1988
+ // preserved so a brand re-install does not clobber state written by claude
1989
+ // during the previous run.
1990
+ const claudeStateFile = join(persistentClaudeDir, ".claude.json");
1991
+ const homeWorkspace = process.env.HOME ?? "/root";
1992
+ let claudeState = {};
1993
+ if (existsSync(claudeStateFile)) {
1994
+ try {
1995
+ claudeState = JSON.parse(readFileSync(claudeStateFile, "utf-8"));
1996
+ }
1997
+ catch {
1998
+ claudeState = {};
1999
+ }
2000
+ }
2001
+ claudeState.hasCompletedOnboarding = true;
2002
+ claudeState.theme = claudeState.theme ?? "auto";
2003
+ const projects = (claudeState.projects ?? {});
2004
+ const homeEntry = projects[homeWorkspace] ?? {};
2005
+ homeEntry.hasTrustDialogAccepted = true;
2006
+ projects[homeWorkspace] = homeEntry;
2007
+ claudeState.projects = projects;
2008
+ writeFileSync(claudeStateFile, JSON.stringify(claudeState, null, 2) + "\n", { mode: 0o600 });
2009
+ console.log(` [install] claude-state primed: ${claudeStateFile} hasCompletedOnboarding=true trustedWorkspace=${homeWorkspace}`);
2010
+ // Brand isolation: installer does not read ~/.maxy/, ~/.cloudflared/, or
2011
+ // ~/.cloudflare/ on non-default brands. These are peer-brand or
2012
+ // shared-singleton paths.
2013
+ // Stop the running service before wiping directories (upgrade path).
2014
+ // The server holds open files in platform/ — rmSync fails with ENOTEMPTY if it's running.
2015
+ // darwin uses `launchctl bootout` instead of systemctl; bootout
2016
+ // returns synchronously when the agent has exited.
2017
+ if (requireSupportedPlatform(process.platform) === "darwin") {
2018
+ spawnSync("launchctl", ["bootout", `${gui()}/${launchdLabel()}`], { stdio: "pipe", timeout: 15_000 });
2019
+ }
2020
+ else {
2021
+ // systemctl stop returns when the main process exits, but ExecStopPost (e.g. VNC cleanup)
2022
+ // may still hold file handles. Poll is-active to wait for full deactivation.
2023
+ const svcName = BRAND.serviceName.replace(".service", "");
2024
+ spawnSync("systemctl", ["--user", "stop", svcName], { stdio: "pipe" });
2025
+ const MAX_STOP_WAIT = 5;
2026
+ for (let i = 0; i < MAX_STOP_WAIT; i++) {
2027
+ const result = spawnSync("systemctl", ["--user", "is-active", svcName], { stdio: "pipe" });
2028
+ const status = result.stdout?.toString().trim();
2029
+ if (status !== "active" && status !== "deactivating") {
2030
+ console.log(` Service stopped (${status || "not found"}).`);
2031
+ break;
2032
+ }
2033
+ if (i === MAX_STOP_WAIT - 1) {
2034
+ console.log(` [WARN] Service still ${status} after ${MAX_STOP_WAIT}s — proceeding with directory wipe.`);
2035
+ break;
2036
+ }
2037
+ spawnSync("sleep", ["1"]);
2038
+ }
2039
+ }
2040
+ // User data lives at {installDir}/data/ — outside the platform/ wipe zone.
2041
+ // Install path creates this fresh; runtime writers populate it on demand.
2042
+ mkdirSync(join(INSTALL_DIR, "data"), { recursive: true });
2043
+ // Task 848 — on upgrade the prior server/, platform/, premium-plugins/ trees are
2044
+ // immutable (chattr +i). Clear all three BEFORE the wipe loop, or the rmSync of
2045
+ // those dirs below fails with EPERM. Gate on INSTALL_DIR existence (any prior
2046
+ // install), not server/ alone — a partial state where server/ was removed but
2047
+ // platform/ stayed frozen must still be unprotected. Fresh install: INSTALL_DIR
2048
+ // not yet created (mkdirSync below), so skip. Linux-only (emits nothing
2049
+ // elsewhere). bestEffort: a missing root chattr-errors harmlessly.
2050
+ const guardPlatform = detectPlatform(process.platform);
2051
+ if (existsSync(INSTALL_DIR)) {
2052
+ for (const c of unprotectCommands(INSTALL_DIR, guardPlatform)) {
2053
+ const target = c.args[c.args.length - 1];
2054
+ console.log(` [agent-guard] op=unprotect target=${target}`);
2055
+ shell(c.command, c.args, { sudo: true, bestEffort: true });
2056
+ }
2057
+ }
2058
+ // Wipe deployment directories to prevent stale files.
2059
+ // data/ is NOT wiped — it contains user data (accounts, uploads) that must survive.
2060
+ for (const dir of ["platform", "server", "maxy", "premium-plugins", "docs", ".claude"]) {
2061
+ const target = join(INSTALL_DIR, dir);
2062
+ if (existsSync(target)) {
2063
+ rmSync(target, { recursive: true, force: true });
2064
+ }
2065
+ }
2066
+ mkdirSync(INSTALL_DIR, { recursive: true });
2067
+ // Deploy payload
2068
+ cpSync(PAYLOAD_DIR, INSTALL_DIR, {
2069
+ recursive: true,
2070
+ force: true,
2071
+ });
2072
+ // Task 848 — the platform source trees are frozen immutable as the final install
2073
+ // action (see main()), not here: the installer keeps writing under platform/
2074
+ // after this deploy (buildPlatform's npm install, service builds, plugin
2075
+ // registration), so an early freeze would EPERM those writes. The pre-wipe
2076
+ // unprotect above is the matching half on upgrade.
2077
+ // Link persistent config into install directory
2078
+ const configDir = join(INSTALL_DIR, "platform/config");
2079
+ mkdirSync(configDir, { recursive: true });
2080
+ if (existsSync(persistentPasswordFile)) {
2081
+ cpSync(persistentPasswordFile, join(configDir, ".neo4j-password"));
2082
+ console.log(" Restored Neo4j password.");
2083
+ }
2084
+ // users.json is read directly from persistentDir by both
2085
+ // platform/ui/app/lib/paths.ts (USERS_FILE = MAXY_DIR/users.json) and the
2086
+ // admin MCP plugin (USERS_FILE = CONFIG_DIR/users.json). No copy into the
2087
+ // wipe zone. The line below observes the row count + userId prefixes so a
2088
+ // future regression is grep-detectable in the install log without any
2089
+ // runtime change.
2090
+ if (existsSync(persistentUsersFile)) {
2091
+ try {
2092
+ const raw = readFileSync(persistentUsersFile, "utf-8").trim();
2093
+ const rows = raw ? JSON.parse(raw) : [];
2094
+ const ids = rows
2095
+ .map(r => (typeof r.userId === "string" ? r.userId.slice(0, 8) : "?"))
2096
+ .join(",");
2097
+ console.log(` [install] users.json preserved: rows=${rows.length} userIds=${ids}`);
2098
+ }
2099
+ catch (err) {
2100
+ const msg = err instanceof Error ? err.message : String(err);
2101
+ console.log(` [install] users.json preserved: rows=? parse-failed error=${msg}`);
2102
+ }
2103
+ }
2104
+ else {
2105
+ console.log(" [install] users.json: no persistent file (fresh install — set-pin will create it)");
2106
+ }
2107
+ // install-time admin-auth invariant check. Walks every
2108
+ // data/accounts/*/account.json admins[] and compares to the persistent
2109
+ // users.json. Log-only (does NOT refuse install); the [install-invariant]
2110
+ // line surfaces the bug to the operator without bricking the device.
2111
+ // Inline rather than imported from platform/lib/admins-write because the
2112
+ // installer is its own npm package and doesn't bundle the platform lib.
2113
+ // Mirrors checkAdminAuthInvariant() in platform/lib/admins-write/src/index.ts;
2114
+ // future divergence between the two should be caught by the test suite.
2115
+ runInstallInvariantCheck(persistentUsersFile, join(INSTALL_DIR, "data", "accounts"));
2116
+ // Write version marker so the running platform knows which create-maxy produced this deployment
2117
+ const versionMarkerPath = join(configDir, `.${BRAND.hostname}-version`);
2118
+ writeFileSync(versionMarkerPath, PKG_VERSION, "utf-8");
2119
+ console.log(` [install] version-marker written path=${versionMarkerPath} version=${PKG_VERSION}`);
2120
+ console.log(` Deployed to ${INSTALL_DIR}`);
2121
+ }
2122
+ // register the local + external Claude Code plugins after the
2123
+ // payload is on disk. The bundler stamps `.claude-plugin/marketplace.json`
2124
+ // at each plugin-tree root (platform/plugins/, premium-plugins/real-agent/
2125
+ // plugins/, premium-plugins/) so this function discovers them generically
2126
+ // from the install directory rather than hardcoding names.
2127
+ //
2128
+ // Idempotent on every step: marketplace add is skipped when already in
2129
+ // `marketplace list`; `plugin install` is skipped when the plugin is
2130
+ // already in `plugin list` (matched by `<name>@<marketplace>` or by name
2131
+ // alone). One `[plugin-install] <name>@<src>
2132
+ // idempotent=<bool>` log line per attempt; failures log
2133
+ // `[plugin-install] ERROR <name>@<src> exit=<n> stderr=<short>` and do
2134
+ // NOT abort — one plugin failing must not block the rest, mirroring the
2135
+ // marketplace-add behaviour at src/index.ts:1018-1019.
2136
+ function registerLocalAndExternalPlugins() {
2137
+ console.log(" Registering local + external Claude Code plugins...");
2138
+ const localTrees = [];
2139
+ // The three known marketplace.json locations the bundler emits. Missing
2140
+ // ones are silently skipped (e.g. a brand that ships no premium plugins).
2141
+ const candidates = [
2142
+ join(INSTALL_DIR, "platform", "plugins"),
2143
+ join(INSTALL_DIR, "premium-plugins", "real-agent", "plugins"),
2144
+ join(INSTALL_DIR, "premium-plugins"),
2145
+ ];
2146
+ for (const dir of candidates) {
2147
+ const mkPath = join(dir, ".claude-plugin", "marketplace.json");
2148
+ if (!existsSync(mkPath))
2149
+ continue;
2150
+ try {
2151
+ const parsed = JSON.parse(readFileSync(mkPath, "utf-8"));
2152
+ if (typeof parsed.name === "string" && parsed.name.length > 0) {
2153
+ localTrees.push({ name: parsed.name, dir });
2154
+ }
2155
+ else {
2156
+ logFile(`[plugin-marketplace] ERROR malformed marketplace at ${mkPath} reason=no-name`);
2157
+ }
2158
+ }
2159
+ catch (err) {
2160
+ const msg = err instanceof Error ? err.message : String(err);
2161
+ logFile(`[plugin-marketplace] ERROR parse ${mkPath} error=${JSON.stringify(msg.slice(0, 200))}`);
2162
+ }
2163
+ }
2164
+ // Add each local marketplace. Idempotence via `marketplace list` grep.
2165
+ // every `claude plugin …` call carries CLAUDE_CONFIG_DIR so
2166
+ // marketplaces register into the per-brand config dir that the runtime
2167
+ // session-manager unit reads from.
2168
+ const mkList = spawnSync("claude", ["plugin", "marketplace", "list"], { stdio: "pipe", encoding: "utf-8", env: claudePluginEnv() });
2169
+ const mkListed = mkList.stdout ?? "";
2170
+ for (const { name, dir } of localTrees) {
2171
+ if (mkListed.includes(name)) {
2172
+ logFile(`[plugin-marketplace] added ${name} idempotent=true CLAUDE_CONFIG_DIR=${CLAUDE_CONFIG_DIR}`);
2173
+ continue;
2174
+ }
2175
+ const add = spawnSync("claude", ["plugin", "marketplace", "add", dir], { stdio: "pipe", encoding: "utf-8", timeout: 60_000, env: claudePluginEnv() });
2176
+ if (add.status === 0) {
2177
+ logFile(`[plugin-marketplace] added ${name} source=${dir} idempotent=false CLAUDE_CONFIG_DIR=${CLAUDE_CONFIG_DIR}`);
2178
+ }
2179
+ else {
2180
+ const stderrShort = (add.stderr ?? "").split("\n")[0]?.slice(0, 200) ?? "";
2181
+ logFile(`[plugin-marketplace] ERROR add ${name} source=${dir} exit=${add.status} stderr=${JSON.stringify(stderrShort)} CLAUDE_CONFIG_DIR=${CLAUDE_CONFIG_DIR}`);
2182
+ }
2183
+ }
2184
+ // Build the desired plugin list = (every local marketplace's plugins) +
2185
+ // (brand.json#externalPlugins). The local entries' `marketplace` field
2186
+ // matches the marketplace.json `name`; the external entries declare
2187
+ // their own.
2188
+ const desired = [];
2189
+ for (const { name: mkName, dir } of localTrees) {
2190
+ const mkPath = join(dir, ".claude-plugin", "marketplace.json");
2191
+ try {
2192
+ const parsed = JSON.parse(readFileSync(mkPath, "utf-8"));
2193
+ for (const p of parsed.plugins ?? []) {
2194
+ if (typeof p.name === "string" && p.name.length > 0) {
2195
+ desired.push({ name: p.name, marketplace: mkName });
2196
+ }
2197
+ }
2198
+ }
2199
+ catch {
2200
+ // Already logged above.
2201
+ }
2202
+ }
2203
+ let externals = [];
2204
+ try {
2205
+ externals = parseExternalPlugins(BRAND.externalPlugins);
2206
+ }
2207
+ catch (err) {
2208
+ const msg = err instanceof Error ? err.message : String(err);
2209
+ logFile(`[plugin-install] ERROR brand.externalPlugins parse error=${JSON.stringify(msg.slice(0, 200))}`);
2210
+ }
2211
+ desired.push(...externals);
2212
+ // The directory-source marketplaces are exactly the local trees discovered
2213
+ // from on-disk marketplace.json above. Remote marketplaces (the Anthropic
2214
+ // ones, GitHub externals) are never in this set, so they keep version-pinned
2215
+ // idempotence. (Task 643.)
2216
+ const directorySourceMarketplaces = new Set(localTrees.map(t => t.name));
2217
+ // Snapshot what's installed to compute the install set.
2218
+ const pluginList = spawnSync("claude", ["plugin", "list"], { stdio: "pipe", encoding: "utf-8", env: claudePluginEnv() });
2219
+ const installed = parsePluginList(pluginList.stdout ?? "");
2220
+ const { toInstall, toResync, alreadyInstalled } = computeInstallActions(desired, installed, directorySourceMarketplaces);
2221
+ for (const ref of alreadyInstalled) {
2222
+ logFile(`[plugin-install] ${ref.name}@${ref.marketplace} idempotent=true`);
2223
+ }
2224
+ // Single source of truth for the install invocation, shared by the resync
2225
+ // and fresh-install loops so a future flag/timeout/scope change cannot drift
2226
+ // between them.
2227
+ const pluginInstall = (ref) => spawnSync("claude", ["plugin", "install", `${ref.name}@${ref.marketplace}`, "--scope", "user"], { stdio: "pipe", encoding: "utf-8", timeout: 120_000, env: claudePluginEnv() });
2228
+ // Synchronous backoff for the resync retry below; the installer is fully
2229
+ // synchronous (spawnSync throughout), so block the thread deterministically.
2230
+ const sleepSync = (ms) => {
2231
+ Atomics.wait(new Int32Array(new SharedArrayBuffer(4)), 0, 0, ms);
2232
+ };
2233
+ // Retry only the install step of a resync — 3 attempts, short backoff. A
2234
+ // failed uninstall leaves the plugin registered (stale but loadable) and the
2235
+ // next install short-circuits, so it is harmless; the hazard this guards is a
2236
+ // failed install after a successful uninstall, which leaves the plugin
2237
+ // deregistered (Task 645).
2238
+ const pluginInstallWithRetry = (ref) => {
2239
+ const backoffsMs = [500, 1000];
2240
+ let result = pluginInstall(ref);
2241
+ for (let attempt = 0; result.status !== 0 && attempt < backoffsMs.length; attempt++) {
2242
+ sleepSync(backoffsMs[attempt]);
2243
+ result = pluginInstall(ref);
2244
+ }
2245
+ return result;
2246
+ };
2247
+ // Resync directory-source plugins (Task 643). A directory marketplace
2248
+ // overwrites its tree in place on upgrade with no version bump, so the
2249
+ // runtime cache snapshot the session loads from (installed_plugins.json
2250
+ // `installPath`) freezes at first-install time — `plugin install` and
2251
+ // `plugin update` both short-circuit on the pinned version and never
2252
+ // re-copy. Uninstall then install is the only sequence that rebuilds the
2253
+ // snapshot from the live tree; `install` reads the directory source live.
2254
+ // The uninstall+install pair is not atomic: a failed reinstall leaves the
2255
+ // plugin deregistered, surfaced by the ERROR line below — hardening tracked
2256
+ // in Task 645.
2257
+ for (const ref of toResync) {
2258
+ spawnSync("claude", ["plugin", "uninstall", `${ref.name}@${ref.marketplace}`, "--scope", "user"], { stdio: "pipe", encoding: "utf-8", timeout: 120_000, env: claudePluginEnv() });
2259
+ const install = pluginInstallWithRetry(ref);
2260
+ if (install.status === 0) {
2261
+ logFile(`[plugin-install] recache ${ref.name}@${ref.marketplace}`);
2262
+ }
2263
+ else {
2264
+ const stderrShort = (install.stderr ?? "").split("\n")[0]?.slice(0, 200) ?? "";
2265
+ logFile(`[plugin-install] ERROR recache ${ref.name}@${ref.marketplace} exit=${install.status} stderr=${JSON.stringify(stderrShort)}`);
2266
+ }
2267
+ }
2268
+ // Per-plugin registration post-condition (Task 645). The uninstall+install
2269
+ // resync is not atomic; if any resynced plugin is still deregistered after
2270
+ // the retry above, the runtime session would hit "Unknown skill" for every
2271
+ // skill in that plugin. Re-read the authoritative registry and abort the
2272
+ // install loudly rather than ship a degraded PTY — the same fail-loud stance
2273
+ // as the marketplace assertion below.
2274
+ if (toResync.length > 0) {
2275
+ let resyncRegistry = {};
2276
+ try {
2277
+ const ipPath = join(CLAUDE_CONFIG_DIR, "plugins", "installed_plugins.json");
2278
+ const parsed = JSON.parse(readFileSync(ipPath, "utf-8"));
2279
+ resyncRegistry = parsed.plugins ?? {};
2280
+ }
2281
+ catch {
2282
+ // An unreadable registry right after a resync is itself breakage — leave
2283
+ // the map empty so every resynced plugin is reported unregistered.
2284
+ }
2285
+ const unregistered = findUnregisteredResyncs(toResync, resyncRegistry);
2286
+ if (unregistered.length > 0) {
2287
+ const names = unregistered.map(r => `${r.name}@${r.marketplace}`);
2288
+ logFile(`[plugin-install] assertion-fail resync-deregistered=${JSON.stringify(names)} CLAUDE_CONFIG_DIR=${CLAUDE_CONFIG_DIR}`);
2289
+ throw new Error(`Plugin resync left ${names.length} plugin(s) deregistered: ${names.join(", ")}. ` +
2290
+ `The uninstall+install resync failed and these plugins are no longer registered at user scope. ` +
2291
+ `Check setup.log for [plugin-install] ERROR recache lines.`);
2292
+ }
2293
+ }
2294
+ for (const ref of toInstall) {
2295
+ const install = pluginInstall(ref);
2296
+ if (install.status === 0) {
2297
+ logFile(`[plugin-install] ${ref.name}@${ref.marketplace} idempotent=false`);
2298
+ }
2299
+ else {
2300
+ const stderrShort = (install.stderr ?? "").split("\n")[0]?.slice(0, 200) ?? "";
2301
+ logFile(`[plugin-install] ERROR ${ref.name}@${ref.marketplace} exit=${install.status} stderr=${JSON.stringify(stderrShort)}`);
2302
+ }
2303
+ }
2304
+ // Cache-vs-live audit (Task 643). Prove the per-plugin cache snapshot the
2305
+ // runtime loads from now matches the live tree, so drift is a logged
2306
+ // post-condition rather than a "no such skill" surprise in a later session.
2307
+ // Read the authoritative load path from installed_plugins.json
2308
+ // (`installPath`) rather than reconstructing the cache path from a pinned
2309
+ // version string. Warn-only: a count mismatch is surfaced, not fatal — a
2310
+ // benign skill directory without a SKILL.md must not abort the install.
2311
+ const countSkills = (skillsDir) => {
2312
+ if (!existsSync(skillsDir))
2313
+ return 0;
2314
+ let n = 0;
2315
+ for (const entry of readdirSync(skillsDir)) {
2316
+ if (existsSync(join(skillsDir, entry, "SKILL.md")))
2317
+ n++;
2318
+ }
2319
+ return n;
2320
+ };
2321
+ let installedPluginsMap = {};
2322
+ try {
2323
+ const ipPath = join(CLAUDE_CONFIG_DIR, "plugins", "installed_plugins.json");
2324
+ const parsed = JSON.parse(readFileSync(ipPath, "utf-8"));
2325
+ installedPluginsMap = parsed.plugins ?? {};
2326
+ }
2327
+ catch {
2328
+ // No readable installed_plugins.json — audit reports cache-skills=0; any
2329
+ // failed install above already logged a recache/install ERROR line.
2330
+ }
2331
+ // `treeDirByMarketplace` is keyed on the directory-source marketplace names
2332
+ // (= `directorySourceMarketplaces`), so a present tree dir is itself the
2333
+ // directory-source test — no separate Set lookup needed.
2334
+ const treeDirByMarketplace = new Map(localTrees.map(t => [t.name, t.dir]));
2335
+ for (const ref of desired) {
2336
+ const treeDir = treeDirByMarketplace.get(ref.marketplace);
2337
+ if (!treeDir)
2338
+ continue;
2339
+ const liveSkills = countSkills(join(treeDir, ref.name, "skills"));
2340
+ // The resync installs at `--scope user`, so audit that scope's snapshot —
2341
+ // not whichever entry happens to be first, since a host may also carry a
2342
+ // stale project-scope entry for the same plugin.
2343
+ const entries = installedPluginsMap[`${ref.name}@${ref.marketplace}`] ?? [];
2344
+ const installPath = (entries.find(e => e.scope === "user") ?? entries[0])?.installPath;
2345
+ const cacheSkills = installPath ? countSkills(join(installPath, "skills")) : 0;
2346
+ logFile(`[plugin-install] audit ${ref.name}@${ref.marketplace} live-skills=${liveSkills} cache-skills=${cacheSkills}`);
2347
+ if (liveSkills !== cacheSkills) {
2348
+ logFile(`[plugin-install] WARN cache-drift ${ref.name}@${ref.marketplace} live-skills=${liveSkills} cache-skills=${cacheSkills}`);
2349
+ }
2350
+ }
2351
+ // post-install assertion. The per-brand CLAUDE_CONFIG_DIR is the
2352
+ // only surface the runtime session-manager reads from; if any expected
2353
+ // marketplace is missing under .claude/plugins/marketplaces/, the operator
2354
+ // will hit "Unknown skill: onboarding" at step 6 of the bring-up. Fail the
2355
+ // install loudly here rather than ship a broken PTY.
2356
+ //
2357
+ // Expected set = 3 Anthropic marketplace names (from the constant in
2358
+ // installClaudeCode) + every parsed localTrees name. Hardcoding the
2359
+ // Anthropic names keeps the assertion independent of `MARKETPLACES` scope.
2360
+ const expectedMarketplaces = new Set([
2361
+ "claude-plugins-official",
2362
+ "knowledge-work-plugins",
2363
+ "claude-for-financial-services",
2364
+ ...localTrees.map(t => t.name),
2365
+ ]);
2366
+ // `claude plugin marketplace list` is the authoritative source.
2367
+ // The `.claude/plugins/marketplaces/` directory only contains subdirs for
2368
+ // remote (git-cloned) marketplaces — local-source marketplaces registered
2369
+ // via `claude plugin marketplace add <directory-path>` live in user
2370
+ // settings and are visible only through `marketplace list`. Parsing the
2371
+ // CLI output covers both. The CLI emits each entry as two lines: the
2372
+ // leader-glyph name (` ❯ <name>`) followed by ` Source: …`, so the
2373
+ // name is on its own line — anchor on `❯` and require the following line
2374
+ // (after blanks) to start with `Source:` to confirm it is a marketplace
2375
+ // header, not a stray glyph in some other CLI panel.
2376
+ const listResult = spawnSync("claude", ["plugin", "marketplace", "list"], { stdio: "pipe", encoding: "utf-8", env: claudePluginEnv() });
2377
+ const listStdout = listResult.stdout ?? "";
2378
+ const listStderr = listResult.stderr ?? "";
2379
+ const stripAnsi = (s) => s.replace(/\x1b\[[0-9;]*[A-Za-z]/g, "");
2380
+ const parseMarketplaceList = (raw) => {
2381
+ const lines = stripAnsi(raw).split("\n");
2382
+ const names = [];
2383
+ for (let i = 0; i < lines.length; i++) {
2384
+ const nameMatch = lines[i].match(/^\s*❯\s+([A-Za-z0-9._-]+)\s*$/);
2385
+ if (!nameMatch)
2386
+ continue;
2387
+ let j = i + 1;
2388
+ while (j < lines.length && lines[j].trim() === "")
2389
+ j++;
2390
+ if (j < lines.length && /^\s*Source:/.test(lines[j])) {
2391
+ names.push(nameMatch[1]);
2392
+ }
2393
+ }
2394
+ return names;
2395
+ };
2396
+ const actualMarketplaces = parseMarketplaceList(listStdout);
2397
+ if (listResult.error || listResult.status !== 0 || actualMarketplaces.length === 0) {
2398
+ const errMsg = listResult.error ? listResult.error.message : `exit=${listResult.status}`;
2399
+ throw new Error(`Plugin registration produced no marketplaces — \`claude plugin marketplace list\` returned no parseable entries (${errMsg}). stdout=${JSON.stringify(listStdout)} stderr=${JSON.stringify(listStderr.split("\n")[0] ?? "")}. Check setup.log for [plugin-marketplace] ERROR lines.`);
2400
+ }
2401
+ const missing = [...expectedMarketplaces].filter(m => !actualMarketplaces.includes(m));
2402
+ if (missing.length > 0) {
2403
+ logFile(`[plugin-marketplace] assertion-fail expected=${JSON.stringify([...expectedMarketplaces])} actual=${JSON.stringify(actualMarketplaces)} missing=${JSON.stringify(missing)} CLAUDE_CONFIG_DIR=${CLAUDE_CONFIG_DIR}`);
2404
+ throw new Error(`Plugin registration incomplete: expected marketplaces ${JSON.stringify([...expectedMarketplaces])} but \`claude plugin marketplace list\` returned ${JSON.stringify(actualMarketplaces)}. Missing: ${JSON.stringify(missing)}. Check setup.log for [plugin-marketplace] ERROR lines.`);
2405
+ }
2406
+ logFile(`[plugin-marketplace] assertion-source=claude-plugin-marketplace-list count=${actualMarketplaces.length} marketplaces=${JSON.stringify(actualMarketplaces)} CLAUDE_CONFIG_DIR=${CLAUDE_CONFIG_DIR}`);
2407
+ // Task 583 — post-install assertion that the brand-scoped permissions
2408
+ // block survived install. Warn-only: a missing block does not abort the
2409
+ // install (consistent with the marketplace ERROR path that logs and
2410
+ // continues per-entry), but surfaces in setup.log for diagnosis.
2411
+ const permissionsAssert = assertBypassPermissionsSeed(CLAUDE_CONFIG_DIR);
2412
+ logFile(`[install-permissions] brand-settings=${permissionsAssert.status} path=${permissionsAssert.path}`);
2413
+ }
2414
+ function buildPlatform() {
2415
+ log("9", TOTAL, "Installing dependencies and building...");
2416
+ console.log(` Installing platform dependencies (${join(INSTALL_DIR, "platform")})...`);
2417
+ shellRetry("npm", ["install", ...NPM_NET_FLAGS], { cwd: join(INSTALL_DIR, "platform") }, 3, 15);
2418
+ // MCP server dist/ files are pre-compiled in the payload — no build step needed.
2419
+ // Server external dependencies (neo4j-driver, @whiskeysockets/baileys, zod, proper-lockfile) are listed in
2420
+ // server/package.json but NOT shipped as pre-built node_modules — npm pack silently
2421
+ // strips files from nested node_modules (e.g. rxjs/package.json), breaking require().
2422
+ // Install fresh on device to guarantee a complete dependency tree.
2423
+ //
2424
+ // On upgrade, wipe `node_modules` first so npm extracts a clean tree. Without
2425
+ // this, an interrupted previous install (network blip, operator cancellation,
2426
+ // power loss) can leave nested package.json files half-truncated — the most
2427
+ // common manifestation is `Error: Invalid package config .../rxjs/package.json`
2428
+ // at server startup, which loops the brand service indefinitely. The wipe
2429
+ // adds ~30 s to upgrades but eliminates a class of unrecoverable customer
2430
+ // states; reliability wins over speed for a one-shot install path.
2431
+ const serverNodeModules = join(INSTALL_DIR, "server", "node_modules");
2432
+ if (existsSync(serverNodeModules)) {
2433
+ console.log(" Wiping previous server/node_modules for a clean reinstall...");
2434
+ rmSync(serverNodeModules, { recursive: true, force: true });
2435
+ }
2436
+ console.log(` Installing server dependencies (${join(INSTALL_DIR, "server")})...`);
2437
+ shellRetry("npm", ["install", "--omit=dev", ...NPM_NET_FLAGS], { cwd: join(INSTALL_DIR, "server") }, 3, 15);
2438
+ // (maxy-code) — claude-session-manager has its own package.json
2439
+ // declaring hono + @hono/node-server + node-pty. node-pty is a native
2440
+ // binding; it MUST be installed on the Pi, not shipped pre-built (different
2441
+ // architecture between the build host and the Pi). Wipe + reinstall on
2442
+ // upgrade so a half-extracted previous install does not loop the unit.
2443
+ const csmDir = join(INSTALL_DIR, "platform", "services", "claude-session-manager");
2444
+ if (existsSync(csmDir)) {
2445
+ const csmNodeModules = join(csmDir, "node_modules");
2446
+ if (existsSync(csmNodeModules)) {
2447
+ console.log(" Wiping previous claude-session-manager/node_modules for a clean reinstall...");
2448
+ rmSync(csmNodeModules, { recursive: true, force: true });
2449
+ }
2450
+ console.log(` Installing claude-session-manager dependencies (${csmDir})...`);
2451
+ shellRetry("npm", ["install", "--omit=dev", ...NPM_NET_FLAGS], { cwd: csmDir }, 3, 15);
2452
+ }
2453
+ // (maxy-code, Task 677 P2) — whatsapp-channel service has its own
2454
+ // package.json declaring @modelcontextprotocol/sdk. It ships dist/ +
2455
+ // package.json (no node_modules, stripped by npm pack like the manager), so
2456
+ // its runtime dep must be installed on the device. The per-sender channel
2457
+ // server (node dist/server.js) is spawned by claude and resolves the SDK
2458
+ // from this node_modules. Wipe + reinstall on upgrade, same as the manager.
2459
+ const wcDir = join(INSTALL_DIR, "platform", "services", "whatsapp-channel");
2460
+ if (existsSync(wcDir)) {
2461
+ const wcNodeModules = join(wcDir, "node_modules");
2462
+ if (existsSync(wcNodeModules)) {
2463
+ console.log(" Wiping previous whatsapp-channel/node_modules for a clean reinstall...");
2464
+ rmSync(wcNodeModules, { recursive: true, force: true });
2465
+ }
2466
+ console.log(` Installing whatsapp-channel dependencies (${wcDir})...`);
2467
+ shellRetry("npm", ["install", "--omit=dev", ...NPM_NET_FLAGS], { cwd: wcDir }, 3, 15);
2468
+ }
2469
+ // (maxy-code, Task 772) — webchat-channel service: identical contract to
2470
+ // whatsapp-channel above (ships dist/ + package.json declaring
2471
+ // @modelcontextprotocol/sdk; the per-conversation channel server resolves
2472
+ // the SDK from this node_modules). Wipe + reinstall on upgrade.
2473
+ const webchatDir = join(INSTALL_DIR, "platform", "services", "webchat-channel");
2474
+ if (existsSync(webchatDir)) {
2475
+ const webchatNodeModules = join(webchatDir, "node_modules");
2476
+ if (existsSync(webchatNodeModules)) {
2477
+ console.log(" Wiping previous webchat-channel/node_modules for a clean reinstall...");
2478
+ rmSync(webchatNodeModules, { recursive: true, force: true });
2479
+ }
2480
+ console.log(` Installing webchat-channel dependencies (${webchatDir})...`);
2481
+ shellRetry("npm", ["install", "--omit=dev", ...NPM_NET_FLAGS], { cwd: webchatDir }, 3, 15);
2482
+ }
2483
+ // Premium-plugin MCP servers (e.g. real-agent/loop) ship dist/ + package.json
2484
+ // in the payload but no node_modules — npm pack strips them, same reason as
2485
+ // server/. Discover every <installDir>/premium-plugins/<bundle>/plugins/<plugin>/mcp
2486
+ // and install --omit=dev there. dirs=0 in the summary line is itself a signal
2487
+ // when a brand ships premium plugins but the discovery glob is broken.
2488
+ const premiumMcpDirs = findPremiumMcpDirs(INSTALL_DIR);
2489
+ console.log(` [install] premium-mcp-install dirs=${premiumMcpDirs.length}`);
2490
+ for (const mcpDir of premiumMcpDirs) {
2491
+ const mcpNodeModules = join(mcpDir, "node_modules");
2492
+ if (existsSync(mcpNodeModules)) {
2493
+ console.log(` Wiping previous ${mcpDir}/node_modules for a clean reinstall...`);
2494
+ rmSync(mcpNodeModules, { recursive: true, force: true });
2495
+ }
2496
+ console.log(` Installing premium plugin MCP dependencies (${mcpDir})...`);
2497
+ shellRetry("npm", ["install", "--omit=dev", ...NPM_NET_FLAGS], { cwd: mcpDir }, 3, 15);
2498
+ }
2499
+ }
2500
+ function setupVncViewer() {
2501
+ if (!isLinux())
2502
+ return;
2503
+ const novncSrc = "/usr/share/novnc";
2504
+ const novncDest = join(INSTALL_DIR, "server/public/novnc");
2505
+ if (!existsSync(join(novncSrc, "core"))) {
2506
+ console.log(" noVNC not found — skipping VNC viewer setup.");
2507
+ return;
2508
+ }
2509
+ console.log(" Installing VNC viewer...");
2510
+ // Copy core/ and vendor/ (pako compression library) — both required by rfb.js
2511
+ cpSync(join(novncSrc, "core"), join(novncDest, "core"), { recursive: true, force: true });
2512
+ const vendorSrc = join(novncSrc, "vendor");
2513
+ if (existsSync(vendorSrc)) {
2514
+ cpSync(vendorSrc, join(novncDest, "vendor"), { recursive: true, force: true });
2515
+ }
2516
+ // Custom viewer: no toolbar, scales to fit, auto-connects with retry.
2517
+ //
2518
+ // Transport: same-origin WebSocket proxied through the Maxy server's
2519
+ // /websockify upgrade handler. The URL is built from location.protocol
2520
+ // and location.host so that:
2521
+ // - HTTP origin → ws://<host>:<port>/websockify (LAN)
2522
+ // - HTTPS origin → wss://<host>:<port>/websockify (Cloudflare tunnel)
2523
+ // This eliminates the mixed-content block that previously killed the
2524
+ // viewer when accessed via https://admin.maxy.bot.
2525
+ //
2526
+ // The viewer does NOT read a host/port from query string — those
2527
+ // parameters are ignored if present (kept for backward compatibility
2528
+ // with any cached callers) and the connection is always same-origin.
2529
+ //
2530
+ // A per-session correlation ID is generated client-side and included
2531
+ // in the WebSocket URL (?corrId=X) and in the POST to
2532
+ // /api/vnc/client-event so the server-side log can correlate the
2533
+ // noVNC disconnect reason to the specific WS upgrade entry.
2534
+ const html = `<!DOCTYPE html>
2535
+ <html>
2536
+ <head>
2537
+ <meta charset="utf-8">
2538
+ <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0">
2539
+ <title>Connect Claude</title>
2540
+ <style>
2541
+ *, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
2542
+ html, body { width: 100%; height: 100%; background: #111; overflow: hidden; }
2543
+ #screen { position: relative; width: 100%; height: 100%; }
2544
+ #status {
2545
+ position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%);
2546
+ color: #888; font-family: -apple-system, BlinkMacSystemFont, sans-serif;
2547
+ font-size: 14px; text-align: center; z-index: 10;
2548
+ transition: opacity 0.3s;
2549
+ }
2550
+ #status.hidden { opacity: 0; pointer-events: none; }
2551
+ .status-spinner {
2552
+ display: inline-block; width: 20px; height: 20px;
2553
+ border: 2px solid #444; border-top-color: #888; border-radius: 50%;
2554
+ animation: spin 0.8s linear infinite; margin-bottom: 8px;
2555
+ }
2556
+ @keyframes spin { to { transform: rotate(360deg); } }
2557
+ .status-reason { font-size: 12px; color: #666; margin-top: 6px; }
2558
+ </style>
2559
+ </head>
2560
+ <body>
2561
+ <div id="screen"></div>
2562
+ <div id="status">
2563
+ <div class="status-spinner"></div>
2564
+ <div>Connecting to browser…</div>
2565
+ <div class="status-reason"></div>
2566
+ </div>
2567
+ <script type="module">
2568
+ import RFB from '/novnc/core/rfb.js';
2569
+
2570
+ // Build a same-origin WebSocket URL. Protocol auto-matches the
2571
+ // parent page so https pages use wss and http pages use ws.
2572
+ const wsScheme = location.protocol === 'https:' ? 'wss:' : 'ws:';
2573
+ // Generate a client-side correlation ID. This ID is used only for
2574
+ // client-side log correlation (the server assigns its own corrId
2575
+ // on the upgrade handler so an attacker cannot forge server
2576
+ // internal ids). Base-36 random concatenation yields up to 16
2577
+ // chars — collision-free in practice for the 1-session-at-a-time
2578
+ // VNC use case.
2579
+ const corrId = (Math.random().toString(36).slice(2, 10) + Math.random().toString(36).slice(2, 10))
2580
+ .replace(/[^a-z0-9]/gi, '') || 'c' + Date.now().toString(36);
2581
+ const wsUrl = wsScheme + '//' + location.host + '/websockify?corrId=' + encodeURIComponent(corrId);
2582
+
2583
+ const screen = document.getElementById('screen');
2584
+ const status = document.getElementById('status');
2585
+ let retryCount = 0;
2586
+ const MAX_RETRIES = 30;
2587
+
2588
+ // Best-effort POST of a disconnect/error reason to the server so
2589
+ // the noVNC-observed failure mode ends up in vnc-boot.log alongside
2590
+ // the server-side proxy events. Network failures are swallowed —
2591
+ // this is a telemetry side channel, not a critical path.
2592
+ function reportClientEvent(phase, reason) {
2593
+ try {
2594
+ fetch('/api/vnc/client-event', {
2595
+ method: 'POST',
2596
+ credentials: 'same-origin',
2597
+ headers: { 'Content-Type': 'application/json' },
2598
+ body: JSON.stringify({ corrId: corrId, phase: phase, reason: reason || '' }),
2599
+ keepalive: true,
2600
+ }).catch(function() { /* swallow */ });
2601
+ } catch (e) { /* swallow */ }
2602
+ }
2603
+
2604
+ // Layer-6 beacon: emit event=rfb-connected and
2605
+ // event=rfb-error to the operator-grep lifecycle endpoint so
2606
+ // server.log shows the noVNC outcome alongside [device-url:click]
2607
+ // / [http] / [websockify]. Same-origin POST works whether the
2608
+ // iframe is parented by the React VNC viewer or by vnc-popout.html.
2609
+ function reportVncIframeEvent(event, fields) {
2610
+ try {
2611
+ var body = JSON.stringify(Object.assign(
2612
+ { event: event, surface: 'iframe' },
2613
+ fields || {},
2614
+ ));
2615
+ fetch('/api/admin/browser-iframe/event', {
2616
+ method: 'POST',
2617
+ credentials: 'same-origin',
2618
+ headers: { 'Content-Type': 'application/json' },
2619
+ body: body,
2620
+ keepalive: true,
2621
+ }).catch(function() { /* swallow */ });
2622
+ } catch (e) { /* swallow */ }
2623
+ }
2624
+ var connectStartedAt = 0;
2625
+
2626
+ function connect() {
2627
+ status.classList.remove('hidden');
2628
+ status.querySelector('.status-spinner').style.display = '';
2629
+ status.querySelector('div:nth-child(2)').textContent =
2630
+ retryCount > 0 ? 'Reconnecting… (' + retryCount + ')' : 'Connecting to browser…';
2631
+ status.querySelector('.status-reason').textContent = '';
2632
+ connectStartedAt = Date.now();
2633
+
2634
+ const rfb = new RFB(screen, wsUrl);
2635
+ rfb.scaleViewport = true;
2636
+ rfb.clipViewport = true;
2637
+ rfb.resizeSession = false;
2638
+ window.rfb = rfb;
2639
+
2640
+ rfb.addEventListener('connect', () => {
2641
+ status.classList.add('hidden');
2642
+ retryCount = 0;
2643
+ reportVncIframeEvent('rfb-connected', {
2644
+ durationMs: Date.now() - connectStartedAt,
2645
+ });
2646
+ });
2647
+
2648
+ rfb.addEventListener('disconnect', (e) => {
2649
+ status.classList.remove('hidden');
2650
+ const detail = e.detail || {};
2651
+ const reason = detail.reason || (detail.clean === false ? 'Connection refused' : '');
2652
+ reportClientEvent('disconnect', reason || (detail.clean === false ? 'unclean-close' : 'normal'));
2653
+ reportVncIframeEvent('rfb-error', {
2654
+ durationMs: Date.now() - connectStartedAt,
2655
+ errorCode: detail.clean === false ? 'unclean-close' : 'normal',
2656
+ message: reason || '',
2657
+ });
2658
+ const reasonEl = status.querySelector('.status-reason');
2659
+ if (retryCount < MAX_RETRIES) {
2660
+ retryCount++;
2661
+ const delay = Math.min(1000 * retryCount, 5000);
2662
+ status.querySelector('div:nth-child(2)').textContent = 'Reconnecting in ' + Math.ceil(delay/1000) + 's…';
2663
+ reasonEl.textContent = reason;
2664
+ setTimeout(connect, delay);
2665
+ } else {
2666
+ status.querySelector('.status-spinner').style.display = 'none';
2667
+ status.querySelector('div:nth-child(2)').textContent = 'Connection lost. Reload the page to retry.';
2668
+ reasonEl.textContent = reason;
2669
+ }
2670
+ });
2671
+
2672
+ // --- Clipboard bridge (local ↔ remote) ---
2673
+
2674
+ // Paste bridge: intercept Cmd/Ctrl+V in the capturing phase before
2675
+ // noVNC's keydown handler can call preventDefault(). noVNC v1.3.0
2676
+ // binds its handler with .bind(this) in the Keyboard constructor and
2677
+ // registers the bound reference via addEventListener — so monkey-
2678
+ // patching the unbound method on the instance is a no-op. A capturing-
2679
+ // phase listener on document fires before noVNC's target-phase handler
2680
+ // regardless of registration timing or internal structure.
2681
+ document.addEventListener('keydown', (e) => {
2682
+ if ((e.ctrlKey || e.metaKey) && (e.key === 'v' || e.key === 'V')) {
2683
+ e.stopImmediatePropagation();
2684
+ reportClientEvent('paste-bridge', 'keydown-intercepted');
2685
+ }
2686
+ }, true);
2687
+
2688
+ // Catch the paste event, sync text to VNC server clipboard, then
2689
+ // send Ctrl+V keystrokes so the remote app pastes the synced content.
2690
+ document.addEventListener('paste', (e) => {
2691
+ e.preventDefault();
2692
+ const text = (e.clipboardData || window.clipboardData)?.getData('text');
2693
+ if (!text || !window.rfb) {
2694
+ reportClientEvent('paste-bridge', 'empty-clipboard');
2695
+ return;
2696
+ }
2697
+ reportClientEvent('paste-bridge', 'paste-event text-length=' + text.length);
2698
+ window.rfb.clipboardPasteFrom(text);
2699
+ reportClientEvent('paste-bridge', 'clipboard-synced');
2700
+ setTimeout(() => {
2701
+ window.rfb.sendKey(0xFFE3, 'ControlLeft', true);
2702
+ window.rfb.sendKey(0x0076, 'v', true);
2703
+ window.rfb.sendKey(0x0076, 'v', false);
2704
+ window.rfb.sendKey(0xFFE3, 'ControlLeft', false);
2705
+ }, 50);
2706
+ });
2707
+
2708
+ // Copy bridge: when the remote clipboard changes, notify the parent frame.
2709
+ rfb.addEventListener('clipboard', (e) => {
2710
+ window.parent.postMessage({ type: 'vnc-clipboard', text: e.detail.text }, '*');
2711
+ });
2712
+ }
2713
+
2714
+ connect();
2715
+ </script>
2716
+ </body>
2717
+ </html>`;
2718
+ writeFileSync(join(INSTALL_DIR, "server/public/vnc-viewer.html"), html);
2719
+ console.log(" VNC viewer ready at /vnc-viewer.html");
2720
+ }
2721
+ function setupAccount() {
2722
+ log("10", TOTAL, "Setting up...");
2723
+ // Account-side setup runs first: creates the account dir, writes the
2724
+ // Claude Code project settings (hooks only — no permissions.allow),
2725
+ // installs specialist templates, seeds account.json. Then seed-neo4j.sh
2726
+ // applies the schema and MERGEs the root :LocalBusiness / owner
2727
+ // :AdminUser nodes. setup-account.sh has no Neo4j env dependency;
2728
+ // seed-neo4j.sh hard-exits without NEO4J_URI, so we derive the URI +
2729
+ // password (a missing password file is a hard error here — the
2730
+ // upstream ensureNeo4jPassword() would have thrown if it couldn't
2731
+ // reach the brand's Neo4j).
2732
+ const setupScript = join(INSTALL_DIR, "platform/scripts/setup-account.sh");
2733
+ if (existsSync(setupScript)) {
2734
+ shell("bash", [setupScript], { cwd: INSTALL_DIR });
2735
+ }
2736
+ const passwordFile = join(INSTALL_DIR, "platform/config/.neo4j-password");
2737
+ if (!existsSync(passwordFile)) {
2738
+ throw new Error(`Neo4j password file missing at ${passwordFile} — required by setup step.`);
2739
+ }
2740
+ const password = readFileSync(passwordFile, "utf-8").trim();
2741
+ const neo4jUri = `bolt://localhost:${NEO4J_PORT}`;
2742
+ const neo4jEnv = { ...process.env, NEO4J_URI: neo4jUri, NEO4J_PASSWORD: password };
2743
+ const seedScript = join(INSTALL_DIR, "platform/scripts/seed-neo4j.sh");
2744
+ if (existsSync(seedScript)) {
2745
+ console.log(` [neo4j] passing NEO4J_URI=${neo4jUri} to seed`);
2746
+ logFile(` [neo4j] passing NEO4J_URI=${neo4jUri} to seed`);
2747
+ shell("bash", [seedScript], { cwd: INSTALL_DIR, env: neo4jEnv });
2748
+ }
2749
+ // Task 165 — register every bundled specialist subagent at
2750
+ // $CLAUDE_CONFIG_DIR/agents/<name>.md. Claude Code's `--agent <name>`
2751
+ // discovery only resolves under this path; without these symlinks,
2752
+ // every `--agent database-operator` etc. silently runs as the admin
2753
+ // agent on admin IDENTITY/SOUL scaffolding. Symlinks (not copies) so
2754
+ // a `npx -y @rubytech/create-maxy-code` upgrade picks up template
2755
+ // changes without a second seed run.
2756
+ registerSpecialistAgents();
2757
+ // install-time defaults. Stamp `account.json` with the
2758
+ // brand's default plugin set + default outputStyle / thinkingView, and
2759
+ // write a minimal admin SOUL.md. The agent boots into a working state
2760
+ // with no onboarding state machine; the operator builds personality up
2761
+ // through use. The graph-write gate blocks user-domain writes
2762
+ // until AdminUser + LocalBusiness/personal-profile Person exist, so the
2763
+ // persona is elicited the first time the operator triggers a write.
2764
+ const accountId = resolveInstallAccountId();
2765
+ if (accountId) {
2766
+ writeInstallDefaults(accountId);
2767
+ }
2768
+ else {
2769
+ console.log(" [install-defaults] SKIPPED reason=no-account-discovered");
2770
+ }
2771
+ }
2772
+ function writeInstallDefaults(accountId) {
2773
+ const accountDir = join(INSTALL_DIR, "data/accounts", accountId);
2774
+ const accountJsonPath = join(accountDir, "account.json");
2775
+ const enabledPlugins = BRAND.plugins?.defaultEnabled ?? [];
2776
+ let config = {};
2777
+ if (existsSync(accountJsonPath)) {
2778
+ try {
2779
+ config = JSON.parse(readFileSync(accountJsonPath, "utf-8"));
2780
+ }
2781
+ catch (err) {
2782
+ console.error(` [install-defaults] account.json unreadable at ${accountJsonPath}: ${err.message}`);
2783
+ logFile(` [install-defaults] account.json unreadable: ${err.message}`);
2784
+ return;
2785
+ }
2786
+ }
2787
+ config.enabledPlugins = enabledPlugins;
2788
+ config.outputStyle = "default";
2789
+ config.thinkingView = "default";
2790
+ if (TIER_FLAG) {
2791
+ config = applyTierToAccountConfig(config, TIER_FLAG);
2792
+ }
2793
+ writeFileSync(accountJsonPath, JSON.stringify(config, null, 2) + "\n");
2794
+ console.log(` [install-defaults] account-json plugins=${enabledPlugins.length} outputStyle=default thinkingView=default`);
2795
+ logFile(` [install-defaults] account-json plugins=${enabledPlugins.length} outputStyle=default thinkingView=default`);
2796
+ if (TIER_FLAG) {
2797
+ const tierLine = ` [install-defaults] tier=${TIER_FLAG} mode=personal source=cli-flag`;
2798
+ console.log(tierLine);
2799
+ logFile(tierLine);
2800
+ }
2801
+ // Admin SOUL.md is user-controlled personalisation: create it from the
2802
+ // bundled template (with ${PRODUCT_NAME} substituted) on a fresh install,
2803
+ // and never overwrite it once it exists. The operator builds the agent's
2804
+ // personality up through use, so an existing SOUL must survive every
2805
+ // upgrade. Task 511: an unconditional write here reset SOUL to the 7-byte
2806
+ // template on every full install. Mirrors the public SOUL guard below and
2807
+ // the create-if-missing branch in setup-account.sh.
2808
+ const soulPath = join(accountDir, "agents/admin/SOUL.md");
2809
+ mkdirSync(dirname(soulPath), { recursive: true });
2810
+ if (existsSync(soulPath)) {
2811
+ const preservedBytes = statSync(soulPath).size;
2812
+ console.log(` [install-defaults] soul-md preserved path=${soulPath} bytes=${preservedBytes}`);
2813
+ logFile(` [install-defaults] soul-md preserved path=${soulPath} bytes=${preservedBytes}`);
2814
+ }
2815
+ else {
2816
+ const adminSoulTemplate = join(INSTALL_DIR, "platform/templates/agents/admin/SOUL.md");
2817
+ let soulContent;
2818
+ try {
2819
+ soulContent = readFileSync(adminSoulTemplate, "utf-8");
2820
+ }
2821
+ catch (err) {
2822
+ console.error(` [install-defaults] admin-soul template missing at ${adminSoulTemplate}: ${err.message}`);
2823
+ logFile(` [install-defaults] admin-soul template missing: ${err.message}`);
2824
+ return;
2825
+ }
2826
+ soulContent = soulContent.replace(/\$\{PRODUCT_NAME\}/g, BRAND.productName);
2827
+ writeFileSync(soulPath, soulContent);
2828
+ console.log(` [install-defaults] soul-md created path=${soulPath} bytes=${soulContent.length}`);
2829
+ logFile(` [install-defaults] soul-md created path=${soulPath} bytes=${soulContent.length}`);
2830
+ }
2831
+ // Public agent IDENTITY.md — the only template-seeded public file, always
2832
+ // overwritten (Rubytech-controlled toolless directive). Per Task 618/623,
2833
+ // each public agent's SOUL.md, KNOWLEDGE.md, and config.json are authored
2834
+ // client-side when the operator creates the agent through the admin UI;
2835
+ // they are not seeded from templates at install time. A public spawn for an
2836
+ // un-authored agent refuses as a dud (soul-empty / knowledge-missing), which
2837
+ // is the intended loud signal — do not re-introduce template SOUL/config
2838
+ // copies here (commit 82c5658d6 removed the template files).
2839
+ const publicDir = join(accountDir, "agents/public");
2840
+ mkdirSync(publicDir, { recursive: true });
2841
+ const publicTemplatesDir = join(INSTALL_DIR, "platform/templates/agents/public");
2842
+ const publicIdentityDst = join(publicDir, "IDENTITY.md");
2843
+ const publicIdentitySrc = join(publicTemplatesDir, "IDENTITY.md");
2844
+ cpSync(publicIdentitySrc, publicIdentityDst);
2845
+ // Defensive verify: a 0-byte IDENTITY.md silently traps the brand server
2846
+ // in STARTING (the reachability auditor logs `reachable=false reason=files
2847
+ // -missing IDENTITY.md:empty` every minute and the splash never clears).
2848
+ // Observed on 192.168.88.16 after a re-install: source 1655 bytes, dest
2849
+ // 0 bytes. Loud-fail here so a corrupt copy can never reach the device's
2850
+ // runtime.
2851
+ try {
2852
+ const srcBytes = statSync(publicIdentitySrc).size;
2853
+ const dstBytes = statSync(publicIdentityDst).size;
2854
+ if (dstBytes === 0 || dstBytes !== srcBytes) {
2855
+ throw new Error(`public-identity copy verify failed: src=${publicIdentitySrc} (${srcBytes} bytes) ` +
2856
+ `dst=${publicIdentityDst} (${dstBytes} bytes). A 0-byte or partial copy traps the brand ` +
2857
+ `server in STARTING forever — re-run the installer after restoring the template, or ` +
2858
+ `report this as a copy regression.`);
2859
+ }
2860
+ }
2861
+ catch (err) {
2862
+ if (err instanceof Error && err.message.startsWith("public-identity copy verify failed"))
2863
+ throw err;
2864
+ throw new Error(`public-identity verify stat failed: ${err instanceof Error ? err.message : String(err)}`);
2865
+ }
2866
+ console.log(` [install-defaults] public-identity path=${publicIdentityDst}`);
2867
+ logFile(` [install-defaults] public-identity path=${publicIdentityDst}`);
2868
+ }
2869
+ /**
2870
+ * Commercial-mode entitlement delivery (Task 240). Writes the decoded payload
2871
+ * bytes verbatim to ~/<BRAND.configDir>/entitlement.json. Signature and shape
2872
+ * validation happen at the verifier at session start (entitlement lib); the
2873
+ * installer is a dumb delivery channel — a malformed payload that survived
2874
+ * --entitlement-base64 parsing will be caught there and degrade the install
2875
+ * to anonymous-fallback, which is the correct loud-fail per doctrine.
2876
+ */
2877
+ function writeEntitlementFromFlag(payload) {
2878
+ const target = entitlementPath(process.env.HOME ?? "/root", BRAND.configDir);
2879
+ mkdirSync(dirname(target), { recursive: true });
2880
+ writeFileSync(target, payload);
2881
+ const line = ` [install-defaults] entitlement-delivered bytes=${payload.length} path=${target} source=cli-flag`;
2882
+ console.log(line);
2883
+ logFile(line);
2884
+ }
2885
+ // Task 394 — premium-bundle agents register through the native Claude Code
2886
+ // subagent registry via `.claude-plugin/plugin.json` manifests emitted by
2887
+ // scripts/generate-plugin-manifests.mjs at bundle time, not through a
2888
+ // parallel symlink channel. This function still wires the bundled platform
2889
+ // specialists (database-operator, project-manager, …) under
2890
+ // platform/templates/specialists/agents/, which are not part of a
2891
+ // registered plugin and rely on $CLAUDE_CONFIG_DIR/agents/ resolution.
2892
+ function registerSpecialistAgents() {
2893
+ try {
2894
+ registerSpecialistAgentsAt(join(INSTALL_DIR, "platform/templates/specialists/agents"), join(CLAUDE_CONFIG_DIR, "agents"), (line) => { console.log(line); logFile(line); });
2895
+ }
2896
+ catch (err) {
2897
+ if (err instanceof SpecialistSymlinkCollision) {
2898
+ console.error(`Setup failed: ${err.message}`);
2899
+ console.error(` Remove the file and re-run.`);
2900
+ process.exit(1);
2901
+ }
2902
+ throw err;
2903
+ }
2904
+ }
2905
+ // ---------------------------------------------------------------------------
2906
+ // Account discovery (shared by installService + the post-install summary)
2907
+ //
2908
+ // `installService` stamps `Environment=ACCOUNT_ID=` into the brand
2909
+ // systemd unit so the writeNodeWithEdges gate has a non-undefined identity to
2910
+ // compare against. Pulled from `INSTALL_DIR/data/accounts/<uuid>/account.json`
2911
+ // written by setup-account.sh during setupAccount(). One reader, one shape, one
2912
+ // source of truth.
2913
+ //
2914
+ // retired the installer's cron registration — `resolveInstallAccountId`
2915
+ // kept its second consumer (installService) and is referenced again at print
2916
+ // time for the post-install banner.
2917
+ // ---------------------------------------------------------------------------
2918
+ function resolveInstallAccountId() {
2919
+ // Managed-service model: prefer the single `role:"house"` account; fall back
2920
+ // to the sole account in the pre-migration window. Returns "" on no accounts
2921
+ // or genuine drift (zero-house with >1, or multiple houses).
2922
+ const accountsDir = join(INSTALL_DIR, "data/accounts");
2923
+ if (!existsSync(accountsDir))
2924
+ return "";
2925
+ try {
2926
+ const candidates = [];
2927
+ const houses = [];
2928
+ for (const d of readdirSync(accountsDir)) {
2929
+ const configPath = join(accountsDir, d, "account.json");
2930
+ if (!existsSync(configPath))
2931
+ continue;
2932
+ candidates.push(d);
2933
+ try {
2934
+ const cfg = JSON.parse(readFileSync(configPath, "utf-8"));
2935
+ if (cfg.role === "house")
2936
+ houses.push(d);
2937
+ }
2938
+ catch { /* unparseable — not a house candidate */ }
2939
+ }
2940
+ if (houses.length === 1)
2941
+ return houses[0];
2942
+ if (houses.length === 0 && candidates.length === 1)
2943
+ return candidates[0];
2944
+ }
2945
+ catch { /* directory unreadable */ }
2946
+ return "";
2947
+ }
2948
+ // retired the ttyd/tmux/xterm admin terminal stack. Upgrades run
2949
+ // via the action runner — `systemd-run --user` transient units spawned by
2950
+ // POST /api/admin/actions/upgrade — whose lifetime is independent of
2951
+ // maxy-ui, achieving the invariant structurally rather than via
2952
+ // a peer edge service proxying a ttyd process. The installer no longer
2953
+ // provisions the ttyd binary, writes a tmux conf, or installs a ttyd
2954
+ // systemd unit. The corresponding admin UI (RemoteTerminal, TerminalOverlay,
2955
+ // xterm.js) was deleted in the same task.
2956
+ // reverse-DNS LaunchAgent label. Becomes both the plist's
2957
+ // <key>Label</key> value and the file basename
2958
+ // (`~/Library/LaunchAgents/com.rubytech.<hostname>.plist`). Per-brand so
2959
+ // installing brand B never displaces brand A's agent (mirrors the per-brand
2960
+ // systemd unit invariant).
2961
+ function launchdLabel() {
2962
+ return `com.rubytech.${BRAND.hostname}`;
2963
+ }
2964
+ function launchAgentsDir() {
2965
+ return resolve(process.env.HOME ?? "/", "Library/LaunchAgents");
2966
+ }
2967
+ function plistPath() {
2968
+ return join(launchAgentsDir(), `${launchdLabel()}.plist`);
2969
+ }
2970
+ function gui() {
2971
+ // launchd's gui domain is keyed on the user's UID. process.getuid is only
2972
+ // defined on POSIX (always present on darwin); typed conservatively.
2973
+ const uid = typeof process.getuid === "function" ? process.getuid() : 0;
2974
+ return `gui/${uid}`;
2975
+ }
2976
+ // darwin LaunchAgent supervisor. Mirrors the systemd-user body
2977
+ // below at the success-criteria level: process registered with the user's
2978
+ // session manager, KeepAlive respawns on crash, RunAtLoad starts the agent
2979
+ // on every login. Out-of-scope today: brew-resolved node path,
2980
+ // dedicated Neo4j on a non-default port. Falls back to /usr/local/bin/node
2981
+ // (homebrew Intel + manual Apple-silicon installs) will replace
2982
+ // this with the resolver.
2983
+ function installServiceDarwin() {
2984
+ const persistDir = resolve(process.env.HOME ?? "/", BRAND.configDir);
2985
+ const logsDir = join(persistDir, "logs");
2986
+ mkdirSync(logsDir, { recursive: true });
2987
+ // Mirror the Linux brand systemd unit's `Environment=` lines into .env.
2988
+ // Linux stamps every var explicitly on the unit; darwin has no systemd
2989
+ // EnvironmentFile primitive, so the wrapper sources .env before exec'ing
2990
+ // node. Any var the boot path or per-request handlers require (PORT,
2991
+ // MAXY_UI_INTERNAL_PORT, CLAUDE_SESSION_MANAGER_PORT, ACCOUNT_ID,
2992
+ // MAXY_PLATFORM_ROOT, NEO4J_URI, CLAUDE_CONFIG_DIR, NODE_ENV) must be
2993
+ // written here or the server hard-fails — boot-throw for module-init
2994
+ // consumers, per-request 500s for handlers like /api/admin/claude-sessions*
2995
+ // that requirePortEnv lazily on the manager port.
2996
+ // VNC/X11 vars (DISPLAY, RFB_PORT, WEBSOCKIFY_PORT, CDP_PORT) are Pi-only
2997
+ // and excluded — darwin runs no kiosk display stack.
2998
+ //
2999
+ // Darwin collapses the two-process model: Linux runs a separate
3000
+ // `maxy-edge.service` on 0.0.0.0:PORT that reverse-proxies into the brand
3001
+ // server on 127.0.0.1:MAXY_UI_INTERNAL_PORT, with edge surviving brand
3002
+ // restarts so the browser WebSocket stays connected. Edge also owns the
3003
+ // VNC websockify stack, which darwin doesn't have. On darwin the brand
3004
+ // server binds the public port directly:
3005
+ // HOSTNAME=0.0.0.0 → bind all interfaces (LAN reachable)
3006
+ // MAXY_UI_INTERNAL_PORT=PORT → same port, no +1 split
3007
+ // Tradeoff: no zero-downtime restarts; a brand restart drops live
3008
+ // websockets. Acceptable on a single-operator dev Mac.
3009
+ const installAccountId = resolveInstallAccountId();
3010
+ if (!installAccountId) {
3011
+ throw new Error(`installServiceDarwin: no account discovered at ${INSTALL_DIR}/data/accounts/<uuid>/account.json — ` +
3012
+ `setupAccount() (setup-account.sh) should have created one. Refusing to write .env ` +
3013
+ `without ACCOUNT_ID; the boot validator would FATAL on every kickstart.`);
3014
+ }
3015
+ const envPath = join(persistDir, ".env");
3016
+ try {
3017
+ let envContent = "";
3018
+ try {
3019
+ envContent = readFileSync(envPath, "utf-8");
3020
+ }
3021
+ catch { /* first install */ }
3022
+ for (const [key, value] of [
3023
+ ["NODE_ENV", "production"],
3024
+ ["DISPLAY_MODE", DISPLAY_MODE],
3025
+ ["EMBED_MODEL", EMBED_MODEL],
3026
+ ["EMBED_DIMENSIONS", String(EMBED_DIMS)],
3027
+ ["NEO4J_URI", `bolt://localhost:${NEO4J_PORT}`],
3028
+ ["PORT", String(PORT)],
3029
+ ["MAXY_UI_INTERNAL_PORT", String(PORT)],
3030
+ ["CLAUDE_SESSION_MANAGER_PORT", String(BRAND.claudeSessionManagerPort)],
3031
+ ["ACCOUNT_ID", installAccountId],
3032
+ ["MAXY_PLATFORM_ROOT", `${INSTALL_DIR}/platform`],
3033
+ ["CLAUDE_CONFIG_DIR", `${persistDir}/.claude`],
3034
+ ["HOSTNAME", "0.0.0.0"],
3035
+ ["KEEP_ALIVE_TIMEOUT", "61000"],
3036
+ // launchd hands the server a bare PATH (/usr/bin:/bin:/usr/sbin:/sbin)
3037
+ // that excludes the two Homebrew prefixes the `claude` binary lives in
3038
+ // under Apple Silicon and Intel. The wrapper sources this file with
3039
+ // `set -a; . "$envPath"; set +a`, so `$PATH` expands at source-time
3040
+ // against the bare launchd PATH and Homebrew prefixes get prepended for
3041
+ // every spawned descendant (claude-session-manager, MCP plugin spawns,
3042
+ // route-level spawn('claude', ...)). Task 386.
3043
+ ["PATH", "/opt/homebrew/bin:/usr/local/bin:$PATH"],
3044
+ ]) {
3045
+ const re = new RegExp(`^${key}=.*$`, "m");
3046
+ if (re.test(envContent)) {
3047
+ envContent = envContent.replace(re, `${key}=${value}`);
3048
+ }
3049
+ else {
3050
+ envContent = envContent.trimEnd() + (envContent.length > 0 ? "\n" : "") + `${key}=${value}\n`;
3051
+ }
3052
+ }
3053
+ writeFileSync(envPath, envContent);
3054
+ logFile(` .env: DISPLAY_MODE=${DISPLAY_MODE}, EMBED_MODEL=${EMBED_MODEL}, EMBED_DIMENSIONS=${EMBED_DIMS}, NEO4J_URI=bolt://localhost:${NEO4J_PORT}, PORT=${PORT}, MAXY_UI_INTERNAL_PORT=${PORT} (darwin-collapsed), CLAUDE_SESSION_MANAGER_PORT=${BRAND.claudeSessionManagerPort}, HOSTNAME=0.0.0.0, ACCOUNT_ID=${installAccountId.slice(0, 8)}…, CLAUDE_CONFIG_DIR=${persistDir}/.claude`);
3055
+ }
3056
+ catch (err) {
3057
+ console.error(` WARNING: failed to write .env to ${envPath}: ${err instanceof Error ? err.message : String(err)}`);
3058
+ }
3059
+ // Render the plist. The wrapper shell script reads .env before exec'ing
3060
+ // node so the runtime config (PORT, MAXY_PLATFORM_ROOT, NEO4J_URI) lands
3061
+ // in the child env. Without this, ProgramArguments executes node directly
3062
+ // and the .env values are unread — server binds the wrong port.
3063
+ const wrapperPath = join(persistDir, "launchd-wrapper.sh");
3064
+ // Resolve node binary at install time so the wrapper picks the right
3065
+ // path on both Intel (/usr/local/bin/node) and Apple Silicon
3066
+ // (/opt/homebrew/bin/node) — Homebrew's prefix differs by arch.
3067
+ const nodeProbe = spawnSync("command", ["-v", "node"], { encoding: "utf-8", shell: true });
3068
+ const nodeBin = (nodeProbe.stdout ?? "").trim() || "/usr/local/bin/node";
3069
+ const wrapperBody = [
3070
+ "#!/bin/bash",
3071
+ "# generated by create-maxy installService(). Reads.env then",
3072
+ "# execs node so launchd's child inherits PORT, NEO4J_URI, etc. Replaces",
3073
+ "# the systemd EnvironmentFile= directive that has no launchd analogue.",
3074
+ `set -a; [ -f "${envPath}" ] && . "${envPath}"; set +a`,
3075
+ `cd "${INSTALL_DIR}/server"`,
3076
+ `exec ${nodeBin} --require ./server-init.cjs server.js`,
3077
+ "",
3078
+ ].join("\n");
3079
+ writeFileSync(wrapperPath, wrapperBody);
3080
+ chmodSync(wrapperPath, 0o755);
3081
+ const label = launchdLabel();
3082
+ const plist = renderPlist({
3083
+ label,
3084
+ programArguments: ["/bin/bash", wrapperPath],
3085
+ stdoutPath: join(logsDir, "server.log"),
3086
+ stderrPath: join(logsDir, "server.log"),
3087
+ keepAlive: true,
3088
+ runAtLoad: true,
3089
+ workingDirectory: `${INSTALL_DIR}/server`,
3090
+ });
3091
+ mkdirSync(launchAgentsDir(), { recursive: true });
3092
+ const path = plistPath();
3093
+ writeFileSync(path, plist);
3094
+ logFile(` ${path} written (${plist.length} bytes)`);
3095
+ // Idempotent re-install: bootout the previous instance (if any) first so
3096
+ // the second `bootstrap` does not exit 5 ("already loaded"). Best-effort —
3097
+ // a missing service is the expected case on fresh installs.
3098
+ spawnSync("launchctl", ["bootout", `${gui()}/${label}`], { stdio: "pipe" });
3099
+ const bootstrap = spawnSync("launchctl", ["bootstrap", gui(), path], {
3100
+ stdio: "pipe",
3101
+ encoding: "utf-8",
3102
+ timeout: 15_000,
3103
+ });
3104
+ if (bootstrap.status === 0) {
3105
+ console.log(` [launchd] bootstrap ${gui()}/${label} ok`);
3106
+ logFile(` [launchd] bootstrap ${gui()}/${label} ok`);
3107
+ logFile(` [create-maxy] launchd-plist=${path} loaded=true`);
3108
+ }
3109
+ else {
3110
+ const stderr = (bootstrap.stderr ?? "").trim();
3111
+ console.error(` [launchd] bootstrap returned ${bootstrap.status}: ${stderr}`);
3112
+ logFile(` [launchd] bootstrap returned ${bootstrap.status}: ${stderr}`);
3113
+ logFile(` [create-maxy] launchd-plist=${path} loaded=false exit=${bootstrap.status}`);
3114
+ throw new Error(`launchctl bootstrap ${gui()} ${path} failed (exit ${bootstrap.status}): ${stderr}`);
3115
+ }
3116
+ // Wait for the server to come up.
3117
+ console.log(" Waiting for web server...");
3118
+ let webServerUp = false;
3119
+ for (let i = 0; i < 20; i++) {
3120
+ try {
3121
+ execFileSync("curl", ["-sf", `http://localhost:${PORT}`, "-o", "/dev/null"], { timeout: 3000 });
3122
+ webServerUp = true;
3123
+ break;
3124
+ }
3125
+ catch {
3126
+ spawnSync("sleep", ["2"]);
3127
+ }
3128
+ }
3129
+ if (!webServerUp) {
3130
+ console.log(` Server may still be starting. Check http://localhost:${PORT} in a moment.`);
3131
+ }
3132
+ }
3133
+ function installService() {
3134
+ log("11", TOTAL, `Starting ${BRAND.productName}...`);
3135
+ // Linux falls through to the systemd-user body below; darwin renders +
3136
+ // bootstraps a LaunchAgent and returns; unsupported throws the literal
3137
+ // refusal at requireSupportedPlatform.
3138
+ const platform = requireSupportedPlatform(process.platform);
3139
+ if (platform === "darwin") {
3140
+ installServiceDarwin();
3141
+ return;
3142
+ }
3143
+ // Persist UDP buffer sizes for cloudflared QUIC stability (applied on every boot via sysctl.d)
3144
+ const sysctlTmpPath = `/tmp/99-${BRAND.hostname}-quic.conf`;
3145
+ const sysctlDestPath = `/etc/sysctl.d/99-${BRAND.hostname}-quic.conf`;
3146
+ try {
3147
+ const sysctlConf = "net.core.rmem_max=7340032\nnet.core.wmem_max=7340032\n";
3148
+ writeFileSync(sysctlTmpPath, sysctlConf);
3149
+ console.log(" [privileged] cp");
3150
+ shell("cp", [sysctlTmpPath, sysctlDestPath], { sudo: true });
3151
+ spawnSync("rm", ["-f", sysctlTmpPath]);
3152
+ spawnSync("sudo", ["sysctl", "--system"], { stdio: "ignore", timeout: 10_000 });
3153
+ }
3154
+ catch { /* non-critical — values applied on next reboot */ }
3155
+ const serviceDir = resolve(process.env.HOME ?? "/root", ".config/systemd/user");
3156
+ mkdirSync(serviceDir, { recursive: true });
3157
+ // Create systemd user service
3158
+ const persistDir = resolve(process.env.HOME ?? "/root", BRAND.configDir);
3159
+ mkdirSync(join(persistDir, "logs"), { recursive: true });
3160
+ // Write install-time config to .env (systemd reads via EnvironmentFile).
3161
+ // Preserves existing .env content (e.g. PORT overrides) — only
3162
+ // replaces or appends each managed line.
3163
+ const envPath = join(persistDir, ".env");
3164
+ try {
3165
+ let envContent = "";
3166
+ try {
3167
+ envContent = readFileSync(envPath, "utf-8");
3168
+ }
3169
+ catch { /* first install */ }
3170
+ // DISPLAY_MODE
3171
+ if (/^DISPLAY_MODE=.*/m.test(envContent)) {
3172
+ envContent = envContent.replace(/^DISPLAY_MODE=.*/m, `DISPLAY_MODE=${DISPLAY_MODE}`);
3173
+ }
3174
+ else {
3175
+ envContent = envContent.trimEnd() + (envContent.length > 0 ? "\n" : "") + `DISPLAY_MODE=${DISPLAY_MODE}\n`;
3176
+ }
3177
+ // EMBED_MODEL
3178
+ if (/^EMBED_MODEL=.*/m.test(envContent)) {
3179
+ envContent = envContent.replace(/^EMBED_MODEL=.*/m, `EMBED_MODEL=${EMBED_MODEL}`);
3180
+ }
3181
+ else {
3182
+ envContent = envContent.trimEnd() + (envContent.length > 0 ? "\n" : "") + `EMBED_MODEL=${EMBED_MODEL}\n`;
3183
+ }
3184
+ // EMBED_DIMENSIONS
3185
+ if (/^EMBED_DIMENSIONS=.*/m.test(envContent)) {
3186
+ envContent = envContent.replace(/^EMBED_DIMENSIONS=.*/m, `EMBED_DIMENSIONS=${EMBED_DIMS}`);
3187
+ }
3188
+ else {
3189
+ envContent = envContent.trimEnd() + (envContent.length > 0 ? "\n" : "") + `EMBED_DIMENSIONS=${EMBED_DIMS}\n`;
3190
+ }
3191
+ // NEO4J_URI — always written so the platform connects to the correct instance.
3192
+ // For shared instances this is bolt://localhost:7687 (the default seed-neo4j.sh
3193
+ // would use anyway), but writing it explicitly makes the .env self-documenting
3194
+ // and ensures upgrade detection works for any future port change.
3195
+ const neo4jUri = `bolt://localhost:${NEO4J_PORT}`;
3196
+ if (/^NEO4J_URI=.*/m.test(envContent)) {
3197
+ envContent = envContent.replace(/^NEO4J_URI=.*/m, `NEO4J_URI=${neo4jUri}`);
3198
+ }
3199
+ else {
3200
+ envContent = envContent.trimEnd() + (envContent.length > 0 ? "\n" : "") + `NEO4J_URI=${neo4jUri}\n`;
3201
+ }
3202
+ writeFileSync(envPath, envContent);
3203
+ logFile(` .env: DISPLAY_MODE=${DISPLAY_MODE}, EMBED_MODEL=${EMBED_MODEL}, EMBED_DIMENSIONS=${EMBED_DIMS}, NEO4J_URI=${neo4jUri}`);
3204
+ }
3205
+ catch (err) {
3206
+ console.error(` WARNING: failed to write .env to ${envPath}: ${err instanceof Error ? err.message : String(err)}`);
3207
+ }
3208
+ // Propagate to child processes — seed-neo4j.sh reads both variables.
3209
+ process.env.EMBED_DIMENSIONS = String(EMBED_DIMS);
3210
+ process.env.NEO4J_URI = `bolt://localhost:${NEO4J_PORT}`;
3211
+ // maxy-ui runs on an internal-only port so a restart does not
3212
+ // drop the public TCP socket. maxy-edge.service owns the public port and
3213
+ // the VNC stack; maxy-ui sits behind it on 127.0.0.1:MAXY_UI_INTERNAL_PORT.
3214
+ // PORT + 1 (derived) avoids a fixed-port collision if the operator chose a
3215
+ // non-default --port.
3216
+ //
3217
+ // PORT in maxy.service's Environment block is the PUBLIC port,
3218
+ // not the internal one. Previously we wrote `Environment=PORT=<internal>`,
3219
+ // which collided with the install-time reader further down, which
3220
+ // correctly treats Environment=PORT= as public. The overload caused +1
3221
+ // drift per upgrade: each run read the internal value, treated it as
3222
+ // public, wrote internal = old_internal + 1. maxy-ui now binds
3223
+ // MAXY_UI_INTERNAL_PORT (with a fallback to PORT for mixed-state installs).
3224
+ const MAXY_UI_INTERNAL_PORT = PORT + 1;
3225
+ const edgeUnitShort = `${BRAND.hostname}-edge`;
3226
+ const edgeUnitName = `${edgeUnitShort}.service`;
3227
+ // Per-brand X display. Same value used for the edge unit's
3228
+ // DISPLAY env (stamped via __VNC_DISPLAY__ a few lines down) so the main
3229
+ // brand service and the edge service agree on which display Chromium runs.
3230
+ // brand.json (BRAND) is the single source of truth for
3231
+ // these fields at install time. The vncDisplay-derived offset rule lives
3232
+ // in the brand-creation tooling; at this point in the installer BRAND
3233
+ // already represents a parsed, validated brand manifest, and any missing
3234
+ // field is a brand-publish defect. Loud-fail rather than silently
3235
+ // substituting an offset (silent-fallback-masks-root-cause recurrence).
3236
+ if (typeof BRAND.vncDisplay !== "number") {
3237
+ console.error(`[create-maxy] error reason=cdp-port-unresolved brand=${BRAND.configDir} field=vncDisplay`);
3238
+ throw new Error(`brand.json missing required field: vncDisplay`);
3239
+ }
3240
+ const VNC_DISPLAY = BRAND.vncDisplay;
3241
+ for (const field of ["rfbPort", "websockifyPort", "cdpPort"]) {
3242
+ if (typeof BRAND[field] !== "number") {
3243
+ console.error(`[create-maxy] error reason=cdp-port-unresolved brand=${BRAND.configDir} field=${field}`);
3244
+ throw new Error(`brand.json missing required field: ${field}`);
3245
+ }
3246
+ }
3247
+ const RFB_PORT = BRAND.rfbPort;
3248
+ const WEBSOCKIFY_PORT_BRAND = BRAND.websockifyPort;
3249
+ const CDP_PORT_BRAND = BRAND.cdpPort;
3250
+ const CLAUDE_SESSION_MANAGER_PORT_BRAND = BRAND.claudeSessionManagerPort;
3251
+ // pre-flight — refuse to write service files if any of the
3252
+ // three brand-scoped ports is already held by a process that is NOT this
3253
+ // brand's own on-demand browser nor a peer brand's edge stack.
3254
+ //
3255
+ // Classification (chromium Xtigervnc + websockify) reads
3256
+ // `/proc/<pid>/cmdline` and applies a holder-specific argv anchor.
3257
+ // covered chromium-only via `--user-data-dir=` closed the gap on
3258
+ // Xtigervnc (no such flag — anchor on the `:N` display literal) and
3259
+ // websockify (anchor on bind port). Brand identities (configDir,
3260
+ // vncDisplay, websockifyPort) come from brand-registry.json which the
3261
+ // bundler stamps at build time from every brands/<brand>/brand.json.
3262
+ //
3263
+ // Decisions per holder:
3264
+ // OWN_BRAND — SIGTERM, recheck, SIGKILL on stragglers, exit-1 only if
3265
+ // the port is still held after both signals.
3266
+ // PEER_BRAND — log OK and return (per-brand port sets are disjoint).
3267
+ // UNRELATED — refuse to write service files; emit operator override.
3268
+ // macOS dev hosts (no ss) fall through the catch and skip pre-flight
3269
+ // entirely — the runtime check in vnc.sh covers Linux production.
3270
+ const ownBrand = {
3271
+ configDir: BRAND.configDir,
3272
+ vncDisplay: VNC_DISPLAY,
3273
+ websockifyPort: WEBSOCKIFY_PORT_BRAND,
3274
+ };
3275
+ // Peer registry — load from payload/platform/config/brand-registry.json
3276
+ // when present. Older bundles ship without the
3277
+ // registry; in that case peerBrands stays empty. PEER_BRAND classification
3278
+ // for Xtigervnc/websockify is a defence-in-depth case anyway (port sets
3279
+ // are disjoint), so the empty-list fallback is safe — peer
3280
+ // chromium will fall through to UNRELATED, matching earlier behaviour
3281
+ // for the only realistic scenario (a stale peer browser on the wrong CDP
3282
+ // port).
3283
+ const peerBrands = (() => {
3284
+ const registryPath = join(PAYLOAD_DIR, "platform", "config", "brand-registry.json");
3285
+ if (!existsSync(registryPath)) {
3286
+ logFile(` [preflight] brand-registry.json not in payload — peer matching disabled`);
3287
+ return [];
3288
+ }
3289
+ try {
3290
+ const raw = JSON.parse(readFileSync(registryPath, "utf-8"));
3291
+ const entries = [];
3292
+ for (const b of raw.brands ?? []) {
3293
+ if (b.hostname === BRAND.hostname)
3294
+ continue;
3295
+ if (typeof b.configDir !== "string" || typeof b.vncDisplay !== "number" || typeof b.websockifyPort !== "number")
3296
+ continue;
3297
+ entries.push({ configDir: b.configDir, vncDisplay: b.vncDisplay, websockifyPort: b.websockifyPort });
3298
+ }
3299
+ return entries;
3300
+ }
3301
+ catch (err) {
3302
+ logFile(` [preflight] brand-registry.json parse failed: ${err instanceof Error ? err.message : String(err)} — peer matching disabled`);
3303
+ return [];
3304
+ }
3305
+ })();
3306
+ const ssReadHolder = (port) => {
3307
+ return execFileSync("ss", ["-tlnpH", `sport = :${port}`], {
3308
+ encoding: "utf-8", timeout: 3000, stdio: ["ignore", "pipe", "ignore"],
3309
+ });
3310
+ };
3311
+ // Pass raw NUL-separated cmdline to the classifier so it can argv-anchor
3312
+ // on `--user-data-dir=`. Replacing NUL with space here would defeat that.
3313
+ const readCmdline = (pid) => readFileSync(`/proc/${pid}/cmdline`, "utf-8");
3314
+ const sleepMs = (ms) => { spawnSync("sleep", [(ms / 1000).toString()]); };
3315
+ // Tightly scoped variant for retry-path ss reads. Failures here (timeout,
3316
+ // ENOMEM, signal) are structural — never the macOS-no-ss case (we already
3317
+ // succeeded once) — so they get a structured exit, not a stack trace.
3318
+ const ssReadOrAbort = (label, port) => {
3319
+ try {
3320
+ return ssReadHolder(port);
3321
+ }
3322
+ catch (err) {
3323
+ console.error(` ERROR: [preflight] ${label}=${port} ss recheck failed: ${err instanceof Error ? err.message : String(err)}`);
3324
+ console.error(` Resolve manually before retrying.`);
3325
+ process.exit(1);
3326
+ }
3327
+ };
3328
+ // Distinguish ESRCH (process already gone — expected) from EPERM/EINVAL
3329
+ // (alarming — signals we can't deliver, possibly a recycled pid). Returns
3330
+ // true for clean kill or ESRCH, false otherwise (caller logs a warning).
3331
+ const killNoThrow = (pid, signal) => {
3332
+ try {
3333
+ process.kill(pid, signal);
3334
+ return true;
3335
+ }
3336
+ catch (err) {
3337
+ const code = err.code;
3338
+ if (code === "ESRCH")
3339
+ return true;
3340
+ logFile(` [preflight] kill(${pid}, ${signal}) failed code=${code ?? "unknown"}`);
3341
+ return false;
3342
+ }
3343
+ };
3344
+ const classify = (ssOutput) => classifyPortHolder({
3345
+ ssOutput, ownBrand, peerBrands, getCmdline: readCmdline,
3346
+ });
3347
+ // log line varies by detected holder so the operator can see
3348
+ // which OWN_BRAND stack is being killed. The kill loop is identical for
3349
+ // all three holders (SIGTERM → 300ms → recheck → SIGKILL → recheck), so
3350
+ // only the announce line differs.
3351
+ const ownBrandAnnounceLine = (label, port, c) => {
3352
+ if (c.holderType === "xtigervnc") {
3353
+ return ` [preflight] ${label}=${port} held by OWN brand Xtigervnc display=:${c.vncDisplay} pid=${c.pid} — sending SIGTERM`;
3354
+ }
3355
+ if (c.holderType === "websockify") {
3356
+ return ` [preflight] ${label}=${port} held by OWN brand websockify pid=${c.pid} — sending SIGTERM`;
3357
+ }
3358
+ // Default — chromium / unknown OWN_BRAND
3359
+ return ` [preflight] ${label}=${port} held by OWN brand process pid=${c.pid} profile=${c.profilePath} — sending SIGTERM`;
3360
+ };
3361
+ const checkInstallPortFree = (label, port) => {
3362
+ let firstSsOutput;
3363
+ try {
3364
+ firstSsOutput = ssReadHolder(port);
3365
+ }
3366
+ catch (err) {
3367
+ // ss may not be present on macOS dev hosts — skip the pre-flight there
3368
+ // rather than abort the install. The runtime check in vnc.sh covers
3369
+ // production-like Linux installs where this matters. This catch is
3370
+ // narrow on purpose: only the first ss invocation may legitimately
3371
+ // fail (binary missing); retry-path failures use ssReadOrAbort.
3372
+ logFile(` [preflight] ${label}=${port} check skipped: ${err instanceof Error ? err.message : String(err)}`);
3373
+ return;
3374
+ }
3375
+ let r = classify(firstSsOutput);
3376
+ // ENOENT race — process exited between ss and cmdline read. Port is
3377
+ // probably free now; one re-check resolves it deterministically.
3378
+ if (r.cmdlineReadFailed)
3379
+ r = classify(ssReadOrAbort(label, port));
3380
+ if (r.kind === "EMPTY")
3381
+ return;
3382
+ if (r.kind === "PEER_BRAND") {
3383
+ logFile(` [preflight] ${label}=${port} held by a peer brand's stack — OK (per-brand ports are disjoint by construction)`);
3384
+ return;
3385
+ }
3386
+ if (r.kind === "OWN_BRAND" && r.pid !== undefined) {
3387
+ logFile(ownBrandAnnounceLine(label, port, r));
3388
+ killNoThrow(r.pid, "SIGTERM");
3389
+ sleepMs(300);
3390
+ const after = classify(ssReadOrAbort(label, port));
3391
+ if (after.kind === "EMPTY") {
3392
+ logFile(` [preflight] ${label}=${port} freed`);
3393
+ return;
3394
+ }
3395
+ if (after.kind === "OWN_BRAND" && after.pid === r.pid) {
3396
+ logFile(` [preflight] ${label}=${port} survived SIGTERM — sending SIGKILL`);
3397
+ killNoThrow(r.pid, "SIGKILL");
3398
+ sleepMs(300);
3399
+ const final = classify(ssReadOrAbort(label, port));
3400
+ if (final.kind === "EMPTY") {
3401
+ logFile(` [preflight] ${label}=${port} freed`);
3402
+ return;
3403
+ }
3404
+ console.error(` ERROR: [preflight] ${label}=${port} OWN_BRAND auto-kill failed pid=${r.pid} — resolve manually before retrying.`);
3405
+ process.exit(1);
3406
+ }
3407
+ // A different OWN_BRAND pid took the port. The brand's user services
3408
+ // are respawning Chromium — installer cannot win this race. Stop the
3409
+ // services, then retry.
3410
+ if (after.kind === "OWN_BRAND") {
3411
+ console.error(` ERROR: [preflight] ${label}=${port} brand respawned a new OWN_BRAND pid (was ${r.pid}, now ${after.pid}).`);
3412
+ console.error(` Stop the brand's user services first: \`systemctl --user stop ${BRAND.hostname}-edge ${BRAND.hostname}\`, then re-run the installer.`);
3413
+ process.exit(1);
3414
+ }
3415
+ // PEER_BRAND or UNRELATED took the port post-kill — fall through to
3416
+ // those branches by re-classifying the surviving holder.
3417
+ r = after;
3418
+ if (r.kind === "EMPTY")
3419
+ return;
3420
+ if (r.kind === "PEER_BRAND") {
3421
+ logFile(` [preflight] ${label}=${port} now held by a peer brand's stack — OK`);
3422
+ return;
3423
+ }
3424
+ // r.kind === "UNRELATED" — fall through to the operator-override block.
3425
+ }
3426
+ // UNRELATED — preserve the operator-override path verbatim.
3427
+ console.error(` ERROR: [preflight:collision] brand=${BRAND.hostname} ${label}=${port} held by an unrelated process:`);
3428
+ console.error(` ${firstSsOutput.trim()}`);
3429
+ if (r.cmdline)
3430
+ console.error(` cmdline: ${r.cmdline}`);
3431
+ console.error(` Refusing to write service files; resolve the collision before retrying.`);
3432
+ console.error(` Operator override: edit brands/${BRAND.hostname}/brand.json, set/add \`${label}\` to a free port, re-bundle, re-install.`);
3433
+ process.exit(1);
3434
+ };
3435
+ checkInstallPortFree("rfbPort", RFB_PORT);
3436
+ checkInstallPortFree("websockifyPort", WEBSOCKIFY_PORT_BRAND);
3437
+ checkInstallPortFree("cdpPort", CDP_PORT_BRAND);
3438
+ // ACCOUNT_ID stamped into the brand unit so the writeNodeWithEdges
3439
+ // gate at platform/lib/graph-write/src/index.ts:170 has a real identity to
3440
+ // compare against (instead of process.env.ACCOUNT_ID === undefined). Resolved
3441
+ // here AFTER setupAccount() ran upstream — setup-account.sh wrote account.json,
3442
+ // so an empty resolution at this point is a corrupted install (e.g. the seed
3443
+ // failed silently, or accounts/ was wiped between setup and unit-write).
3444
+ const installAccountId = resolveInstallAccountId();
3445
+ if (!installAccountId) {
3446
+ throw new Error(`installService: no account discovered at ${INSTALL_DIR}/data/accounts/<uuid>/account.json — ` +
3447
+ `setupAccount() (setup-account.sh) should have created one. Refusing to write a systemd unit ` +
3448
+ `without ACCOUNT_ID; the boot validator would FATAL on every restart.`);
3449
+ }
3450
+ const serviceFile = buildMaxyUnitFile({
3451
+ productName: BRAND.productName,
3452
+ brandHostname: BRAND.hostname,
3453
+ neo4jDedicated: NEO4J_DEDICATED,
3454
+ installDir: INSTALL_DIR,
3455
+ persistDir,
3456
+ port: PORT,
3457
+ maxyUiInternalPort: MAXY_UI_INTERNAL_PORT,
3458
+ vncDisplay: VNC_DISPLAY,
3459
+ rfbPort: RFB_PORT,
3460
+ websockifyPort: WEBSOCKIFY_PORT_BRAND,
3461
+ cdpPort: CDP_PORT_BRAND,
3462
+ claudeSessionManagerPort: CLAUDE_SESSION_MANAGER_PORT_BRAND,
3463
+ chromiumBin: RESOLVED_CHROMIUM_BIN,
3464
+ accountId: installAccountId,
3465
+ });
3466
+ writeFileSync(join(serviceDir, BRAND.serviceName), serviceFile);
3467
+ // (maxy-code) — write the claude-session-manager unit. The main
3468
+ // brand unit Requires= + After= this one, so systemd starts it first.
3469
+ const claudeSessionManagerUnitName = `${BRAND.hostname}-claude-session-manager.service`;
3470
+ const claudeSessionManagerUnit = buildClaudeSessionManagerUnitFile({
3471
+ productName: BRAND.productName,
3472
+ brandHostname: BRAND.hostname,
3473
+ installDir: INSTALL_DIR,
3474
+ persistDir,
3475
+ claudeSessionManagerPort: CLAUDE_SESSION_MANAGER_PORT_BRAND,
3476
+ brandPort: PORT,
3477
+ maxyUiInternalPort: MAXY_UI_INTERNAL_PORT,
3478
+ accountId: installAccountId,
3479
+ cdpPort: CDP_PORT_BRAND,
3480
+ });
3481
+ writeFileSync(join(serviceDir, claudeSessionManagerUnitName), claudeSessionManagerUnit);
3482
+ logFile(` ${claudeSessionManagerUnitName}: CLAUDE_SESSION_MANAGER_PORT=${CLAUDE_SESSION_MANAGER_PORT_BRAND} MAXY_UI_INTERNAL_PORT=${MAXY_UI_INTERNAL_PORT}`);
3483
+ // Task 250 — write the brand-agnostic `claude-ptys.slice` unit. Every
3484
+ // brand's session manager drops its per-spawn scope units under this
3485
+ // slice. Writing it once per install is idempotent (the content is
3486
+ // identical across brands and across runs); subsequent brand installs
3487
+ // re-stamp the same content. No service restart is needed — `daemon-reload`
3488
+ // below picks it up.
3489
+ const claudePtysSliceName = "claude-ptys.slice";
3490
+ writeFileSync(join(serviceDir, claudePtysSliceName), buildClaudePtysSliceUnitFile());
3491
+ logFile(` ${claudePtysSliceName}: Task 250 slice for claude-session-*.scope cohort`);
3492
+ // Task 602 — write the brand-agnostic `cloudflared.slice` unit. Every
3493
+ // cloudflared-<brand>.service spawned by resume-tunnel.sh drops under this
3494
+ // slice (Task 757 changed the unit from a scope to a supervised service).
3495
+ // Writing once per install is idempotent; daemon-reload below picks it up.
3496
+ const cloudflaredSliceName = "cloudflared.slice";
3497
+ writeFileSync(join(serviceDir, cloudflaredSliceName), buildCloudflaredSliceUnitFile());
3498
+ logFile(` ${cloudflaredSliceName}: Task 602 slice for cloudflared-*.service cohort`);
3499
+ // Task 600 — per-brand RSS sampler: a long-running user service that
3500
+ // periodically writes per-claude.exe RSS + aggregate RSS to disk.
3501
+ // Named per-brand (BRAND.hostname prefix) so two brands on the same
3502
+ // device each own their own sampler writing to their own log path.
3503
+ const rssSamplerUnitName = `${BRAND.hostname}-rss-sampler.service`;
3504
+ const rssSamplerScriptPath = resolve(INSTALL_DIR, "platform/scripts/rss-sampler.sh");
3505
+ const rssSamplerLogPath = join(persistDir, "rss-sampler.log");
3506
+ const rssSamplerUnit = `[Unit]
3507
+ Description=${BRAND.productName} RSS Sampler
3508
+
3509
+ [Service]
3510
+ Type=simple
3511
+ ExecStart=/bin/bash ${rssSamplerScriptPath}
3512
+ Environment=LOG_PATH=${rssSamplerLogPath}
3513
+ Restart=on-failure
3514
+ RestartSec=10
3515
+
3516
+ [Install]
3517
+ WantedBy=default.target
3518
+ `;
3519
+ writeFileSync(join(serviceDir, rssSamplerUnitName), rssSamplerUnit);
3520
+ logFile(` rss-sampler installed: ${rssSamplerUnitName} LOG_PATH=${rssSamplerLogPath}`);
3521
+ // the edge service: always-on front door that owns the public
3522
+ // port (PORT) and the VNC stack (Xtigervnc + websockify). Its lifecycle is
3523
+ // independent of the main brand service, so an in-place upgrade triggered
3524
+ // from the admin terminal can restart the main brand service without
3525
+ // disconnecting the browser's remote terminal WebSocket.
3526
+ //
3527
+ // the unit is per-brand so two brands on the same device each
3528
+ // own their own edge listener on their own EDGE_PORT — installing brand B
3529
+ // never rewrites brand A's unit or steals brand A's public port. Upgrades
3530
+ // from pre-662 installs require the manual recovery paragraph in
3531
+ // .docs/deployment.md before re-running this installer; auto-migration is
3532
+ // intentionally scoped out.
3533
+ // VNC_DISPLAY (defined above for the main brand unit) is also stamped into
3534
+ // the edge unit so both services agree on the X display. Per-brand display
3535
+ // closes the cross-brand cookie leak documented.
3536
+ const edgeTemplatePath = resolve(INSTALL_DIR, "platform/templates/systemd/edge.service.template");
3537
+ if (existsSync(edgeTemplatePath)) {
3538
+ const edgeServiceContent = readFileSync(edgeTemplatePath, "utf-8")
3539
+ .replace(/__INSTALL_DIR__/g, INSTALL_DIR)
3540
+ .replace(/__EDGE_PORT__/g, String(PORT))
3541
+ .replace(/__MAXY_UI_PORT__/g, String(MAXY_UI_INTERNAL_PORT))
3542
+ .replace(/__PERSIST_DIR__/g, persistDir)
3543
+ .replace(/__VNC_DISPLAY__/g, String(VNC_DISPLAY))
3544
+ .replace(/__WEBSOCKIFY_PORT__/g, String(WEBSOCKIFY_PORT_BRAND))
3545
+ .replace(/__CDP_PORT__/g, String(CDP_PORT_BRAND))
3546
+ .replace(/__RFB_PORT__/g, String(RFB_PORT));
3547
+ writeFileSync(join(serviceDir, edgeUnitName), edgeServiceContent);
3548
+ logFile(` ${edgeUnitName}: EDGE_PORT=${PORT} MAXY_UI_PORT=${MAXY_UI_INTERNAL_PORT} VNC_DISPLAY=:${VNC_DISPLAY} RFB_PORT=${RFB_PORT} WEBSOCKIFY_PORT=${WEBSOCKIFY_PORT_BRAND} CDP_PORT=${CDP_PORT_BRAND}`);
3549
+ }
3550
+ else {
3551
+ console.error(` WARNING: edge.service.template missing at ${edgeTemplatePath} — VNC transport unavailable`);
3552
+ }
3553
+ // the unit declares Environment=PATH=%h/.local/bin:... so the graph
3554
+ // MCP shim's spawn("uvx", ...) resolves against uv's install location. Without
3555
+ // this line, the service inherits the default systemd-user PATH — which
3556
+ // excludes ~/.local/bin — and the shim exits ENOENT before any query lands.
3557
+ logFile(` ${BRAND.serviceName}: PATH env includes %h/.local/bin for uvx resolution`);
3558
+ // WiFi AP provisioning service — system-level (requires root for hostapd/dnsmasq).
3559
+ // Runs at boot to check connectivity. If no saved WiFi and no ethernet, activates
3560
+ // a temporary AP with a captive portal for first-time WiFi configuration.
3561
+ const currentUser = execFileSync("whoami", [], { encoding: "utf-8" }).trim();
3562
+ const wifiProvisionService = `[Unit]
3563
+ Description=${BRAND.productName} WiFi Provisioning
3564
+ After=NetworkManager.service
3565
+ Before=${BRAND.serviceName}
3566
+
3567
+ [Service]
3568
+ Type=simple
3569
+ ExecStart=/bin/bash ${INSTALL_DIR}/platform/scripts/wifi-provision.sh
3570
+ ExecStopPost=/bin/bash ${INSTALL_DIR}/platform/scripts/wifi-provision.sh cleanup
3571
+ Environment=MAXY_PLATFORM_ROOT=${INSTALL_DIR}/platform
3572
+ Environment=INSTALL_USER=${currentUser}
3573
+ Environment=INSTALL_HOME=${process.env.HOME ?? "/home/" + currentUser}
3574
+ TimeoutStartSec=300
3575
+ TimeoutStopSec=30
3576
+
3577
+ [Install]
3578
+ WantedBy=multi-user.target
3579
+ `;
3580
+ const systemServiceDir = "/etc/systemd/system";
3581
+ const wifiProvisionPath = join(systemServiceDir, "wifi-provision.service");
3582
+ try {
3583
+ const tmpPath = "/tmp/wifi-provision.service";
3584
+ writeFileSync(tmpPath, wifiProvisionService);
3585
+ console.log(" [privileged] cp");
3586
+ shell("cp", [tmpPath, wifiProvisionPath], { sudo: true });
3587
+ spawnSync("rm", ["-f", tmpPath]);
3588
+ spawnSync("sudo", ["systemctl", "daemon-reload"], { stdio: "inherit" });
3589
+ spawnSync("sudo", ["systemctl", "enable", "wifi-provision"], { stdio: "inherit" });
3590
+ logFile(" WiFi provisioning service installed and enabled");
3591
+ }
3592
+ catch (err) {
3593
+ console.error(` WARNING: Failed to install wifi-provision service: ${err instanceof Error ? err.message : String(err)}`);
3594
+ }
3595
+ // Disable hostapd and dnsmasq system services (we manage them manually
3596
+ // from wifi-provision.sh — the system services would conflict).
3597
+ spawnSync("sudo", ["systemctl", "stop", "hostapd"], { stdio: "ignore" });
3598
+ spawnSync("sudo", ["systemctl", "disable", "hostapd"], { stdio: "ignore" });
3599
+ spawnSync("sudo", ["systemctl", "stop", "dnsmasq"], { stdio: "ignore" });
3600
+ spawnSync("sudo", ["systemctl", "disable", "dnsmasq"], { stdio: "ignore" });
3601
+ // Enable lingering so user services run without login
3602
+ try {
3603
+ spawnSync("sudo", ["loginctl", "enable-linger", currentUser], { stdio: "inherit" });
3604
+ }
3605
+ catch { /* not critical */ }
3606
+ // Task 504: persist the systemd journal so per-unit lifecycle events
3607
+ // (SIGTERM/SIGKILL transitions, dependency-propagated stops, restart job
3608
+ // records) survive reboots and remain greppable via `journalctl --user -u
3609
+ // <brand>.service` after a restart loop quiets.
3610
+ //
3611
+ // Why a drop-in and not the Task-249 `mkdir /var/log/journal`: the directory
3612
+ // heuristic only takes effect under journald's default `Storage=auto`. A
3613
+ // base image (common on RPi to spare the SD card) that ships an explicit
3614
+ // `Storage=volatile` overrides directory existence, so the bare mkdir is a
3615
+ // no-op there — exactly the state observed on the realagent-code device. An
3616
+ // explicit `Storage=persistent` drop-in wins regardless of the base default,
3617
+ // and journald itself creates `/var/log/journal/<machine-id>` on restart, so
3618
+ // the mkdir is no longer needed.
3619
+ //
3620
+ // journald is one system instance, so the drop-in is host-wide with a neutral
3621
+ // filename — idempotent across brands and reinstalls. Restart journald only
3622
+ // when the drop-in content actually changes, to avoid churning the system
3623
+ // journal on every reinstall. Best-effort: a failure here warns, never aborts
3624
+ // the install.
3625
+ try {
3626
+ const journaldDropinDir = "/etc/systemd/journald.conf.d";
3627
+ const journaldDropinPath = `${journaldDropinDir}/10-maxy-persistent.conf`;
3628
+ const desiredJournaldConf = "[Journal]\nStorage=persistent\n";
3629
+ let journaldCurrent = "";
3630
+ if (existsSync(journaldDropinPath)) {
3631
+ try {
3632
+ journaldCurrent = readFileSync(journaldDropinPath, "utf-8");
3633
+ }
3634
+ catch {
3635
+ // Unreadable existing drop-in — treat as changed so we rewrite + restart.
3636
+ journaldCurrent = "";
3637
+ }
3638
+ }
3639
+ if (journaldCurrent === desiredJournaldConf) {
3640
+ logFile(` journald persistence: already active (${journaldDropinPath} matches Storage=persistent)`);
3641
+ }
3642
+ else {
3643
+ const journaldTmpPath = "/tmp/10-maxy-persistent.conf";
3644
+ writeFileSync(journaldTmpPath, desiredJournaldConf);
3645
+ console.log(" [privileged] install journald Storage=persistent drop-in");
3646
+ shell("mkdir", ["-p", journaldDropinDir], { sudo: true });
3647
+ shell("cp", [journaldTmpPath, journaldDropinPath], { sudo: true });
3648
+ spawnSync("rm", ["-f", journaldTmpPath]);
3649
+ console.log(" [privileged] systemctl restart systemd-journald");
3650
+ spawnSync("sudo", ["systemctl", "restart", "systemd-journald"], { stdio: "inherit", timeout: 15_000 });
3651
+ logFile(` journald persistence: enabled (wrote ${journaldDropinPath} Storage=persistent + restarted journald)`);
3652
+ }
3653
+ }
3654
+ catch (err) {
3655
+ console.error(` WARNING: failed to enable journald persistence: ${err instanceof Error ? err.message : String(err)}`);
3656
+ }
3657
+ // Task 504: capture the initiator of a brand-service restart so the next
3658
+ // recurrence of the restart loop is attributable to its source from
3659
+ // device-retained evidence. The brand admin process logs only that it
3660
+ // *received* SIGTERM (not the sender), and a JS signal handler cannot read
3661
+ // si_pid. auditd is the device-side primitive that names the initiator:
3662
+ //
3663
+ // - `kill` syscall with sig=15 (SIGTERM): names a process that sends
3664
+ // SIGTERM directly to the brand pid. For a systemd-managed stop the
3665
+ // sender is the user systemd manager itself, so this rule alone does NOT
3666
+ // name the upstream actor of a managed restart — but it does catch a
3667
+ // direct, non-systemd kill.
3668
+ // - `execve` of systemctl: names the pid/cgroup that drives a CLI restart
3669
+ // (`systemctl --user restart <unit>`), which is the upstream actor the
3670
+ // kill rule misses for the systemd-mediated path.
3671
+ // - Once auditd runs, systemd emits native SERVICE_START/SERVICE_STOP audit
3672
+ // records with no rule needed, covering a restart issued over raw D-Bus
3673
+ // (no systemctl binary, so the execve rule would miss it).
3674
+ //
3675
+ // Rules are deliberately narrow (SIGTERM + systemctl execve only) so audit
3676
+ // write volume stays bounded on a low-power device; auditd's default log
3677
+ // rotation bounds disk further. Everything here is best-effort: a box with no
3678
+ // apt mirror, or a kernel without audit support, warns and the install still
3679
+ // completes. Load via `augenrules --load` (merges rules.d into the running
3680
+ // daemon without a disruptive auditd restart).
3681
+ try {
3682
+ console.log(" [privileged] apt-get install auditd");
3683
+ shell("apt-get", ["install", "-y", "auditd"], { sudo: true, bestEffort: true });
3684
+ const auditRulesPath = "/etc/audit/rules.d/90-maxy-restart-forensics.rules";
3685
+ // Rule ordering matters: auditctl loads rules in file order, and a rule a
3686
+ // kernel rejects (the arch=b32 kill rule on an arm64 kernel without 32-bit
3687
+ // compat) must not sit ahead of rules that should load. So the b64 kill
3688
+ // rule and the systemctl watch come first; the b32 kill rule (the one that
3689
+ // may be rejected) comes last. The systemctl capture uses a file watch
3690
+ // (`-w … -p x`), the idiomatic form for "audit execution of this binary" —
3691
+ // it records the caller pid/cgroup and is arch-agnostic, avoiding the
3692
+ // invalid `arch`+`path`+`perm` field mix.
3693
+ const auditRules = [
3694
+ "# Maxy restart-loop forensics (Task 504) — name the initiator of a",
3695
+ "# brand-service restart on the next recurrence.",
3696
+ "# SIGTERM sender (a0=target pid, a1=signal).",
3697
+ "-a always,exit -F arch=b64 -S kill -F a1=15 -k maxy_sigterm",
3698
+ "# systemctl execution — names the caller pid/cgroup of a CLI restart.",
3699
+ "-w /usr/bin/systemctl -p x -k maxy_systemctl",
3700
+ "# b32 kill sibling last: a 32-bit-compat caller is still captured, and a",
3701
+ "# rejection on an arm64 kernel without compat cannot block the rules above.",
3702
+ "-a always,exit -F arch=b32 -S kill -F a1=15 -k maxy_sigterm",
3703
+ "",
3704
+ ].join("\n");
3705
+ const auditTmpPath = "/tmp/90-maxy-restart-forensics.rules";
3706
+ writeFileSync(auditTmpPath, auditRules);
3707
+ console.log(" [privileged] install auditd restart-forensics rules");
3708
+ shell("mkdir", ["-p", "/etc/audit/rules.d"], { sudo: true, bestEffort: true });
3709
+ shell("cp", [auditTmpPath, auditRulesPath], { sudo: true, bestEffort: true });
3710
+ spawnSync("rm", ["-f", auditTmpPath]);
3711
+ console.log(" [privileged] augenrules --load");
3712
+ shell("augenrules", ["--load"], { sudo: true, bestEffort: true });
3713
+ logFile(` auditd restart forensics: rules at ${auditRulesPath} (keys maxy_sigterm, maxy_systemctl) — verify on device with \`ausearch -k maxy_sigterm\``);
3714
+ }
3715
+ catch (err) {
3716
+ console.error(` WARNING: failed to install auditd restart forensics: ${err instanceof Error ? err.message : String(err)}`);
3717
+ }
3718
+ // Reload and (re)start.
3719
+ //
3720
+ // ordering: on upgrades, the old main brand service still holds
3721
+ // the public port (PORT). Stop it FIRST so the edge can bind that socket;
3722
+ // starting the edge first would race against the old main brand service
3723
+ // and fail with EADDRINUSE. Fresh installs: the stop is a no-op.
3724
+ const unitName = BRAND.serviceName.replace(".service", "");
3725
+ const claudeSessionManagerUnitShort = claudeSessionManagerUnitName.replace(".service", "");
3726
+ spawnSync("systemctl", ["--user", "stop", unitName], { stdio: "inherit" });
3727
+ spawnSync("systemctl", ["--user", "daemon-reload"], { stdio: "inherit" });
3728
+ spawnSync("systemctl", ["--user", "enable", edgeUnitShort], { stdio: "inherit" });
3729
+ spawnSync("systemctl", ["--user", "enable", claudeSessionManagerUnitShort], { stdio: "inherit" });
3730
+ spawnSync("systemctl", ["--user", "enable", unitName], { stdio: "inherit" });
3731
+ spawnSync("systemctl", ["--user", "enable", `${BRAND.hostname}-rss-sampler`], { stdio: "inherit" });
3732
+ // edge first: binds public port + starts VNC stack. Then claude-session-manager
3733
+ // (so the main brand unit's Requires= is satisfied). Then main brand service.
3734
+ // rss-sampler is independent — start last, failure is non-blocking.
3735
+ spawnSync("systemctl", ["--user", "restart", edgeUnitShort], { stdio: "inherit" });
3736
+ spawnSync("systemctl", ["--user", "restart", claudeSessionManagerUnitShort], { stdio: "inherit" });
3737
+ spawnSync("systemctl", ["--user", "restart", unitName], { stdio: "inherit" });
3738
+ spawnSync("systemctl", ["--user", "restart", `${BRAND.hostname}-rss-sampler`], { stdio: "inherit" });
3739
+ // Session manager runs in its own systemd user unit and can boot-fail silently
3740
+ // (e.g. mcp-block-missing). The web server below comes up regardless, so the
3741
+ // install terminal would otherwise report success while every API call 503s.
3742
+ // Surface the boot failure on the trusted surface and refuse to declare success.
3743
+ console.log(" Waiting for session manager...");
3744
+ let sessionManagerActive = false;
3745
+ for (let i = 0; i < 5; i++) {
3746
+ const probe = spawnSync("systemctl", ["--user", "is-active", claudeSessionManagerUnitShort], { stdio: "pipe", encoding: "utf-8" });
3747
+ if ((probe.stdout ?? "").trim() === "active") {
3748
+ sessionManagerActive = true;
3749
+ break;
3750
+ }
3751
+ spawnSync("sleep", ["2"]);
3752
+ }
3753
+ if (!sessionManagerActive) {
3754
+ const status = spawnSync("systemctl", ["--user", "status", claudeSessionManagerUnitShort, "--no-pager", "-n", "20"], { stdio: "pipe", encoding: "utf-8" });
3755
+ const statusOutput = `${status.stdout ?? ""}${status.stderr ?? ""}`.trimEnd();
3756
+ console.error(statusOutput);
3757
+ logFile(statusOutput);
3758
+ const failureLine = `Session manager (${claudeSessionManagerUnitShort}) failed to start. See above for boot-failed reason.`;
3759
+ console.error(failureLine);
3760
+ logFile(failureLine);
3761
+ process.exit(1);
3762
+ }
3763
+ // Wait for the server to come up
3764
+ console.log(" Waiting for web server...");
3765
+ let webServerUp = false;
3766
+ for (let i = 0; i < 20; i++) {
3767
+ try {
3768
+ execFileSync("curl", ["-sf", `http://localhost:${PORT}`, "-o", "/dev/null"], { timeout: 3000 });
3769
+ webServerUp = true;
3770
+ break;
3771
+ }
3772
+ catch {
3773
+ spawnSync("sleep", ["2"]);
3774
+ }
3775
+ }
3776
+ if (!webServerUp) {
3777
+ console.log(` Server may still be starting. Check http://${DEVICE_HOSTNAME}.local:${PORT} in a moment.`);
3778
+ }
3779
+ // Validate CDP: the programmatic Playwright MCP server connects to Chromium
3780
+ // via --cdp-endpoint http://127.0.0.1:9222. In virtual (VNC) mode, Chromium is
3781
+ // started by vnc.sh (ExecStartPre) before the web server — a failed probe here
3782
+ // indicates a genuine VNC boot failure and must fail the install loudly.
3783
+ // In native mode, Chromium is launched on-demand by the server and is not
3784
+ // expected to be bound at install time — the probe is skipped.
3785
+ if (DISPLAY_MODE === "native") {
3786
+ console.log(" [cdp-check] skipped reason=native-display (on-demand Chromium)");
3787
+ }
3788
+ else {
3789
+ console.log(` Verifying browser automation (CDP on port ${CDP_PORT_BRAND})...`);
3790
+ const cdpCheck = spawnSync("curl", ["-sf", `http://127.0.0.1:${CDP_PORT_BRAND}/json/version`, "-o", "/dev/null"], {
3791
+ timeout: 5000,
3792
+ stdio: "pipe",
3793
+ });
3794
+ if (cdpCheck.status === 0) {
3795
+ console.log(" Browser automation ready (CDP connected).");
3796
+ }
3797
+ else {
3798
+ const vncLogPath = resolve(process.env.HOME ?? "/root", BRAND.configDir, "logs/vnc-boot.log");
3799
+ let vncLog = "";
3800
+ try {
3801
+ vncLog = readFileSync(vncLogPath, "utf-8").slice(-2000);
3802
+ }
3803
+ catch {
3804
+ vncLog = `(no boot log found at ${vncLogPath})`;
3805
+ }
3806
+ console.error("");
3807
+ console.error(`Setup failed: Browser automation unavailable — CDP port ${CDP_PORT_BRAND} not responding`);
3808
+ console.error(` ERROR: Browser automation unavailable — CDP port ${CDP_PORT_BRAND} not responding.`);
3809
+ console.error(" Chromium should be started by vnc.sh (ExecStartPre). Check the boot log:");
3810
+ console.error("");
3811
+ console.error(vncLog);
3812
+ process.exit(1);
3813
+ }
3814
+ }
3815
+ }
3816
+ // ---------------------------------------------------------------------------
3817
+ // Samba provisioning. Runs after installService() so SMB never
3818
+ // blocks the admin server starting; pure decisions live in samba-provision.ts.
3819
+ //
3820
+ // Four steps, each emitting one [install-invariant] samba-provision-<step>
3821
+ // marker:
3822
+ // apt — install the `samba` package
3823
+ // conf — write the brand stanza + LAN-only globals to /etc/samba/smb.conf
3824
+ // user — smbpasswd the install-owner Linux user; deferred at install time
3825
+ // on fresh Pi installs (no plaintext PIN until the operator runs set-pin)
3826
+ // units — systemctl enable --now smbd (nmbd is never enabled; Task 755)
3827
+ //
3828
+ // The platform's set-pin route handler closes the deferral loop by running
3829
+ // `smbpasswd -a -s <install-owner>` inline whenever the PIN is set or
3830
+ // rotated. Install owner is the Unix user the installer is running as —
3831
+ // `admin` on a Pi/Hetzner box, `neo` (etc.) on a self-hosted laptop. It is
3832
+ // persisted to `~/.<brand>/.install-owner` so every later read uses the same
3833
+ // value the installer wrote.
3834
+ // ---------------------------------------------------------------------------
3835
+ function emitSambaMarker(step, state) {
3836
+ const line = formatSambaMarker(step, state);
3837
+ console.log(` ${line}`);
3838
+ logFile(` ${line}`);
3839
+ }
3840
+ function provisionSamba() {
3841
+ if (!isLinux()) {
3842
+ logFile(` samba-provision skipped: platform=${process.platform}`);
3843
+ return;
3844
+ }
3845
+ const brand = BRAND.hostname;
3846
+ const sharePath = INSTALL_DIR;
3847
+ // Install owner — the Unix user that owns this brand's install on the
3848
+ // device. On a Pi/Hetzner box this is `admin`; on a self-hosted laptop it
3849
+ // is the operator's Unix user (`neo` etc.). Persisted to a file next to
3850
+ // the other install identity (`.neo4j-password`, `.admin-pin`) so the
3851
+ // platform's set-pin route and the uninstall path read the same value the
3852
+ // installer wrote, rather than re-detecting at request time. Task 534.
3853
+ const installOwner = userInfo().username;
3854
+ const installOwnerPersistDir = resolve(process.env.HOME ?? "/root", BRAND.configDir);
3855
+ mkdirSync(installOwnerPersistDir, { recursive: true });
3856
+ writeFileSync(join(installOwnerPersistDir, ".install-owner"), `${installOwner}\n`, { mode: 0o644 });
3857
+ // Step 1 — apt install samba. Precheck `dpkg -s samba` first; if the
3858
+ // package is already installed, skip apt entirely so the install does not
3859
+ // contend with `unattended-upgrades` for `/var/lib/dpkg/lock-frontend`
3860
+ // every time. Mirrors the [1/11] system-deps step.
3861
+ try {
3862
+ const dpkgCheck = spawnSync("dpkg", ["-s", "samba"], { stdio: "pipe", timeout: 5_000 });
3863
+ if (dpkgCheck.status === 0) {
3864
+ logFile(" samba already installed — skipping apt install.");
3865
+ emitSambaMarker("apt", "ok-already-installed");
3866
+ }
3867
+ else {
3868
+ installAptGroup("samba", ["samba"]);
3869
+ emitSambaMarker("apt", "ok");
3870
+ }
3871
+ }
3872
+ catch (err) {
3873
+ const stderr = err instanceof Error ? err.message : String(err);
3874
+ emitSambaMarker("apt", `fail: ${stderr}`);
3875
+ throw err;
3876
+ }
3877
+ // Step 2 — write the brand stanza into /etc/samba/smb.conf. Classify the
3878
+ // host's interfaces (Task 755): a private LAN interface → bind `lo <iface>`;
3879
+ // a public-only host (Hetzner) → bind loopback-only (`lanInterface = null`)
3880
+ // so the share is reachable only from the box itself; no non-loopback IPv4
3881
+ // interface at all → hard-fail, as before. Loopback-only is a distinct third
3882
+ // outcome, NOT the null/throw case.
3883
+ const bind = pickBindDecision(networkInterfaces());
3884
+ if (bind.kind === "none") {
3885
+ emitSambaMarker("conf", "fail: no non-loopback IPv4 interface");
3886
+ throw new Error("samba-provision: no LAN interface with IPv4 — cannot bind smbd safely");
3887
+ }
3888
+ const lanInterface = bind.kind === "lan" ? bind.lanInterface : null;
3889
+ const bindPosture = bind.kind === "lan" ? `bind=lan iface=${bind.lanInterface}` : "bind=loopback-only";
3890
+ const SMB_CONF = "/etc/samba/smb.conf";
3891
+ let existing = "";
3892
+ if (existsSync(SMB_CONF)) {
3893
+ try {
3894
+ const cat = spawnSync("sudo", ["cat", SMB_CONF], { encoding: "utf-8", stdio: "pipe", timeout: 5_000 });
3895
+ if (cat.status === 0)
3896
+ existing = cat.stdout ?? "";
3897
+ }
3898
+ catch { /* treat as empty */ }
3899
+ }
3900
+ const merged = mergeSmbConf({ existing, brand, sharePath, lanInterface, installOwner });
3901
+ try {
3902
+ const tee = spawnSync("sudo", ["tee", SMB_CONF], { input: merged, encoding: "utf-8", stdio: ["pipe", "pipe", "pipe"], timeout: 10_000 });
3903
+ if (tee.status !== 0) {
3904
+ throw new Error(`sudo tee ${SMB_CONF} exited ${tee.status}: ${(tee.stderr ?? "").trim()}`);
3905
+ }
3906
+ const testparm = spawnSync("sudo", ["testparm", "-s", "--suppress-prompt"], { stdio: "pipe", encoding: "utf-8", timeout: 10_000 });
3907
+ if (testparm.status !== 0) {
3908
+ throw new Error(`testparm rejected merged smb.conf: ${(testparm.stderr ?? "").trim()}`);
3909
+ }
3910
+ // Grant passwordless sudo to the install-owner Unix user for the two
3911
+ // smbpasswd invocations the platform's set-pin route makes (add-user-
3912
+ // with-stdin and remove-user). Without this, the user systemd-unit-
3913
+ // spawned admin server cannot sync the SMB password when the operator
3914
+ // sets/rotates the PIN. Scoped tight: only these two literal arg-vectors
3915
+ // are permitted; every other smbpasswd flavour still prompts. Principal
3916
+ // and `-a -s <user>` / `-x <user>` arguments are the install owner, not
3917
+ // a literal `admin`, so the grant works on a Pi (owner=admin) and on a
3918
+ // laptop (owner=neo) without divergence. Task 534.
3919
+ const SUDOERS = "/etc/sudoers.d/maxy-samba";
3920
+ const sudoersBody = "# maxy-code Samba provisioning (smbpasswd sync from platform set-pin route).\n" +
3921
+ `${installOwner} ALL=(root) NOPASSWD: /usr/bin/smbpasswd -a -s ${installOwner}, /usr/bin/smbpasswd -x ${installOwner}\n`;
3922
+ const sudoersTee = spawnSync("sudo", ["tee", SUDOERS], { input: sudoersBody, encoding: "utf-8", stdio: ["pipe", "pipe", "pipe"], timeout: 5_000 });
3923
+ if (sudoersTee.status !== 0) {
3924
+ throw new Error(`sudo tee ${SUDOERS} exited ${sudoersTee.status}: ${(sudoersTee.stderr ?? "").trim()}`);
3925
+ }
3926
+ spawnSync("sudo", ["chmod", "0440", SUDOERS], { stdio: "pipe", timeout: 5_000 });
3927
+ const visudoCheck = spawnSync("sudo", ["visudo", "-c", "-f", SUDOERS], { stdio: "pipe", encoding: "utf-8", timeout: 5_000 });
3928
+ if (visudoCheck.status !== 0) {
3929
+ throw new Error(`visudo rejected ${SUDOERS}: ${(visudoCheck.stderr ?? "").trim()}`);
3930
+ }
3931
+ emitSambaMarker("conf", `ok ${bindPosture} owner=${installOwner}`);
3932
+ }
3933
+ catch (err) {
3934
+ const stderr = err instanceof Error ? err.message : String(err);
3935
+ emitSambaMarker("conf", `fail: ${stderr}`);
3936
+ throw err;
3937
+ }
3938
+ // Step 3 — smbpasswd for the install-owner Unix user. At install time the
3939
+ // plaintext PIN is not in any file on disk (users.json stores the SHA-256
3940
+ // hash only); the platform's set-pin route is responsible for syncing on
3941
+ // PIN set/rotate. Mark as deferred so the four-marker contract still fires
3942
+ // unbroken. Owner is recorded in the marker state so the install log shows
3943
+ // which Unix user the smbpasswd entry will target. Task 534.
3944
+ emitSambaMarker("user", `deferred reason=no-plaintext-pin-at-install owner=${installOwner} (set-pin route syncs)`);
3945
+ // Step 4 — enable + start smbd. nmbd (NetBIOS) is deliberately excluded —
3946
+ // nothing mounts the share by NetBIOS name and it is a public DDoS-reflection
3947
+ // vector (Task 755). The unit list is locked in samba-provision.ts.
3948
+ try {
3949
+ shell("systemctl", ["enable", "--now", ...SAMBA_ENABLE_UNITS], { sudo: true, timeout: 30_000 });
3950
+ emitSambaMarker("units", "ok");
3951
+ }
3952
+ catch (err) {
3953
+ const stderr = err instanceof Error ? err.message : String(err);
3954
+ emitSambaMarker("units", `fail: ${stderr}`);
3955
+ throw err;
3956
+ }
3957
+ }
3958
+ // ---------------------------------------------------------------------------
3959
+ // Main
3960
+ // ---------------------------------------------------------------------------
3961
+ // Route to uninstall if --uninstall flag is present
3962
+ const _args = process.argv.slice(2);
3963
+ if (_args.includes("--uninstall")) {
3964
+ const { runUninstall } = await import("./uninstall.js");
3965
+ const exportIdx = _args.indexOf("--export-data");
3966
+ const exportPath = exportIdx !== -1 ? _args[exportIdx + 1] : undefined;
3967
+ const skipConfirm = _args.includes("--yes");
3968
+ if (exportIdx !== -1 && !exportPath) {
3969
+ console.error("Setup failed: --export-data requires a path argument");
3970
+ console.error("--export-data requires a path argument.");
3971
+ process.exit(1);
3972
+ }
3973
+ await runUninstall({ exportPath, skipConfirm });
3974
+ process.exit(0);
3975
+ }
3976
+ // ---------------------------------------------------------------------------
3977
+ // Port — install-time flag, not a brand attribute.
3978
+ //
3979
+ // Priority: --port flag > .env override > existing service file > default 19200.
3980
+ // systemd applies EnvironmentFile=-~/.{brand}/.env AFTER Environment=PORT,
3981
+ // so .env is the final runtime truth and must be checked first on upgrade.
3982
+ //
3983
+ // this block also performs one-shot port-drift recovery against
3984
+ // maxy-edge.service's Environment=EDGE_PORT=. See port-resolution.ts for the
3985
+ // pure logic; unit tests live at __tests__/port-canonicalisation.test.mjs.
3986
+ // ---------------------------------------------------------------------------
3987
+ let portFlag;
3988
+ const portIdx = _args.indexOf("--port");
3989
+ if (portIdx !== -1) {
3990
+ const raw = _args[portIdx + 1];
3991
+ const parsed = raw ? parseInt(raw, 10) : NaN;
3992
+ if (isNaN(parsed) || parsed < 1024 || parsed > 65535) {
3993
+ console.error(`Setup failed: --port requires a numeric value between 1024 and 65535 (got: ${raw ?? "nothing"})`);
3994
+ console.error(`Error: --port requires a numeric value between 1024 and 65535 (got: ${raw ?? "nothing"}).`);
3995
+ process.exit(1);
3996
+ }
3997
+ portFlag = parsed;
3998
+ }
3999
+ const _portResolution = resolveInstallPortFromFs({
4000
+ portFlag,
4001
+ persistDir: resolve(process.env.HOME ?? "/root", BRAND.configDir),
4002
+ serviceDir: resolve(process.env.HOME ?? "/root", ".config/systemd/user"),
4003
+ brandServiceFileName: BRAND.serviceName,
4004
+ brandEdgeServiceFileName: `${BRAND.hostname}-edge.service`,
4005
+ });
4006
+ let PORT = _portResolution.port;
4007
+ let PORT_SOURCE = _portResolution.source;
4008
+ for (const line of _portResolution.driftLogs)
4009
+ console.log(line);
4010
+ // ---------------------------------------------------------------------------
4011
+ // Hostname — install-time flag, not solely a brand attribute.
4012
+ //
4013
+ // Priority: --hostname flag > OS detection (same-brand upgrade) > OS preservation
4014
+ // (another brand's service detected) > BRAND.hostname (fresh install).
4015
+ // When --hostname is provided, it is set unconditionally — no detection, no preservation.
4016
+ // ---------------------------------------------------------------------------
4017
+ let HOSTNAME_FLAG;
4018
+ const hostnameIdx = _args.indexOf("--hostname");
4019
+ if (hostnameIdx !== -1) {
4020
+ const raw = _args[hostnameIdx + 1];
4021
+ if (!raw || raw.startsWith("--")) {
4022
+ console.error("Setup failed: --hostname requires a value");
4023
+ console.error("Error: --hostname requires a value (e.g. --hostname muvin).");
4024
+ process.exit(1);
4025
+ }
4026
+ // RFC 1123: lowercase alphanumeric + hyphens, max 63 chars, no leading/trailing hyphen
4027
+ if (!/^[a-z0-9]([a-z0-9-]{0,61}[a-z0-9])?$/.test(raw)) {
4028
+ console.error(`Setup failed: --hostname value '${raw}' is invalid`);
4029
+ console.error(`Error: --hostname value '${raw}' is invalid. Must be lowercase letters, digits, and hyphens only (max 63 chars, no leading/trailing hyphen).`);
4030
+ process.exit(1);
4031
+ }
4032
+ HOSTNAME_FLAG = raw;
4033
+ }
4034
+ // ---------------------------------------------------------------------------
4035
+ // Founder-side tier-set flags (Task 240).
4036
+ //
4037
+ // `--tier <solo|family|pro>` stamps account.json.tier directly when the brand
4038
+ // is personal-mode (today's default for both maxy-code and realagent-code).
4039
+ // `--entitlement-base64 <b64>` decodes a signed payload and writes it to
4040
+ // ~/<BRAND.configDir>/entitlement.json when the brand is commercial-mode.
4041
+ // The verifier at session start consumes whichever path the brand is on.
4042
+ //
4043
+ // Mode-mismatch combinations reject loudly at parse time — operator gets a
4044
+ // redirect message pointing at the correct flag. The installer is the sole
4045
+ // doctrine-sanctioned device-mutation channel; the admin agent has no tier-
4046
+ // upgrade surface by design.
4047
+ // ---------------------------------------------------------------------------
4048
+ let TIER_FLAG;
4049
+ let ENTITLEMENT_PAYLOAD;
4050
+ const tierIdx = _args.indexOf("--tier");
4051
+ if (tierIdx !== -1) {
4052
+ try {
4053
+ TIER_FLAG = validateTierFlag(_args[tierIdx + 1], BRAND.commercialMode === true);
4054
+ }
4055
+ catch (err) {
4056
+ const msg = err instanceof Error ? err.message : String(err);
4057
+ console.error(`Setup failed: ${msg}`);
4058
+ console.error(`Error: ${msg}`);
4059
+ process.exit(1);
4060
+ }
4061
+ }
4062
+ const entitlementIdx = _args.indexOf("--entitlement-base64");
4063
+ if (entitlementIdx !== -1) {
4064
+ try {
4065
+ ENTITLEMENT_PAYLOAD = validateEntitlementBase64(_args[entitlementIdx + 1], BRAND.commercialMode === true);
4066
+ }
4067
+ catch (err) {
4068
+ const msg = err instanceof Error ? err.message : String(err);
4069
+ console.error(`Setup failed: ${msg}`);
4070
+ console.error(`Error: ${msg}`);
4071
+ process.exit(1);
4072
+ }
4073
+ }
4074
+ let DISPLAY_MODE = "virtual";
4075
+ let DISPLAY_MODE_SOURCE = "default";
4076
+ const displayIdx = _args.indexOf("--display");
4077
+ if (displayIdx !== -1) {
4078
+ const raw = _args[displayIdx + 1];
4079
+ if (!raw || raw.startsWith("--")) {
4080
+ console.error("Setup failed: --display requires a value");
4081
+ console.error("Error: --display requires a value: native or virtual.");
4082
+ process.exit(1);
4083
+ }
4084
+ if (raw !== "native" && raw !== "virtual") {
4085
+ console.error(`Setup failed: --display value '${raw}' is invalid`);
4086
+ console.error(`Error: --display value '${raw}' is invalid. Must be 'native' or 'virtual'.`);
4087
+ process.exit(1);
4088
+ }
4089
+ DISPLAY_MODE = raw;
4090
+ DISPLAY_MODE_SOURCE = "--display flag";
4091
+ }
4092
+ else {
4093
+ // Upgrade detection: preserve existing DISPLAY_MODE from .env
4094
+ const persistDir = resolve(process.env.HOME ?? "/root", BRAND.configDir);
4095
+ const envPath = join(persistDir, ".env");
4096
+ let preservedFromEnv = false;
4097
+ try {
4098
+ if (existsSync(envPath)) {
4099
+ const envContent = readFileSync(envPath, "utf-8");
4100
+ const envMatch = envContent.match(/^DISPLAY_MODE=(native|virtual)$/m);
4101
+ if (envMatch) {
4102
+ DISPLAY_MODE = envMatch[1];
4103
+ DISPLAY_MODE_SOURCE = ".env (preserved)";
4104
+ preservedFromEnv = true;
4105
+ }
4106
+ }
4107
+ }
4108
+ catch { /* non-critical */ }
4109
+ // Darwin has no VNC/X11 stack — `virtual` mode is Pi-only (tigervnc +
4110
+ // websockify + novnc, none of which exist on macOS). A preserved
4111
+ // DISPLAY_MODE=virtual is never operator intent on darwin — it is the
4112
+ // legacy default from installers before 0.1.127, when `virtual` was the
4113
+ // only initial value written. The guard fires whenever the resolved
4114
+ // value is not already `native`, covering both fresh installs and
4115
+ // upgrades that inherited the legacy default.
4116
+ if (process.platform === "darwin" && DISPLAY_MODE !== "native") {
4117
+ DISPLAY_MODE_SOURCE = preservedFromEnv
4118
+ ? "darwin-auto (override-legacy-virtual)"
4119
+ : "darwin-auto (no VNC stack)";
4120
+ DISPLAY_MODE = "native";
4121
+ }
4122
+ }
4123
+ // ---------------------------------------------------------------------------
4124
+ // Embedding model — install-time flag, not a brand attribute.
4125
+ //
4126
+ // Controls which Ollama embedding model is pulled and the dimension count used
4127
+ // for Neo4j vector indexes. Dimensions are fixed at schema-creation time; changing
4128
+ // them later requires dropping and recreating all vector indexes.
4129
+ //
4130
+ // Priority: --embed-model flag > .env (upgrade) > default nomic-embed-text.
4131
+ // --embed-dimensions is required for models not in the curated lookup table.
4132
+ // --embed-dimensions without --embed-model is rejected (dimensions are model-specific).
4133
+ // ---------------------------------------------------------------------------
4134
+ const EMBED_MODEL_DIMS = {
4135
+ "nomic-embed-text": 768,
4136
+ "nomic-embed-text-v1.5": 768,
4137
+ "mxbai-embed-large": 1024,
4138
+ "snowflake-arctic-embed:335m": 768,
4139
+ };
4140
+ const DEFAULT_EMBED_MODEL = "nomic-embed-text";
4141
+ const DEFAULT_EMBED_DIMS = 768;
4142
+ let EMBED_MODEL = DEFAULT_EMBED_MODEL;
4143
+ let EMBED_DIMS = DEFAULT_EMBED_DIMS;
4144
+ let EMBED_SOURCE = "default";
4145
+ const embedModelIdx = _args.indexOf("--embed-model");
4146
+ const embedDimsIdx = _args.indexOf("--embed-dimensions");
4147
+ if (embedDimsIdx !== -1 && embedModelIdx === -1) {
4148
+ console.error("Setup failed: --embed-dimensions requires --embed-model");
4149
+ console.error("Error: --embed-dimensions requires --embed-model (dimensions are model-specific).");
4150
+ process.exit(1);
4151
+ }
4152
+ if (embedModelIdx !== -1) {
4153
+ const raw = _args[embedModelIdx + 1];
4154
+ if (!raw || raw.startsWith("--")) {
4155
+ console.error("Setup failed: --embed-model requires a value");
4156
+ console.error("Error: --embed-model requires a value (e.g. --embed-model mxbai-embed-large).");
4157
+ process.exit(1);
4158
+ }
4159
+ EMBED_MODEL = raw;
4160
+ EMBED_SOURCE = "--embed-model flag";
4161
+ if (embedDimsIdx !== -1) {
4162
+ // Explicit dimensions override the lookup table
4163
+ const rawDims = _args[embedDimsIdx + 1];
4164
+ const parsed = rawDims ? parseInt(rawDims, 10) : NaN;
4165
+ if (isNaN(parsed) || parsed <= 0) {
4166
+ console.error(`Setup failed: --embed-dimensions requires a positive integer (got: ${rawDims ?? "nothing"})`);
4167
+ console.error(`Error: --embed-dimensions requires a positive integer (got: ${rawDims ?? "nothing"}).`);
4168
+ process.exit(1);
4169
+ }
4170
+ EMBED_DIMS = parsed;
4171
+ }
4172
+ else if (EMBED_MODEL in EMBED_MODEL_DIMS) {
4173
+ // Known model — resolve dimensions from lookup table
4174
+ EMBED_DIMS = EMBED_MODEL_DIMS[EMBED_MODEL];
4175
+ }
4176
+ else {
4177
+ // Unknown model without explicit dimensions — cannot proceed
4178
+ console.error(`Setup failed: unknown embedding model '${EMBED_MODEL}'`);
4179
+ console.error(`Error: Unknown embedding model '${EMBED_MODEL}'.`);
4180
+ console.error("Known models and their dimensions:");
4181
+ for (const [model, dims] of Object.entries(EMBED_MODEL_DIMS)) {
4182
+ console.error(` ${model} — ${dims} dimensions`);
4183
+ }
4184
+ console.error("\nFor a custom model, pass --embed-dimensions N explicitly:");
4185
+ console.error(` npx -y @rubytech/create-maxy --embed-model ${EMBED_MODEL} --embed-dimensions 512`);
4186
+ process.exit(1);
4187
+ }
4188
+ }
4189
+ else {
4190
+ // No --embed-model flag: check .env for upgrade preservation
4191
+ const persistDir = resolve(process.env.HOME ?? "/root", BRAND.configDir);
4192
+ const envPath = join(persistDir, ".env");
4193
+ try {
4194
+ if (existsSync(envPath)) {
4195
+ const envContent = readFileSync(envPath, "utf-8");
4196
+ const modelMatch = envContent.match(/^EMBED_MODEL=(.+)$/m);
4197
+ const dimsMatch = envContent.match(/^EMBED_DIMENSIONS=(\d+)$/m);
4198
+ if (modelMatch) {
4199
+ EMBED_MODEL = modelMatch[1];
4200
+ EMBED_SOURCE = ".env (preserved)";
4201
+ if (dimsMatch) {
4202
+ EMBED_DIMS = parseInt(dimsMatch[1], 10);
4203
+ }
4204
+ else if (EMBED_MODEL in EMBED_MODEL_DIMS) {
4205
+ EMBED_DIMS = EMBED_MODEL_DIMS[EMBED_MODEL];
4206
+ }
4207
+ // Unknown model without dims in .env: keep DEFAULT_EMBED_DIMS — the schema
4208
+ // was created with whatever dims were configured at original install time.
4209
+ }
4210
+ }
4211
+ }
4212
+ catch { /* non-critical */ }
4213
+ }
4214
+ // ---------------------------------------------------------------------------
4215
+ // Neo4j port — multi-brand data isolation.
4216
+ //
4217
+ // Default Maxy brand: 7687 (shared system Neo4j instance). Branded builds ship
4218
+ // a dedicated port in brand.json (e.g. Real Agent = 7688) so installing a
4219
+ // second brand on the same device gets its own database by default.
4220
+ //
4221
+ // Priority: --neo4j-port flag > .env NEO4J_URI (upgrade preserve) > BRAND.neo4jPort > 7687.
4222
+ // ---------------------------------------------------------------------------
4223
+ const DEFAULT_NEO4J_PORT = 7687;
4224
+ let NEO4J_PORT = BRAND.neo4jPort ?? DEFAULT_NEO4J_PORT;
4225
+ let NEO4J_PORT_SOURCE = BRAND.neo4jPort ? "brand.json" : "default";
4226
+ const neo4jPortIdx = _args.indexOf("--neo4j-port");
4227
+ if (neo4jPortIdx !== -1) {
4228
+ const raw = _args[neo4jPortIdx + 1];
4229
+ const parsed = raw ? parseInt(raw, 10) : NaN;
4230
+ if (isNaN(parsed) || parsed < 1024 || parsed > 65535) {
4231
+ console.error(`Setup failed: --neo4j-port requires a numeric value between 1024 and 65535 (got: ${raw ?? "nothing"})`);
4232
+ console.error(`Error: --neo4j-port requires a numeric value between 1024 and 65535 (got: ${raw ?? "nothing"}).`);
4233
+ process.exit(1);
4234
+ }
4235
+ NEO4J_PORT = parsed;
4236
+ NEO4J_PORT_SOURCE = "--neo4j-port flag";
4237
+ }
4238
+ else {
4239
+ // Upgrade detection: check .env for NEO4J_URI=bolt://localhost:{port}.
4240
+ // Preserves an existing install's port even if brand.json now says different.
4241
+ const persistDir = resolve(process.env.HOME ?? "/root", BRAND.configDir);
4242
+ const envPath = join(persistDir, ".env");
4243
+ try {
4244
+ if (existsSync(envPath)) {
4245
+ const envContent = readFileSync(envPath, "utf-8");
4246
+ const uriMatch = envContent.match(/^NEO4J_URI=bolt:\/\/localhost:(\d+)$/m);
4247
+ if (uriMatch) {
4248
+ const envPort = parseInt(uriMatch[1], 10);
4249
+ if (envPort >= 1024 && envPort <= 65535) {
4250
+ NEO4J_PORT = envPort;
4251
+ NEO4J_PORT_SOURCE = ".env (preserved)";
4252
+ }
4253
+ }
4254
+ }
4255
+ }
4256
+ catch { /* non-critical */ }
4257
+ }
4258
+ // Dedicated = port differs from the default shared instance
4259
+ const NEO4J_DEDICATED = NEO4J_PORT !== DEFAULT_NEO4J_PORT;
4260
+ // ---------------------------------------------------------------------------
4261
+ // removed the per-brand ttyd port — the admin terminal stack
4262
+ // (ttyd, tmux, xterm.js) was retired in favour of the action runner that
4263
+ // spawns transient `systemd-run --user` units per upgrade or setup-tunnel
4264
+ // invocation. No TCP listener on the device needs to be reserved for an
4265
+ // interactive-shell surface any more.
4266
+ const PKG_VERSION = JSON.parse(readFileSync(resolve(import.meta.dirname, "../package.json"), "utf-8")).version;
4267
+ // ---------------------------------------------------------------------------
4268
+ // pre-flight platform refusal.
4269
+ //
4270
+ // Runs BEFORE initLogging() (LOG_DIR creation), port resolution, and any
4271
+ // brew/scutil/hostnamectl probe. Only Linux + darwin are supported;
4272
+ // on darwin, macOS major must be ≥ 14 (the floor required by Tasks 838/839).
4273
+ // Older macOS partially succeeds, then breaks at the supervisor or brew-cellar
4274
+ // layer with cryptic errors — refusing loudly here is the contract.
4275
+ //
4276
+ // Platform-header line is emitted on every install start so operators can grep
4277
+ // `[create-maxy] platform=` to confirm pre-flight ran. On darwin the line also
4278
+ // carries `macos=<v>` (token) so the macOS-14 floor check is visible.
4279
+ // ---------------------------------------------------------------------------
4280
+ const PLATFORM = requireSupportedPlatform(process.platform);
4281
+ let MACOS_VERSION = null;
4282
+ if (PLATFORM === "darwin") {
4283
+ const swVers = spawnSync("sw_vers", [], { encoding: "utf-8", stdio: "pipe", timeout: 5_000 });
4284
+ const parsed = parseSwVers(swVers.stdout ?? "");
4285
+ if (!parsed) {
4286
+ const head = (swVers.stdout ?? "").split("\n").slice(0, 2).join(" | ");
4287
+ console.error(`[create-maxy] sw_vers stdout malformed: ${head}`);
4288
+ console.error(`[create-maxy] platform=darwin macos=<unknown> — refusing: macOS 14+ required`);
4289
+ process.exit(1);
4290
+ }
4291
+ MACOS_VERSION = parsed.version;
4292
+ if (!isSupportedMacosVersion(MACOS_VERSION)) {
4293
+ console.error(`[create-maxy] platform=darwin macos=${MACOS_VERSION} — refusing: macOS 14+ required`);
4294
+ process.exit(1);
4295
+ }
4296
+ }
4297
+ // Platform-header — first log line. Operators grep `[create-maxy] platform=`
4298
+ // to confirm pre-flight ran. The /* macos=<v> */ token is the marker;
4299
+ // keep it on this same line so 3-way merges with parallel installer edits stay
4300
+ // mechanical (no rewrap, no split into two log lines).
4301
+ const PLATFORM_HEADER = `[create-maxy] platform=${PLATFORM} arch=${process.arch}` +
4302
+ (MACOS_VERSION ? ` macos=${MACOS_VERSION}` : ``) +
4303
+ ` version=${PKG_VERSION}`;
4304
+ // emit platform header and the resolved log/persist paths to
4305
+ // stdout BEFORE the log file is opened. If initLogging's mkdir or first
4306
+ // appendFileSync throws, the operator still sees brand/version/arch and the
4307
+ // exact path the log file SHOULD live at, instead of a silent exit between
4308
+ // the LOG_DIR mkdir and the first log write.
4309
+ console.log(PLATFORM_HEADER);
4310
+ console.log(`[create-maxy] log=${LOG_FILE} persist=${PERSIST_DIR}`);
4311
+ initLogging();
4312
+ console.log("================================================================");
4313
+ console.log(` ${BRAND.productName} — ${BRAND.tagline}. (${BRAND.hostname} v${PKG_VERSION})`);
4314
+ console.log("================================================================");
4315
+ console.log(` Install log: ${LOG_FILE}`);
4316
+ console.log(` Port: ${PORT} (${PORT_SOURCE})`);
4317
+ if (HOSTNAME_FLAG)
4318
+ console.log(` Hostname: ${HOSTNAME_FLAG} (from --hostname flag)`);
4319
+ console.log(` Display: ${DISPLAY_MODE} (${DISPLAY_MODE_SOURCE})`);
4320
+ console.log(` Embed model: ${EMBED_MODEL} (${EMBED_DIMS} dims, ${EMBED_SOURCE})`);
4321
+ console.log(` Neo4j: ${NEO4J_DEDICATED ? "dedicated" : "shared"} on bolt://localhost:${NEO4J_PORT} (${NEO4J_PORT_SOURCE})`);
4322
+ console.log("");
4323
+ logDiagnostics("pre-flight");
4324
+ logFile(` Neo4j instance: ${NEO4J_DEDICATED ? "dedicated" : "shared"} on bolt://localhost:${NEO4J_PORT}`);
4325
+ try {
4326
+ // Disable any pre-existing hardware-watchdog drop-in BEFORE any heavy step.
4327
+ // configureHardwareWatchdog() re-arms it at install end. Without this, the
4328
+ // 20s deadline armed from boot reboots the box mid-install on every install
4329
+ // after the first.
4330
+ disableHardwareWatchdogForInstall();
4331
+ installSystemDeps();
4332
+ installNodejs();
4333
+ installClaudeCode();
4334
+ installNeo4j();
4335
+ setupDedicatedNeo4j();
4336
+ installOllama(EMBED_MODEL);
4337
+ installUv();
4338
+ installCloudflared();
4339
+ installWhisperCpp();
4340
+ deployPayload(); // Must happen before ensureNeo4jPassword — restores config backup
4341
+ // write the resolved Chromium absolute path into the deployed
4342
+ // platform/config/ so vnc.sh and writeChromiumWrapper read the same
4343
+ // value. Must run after deployPayload (config dir is
4344
+ // a payload subdirectory). Linux-only; no-op on darwin/non-linux.
4345
+ writeChromiumBinaryPathFile();
4346
+ // scrub plaintext neo4j passwords from any pre-fix install-*.log.
4347
+ // Idempotent — re-running on already-redacted logs is a no-op. Runs after
4348
+ // payload deploy so the bundled redact-install-logs.sh is on disk.
4349
+ redactInstallLogs();
4350
+ ensureNeo4jPassword(); // Now config/.neo4j-password is available if it existed before
4351
+ provisionRemoteSessionSecret(); // shared HMAC key readable by maxy-edge + maxy-ui
4352
+ buildPlatform();
4353
+ registerLocalAndExternalPlugins(); // install-time plugin registration
4354
+ setupVncViewer();
4355
+ setupAccount();
4356
+ if (ENTITLEMENT_PAYLOAD) {
4357
+ writeEntitlementFromFlag(ENTITLEMENT_PAYLOAD);
4358
+ }
4359
+ installService();
4360
+ // Samba on the LAN. Runs after the brand systemd unit is up so
4361
+ // SMB provisioning never blocks the admin server starting; loud-fail per
4362
+ // step. The smbpasswd `user` step is deferred at install time and synced
4363
+ // by the platform's /set-pin route when the operator sets a PIN.
4364
+ provisionSamba();
4365
+ // Task 848 — freeze the platform source trees as the final install action, after
4366
+ // every install-time write under platform/ (buildPlatform's npm install →
4367
+ // platform/node_modules, the service builds under platform/services/*/dist, and
4368
+ // plugin registration). server/, platform/, premium-plugins/ become immutable to
4369
+ // the agent's user; platform/config/ is excluded by protectCommands (it is
4370
+ // runtime-writable). Load-bearing, so the outcome is verified positively: `chattr
4371
+ // -R` exits nonzero on the benign symlinks/special files an npm tree always
4372
+ // contains, so its aggregate exit code is not a reliable signal — instead
4373
+ // re-read each target's own immutable bit with `lsattr -d`. A freeze command
4374
+ // (+i) succeeded iff the target is now immutable; the config exclusion (-i)
4375
+ // succeeded iff it is now mutable. A failed protect does not abort the install;
4376
+ // the drift detector remains the backstop. Linux-only (emits nothing elsewhere).
4377
+ const guardPlatformProtect = detectPlatform(process.platform);
4378
+ for (const c of protectCommands(INSTALL_DIR, guardPlatformProtect)) {
4379
+ const target = c.args[c.args.length - 1];
4380
+ const freezing = c.args.includes("+i");
4381
+ const op = freezing ? "protect" : "protect-exclude";
4382
+ logFile(`> sudo ${c.command} ${c.args.join(" ")}`);
4383
+ spawnSync("sudo", [c.command, ...c.args], { stdio: "pipe", timeout: 30_000 });
4384
+ const probe = spawnSync("lsattr", ["-d", target], { stdio: "pipe", timeout: 10_000 });
4385
+ const immutable = probe.status === 0 && lsattrShowsImmutable(probe.stdout?.toString() ?? "");
4386
+ const ok = freezing ? immutable : !immutable;
4387
+ console.log(` [agent-guard] op=${ok ? op : `${op}-failed`} target=${target}`);
4388
+ }
4389
+ // Arm the hardware watchdog as the final install action — after the heavy
4390
+ // build/swap window, so a tight watchdog can never reboot the box mid-install
4391
+ // (the reboot-loop this defends against). A partial/failed install exits
4392
+ // before this point and never writes the drop-in.
4393
+ configureHardwareWatchdog();
4394
+ console.log("");
4395
+ console.log("================================================================");
4396
+ console.log("");
4397
+ if (isLinux()) {
4398
+ console.log(` Same network (Pi / LAN): http://${DEVICE_HOSTNAME}.local:${PORT}`);
4399
+ console.log("");
4400
+ console.log(` Remote access (Hetzner / cloud) — on your local machine run:`);
4401
+ console.log(` ssh -L ${PORT}:localhost:${PORT} -L ${BRAND.websockifyPort}:localhost:${BRAND.websockifyPort} admin@<server-ipv4>`);
4402
+ console.log(` Then open:`);
4403
+ console.log(` Dashboard: http://localhost:${PORT}`);
4404
+ console.log(` VNC browser (Claude OAuth + Cloudflare): http://localhost:${BRAND.websockifyPort}/vnc.html`);
4405
+ }
4406
+ else {
4407
+ console.log(` Open in your browser: http://${DEVICE_HOSTNAME}.local:${PORT}`);
4408
+ }
4409
+ console.log("");
4410
+ console.log("================================================================");
4411
+ }
4412
+ catch (err) {
4413
+ console.error("");
4414
+ console.error(`Setup failed: ${err instanceof Error ? err.message : String(err)}`);
4415
+ console.error(` Full log: ${LOG_FILE}`);
4416
+ logDiagnostics("post-failure");
4417
+ process.exit(1);
4418
+ }