@neuralis/brain-core 0.3.2 → 0.4.1

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 (388) hide show
  1. package/README.md +80 -1410
  2. package/app/README.md +1 -1
  3. package/app/cards/FilesystemCardShell.tsx +42 -4
  4. package/app/cards/FilesystemChangeCard.tsx +34 -11
  5. package/app/cards/README.md +6 -5
  6. package/app/cards/diffUtils.ts +99 -1
  7. package/app/filesystem/FilesystemHost.tsx +17 -2
  8. package/app/filesystem/api/README.md +3 -3
  9. package/app/filesystem/api/index.ts +35 -11
  10. package/app/filesystem/api/projectPackages.ts +13 -102
  11. package/app/filesystem/domain/types.ts +30 -10
  12. package/app/filesystem/hooks/README.md +3 -3
  13. package/app/filesystem/hooks/useDiscoverableSources.ts +19 -30
  14. package/app/filesystem/hooks/useFilesystemSSE.ts +1 -1
  15. package/app/filesystem/host/README.md +5 -3
  16. package/app/filesystem/host/buildFilesystemHostValue.ts +19 -0
  17. package/app/filesystem/host/installFilesystemHostComponents.tsx +1 -1
  18. package/app/filesystem/lib/sourceKindForm.ts +118 -39
  19. package/app/filesystem/lib/treeVisualState.tsx +98 -4
  20. package/app/filesystem/store/README.md +1 -0
  21. package/app/filesystem/store/filesystemStore.ts +86 -5
  22. package/app/filesystem/store/gitSlice.ts +5 -0
  23. package/app/filesystem/store/helpers.ts +17 -0
  24. package/app/filesystem/store/listSlice.ts +8 -0
  25. package/app/filesystem/ui/CodeEditor.tsx +18 -3
  26. package/app/filesystem/ui/FileEditor.tsx +15 -10
  27. package/app/filesystem/ui/FileTree.tsx +41 -16
  28. package/app/filesystem/ui/FolderPicker.tsx +251 -0
  29. package/app/filesystem/ui/GitControlPanel.tsx +5 -0
  30. package/app/filesystem/ui/PackagesPanel.tsx +52 -374
  31. package/app/filesystem/ui/PolicyEditor.tsx +109 -24
  32. package/app/filesystem/ui/README.md +17 -11
  33. package/app/filesystem/ui/RawMediaPreview.tsx +58 -0
  34. package/app/filesystem/ui/SourceBranchHeader.tsx +4 -4
  35. package/app/filesystem/ui/SourcesPanel.tsx +420 -360
  36. package/app/filesystem/ui/Toolbar.tsx +1 -2
  37. package/app/shared/filesystem.png +0 -0
  38. package/dist/app/host.js +53 -48
  39. package/dist/scripts/sourceRootPairV1.d.ts +47 -0
  40. package/dist/scripts/sourceRootPairV1.d.ts.map +1 -0
  41. package/dist/scripts/sourceRootPairV1.js +147 -0
  42. package/dist/scripts/sourceRootPairV1.js.map +1 -0
  43. package/dist/scripts/sourceToFolderV1.d.ts +56 -0
  44. package/dist/scripts/sourceToFolderV1.d.ts.map +1 -0
  45. package/dist/scripts/sourceToFolderV1.js +152 -0
  46. package/dist/scripts/sourceToFolderV1.js.map +1 -0
  47. package/dist/scripts/sourceToHostV1.d.ts +56 -0
  48. package/dist/scripts/sourceToHostV1.d.ts.map +1 -0
  49. package/dist/scripts/sourceToHostV1.js +132 -0
  50. package/dist/scripts/sourceToHostV1.js.map +1 -0
  51. package/dist/src/config/env.d.ts +8 -0
  52. package/dist/src/config/env.d.ts.map +1 -1
  53. package/dist/src/config/env.js +17 -6
  54. package/dist/src/config/env.js.map +1 -1
  55. package/dist/src/connectors/AppSourceConfigStore.d.ts +17 -3
  56. package/dist/src/connectors/AppSourceConfigStore.d.ts.map +1 -1
  57. package/dist/src/connectors/AppSourceConfigStore.js +46 -6
  58. package/dist/src/connectors/AppSourceConfigStore.js.map +1 -1
  59. package/dist/src/connectors/HostConnector.d.ts +201 -0
  60. package/dist/src/connectors/HostConnector.d.ts.map +1 -0
  61. package/dist/src/connectors/HostConnector.js +903 -0
  62. package/dist/src/connectors/HostConnector.js.map +1 -0
  63. package/dist/src/connectors/inProcessTransport.d.ts +131 -0
  64. package/dist/src/connectors/inProcessTransport.d.ts.map +1 -0
  65. package/dist/src/connectors/inProcessTransport.js +447 -0
  66. package/dist/src/connectors/inProcessTransport.js.map +1 -0
  67. package/dist/src/domain/BrainError.d.ts +14 -0
  68. package/dist/src/domain/BrainError.d.ts.map +1 -1
  69. package/dist/src/domain/BrainError.js +21 -0
  70. package/dist/src/domain/BrainError.js.map +1 -1
  71. package/dist/src/domain/access/callerPermissions.d.ts +29 -0
  72. package/dist/src/domain/access/callerPermissions.d.ts.map +1 -1
  73. package/dist/src/domain/access/callerPermissions.js +85 -5
  74. package/dist/src/domain/access/callerPermissions.js.map +1 -1
  75. package/dist/src/domain/access/nativeLocalFence.d.ts +65 -0
  76. package/dist/src/domain/access/nativeLocalFence.d.ts.map +1 -0
  77. package/dist/src/domain/access/nativeLocalFence.js +171 -0
  78. package/dist/src/domain/access/nativeLocalFence.js.map +1 -0
  79. package/dist/src/domain/access/uriPermission.js +3 -3
  80. package/dist/src/domain/access/uriPermission.js.map +1 -1
  81. package/dist/src/domain/byteRange.d.ts +15 -0
  82. package/dist/src/domain/byteRange.d.ts.map +1 -0
  83. package/dist/src/domain/byteRange.js +30 -0
  84. package/dist/src/domain/byteRange.js.map +1 -0
  85. package/dist/src/domain/defaultPermissions.d.ts.map +1 -1
  86. package/dist/src/domain/defaultPermissions.js +29 -0
  87. package/dist/src/domain/defaultPermissions.js.map +1 -1
  88. package/dist/src/domain/mime.d.ts +8 -16
  89. package/dist/src/domain/mime.d.ts.map +1 -1
  90. package/dist/src/domain/mime.js +10 -99
  91. package/dist/src/domain/mime.js.map +1 -1
  92. package/dist/src/domain/paths.d.ts.map +1 -1
  93. package/dist/src/domain/paths.js +5 -3
  94. package/dist/src/domain/paths.js.map +1 -1
  95. package/dist/src/domain/sourceConfig.d.ts +52 -19
  96. package/dist/src/domain/sourceConfig.d.ts.map +1 -1
  97. package/dist/src/domain/sourceConfig.js +103 -19
  98. package/dist/src/domain/sourceConfig.js.map +1 -1
  99. package/dist/src/domain/sourcePackages.d.ts +8 -8
  100. package/dist/src/domain/sourcePackages.d.ts.map +1 -1
  101. package/dist/src/domain/sourceRootPair.d.ts +88 -0
  102. package/dist/src/domain/sourceRootPair.d.ts.map +1 -0
  103. package/dist/src/domain/sourceRootPair.js +108 -0
  104. package/dist/src/domain/sourceRootPair.js.map +1 -0
  105. package/dist/src/domain/syncTypes.d.ts +8 -1
  106. package/dist/src/domain/syncTypes.d.ts.map +1 -1
  107. package/dist/src/domain/syncTypes.js +1 -0
  108. package/dist/src/domain/syncTypes.js.map +1 -1
  109. package/dist/src/domain/types.d.ts +29 -1
  110. package/dist/src/domain/types.d.ts.map +1 -1
  111. package/dist/src/domain/uri.d.ts.map +1 -1
  112. package/dist/src/domain/uri.js +3 -2
  113. package/dist/src/domain/uri.js.map +1 -1
  114. package/dist/src/embeddings/clients/GeminiEmbedder.d.ts.map +1 -1
  115. package/dist/src/embeddings/clients/GeminiEmbedder.js +2 -5
  116. package/dist/src/embeddings/clients/GeminiEmbedder.js.map +1 -1
  117. package/dist/src/embeddings/clients/OpenAIEmbedder.d.ts.map +1 -1
  118. package/dist/src/embeddings/clients/OpenAIEmbedder.js +2 -3
  119. package/dist/src/embeddings/clients/OpenAIEmbedder.js.map +1 -1
  120. package/dist/src/embeddings/clients/QwenEmbedder.d.ts +2 -0
  121. package/dist/src/embeddings/clients/QwenEmbedder.d.ts.map +1 -1
  122. package/dist/src/embeddings/clients/QwenEmbedder.js +10 -2
  123. package/dist/src/embeddings/clients/QwenEmbedder.js.map +1 -1
  124. package/dist/src/embeddings/clients/VoyageEmbedder.d.ts +2 -0
  125. package/dist/src/embeddings/clients/VoyageEmbedder.d.ts.map +1 -1
  126. package/dist/src/embeddings/clients/VoyageEmbedder.js +8 -1
  127. package/dist/src/embeddings/clients/VoyageEmbedder.js.map +1 -1
  128. package/dist/src/embeddings/factory.d.ts +5 -3
  129. package/dist/src/embeddings/factory.d.ts.map +1 -1
  130. package/dist/src/embeddings/factory.js +7 -3
  131. package/dist/src/embeddings/factory.js.map +1 -1
  132. package/dist/src/embeddings/models.d.ts +2 -3
  133. package/dist/src/embeddings/models.d.ts.map +1 -1
  134. package/dist/src/embeddings/models.js +1 -2
  135. package/dist/src/embeddings/models.js.map +1 -1
  136. package/dist/src/embeddings/retry.js +1 -1
  137. package/dist/src/embeddings/retry.js.map +1 -1
  138. package/dist/src/embeddings/types.d.ts +6 -0
  139. package/dist/src/embeddings/types.d.ts.map +1 -1
  140. package/dist/src/embeddings/types.js +11 -0
  141. package/dist/src/embeddings/types.js.map +1 -1
  142. package/dist/src/git/GitRunner.d.ts +110 -30
  143. package/dist/src/git/GitRunner.d.ts.map +1 -1
  144. package/dist/src/git/GitRunner.js +511 -199
  145. package/dist/src/git/GitRunner.js.map +1 -1
  146. package/dist/src/git/GitWatchRegistry.d.ts +41 -35
  147. package/dist/src/git/GitWatchRegistry.d.ts.map +1 -1
  148. package/dist/src/git/GitWatchRegistry.js +61 -79
  149. package/dist/src/git/GitWatchRegistry.js.map +1 -1
  150. package/dist/src/git/gitPlace.d.ts +61 -0
  151. package/dist/src/git/gitPlace.d.ts.map +1 -0
  152. package/dist/src/git/gitPlace.js +74 -0
  153. package/dist/src/git/gitPlace.js.map +1 -0
  154. package/dist/src/git/sourceGitControl.d.ts +31 -19
  155. package/dist/src/git/sourceGitControl.d.ts.map +1 -1
  156. package/dist/src/git/sourceGitControl.js +208 -92
  157. package/dist/src/git/sourceGitControl.js.map +1 -1
  158. package/dist/src/git/sourceGitStatus.js +1 -1
  159. package/dist/src/git/sourceGitStatus.js.map +1 -1
  160. package/dist/src/git/untrackedStats.js +1 -1
  161. package/dist/src/git/untrackedStats.js.map +1 -1
  162. package/dist/src/index.d.ts +2 -1
  163. package/dist/src/index.d.ts.map +1 -1
  164. package/dist/src/index.js +2 -1
  165. package/dist/src/index.js.map +1 -1
  166. package/dist/src/lifecycle.d.ts +12 -16
  167. package/dist/src/lifecycle.d.ts.map +1 -1
  168. package/dist/src/lifecycle.js +2 -1
  169. package/dist/src/lifecycle.js.map +1 -1
  170. package/dist/src/routes/approve.d.ts.map +1 -1
  171. package/dist/src/routes/approve.js +3 -3
  172. package/dist/src/routes/approve.js.map +1 -1
  173. package/dist/src/routes/git.d.ts.map +1 -1
  174. package/dist/src/routes/git.js +183 -54
  175. package/dist/src/routes/git.js.map +1 -1
  176. package/dist/src/routes/health.d.ts.map +1 -1
  177. package/dist/src/routes/health.js +8 -5
  178. package/dist/src/routes/health.js.map +1 -1
  179. package/dist/src/routes/helpers/uriGuard.d.ts +1 -1
  180. package/dist/src/routes/helpers/uriGuard.d.ts.map +1 -1
  181. package/dist/src/routes/helpers/uriGuard.js +3 -2
  182. package/dist/src/routes/helpers/uriGuard.js.map +1 -1
  183. package/dist/src/routes/helpers.d.ts +20 -4
  184. package/dist/src/routes/helpers.d.ts.map +1 -1
  185. package/dist/src/routes/helpers.js +38 -5
  186. package/dist/src/routes/helpers.js.map +1 -1
  187. package/dist/src/routes/list.d.ts.map +1 -1
  188. package/dist/src/routes/list.js +5 -6
  189. package/dist/src/routes/list.js.map +1 -1
  190. package/dist/src/routes/pending.d.ts.map +1 -1
  191. package/dist/src/routes/pending.js +5 -5
  192. package/dist/src/routes/pending.js.map +1 -1
  193. package/dist/src/routes/policies.d.ts +6 -4
  194. package/dist/src/routes/policies.d.ts.map +1 -1
  195. package/dist/src/routes/policies.js +22 -16
  196. package/dist/src/routes/policies.js.map +1 -1
  197. package/dist/src/routes/raw.d.ts.map +1 -1
  198. package/dist/src/routes/raw.js +68 -14
  199. package/dist/src/routes/raw.js.map +1 -1
  200. package/dist/src/routes/read.d.ts.map +1 -1
  201. package/dist/src/routes/read.js +3 -3
  202. package/dist/src/routes/read.js.map +1 -1
  203. package/dist/src/routes/search.d.ts.map +1 -1
  204. package/dist/src/routes/search.js +3 -3
  205. package/dist/src/routes/search.js.map +1 -1
  206. package/dist/src/routes/sources.d.ts +60 -18
  207. package/dist/src/routes/sources.d.ts.map +1 -1
  208. package/dist/src/routes/sources.js +420 -308
  209. package/dist/src/routes/sources.js.map +1 -1
  210. package/dist/src/routes/upload.d.ts.map +1 -1
  211. package/dist/src/routes/upload.js +3 -3
  212. package/dist/src/routes/upload.js.map +1 -1
  213. package/dist/src/services/BridgeService.d.ts +15 -35
  214. package/dist/src/services/BridgeService.d.ts.map +1 -1
  215. package/dist/src/services/BridgeService.js +30 -88
  216. package/dist/src/services/BridgeService.js.map +1 -1
  217. package/dist/src/services/FilesystemService.d.ts +3 -2
  218. package/dist/src/services/FilesystemService.d.ts.map +1 -1
  219. package/dist/src/services/FilesystemService.js +116 -32
  220. package/dist/src/services/FilesystemService.js.map +1 -1
  221. package/dist/src/services/FilesystemUiService.d.ts +4 -1
  222. package/dist/src/services/FilesystemUiService.d.ts.map +1 -1
  223. package/dist/src/services/FilesystemUiService.js +71 -27
  224. package/dist/src/services/FilesystemUiService.js.map +1 -1
  225. package/dist/src/services/SyncScheduler.d.ts +12 -4
  226. package/dist/src/services/SyncScheduler.d.ts.map +1 -1
  227. package/dist/src/services/SyncScheduler.js +45 -10
  228. package/dist/src/services/SyncScheduler.js.map +1 -1
  229. package/dist/src/services/baselineRepair.d.ts +13 -3
  230. package/dist/src/services/baselineRepair.d.ts.map +1 -1
  231. package/dist/src/services/baselineRepair.js +13 -3
  232. package/dist/src/services/baselineRepair.js.map +1 -1
  233. package/dist/src/services/declaredSources.d.ts +125 -42
  234. package/dist/src/services/declaredSources.d.ts.map +1 -1
  235. package/dist/src/services/declaredSources.js +117 -45
  236. package/dist/src/services/declaredSources.js.map +1 -1
  237. package/dist/src/store/dataFormats.d.ts +17 -2
  238. package/dist/src/store/dataFormats.d.ts.map +1 -1
  239. package/dist/src/store/dataFormats.js +18 -3
  240. package/dist/src/store/dataFormats.js.map +1 -1
  241. package/dist/src/sync/DeltaSyncRunner.d.ts.map +1 -1
  242. package/dist/src/sync/DeltaSyncRunner.js +144 -4
  243. package/dist/src/sync/DeltaSyncRunner.js.map +1 -1
  244. package/dist/src/sync/SyncJobQueue.d.ts +14 -2
  245. package/dist/src/sync/SyncJobQueue.d.ts.map +1 -1
  246. package/dist/src/sync/SyncJobQueue.js +56 -10
  247. package/dist/src/sync/SyncJobQueue.js.map +1 -1
  248. package/dist/src/sync/SyncWatchService.d.ts +21 -4
  249. package/dist/src/sync/SyncWatchService.d.ts.map +1 -1
  250. package/dist/src/sync/SyncWatchService.js +115 -10
  251. package/dist/src/sync/SyncWatchService.js.map +1 -1
  252. package/dist/src/sync/categoryInference.d.ts +1 -1
  253. package/dist/src/sync/categoryInference.js +1 -1
  254. package/dist/src/tools/execCtx.d.ts +6 -0
  255. package/dist/src/tools/execCtx.d.ts.map +1 -1
  256. package/dist/src/tools/execCtx.js +11 -0
  257. package/dist/src/tools/execCtx.js.map +1 -1
  258. package/dist/src/tools/fs_list.js +2 -2
  259. package/dist/src/tools/fs_list.js.map +1 -1
  260. package/dist/src/tools/fs_read.js +2 -2
  261. package/dist/src/tools/fs_read.js.map +1 -1
  262. package/dist/src/tools/fs_search.js +2 -2
  263. package/dist/src/tools/fs_search.js.map +1 -1
  264. package/dist/src/tools/fs_write.js +2 -2
  265. package/dist/src/tools/fs_write.js.map +1 -1
  266. package/dist/src/usecases/admitSourceRoot.d.ts +65 -0
  267. package/dist/src/usecases/admitSourceRoot.d.ts.map +1 -0
  268. package/dist/src/usecases/admitSourceRoot.js +85 -0
  269. package/dist/src/usecases/admitSourceRoot.js.map +1 -0
  270. package/dist/src/usecases/browseSourceFolders.d.ts +85 -0
  271. package/dist/src/usecases/browseSourceFolders.d.ts.map +1 -0
  272. package/dist/src/usecases/browseSourceFolders.js +210 -0
  273. package/dist/src/usecases/browseSourceFolders.js.map +1 -0
  274. package/dist/src/usecases/createDeclaredSources.d.ts +13 -2
  275. package/dist/src/usecases/createDeclaredSources.d.ts.map +1 -1
  276. package/dist/src/usecases/createDeclaredSources.js +39 -0
  277. package/dist/src/usecases/createDeclaredSources.js.map +1 -1
  278. package/dist/src/usecases/deprovisionProject.d.ts +4 -5
  279. package/dist/src/usecases/deprovisionProject.d.ts.map +1 -1
  280. package/dist/src/usecases/deprovisionProject.js +3 -8
  281. package/dist/src/usecases/deprovisionProject.js.map +1 -1
  282. package/dist/src/usecases/list.d.ts.map +1 -1
  283. package/dist/src/usecases/list.js +83 -26
  284. package/dist/src/usecases/list.js.map +1 -1
  285. package/dist/src/usecases/listAttachableDevices.d.ts +13 -0
  286. package/dist/src/usecases/listAttachableDevices.d.ts.map +1 -0
  287. package/dist/src/usecases/listAttachableDevices.js +10 -0
  288. package/dist/src/usecases/listAttachableDevices.js.map +1 -0
  289. package/dist/src/usecases/listSourcePackages.d.ts.map +1 -1
  290. package/dist/src/usecases/listSourcePackages.js +95 -79
  291. package/dist/src/usecases/listSourcePackages.js.map +1 -1
  292. package/dist/src/usecases/purgeExcludedPoints.d.ts.map +1 -1
  293. package/dist/src/usecases/purgeExcludedPoints.js +3 -2
  294. package/dist/src/usecases/purgeExcludedPoints.js.map +1 -1
  295. package/dist/src/usecases/readFiles.d.ts.map +1 -1
  296. package/dist/src/usecases/readFiles.js +17 -1
  297. package/dist/src/usecases/readFiles.js.map +1 -1
  298. package/dist/src/usecases/reconcileSourcePackageRoots.d.ts +1 -1
  299. package/dist/src/usecases/reconcileSourcePackageRoots.d.ts.map +1 -1
  300. package/dist/src/usecases/reconcileSourcePackageRoots.js +2 -1
  301. package/dist/src/usecases/reconcileSourcePackageRoots.js.map +1 -1
  302. package/dist/src/usecases/revokePrincipal.d.ts +7 -5
  303. package/dist/src/usecases/revokePrincipal.d.ts.map +1 -1
  304. package/dist/src/usecases/revokePrincipal.js +29 -7
  305. package/dist/src/usecases/revokePrincipal.js.map +1 -1
  306. package/dist/src/usecases/scheduleSourceSync.d.ts +7 -0
  307. package/dist/src/usecases/scheduleSourceSync.d.ts.map +1 -1
  308. package/dist/src/usecases/scheduleSourceSync.js +6 -5
  309. package/dist/src/usecases/scheduleSourceSync.js.map +1 -1
  310. package/dist/src/usecases/searchFiles.d.ts.map +1 -1
  311. package/dist/src/usecases/searchFiles.js +13 -3
  312. package/dist/src/usecases/searchFiles.js.map +1 -1
  313. package/dist/src/usecases/sourcePackageInventory.d.ts +10 -2
  314. package/dist/src/usecases/sourcePackageInventory.d.ts.map +1 -1
  315. package/dist/src/usecases/sourcePackageInventory.js +24 -7
  316. package/dist/src/usecases/sourcePackageInventory.js.map +1 -1
  317. package/dist/src/usecases/triggerSourceSync.d.ts +46 -0
  318. package/dist/src/usecases/triggerSourceSync.d.ts.map +1 -0
  319. package/dist/src/usecases/triggerSourceSync.js +75 -0
  320. package/dist/src/usecases/triggerSourceSync.js.map +1 -0
  321. package/dist/src/usecases/uploadBinary.d.ts +2 -1
  322. package/dist/src/usecases/uploadBinary.d.ts.map +1 -1
  323. package/dist/src/usecases/uploadBinary.js +2 -2
  324. package/dist/src/usecases/uploadBinary.js.map +1 -1
  325. package/dist/src/usecases/vector/endpointGuard.d.ts +1 -1
  326. package/dist/src/usecases/vector/endpointGuard.js +1 -1
  327. package/dist/src/usecases/vectorActivityWatch.d.ts +20 -13
  328. package/dist/src/usecases/vectorActivityWatch.d.ts.map +1 -1
  329. package/dist/src/usecases/vectorActivityWatch.js +61 -36
  330. package/dist/src/usecases/vectorActivityWatch.js.map +1 -1
  331. package/dist/src/usecases/vectorMaintenance.d.ts.map +1 -1
  332. package/dist/src/usecases/vectorMaintenance.js +16 -1
  333. package/dist/src/usecases/vectorMaintenance.js.map +1 -1
  334. package/dist/src/usecases/write/index.d.ts.map +1 -1
  335. package/dist/src/usecases/write/index.js +17 -2
  336. package/dist/src/usecases/write/index.js.map +1 -1
  337. package/dist/src/usecases/write/occupancy.d.ts +5 -1
  338. package/dist/src/usecases/write/occupancy.d.ts.map +1 -1
  339. package/dist/src/usecases/write/occupancy.js +13 -4
  340. package/dist/src/usecases/write/occupancy.js.map +1 -1
  341. package/dist/src/usecases/write/structure.d.ts.map +1 -1
  342. package/dist/src/usecases/write/structure.js +20 -5
  343. package/dist/src/usecases/write/structure.js.map +1 -1
  344. package/dist/src/vector/FilesystemVectorIndex.d.ts +72 -2
  345. package/dist/src/vector/FilesystemVectorIndex.d.ts.map +1 -1
  346. package/dist/src/vector/FilesystemVectorIndex.js +211 -27
  347. package/dist/src/vector/FilesystemVectorIndex.js.map +1 -1
  348. package/dist/src/vector/InMemoryVectorIndex.d.ts.map +1 -1
  349. package/dist/src/vector/InMemoryVectorIndex.js +55 -7
  350. package/dist/src/vector/InMemoryVectorIndex.js.map +1 -1
  351. package/dist/src/vector/qdrantClient.d.ts +18 -1
  352. package/dist/src/vector/qdrantClient.d.ts.map +1 -1
  353. package/dist/src/vector/qdrantClient.js +48 -6
  354. package/dist/src/vector/qdrantClient.js.map +1 -1
  355. package/dist/src/wiring.d.ts +10 -12
  356. package/dist/src/wiring.d.ts.map +1 -1
  357. package/dist/src/wiring.js +101 -61
  358. package/dist/src/wiring.js.map +1 -1
  359. package/package.json +166 -54
  360. package/skills/connect-business-data/SKILL.md +2 -2
  361. package/skills/create-package/SKILL.md +18 -18
  362. package/skills/create-package/references/config-and-credentials.md +16 -13
  363. package/skills/create-package/references/connectors-and-uri-policies.md +36 -27
  364. package/skills/create-package/references/manifest-and-discovery.md +12 -12
  365. package/skills/create-package/references/runtime-and-build.md +18 -18
  366. package/skills/create-package/references/skills-and-context.md +35 -19
  367. package/skills/create-package/references/surfaces-and-design.md +16 -16
  368. package/skills/create-package/references/team-and-workflows.md +2 -2
  369. package/skills/create-package/references/test-and-ship.md +17 -17
  370. package/skills/create-package/references/tools-and-schemas.md +5 -5
  371. package/skills/create-package/scripts/{check-package.sh → check-package.mjs} +78 -64
  372. package/skills/create-package/scripts/{verify-loaded.sh → verify-loaded.mjs} +156 -162
  373. package/skills/git/SKILL.md +31 -29
  374. package/skills/manage-files/SKILL.md +11 -14
  375. package/skills/manage-sources/SKILL.md +85 -45
  376. package/skills/manage-uri-policy/SKILL.md +9 -6
  377. package/skills/sync/SKILL.md +2 -2
  378. package/dist/src/connectors/LocalDiskConnector.d.ts +0 -171
  379. package/dist/src/connectors/LocalDiskConnector.d.ts.map +0 -1
  380. package/dist/src/connectors/LocalDiskConnector.js +0 -1233
  381. package/dist/src/connectors/LocalDiskConnector.js.map +0 -1
  382. package/skills/manage-files/scripts/copy.sh +0 -7
  383. package/skills/manage-files/scripts/create.sh +0 -7
  384. package/skills/manage-files/scripts/mkdir.sh +0 -7
  385. package/skills/manage-files/scripts/modify.sh +0 -7
  386. package/skills/manage-files/scripts/upload.sh +0 -16
  387. package/skills/manage-files/scripts/write.sh +0 -29
  388. package/skills/manage-sources/scripts/reembed.sh +0 -23
@@ -31,10 +31,10 @@ a human can press is half a capability.
31
31
 
32
32
  1. **Prove it does not already exist.** Mandatory, not advisory: a second skill that half-duplicates an existing one is worse than none — both match, and the model picks between them at random.
33
33
  2. **Fix before you add.** Extend the existing skill, tool or reference; a new file needs a stated reason the existing owner cannot hold it. An edit leaves the file no larger unless it says why — improve the sentence that is now wrong, never append a changelog or a "we used to think" note.
34
- 3. **Category comes from the folder, never from frontmatter** — `skills/<name>/SKILL.md`, and flat `.md` under `rules/`, `instructions/`, `agents/`, `docs/`. A `category:` or `role:` key is ignored. And every `.md` in ALL FOUR flat categories needs `id:` or `name:` frontmatter (a non-empty string) or discovery silently skips it — ONE kernel rule (`admitsContribution`) that runs the same on an installed package, a `_packages/` drop, a synced source (where the file is indexed as a plain `file` instead) and the marketplace scanner. Exempt are only the forms whose FILENAME is the identity by protocol: `skills/<name>/SKILL.md` (id from the folder name), `commands/*.md`, the identity basenames (`AGENTS.md`, `CLAUDE.md`, `CLAUDE.local.md`, `GEMINI.md`, `.github/copilot-instructions.md`), `.cursorrules`/`.windsurfrules` and `.cursor/rules/*.mdc`. `*.agent.md` is NOT exempt.
34
+ 3. **Category comes from the folder, never from frontmatter** — `skills/<name>/SKILL.md`, and flat `.md` under `rules/`, `instructions/`, `agents/`, `docs/`. A `category:` or `role:` key is ignored. And every `.md` in ALL FOUR flat categories needs a non-empty `id:` or `name:` frontmatter or discovery silently skips it — ONE kernel rule (`admitsContribution`) that runs the same on an installed package, a `_packages/` drop, a synced source (there it is indexed as a plain `file`) and the marketplace scanner. Exempt are only the forms whose FILENAME is the identity: `skills/<name>/SKILL.md` (id from the folder name), `commands/*.md`, the identity basenames (`AGENTS.md`/`AGENTS.local.md`/`AGENT.md`, `CLAUDE.md`/`CLAUDE.local.md`, `GEMINI.md`, `.github/copilot-instructions.md`), `.cursorrules`/`.windsurfrules` and `.cursor/rules/*.mdc`. `*.agent.md` is NOT exempt.
35
35
  4. **`requiredFeatures: [a, b]` is flat.** A nested `requires:` block is read by nothing, so your gate silently does not exist.
36
36
  5. **Hidden means absent.** A caller lacking a feature never sees the skill, tool or widget, and activating it returns the same generic "not found" as a typo. Never build a "locked" state.
37
- 6. **Trust is assigned by where the package came from, never declared by it.** `access.trust: "first-party"` in a dropped manifest changes nothing.
37
+ 6. **Trust is assigned by where the package came from, never declared by it.** `access.trust: "native"` in a dropped manifest changes nothing.
38
38
  7. **`package.json#files` must list every first-level runtime folder** (`dist`, `tools`, `workflows`, `skills`, `rules`, `instructions`, `agents`, `docs`, `team`, `hooks.json`, `app`). Omit one and it works locally and ships empty.
39
39
  8. **A tool's name is its filename; the model-visible description is the root `description` field.** A tool file with no root `description` reaches the model with none.
40
40
  9. **A widget needs a companion `kind: "dock"` surface.** A `dock:` block inside a widget is inert; without the companion the widget is unreachable and nothing warns.
@@ -67,10 +67,10 @@ system — a governed tool plus a skill teaching the craft of driving it.
67
67
 
68
68
  ### Surfaces: two renderers, one entry rule
69
69
 
70
- **`direct`** is compiled React that the package's own first-party host entrypoint registers — the
70
+ **`direct`** is compiled React that the package's own native host entrypoint registers — the
71
71
  host never imports package TSX, so a `direct` surface renders only once that entrypoint is
72
72
  installed at runtime from the prebuilt module the manifest's `app.module` names
73
- (`neuralis-build ui`, first-party only).
73
+ (`neuralis-build ui`, native only).
74
74
  **`iframe`** is every other path and the only one a dropped package has. Nothing else exists:
75
75
  `inline-html` and `wasm-ui` were removed and now fail validation with a migration message. WASM is
76
76
  a **tool** runtime; there is no WASM UI engine.
@@ -112,7 +112,7 @@ what your package may contain.
112
112
  |---|---|---|---|
113
113
  | Lives in | a host dependency → `node_modules/@scope/name` | `<project>/_packages/<id>/` | a folder in a synced source, in a recognised layout |
114
114
  | Who ships it | whoever controls the deploy config — **the dependency IS the trust act** | anyone who can write `_packages/` | anyone who can write the source |
115
- | Trust | first-party (host-assigned) | untrusted; an admin may elevate to trusted; **never** first-party | inherits the source's scope and policy |
115
+ | Trust | native (host-assigned) | untrusted; an admin may elevate to trusted; **never** native | inherits the source's scope and policy |
116
116
  | Install step | add the dependency, restart | drop the folder (rescanned in ~half a second) | **none** — but it must be INDEXED to exist (below); once indexed it shows on the next stream |
117
117
  | Manifest | `package.json#neuralis` | `package.json#neuralis` or `neuralis.package.json` | none — the folder layout IS the anchor |
118
118
  | The five markdown categories | all five; rules inject | all five, but **rules become docs** and `prompt-context` activation is rewritten to `workspace` | all five, but **rules and identity files default OFF**, docs manual-only |
@@ -133,9 +133,9 @@ its own category, and none of them ships a skill, rule or agent you should follo
133
133
  instruction.
134
134
 
135
135
  **Column (a) has an operator loop, and it is not "restart".** An installed node package is brought
136
- in by the person who controls the deploy configuration — registering the dependency, and, when it
136
+ in by the person who controls the deploy configuration — registering the dependency, and, in a Docker install where it
137
137
  points at a folder being edited rather than a registry version, mounting that folder so the
138
- container can see it. The first install needs a real image rebuild; after that the package can be
138
+ container can see it. There the first install needs a real image rebuild; after that the package can be
139
139
  rebuilt and swapped into the running container in about a minute instead of ten. Those commands are
140
140
  not yours to run and not yours to document: the deployment ships its own operator runbook
141
141
  (`neuralis-operations`) which owns them, including which form applies to how it was installed.
@@ -143,7 +143,7 @@ What IS yours: declare `files` correctly, because that whitelist decides what a
143
143
  actually ships — see `references/manifest-and-discovery.md`. Columns (b) and (c) have no such loop;
144
144
  a drop is rescanned in about half a second and source markdown needs no install at all.
145
145
 
146
- **And a column-(a) package need not live in the host's tree at all.** A dependency can point at any directory on the deploying machine, so a package that is a product in its own right gets its own repository, its own history and its own release cadence, reached through a mount. Two things change when it does: the kernel packages become `peerDependencies` (the host already loads them — a hard dependency would give one contract two module graphs) with a relative `link:` devDependency so `tsc` still resolves, and your `tsconfig` has to inline what it used to extend. Four acts stay separate and none implies the next — git remote, mount, dependency registration, registry publish; only the third makes the package load. `references/runtime-and-build.md` §7b has the shape, including the two ways an in-container gate fails while the package itself runs perfectly.
146
+ **And a column-(a) package need not live in the host's tree at all.** A dependency can point at any directory on the deploying machine, so a package that is a product in its own right gets its own repository, its own history and its own release cadence, reached through a mount in a Docker install. Two things change when it does: the kernel packages become `peerDependencies` (the host already loads them — a hard dependency would give one contract two module graphs) with a relative `link:` devDependency so `tsc` still resolves, and your `tsconfig` has to inline what it used to extend. Four acts stay separate and none implies the next — git remote, mount, dependency registration, registry publish; only the third makes the package load. `references/runtime-and-build.md` §7b has the shape, including the two ways an app-side gate fails while the package itself runs perfectly.
147
147
 
148
148
  **Where your files go.** A drop: `fs_write({ uri: "packages://<dir>/package.json", create: { content } })` — that URI
149
149
  is the project's `_packages/` folder, parent dirs made for you. The `packages://` path segment is
@@ -158,9 +158,9 @@ where you own them — improve those in place, never weakening a security rule y
158
158
 
159
159
  **Address it.** A source slug is its own URI scheme, so a source package lives at `<slug>://<path>`:
160
160
  a skill at `data://acme/skills/release-notes/SKILL.md` makes `data://acme` a package carrying one
161
- skill, id `data://acme?project=<p>&scope=project`. Every project seeds two writable local sources, `data://` and
161
+ skill, id `data://acme?project=<p>&scope=project`. Every project seeds two writable folder sources, `data://` and
162
162
  `packages://`. Only the `<runtime_stack>` `sources` list has paths and permissions: `policy=` is your
163
- own read/write/exec, `os_uri=` the host path, `container=` the shell's path — printed only when the
163
+ own read/write/exec, `os_uri=` the host path, `container=` the shell's path (on a native install the same as `os_uri`) — printed only when the
164
164
  source has one; absent, cwd the URI itself (`cwd: "data://acme"`). `fs_list` with no `uri` gives
165
165
  roots and index counts — no path, no policy. Write with `execute` (`action: "shell"`), not
166
166
  `fs_write`: it stamps `category: "file"` and captures no frontmatter, and discovery keeps only the
@@ -196,7 +196,7 @@ decide how far you get — and the two ways to put a file down are gated differe
196
196
  - **Writing with `fs_write`** (`files.write`) — absent from your inventory without it, and that
197
197
  gate governs the write tool only.
198
198
  - **Writing with the shell** (`execute` present + the source's policy, never `files.write`) — the
199
- gate wants source-level `exec` on the dir you `cwd` into and `write` on every path you write, same
199
+ gate wants `exec` on the dir you `cwd` into (that folder's rules) and `write` on every path you write, same
200
200
  `policy=` row, uncovered paths denied. `files.write` off + `execute` on still ships.
201
201
  - **Installing or building** (`packages.author`). Without it the Build and Install actions vanish
202
202
  from the UI and those routes refuse you; code cannot be compiled, markdown needs neither.
@@ -218,7 +218,7 @@ before reporting you cannot.
218
218
  | write a `tools/*.json` or its handler | `references/tools-and-schemas.md` | the `$schema` string, the closed `x-neuralis` keys, banned inputs, result bounding |
219
219
  | build a widget, dock item, or chat card | `references/surfaces-and-design.md` | the dock companion rule, the canonical entry root, the self-contained entry, renderer × trust, the design floor |
220
220
  | write server-side code (`src/lifecycle.ts`, `src/routes/*`, `src/tools/*`) or a sandboxed package | `references/runtime-and-build.md` | the exported shape, output paths, route pattern/feature literals, the build |
221
- | develop a first-party package from ITS OWN repository, outside the host's tree — kernel deps, `tsconfig` with nothing to extend, where the gates actually run, and which of git / mount / dependency / publish makes it LOAD | `references/runtime-and-build.md` §7b | a hard kernel dependency giving one contract two module graphs; a `tsc` that cannot resolve inside the container while the package runs fine; assuming a pushed commit changed the deployment |
221
+ | develop a native package from ITS OWN repository, outside the host's tree — kernel deps, `tsconfig` with nothing to extend, where the gates actually run, and which of git / mount / dependency / publish makes it LOAD | `references/runtime-and-build.md` §7b | a hard kernel dependency giving one contract two module graphs; a `tsc` that cannot resolve inside the container while the package runs fine; assuming a pushed commit changed the deployment |
222
222
  | call ANOTHER package's routes from sandboxed code (`ctx.callRoute`, the `ctx.fs.*` sugar, the per-package route catalog links) | `references/runtime-and-build.md` §6 | trusted-only, caller's real session, deny-by-default feature gates, writes land pending_review |
223
223
  | attach an external system as a data source, set path permissions — or your connector never appears in `GET /connectors` | `references/connectors-and-uri-policies.md` | the connector port contract, which project a connector registers into (and when it registers into NONE), the admin-only write gate, `sources[]`, `uriPolicies` self-namespacing |
224
224
  | need a secret, an API key, or any adjustable value | `references/config-and-credentials.md` | declare-don't-hardcode, credential scopes, shell env projection |
@@ -249,23 +249,23 @@ shell → `grep -rn "requiredFeatures" ${SKILL_DIR}/references/`.
249
249
  Two scripts do the mechanical half:
250
250
 
251
251
  ```bash
252
- bash ${SKILL_DIR}/scripts/check-package.sh <absolute-package-root> # any path, before you ship
253
- bash ${SKILL_DIR}/scripts/verify-loaded.sh <package-id> # any path, after
252
+ node "${SKILL_DIR}/scripts/check-package.mjs" <absolute-package-root> # any path, before you ship
253
+ node "${SKILL_DIR}/scripts/verify-loaded.mjs" <package-id> # any path, after
254
254
  ```
255
255
 
256
- `check-package.sh` is static, needs no server, and modes off disk: with a manifest it runs
256
+ `check-package.mjs` is static, needs no server, and modes off disk: with a manifest it runs
257
257
  everything; with **none** it runs markdown mode — package recognition, the categories, every
258
258
  frontmatter gate — then prints the manifest/tools/workflows/surfaces/runtime/dist checks it skipped,
259
- so no skip reads as a pass. `verify-loaded.sh` covers all three paths (for (c) pass
259
+ so no skip reads as a pass. `verify-loaded.mjs` covers all three paths (for (c) pass
260
260
  `<rootUri>?project=<p>&scope=…`) and reads package diagnostics, so it needs `core.observe` — lacking that it
261
261
  reports it could not reach them rather than claiming the package is absent.
262
262
 
263
263
  **Enable, trust, install and rescan apply from the NEXT stream.** A stream captures the set of
264
264
  packages it may use once, at its start: a package you just enabled, trusted or installed becomes
265
265
  activatable in the next stream — a new user message, a workflow run, a fresh conversation — never
266
- mid-turn. A delegate spawned after the change sees its `<packages>` entry, injected
266
+ mid-turn. A foreground delegate spawned after the change sees its `<packages>` entry, injected
267
267
  rules/instructions and agent resolution fresh, but its tool catalog and skill activation still
268
- use the parent stream's gate. A `Skill not found` in
268
+ use the parent stream's gate; a background delegate re-reads all of them at its wake. A `Skill not found` in
269
269
  the same continuous turn that flipped the package is this rule, not a broken package: retry from
270
270
  a fresh stream before re-diagnosing.
271
271
 
@@ -48,13 +48,13 @@ Effective value cascade, exactly three steps: **platform file override → `envF
48
48
  - **`envFallback` is ignored for `type:"json"`** (validation warning; the administrator sets the env var and nothing changes), and **`type:"json"` rows are excluded from the flat settings list** — the key still reads through the cascade, it is just not on the list.
49
49
  - **`category: "vector"` is filtered out of the flat Platform Settings list** — a dedicated Vector section owns it, so any non-embedding key you file there is invisible in the admin UI.
50
50
  - **Secret-shaped names are warned, not blocked.** A `key` or `envFallback` matching `secret|token|passw|credential|apikey|api_key|private` produces a manifest warning — and the value still renders as plaintext. Declare a credential instead.
51
- - **Do not invent an `envFallback`.** It projects an arbitrary environment variable's VALUE into administrator-visible state — which is exactly why `configSettings[]` is honoured for **first-party** packages only.
51
+ - **Do not invent an `envFallback`.** It projects an arbitrary environment variable's VALUE into administrator-visible state — which is exactly why `configSettings[]` is honoured for **native** packages only.
52
52
 
53
53
  **Declaration is not a grant.** A row registers a schema entry on the feature-gated admin Config surface. It gives your package no write authority over anything.
54
54
 
55
55
  ## Task — read a config value in your code
56
56
 
57
- `ctx.config.get(key)` reads a declared platform setting live. Every first-party key is registered before `init`; an undeclared key throws. Reads below host-assigned first-party trust are denied.
57
+ `ctx.config.get(key)` reads a declared platform setting live. Every native key is registered before `init`; an undeclared key throws. Reads below host-assigned native trust are denied.
58
58
 
59
59
  ```ts
60
60
  import type { PackageInitContext } from '@neuralis/package-system/contracts';
@@ -80,8 +80,8 @@ The shape is exactly `{ id, label, category?, oauth? }` — `id` and `label` req
80
80
 
81
81
  - **`id` must pass `^[A-Za-z_][A-Za-z0-9_.-]*$`, at most 128 chars.** The id becomes an `<id>.enc.json` path segment, so a slash, whitespace or a leading dot is rejected — an id can never escape its scope directory. Duplicate ids in one manifest, a missing `id`/`label`, or a non-object entry all fail validation with a named error.
82
82
  - **Declare only what something RESOLVES.** A catalog row an owner fills in that no code reads is worse than no row — the operator believes the key is configured while the feature stays dark. A drift guard asserts declarations and consumers match **in both directions**, so a dead declaration fails the build. Boot-critical infrastructure read from the environment (a vector-DB key wired before any credential can be decrypted) belongs in `.env`, not here.
83
- - **Reserved namespaces are first-party-only.** The git (`git.<host>.pat`, `git.<host>.oauth.*`), channel, and MCP (`mcp.<server>.*`) id classes have host-owned resolution semantics — a resolver reads them at a member's OWN scope on that member's behalf — so a non-first-party manifest declaring one is a **validation error, not a warning**: unlike a retired key, it fails the manifest and the package does not load. Squatting `git.github.com.pat` would otherwise put a token an owner filled in at global scope into the cascade for every member without their own. Declare ids in your own namespace (`acme.apiKey`).
84
- - **The catalog is dynamic**: the union of package `credentials[]`, every installed skill's `credentials:` frontmatter, and ids already stored by hand. Entries carry only `hasValue`, never the value. There is **no visibility trust gate** — your package's own ids appear at any trust tier, or an owner could never set them. Trust governs ATTRIBUTION instead: a first-party declaration wins the label/category, a later declarer only joins the `declaredBy` list, and the UI renders the trust tier next to a non-first-party declarer.
83
+ - **Reserved namespaces are native-only.** The git (`git.<host>.pat`, `git.<host>.oauth.*`), channel, and MCP (`mcp.<server>.*`) id classes have host-owned resolution semantics — a resolver reads them at a member's OWN scope on that member's behalf — so a non-native manifest declaring one is a **validation error, not a warning**: unlike a retired key, it fails the manifest and the package does not load. Squatting `git.github.com.pat` would otherwise put a token an owner filled in at global scope into the cascade for every member without their own. Declare ids in your own namespace (`acme.apiKey`).
84
+ - **The catalog is dynamic**: the union of package `credentials[]`, every installed skill's `credentials:` frontmatter, and ids already stored by hand. Entries carry only `hasValue`, never the value. There is **no visibility trust gate** — your package's own ids appear at any trust tier, or an owner could never set them. Trust governs ATTRIBUTION instead: a native declaration wins the label/category, a later declarer only joins the `declaredBy` list, and the UI renders the trust tier next to a non-native declarer.
85
85
  - **Declaration is not a grant here either.** A row is catalog metadata; it confers no write authority, and consumption still resolves against the caller's real scope.
86
86
  - **`oauth: true` is a DISPLAY hint only** — it changes admin chrome to Connect/Disconnect. It gives you no OAuth flow, and on an unwired provider the row is a dead button.
87
87
 
@@ -112,19 +112,22 @@ description: Fetch a city forecast via the Weather API.
112
112
  credentials:
113
113
  - WEATHER_API_KEY
114
114
  ---
115
- Run: `bash ${SKILL_DIR}/scripts/forecast.sh "$CITY"`
115
+ Run: `node "${SKILL_DIR}/scripts/forecast.mjs" "$CITY"`
116
116
  ```
117
117
 
118
- ```bash
119
- # skills/forecast/scripts/forecast.sh
120
- set -euo pipefail
121
- : "${WEATHER_API_KEY:?not configured — set it under Credentials}"
122
- curl --fail-with-body -sS -H "Authorization: Bearer $WEATHER_API_KEY" "https://api.weather.example/v1/forecast?q=$1"
118
+ ```js
119
+ // skills/forecast/scripts/forecast.mjs
120
+ const key = process.env.WEATHER_API_KEY;
121
+ if (!key) { process.stderr.write('WEATHER_API_KEY is not configured — set it under Credentials\n'); process.exit(2); }
122
+ const res = await fetch(`https://api.weather.example/v1/forecast?q=${encodeURIComponent(process.argv[2] ?? '')}`, { headers: { Authorization: `Bearer ${key}` } });
123
+ const body = await res.text();
124
+ if (!res.ok) { process.stderr.write(`HTTP ${res.status}\n${body}\n`); process.exit(1); } // keep the error body
125
+ process.stdout.write(body);
123
126
  ```
124
127
 
125
128
  On activation the host resolves each declared id at the caller's real `(userId, projectId, agentId)` scope, within the caller's tier ceiling: own user key always; agent and project keys with `project.credentials.write`; global with `platform.scope` too. A tier above it reads as missing, so a member's run needs the member's own key (`credentials.self`). **The model never sees a resolved value.**
126
129
 
127
- - **`credentials:` must be a list of plain strings.** A scalar or a list of objects is dropped silently by the whitelist frontmatter parser: the skill activates normally, the catalog shows no ids, and your script exits on the `${VAR:?…}` guard with no parse error anywhere.
130
+ - **`credentials:` must be a list of plain strings.** A scalar or a list of objects is dropped silently by the whitelist frontmatter parser: the skill activates normally, the catalog shows no ids, and your script exits on its missing-key guard with no parse error anywhere.
128
131
  - **A missing value is non-fatal.** The id lands on a `missing` list, the rendered body carries a `(missing: <id>)` marker, and no variable is set — which is why scripts should fail with a message pointing the user at the Credentials surface.
129
132
  - **Sanitise exactly once.** Pass `env` and the allow-list straight through to the shell runner. A second defensive sanitise pass has no allow-list and strips exactly the credential keys that were just projected — and the symptom, "the credential is configured but the script says it is missing", sends you debugging the wrong layer.
130
133
  - **The allow-list applies to the OVERRIDES side only.** It never un-strips a same-named variable already present in the host process environment. That is deliberate: a leaked host secret must not piggyback on an allow-listed name.
@@ -153,10 +156,10 @@ Never inline a secret in a manifest or a source config file, and never default-a
153
156
  ## What works on which reach path
154
157
 
155
158
  - **Installed package (in-process):** the only path where both halves work fully. Trust comes from being installed, so keys register at boot, the Config tab shows your package as declarer, `ctx.credentials` is available, and skill `credentials:` projects into script environments.
156
- - **Project `_packages/` drop (sandboxed, untrusted):** `configSettings[]` is **silently dropped** — the only trace is a `config.declaration_skipped` warning, nothing fails at install time, and the first `get()` throws `Config key not registered`. The sandbox bridge exposes no config and no credential host function at all, so declared `credentials[]` still show in the catalog but sandboxed code cannot read a value. Take tunables as tool inputs or from your own data files, and do not plan on secret access. **An admin can elevate a dropped package to `trusted`, never to first-party** — the drop path pins `untrusted` and the elevation channel has no first-party value — so neither array ever comes back on this path. If you need declared config or credential access, ship the package on the installed path instead.
159
+ - **Project `_packages/` drop (sandboxed, untrusted):** `configSettings[]` is **silently dropped** — the only trace is a `config.declaration_skipped` warning, nothing fails at install time, and the first `get()` throws `Config key not registered`. The sandbox bridge exposes no config and no credential host function at all, so declared `credentials[]` still show in the catalog but sandboxed code cannot read a value. Take tunables as tool inputs or from your own data files, and do not plan on secret access. **An admin can elevate a dropped package to `trusted`, never to native** — the drop path pins `untrusted` and the elevation channel has no native value — so neither array ever comes back on this path. If you need declared config or credential access, ship the package on the installed path instead.
157
160
  - **Source markdown package (no install step):** no manifest, so neither array exists on this path. Per-skill `credentials:` frontmatter still works exactly as above — a source-package skill can shell out with a secret in its environment; it just cannot declare a tunable or a catalog row of its own.
158
161
 
159
162
  ## Going deeper
160
163
 
161
164
  - Configuration tiers and the cascade: <https://docs.neuralisapp.com/enterprise/configuration>
162
- - Credential scopes, the dynamic catalog and the encrypted store: <https://docs.neuralisapp.com/enterprise/credentials>
165
+ - Credential scopes, the dynamic catalog and the encrypted store: <https://docs.neuralisapp.com/package-system/credentials>
@@ -28,6 +28,9 @@ The dataset lives only behind the configured source/connector. An arbitrary writ
28
28
  { "id": "acme-mcp", "type": "mcp", "transport": "stdio", "command": "npx",
29
29
  "args": ["-y", "@acme/mcp-server"],
30
30
  "auth": { "type": "env-vars", "envVarName": "ACME_TOKEN" } },
31
+ { "id": "acme-remote", "type": "mcp", "transport": "streamable-http",
32
+ "url": "https://mcp.acme.test/mcp", "name": "Acme", "description": "Orders and invoices",
33
+ "auth": { "type": "oauth2", "scopes": ["read"] } },
31
34
  { "id": "acme-api", "type": "openapi",
32
35
  "openApiSpec": "https://api.acme.test/openapi.json",
33
36
  "openApiOperationFilter": { "include": ["listOrders", "getOrder"] },
@@ -41,18 +44,19 @@ The dataset lives only behind the configured source/connector. An arbitrary writ
41
44
  - `auth.type` is closed: `none | api-key | bearer-token | basic | oauth2 | oauth2-pkce | env-vars`. `env-vars` is the one for a stdio MCP subprocess — decrypted values go into the child process env.
42
45
  - **Secrets are collected through `auth.setupFields[]`** (shape in `references/config-and-credentials.md`). There is no `credentialRef` auth field; writing one collects nothing and the connector starts unauthenticated.
43
46
  - A `type: "source"` entry is handled only by the source pipeline; the outbound lifecycle skips it.
47
+ - **A remote `mcp` row is offered to the user, never auto-connected.** It needs `transport: "streamable-http"` and a `url` (a package fails validation otherwise; `stdio` + `command` is the trusted sidecar form above), and it is never registered as a connector. Every agent whose owner may see the package — its base-access feature, and the package switched on for that agent — gets it under Connections → MCP servers as "Offered by <package>" (and as an `offered` row of `connect {list:{kind:"mcp"}}`); Add, or `connect {add:{kind:"mcp", offer:"<packageId>#<connectorId>"}}`, adopts it as that agent's own MCP server and signs in through the server's OAuth (discovery, dynamic client registration, PKCE). Only `url`, `name`, `description`, `icon` and `auth.scopes` are read; `auth.type` is `oauth2`, `oauth2-pkce` or `none`, and any other type is not offered. No MCP request reaches the server before the user signs in (the sign-in reads its OAuth metadata and registers a client), no Neuralis identity header is ever sent, and an adopted server stays the user's when the package is later switched off.
44
48
 
45
49
  ### Which tenant an outbound connector registers into
46
50
 
47
51
  A `connectors[]` entry is **not** registered once for the whole deployment. It lands in exactly one **partition**, and which one is decided by how the package reached the host — never by anything you can write in the manifest:
48
52
 
49
- - **Installed package, first-party** → the **platform lane**. One registration, visible in every project on the deployment. It is the only lane a package with no owning project may reach.
53
+ - **Installed package, native** → the **platform lane**. One registration, visible in every project on the deployment. It is the only lane a package with no owning project may reach.
50
54
  - **Project `_packages/` drop** → **that project's own partition**. The connector exists for that project and nowhere else; two projects dropping the same package get two independent connectors with independent config, status and health.
51
- - **No resolvable owning project and not first-party → NOTHING is registered.** Fail-closed on purpose: the only partition left would be the platform lane, which every project can see. **This is the first thing to check when a connector "disappeared"** — the package loads clean, `check-package.sh` is happy, the manifest is valid, and `GET /connectors` simply never lists it. The only trace is the server line `Connector registration refused: unresolved owning project`. Nothing in the manifest will fix it; find why the package has no owning project.
55
+ - **No resolvable owning project and not native → NOTHING is registered.** Fail-closed on purpose: the only partition left would be the platform lane, which every project can see. **This is the first thing to check when a connector "disappeared"** — the package loads clean, `check-package.mjs` is happy, the manifest is valid, and `GET /connectors` simply never lists it. The only trace is the server line `Connector registration refused: unresolved owning project`. Nothing in the manifest will fix it; find why the package has no owning project.
52
56
 
53
57
  Reads follow the same partition. `GET /connectors` answers with the caller's own visibility — the platform lane UNION their project — and an id-addressed call resolves own-project first, then platform. An id belonging to **another** project answers the same generic **`404 Not found`** as an unknown id or a malformed one: the three are deliberately indistinguishable, so no caller can enumerate another project's connector ids out of the error text. Do not build a retry, a fallback or a "does it exist elsewhere" probe on that 404 — it will never become a more specific code.
54
58
 
55
- Tools follow it too: a connected remote-MCP connector's tools are merged into the sessions of its own tenant — the platform lane's into every project, a project's into that project alone.
59
+ A remote MCP row never takes this path: it is an offer each agent adopts (above), so its tools reach exactly the agents that added it.
56
60
 
57
61
  **Reading is not writing.** Listing connectors, reading one's health and reading its resolved tools ride the module's `core.observe`. Every MUTATING arm — create, delete, configure, connect, disconnect, enable, disable — additionally requires the **`core.connectors`** feature — granted to `admin` by default, reached by an owner-strength role through its `'*'` wildcard, and held by no one else. A caller who can SEE a connector row and gets `403 Forbidden` on Connect is looking at that gate, not at a broken connector: name the feature and stop. Never retry it, and never reach for another identity.
58
62
 
@@ -93,21 +97,26 @@ None of this touches a `type: "source"` entry. A filesystem kind is registered a
93
97
  1. **Omitting `"additionalProperties": false` is PERMISSIVE, not rejecting.** Arbitrary unvalidated keys land in your factory's `config`; the rejection you assumed was happening never happens.
94
98
  2. **It is a hand-rolled draft-07 SUBSET.** Supported: top-level `type: "object"`, `required`, `additionalProperties: false`, and per-property `type`, `enum`, `const`, `minLength`, `maxLength`, `pattern`, `minimum`, `maximum`, `items`. Everything else — `$ref`, `oneOf`/`anyOf`/`allOf`, `format`, `dependencies`, nested object schemas — is **silently ignored**: no error, no warning, invalid config reaching your factory as a type crash deep inside the connector. Keep the form flat.
95
99
 
96
- 3. **A `root` property must say WHICH PLANE it is on.** The Add-Source form renders every field
97
- from its declared `x-neuralis.ui`, and `root` is where the chrome differs:
98
- `"control": "container-path"` means the path lives in the CONTAINER filesystem, so the form
99
- offers the `/mounts` volume picker, the `neuralis mount add` callout and the Browse button;
100
- `"control": "host-path"` means it lives on a paired device — a machine outside the app (reached
101
- through that device's broker), so it gets none of them — Browse least of all, because `GET /sources/browse` readdirs
102
- in the SERVER process, which is the wrong machine for a host root. The bare legacy
103
- `"control": "path"` still works and is treated as container-plane. Declare `label` and
104
- `placeholder` too: the form uses yours, and a kind that declares neither renders a bare `Path`
105
- with an empty placeholder.
100
+ 3. **A `root` property declares `"control": "container-path"`** (the bare legacy `"path"` still
101
+ works the same): the path lives on the app's own machine — in a Docker install the container,
102
+ where the form suggests the `/mounts` binds and the `neuralis mount add` callout; on a native
103
+ install only the project's own folder, any other folder being attached on the user's paired
104
+ device. `"browse": true` offers the folder picker. Declare `label` and `placeholder` too: the
105
+ form uses yours, and a kind that declares neither renders a bare `Path` with an empty
106
+ placeholder. One kind may serve both planes: a field marked `"transport": true` (the `host`
107
+ kind's `device`) renders BEFORE the root and, while it holds a value, turns the root into a path
108
+ on that device — your `deviceLabel`/`devicePlaceholder` (or a `devicePlaceholders` entry per
109
+ the chosen row's `platform`: `win32` · `darwin` · `linux`), browsed through that device's broker —
110
+ and a schema-level `"not": {"required": ["device", "hostRoot"]}` both refuses the pair and hides
111
+ the excluded field. `"advanced": true` folds a field under "Advanced" and `"help"` is its short
112
+ line; the schema-level `"x-neuralis": {"ui": {"summary": "…"}}` is the kind's one-line form text
113
+ (your `description` stays the agent's).
106
114
  4. **Any other field is a text input, or a `select` filled by YOUR route.** `"control": "select",
107
115
  "optionsRoute": "things?scope=mine"` makes the form read that relative route of your own package and
108
- offer the first array in the JSON answer as rows `{id, name?, status?}` (value = `id`; a
116
+ offer the first array in the JSON answer as rows `{id, name?, platform?, status?}` (value = `id`; a
109
117
  `revoked` row is not offered). An absolute route, a scheme or a `..` segment is refused and the
110
- field falls back to text with the reason. The list is UX only: re-check the value in your connector.
118
+ field falls back to text with the reason. With `"optional": true` the select also offers the
119
+ empty value as a real choice, labelled `emptyLabel`. The list is UX only: re-check the value in your connector.
111
120
 
112
121
  **Never put a secret in `configSchema`.** There is no `credentialFields[]` key that splits schema properties into the credential store, and the factory context carries no `credentials` map — a config property IS plain config, persisted in `sourceConfig.json`. Declare the secret in `neuralis.credentials[]` and read it through the `CredentialResolver` the loader injects into your package's `init(ctx)` — **that** `ctx`, not the factory's — and let the factory close over the resolver. Rules in `references/config-and-credentials.md`.
113
122
 
@@ -132,7 +141,7 @@ export function createNotesConnector(ctx: ConnectorFactoryContext): ConnectorPor
132
141
  }
133
142
  ```
134
143
 
135
- - **Declared capabilities must EXACTLY equal the runtime set**, both directions. Closed vocabulary: `list`, `read`, `stat`, `write`, `delete`, `move`, `mkdir`, `rmdir`, `exec`, `execDetached`, `scanDelta`, `walk`, `count`, `peekCount`, `scanContent`, `subscribeEvents`, `resolveOsUri`; `list` and `read` are mandatory, each of the rest gates one optional method. Symptom: `connector.source.capability-mismatch` with declared-vs-actual sets, thrown at **per-source instantiation** — "installed fine, breaks the first time someone creates a source of this kind." First-party ⇒ boot-fatal; otherwise the kind goes unavailable and callers get `ConnectorCapabilityMissing`.
144
+ - **Declared capabilities must EXACTLY equal the runtime set**, both directions. Closed vocabulary: `list`, `read`, `stat`, `write`, `delete`, `move`, `mkdir`, `rmdir`, `exec`, `execDetached`, `scanDelta`, `walk`, `count`, `peekCount`, `scanContent`, `subscribeEvents`, `resolveOsUri`; `list` and `read` are mandatory, each of the rest gates one optional method. Symptom: `connector.source.capability-mismatch` with declared-vs-actual sets, thrown at **per-source instantiation** — "installed fine, breaks the first time someone creates a source of this kind." Native ⇒ boot-fatal; otherwise the kind goes unavailable and callers get `ConnectorCapabilityMissing`.
136
145
  - **Pin the implemented ABI: `4 satisfies ConnectorPortVersion`.** A package shipped SEPARATELY from the kernel pins the number it was built against — importing the host's runtime constant makes an old binary relabel itself as current on the next platform upgrade, which is the one failure the version check exists to catch. (A connector that ships IN LOCKSTEP with the kernel may import the constant instead; yours does not.) Older exec signatures are rejected without adaptation; version equality alone does not prove external code enforces authorization.
137
146
  - **Exec is authenticated, and you do NOT write the entry check.** `exec({ command, cwd, timeout?, env?, background? }, { session, signal? })` receives the real `SessionContext` and exact source URI. Declaring the `exec` capability REQUIRES declaring `"execRequires": ["<feature.id>", …]` beside it — the feature id(s) that open a shell on your kind. A missing or EMPTY list is a manifest error, because "every id in an empty list is held" is a door that is always open. The platform stamps a frozen copy of those ids on the instance and wraps `exec` so each one is checked before your code runs, and the calling tool then evaluates the SOURCE's own uri-policy `exec` bit on the cwd. So enforce your lifecycle and supported options — not the entry feature; a second copy in your provider would be free to drift from your manifest. Return the existing result fields plus optional bounded `text`. Exec bindings require an absolute factory `projectRoot`. The loader snapshots provider/source/project/scope before factory execution and stamps the checked instance; callers verify `getConnectorBindingProvenance` against current authority. Never reuse one instance across bindings.
138
147
  - **A run that OUTLIVES its call is `execDetached` + the `detached` facet.** Declare the capability (it also requires `exec`) and implement all FIVE verbs — `start`, `status`, `output`, `kill`, `release` — or the loader refuses the binding: a declared capability with a missing verb is a run the platform can start and never stop. `start(request, context)` is a second exec ENTRY, so the platform wraps it with your `execRequires` exactly like `exec`; the other four take the run id you returned and NOTHING else, because a caller who has since lost the entry feature must still be able to read and stop their own run. Ownership is the platform's stored record, never a claim in your arguments: the optional `actor` on `kill` is for your audit row only. Report a kill as an ACKNOWLEDGEMENT and the real end through `status`; answer `null` for a run you no longer know, and keep `output` rows monotonic by `seq` so the platform can prove it copied the whole log before it reports the run finished.
@@ -156,12 +165,12 @@ export function createNotesConnector(ctx: ConnectorFactoryContext): ConnectorPor
156
165
  ]
157
166
  ```
158
167
 
159
- Required: `source` (unique slug), `kind`, `scope` ∈ `project|user|agent`, a non-empty `description`, `seed` ∈ `auto|discoverable`. Optional: `root`, `label`, `sync`, `permissions`, `recognizesPackages`, `visibility.seeRequires`.
168
+ Required: `source` (unique slug), `kind`, `scope` ∈ `project|user|agent`, a non-empty `description`, `seed` ∈ `auto|discoverable`. Optional: `root`, `label`, `sync`, `permissions`, `packageFolders`, `visibility.seeRequires`.
160
169
 
161
- - `seed: "auto"` seeds into every project with no human in the loop → requires **trusted or better**, else `seed="auto" requires trust >= 'trusted'` and the package fails to load. A root naming a platform token (`${appRoot}`) requires **first-party**. Otherwise roots must be project-relative: no leading `/`, no `${…}` token, no `.` / `..` segments.
170
+ - `seed: "auto"` seeds into every project with no human in the loop → requires **trusted or better**, else `seed="auto" requires trust >= 'trusted'` and the package fails to load. A root naming a platform token (`${appRoot}`) requires **native**. Otherwise roots must be project-relative: no leading `/`, no `${…}` token, no `.` / `..` segments.
162
171
  - An untrusted drop gets `seed: "discoverable"` with a project-relative root and nothing more — its declarations never enter the trusted attribution map, so the source appears unattributed, with no package-supplied label or description.
163
172
  - **`visibility.seeRequires` is a UX default, not the gate.** The authoritative see-filter and the add-feature check live server-side. Ship a source believing `seeRequires` hides it and you have shipped an unhidden source; setting it grants nothing either.
164
- - **`recognizesPackages` does NOT switch markdown discovery on**, despite the name. Default unset (⇒ false); allowed `true` only on a `local`-kind source (`recognizesPackages may only be true for local-kind sources.`), and settable only by an owner/admin-effective caller (`Setting recognizesPackages requires an owner/admin-effective role.`). Its real job is the *code-LOAD* axis: the host scans a flagged, enabled, local source's directory for **installable** packages, the way it always scans the project `packages` drop-zone (which needs no flag). Its one effect on markdown is a dedup nuance — under a flagged source the package slug is read as the FIRST path segment, so a subtree duplicating an already-loaded package stops double-injecting. **Symptom when unset: none for markdown.** A plain synced folder still contributes skills, instructions, rules, agents and docs by folder layout alone — recognition criteria are the reach-path table in `SKILL.md` (column (c)) and the discovery rules in `references/manifest-and-discovery.md`. If a source package is invisible, this flag is not the cause; work the diagnosis table below.
173
+ - **`packageFolders` does NOT switch markdown discovery on.** Default unset (⇒ none); `[""]` makes the whole declared `host` source one package folder, `["a/b"]` one folder under its root — the same field the created source stores (`packageFolders may only be set when connection.kind is "host".`), settable only by an owner/admin-effective caller (`Setting packageFolders requires an owner/admin-effective role.`). Its real job is the *code-LOAD* axis: the host scans each package folder of an enabled folder it can open for **installable** packages, the way it always scans the project `packages` drop-zone (which needs no flag); a package folder on a paired device loads over the device link while the device is online, and while it is offline the package stays listed as not available. A loaded package's source twin is not injected twice — the dedup is by exact origin. **Symptom when unset: none for markdown.** A plain synced folder still contributes skills, instructions, rules, agents and docs by folder layout alone — recognition criteria are the reach-path table in `SKILL.md` (column (c)) and the discovery rules in `references/manifest-and-discovery.md`. If a source package is invisible, this flag is not the cause; work the diagnosis table below.
165
174
 
166
175
  ## Set path permissions (`uriPolicies`)
167
176
 
@@ -175,24 +184,24 @@ An **object keyed by URI pattern** — not an array, and no `access` enum. The p
175
184
  { "pattern": "data://<self>/private/**", "permissions": { "read": false } },
176
185
  { "pattern": "data://<self>/private/$self/**", "permissions": { "read": true }, "override": true },
177
186
  { "pattern": "data://<self>/private/**", "permissions": { "read": true },
178
- "roles": ["owner", "admin"], "override": true } ] } }
187
+ "priority": 2, "override": true } ] } }
179
188
  ```
180
189
 
181
190
  1. **Every key must start with `packages://<self>/` or `data://<self>/`** (or equal that prefix minus the trailing slash). A foreign namespace — another package's id, `app://`, `neuralis://`, a bare OS path — **rejects the WHOLE manifest**: no partial registration, the package does not load at all. Inner `paths[].pattern` entries containing `://` are checked identically; relative inner patterns pass.
182
191
  2. **`<self>` is a load-time placeholder** substituted with your package slug at boot. Never hardcode your own id in a key.
183
192
  3. **`$self`, `$creator`, `$source` are a DIFFERENT family** — runtime tokens substituted inside `paths[].pattern` with the caller's agent id, the source creator's user id, and the source slug. Confusing them is the classic failure: `<self>` in a path position becomes a literal, never-matching segment (the rule appears to do nothing); `$self` in a *key* is not substituted at load, fails the prefix check, and rejects the manifest. This pair is also how self-maintaining identity works: `data://<self>/$self/**` writable while `data://<self>/*/**` is not means an agent rewrites its own identity files and no one else's — a uri-policy grant, not a special case.
184
193
  4. **Every value needs `default: { read, write, exec }`, all three booleans present**, or the manifest fails with `missing required default { read, write, exec } booleans`. **Every `paths[]` row needs its capabilities nested under a `permissions` object**, not at the row's top level — the top-level spelling used to normalize to `permissions: {}` and the rule became SILENTLY INERT (it read like a real deny in the manifest and in every persisted copy of it). It is now a load-time rejection, so an inert row cannot ship.
185
- 5. **Patterns match the FULL URI** (leading slash stripped): `?` = one non-separator char, `*` = a run of non-`/`, `**` = anything including `/`, a leading `**/` may match zero segments, anchored both ends. Two symptoms follow: a source-relative pattern (`memory/**` instead of `data://<self>/memory/**`) **silently never matches**, so the intended deny is absent and access falls back to `default`; and `data://<self>/**` does **not** cover the bare root `data://<self>`, so directory-level denies leak on the directory node itself. Spelling is NOT one of the symptoms: slash runs, `.` and `..` are canonicalized on the pattern AND on the URI under test before matching (see the floor paragraph below), so you cannot miss a rule by writing it non-canonically and no caller reaches a file by rewriting its URI.
194
+ 5. **Patterns match the FULL URI** (leading slash stripped): `?` = one non-separator char, `*` = a run of non-`/`, `**` = anything including `/`, a leading `**/` may match zero segments, anchored both ends. Two symptoms follow: a source-relative pattern (`memory/**` instead of `data://<self>/memory/**`) **silently never matches**, so the intended deny is absent and access falls back to `default`; and `data://<self>/**` does **not** cover the bare root `data://<self>`, so directory-level denies leak on the directory node itself. Spelling is NOT one of the symptoms: slash runs, `.` and `..` are canonicalized on the pattern AND on the URI under test before matching (see the floor paragraph below), so you cannot miss a rule by writing it non-canonically and no caller reaches a file by rewriting its URI. Letter case is handled too: a rule's `false` bits match every case of its pattern (`CONVERSATIONS/` hits a `conversations/**` deny on every OS), its `true` bits only the exact spelling — write patterns in the case your package creates the files.
186
195
 
187
- **Evaluation order:** `default` → `byRole` → `byUser` → `byAgent` → `paths`. Path rules are **deny-wins**: a `read: true` rule applies only when the result is not already `false`. To re-open something a broader rule denied, set `override: true` — otherwise the carve-out looks correct in the manifest and the caller still gets 403. Rules narrow with `roles[]` and/or `agents[]`.
196
+ **Evaluation order:** `default` → `byRole` → `byUser` → `byAgent` → `paths`. Path rules are **deny-wins**: a `read: true` rule applies only when the result is not already `false`. To re-open something a broader rule denied, set `override: true` — otherwise the carve-out looks correct in the manifest and the caller still gets 403. Rules narrow with `priority`, `users[]` and/or `agents[]`; every condition present on one rule must hold, so "A or B" is two rules.
188
197
 
189
- **`byRole` is keyed by name but resolved by STRENGTH; `roles[]` is still a literal name match.** Do not treat them as one mechanism. A `byRole` entry applies to the caller whose role NAME matches, else to the caller at that entry's exact declared `priority` (so a custom role at the owner anchor gets the `owner` entry), else — for every entry belonging to a role at least as strong as the caller — its explicit `false` bits only, never a grant. A role weaker than `viewer` therefore INHERITS viewer's denials instead of escaping them, and an `owner` never inherits a viewer restriction. A `paths[].roles[]` array has none of that: it matches the role name exactly, so a rule scoped to `["owner","admin"]` does not reach a custom owner-strength role until that role's name is added to the array. If your policy needs a custom role to reach a carve-out, name it in `roles[]`.
198
+ **`byRole` is keyed by name but resolved by STRENGTH; a path rule names its subject by the caller's role priority with `priority`.** Do not treat them as one mechanism. A `byRole` entry applies to the caller whose role NAME matches, else to the caller at that entry's exact declared `priority` (so a custom role at the owner anchor gets the `owner` entry), else — for every entry belonging to a role at least as strong as the caller — its explicit `false` bits only, never a grant. A role weaker than `viewer` therefore INHERITS viewer's denials instead of escaping them, and an `owner` never inherits a viewer restriction. On a `paths[]` rule, `"priority": 2` matches every caller whose role priority is n or stronger (`<= 2`; lower = stronger: owner 1, admin 2, manager 10, member 20, viewer 30), a custom role at that strength included — it is the caller's role strength, not the rule's order. It fails closed: a value that is not an integer from 1 to 99, or a caller without a priority, never matches, and the manifest is rejected. `priority` is grant-only (`override: true`, every declared bit `true`), never on a deny or `floor: true` row. `paths[].roles[]` is rejected in a manifest (`roles is not allowed in a package manifest`): it matches a role NAME exactly, and only a project's own stored rules may use it.
190
199
 
191
200
  **Uncovered paths deny by default.** A filesystem-touching package with no policy baseline is not "open" — it is denied everywhere and its writes fail quietly. Missing path policy is a bug to flag, never a passing state.
192
201
 
193
202
  **`exec` is the dimension the sandboxed shell reads.** Keep it `false` on a data zone. The other direction's symptom: `execute action=shell` denies on the cwd with `capability: 'exec'` and `Source "<slug>" denies shell execution (exec) to this caller`, though reads and writes there succeed.
194
203
 
195
- **Your baseline's `default` applies to YOUR PATTERN, not to the source.** The key you declare (`data://<self>/**`) scopes the whole entry: at seeding, that `default` block becomes a path RULE on that pattern, and the source keeps its own source-level default. This is why a `default: { exec: false }` in your manifest does not — and must not — turn off `exec` for the entire shared `data` source that every other package also declares against. One consequence worth knowing: because the shell and terminal read SOURCE-level policy for `exec`, a manifest `exec:false` is enforced on the brain-core git remote-op gate but does not restrict code execution under your subtree. Use a `floor: true` row for anything that must actually be unreachable.
204
+ **Your baseline's `default` applies to YOUR PATTERN, not to the source.** The key you declare (`data://<self>/**`) scopes the whole entry: at seeding, that `default` block becomes a path RULE on that pattern, and the source keeps its own source-level default. This is why a `default: { exec: false }` in your manifest does not — and must not — turn off `exec` for the entire shared `data` source that every other package also declares against. One consequence worth knowing: the shell and terminal judge `exec` on the working directory, so your manifest `exec:false` stops a shell from STARTING anywhere under your subtree (and binds the brain-core git remote-op gate) — but a command started elsewhere can still run a script it can read from there. Use a `floor: true` row for anything that must actually be unreachable.
196
205
 
197
206
  **Two limits on where your baselines land — and the one exception that is not limited.** Manifest `uriPolicies` baselines are seeded **only at first source attach, and only for source slugs literally named `data` or `packages`** — declare them expecting them to apply to a custom slug (`repo`, `machine`) and nothing happens; the persisted config is used verbatim. And **a new non-floor pattern in an updated package version does not reach existing installs**: only brand-new sources get it, pre-existing projects keep the old permissions indefinitely, and reaching them takes a version-stamped baseline repair pass. Plan for that whenever you tighten a shipped policy.
198
207
 
@@ -211,7 +220,7 @@ Denial surfaces as `uri_policy_denied` (HTTP 403, structured body with `uri` and
211
220
  | Refused, source slug unknown here | `source_not_configured` (`nextStep: check_configured_sources`, HTTP 404) | no persisted SourceConfig for that slug in this project — or one scoped to someone else, which answers identically. NB the uri gate runs FIRST and denies an unconfigured source as `uri_policy_denied`, so this code surfaces on the routes with no pre-guard (`list`) and for scheme-less uris — a scheme-bearing guess usually reads as the 403 row above | read the reply's `availableSources` (the caller's own visible set) and address one of those; retrying the same slug never helps |
212
221
  | Kind absent from the picker | *(log only)* | manifest entry incomplete, factory unresolvable, or trust rejected | read the server log line |
213
222
  | A mutating connector call refused while listing works | `403 Forbidden` on a `/connectors` write arm | the caller holds `core.observe` but not `core.connectors` | an admin performs it, or the feature is granted — never retry |
214
- | An outbound connector is listed nowhere, package `loaded` | *(log only:* `Connector registration refused: unresolved owning project`*)* | the package is not first-party and has no owning project, so it was registered into NO partition | resolve the owning project; the manifest is not the problem |
223
+ | An outbound connector is listed nowhere, package `loaded` | *(log only:* `Connector registration refused: unresolved owning project`*)* | the package is not native and has no owning project, so it was registered into NO partition | resolve the owning project; the manifest is not the problem |
215
224
  | Readable but invisible to semantic search | *(none)* | sync-excluded path — on disk, never indexed | do not conclude the file is missing |
216
225
 
217
226
  **Policy and enabled are orthogonal; the enabled check runs right after visibility** (a source you cannot see answers as absent, before any enabled or policy answer). Policy answers *which URIs you may touch*; the enable toggle (`true | false | 'auto'`, where `'auto'` derives from the connector runtime probe) answers *whether the source is live at all*. Conflate them and users flip the wrong switch.
@@ -220,7 +229,7 @@ Denial surfaces as `uri_policy_denied` (HTTP 403, structured body with `uri` and
220
229
 
221
230
  Live and enforced before any handler runs, where a **deny is absolute**. Three kinds compile:
222
231
 
223
- - **`safety`** — `config.blockedTools: string[]` is a tool blocklist and `config.timeoutMs` **plus** `config.target` is a per-tool timeout (`target` = a tool name, `*`, or a `fs_*` prefix; smallest matching timeout wins). Either half alone compiles to nothing. Both are **global** — a blocked name is denied for every caller and every package, not only yours — and that is exactly why they are **first-party-only**: from an installed or dropped package both are dropped at load, with a warning naming the kind. Do not reach for `safety` to restrict your own tools; `permission` does that at every trust level.
232
+ - **`safety`** — `config.blockedTools: string[]` is a tool blocklist and `config.timeoutMs` **plus** `config.target` is a per-tool timeout (`target` = a tool name, `*`, or a `fs_*` prefix; smallest matching timeout wins). Either half alone compiles to nothing. Both are **global** — a blocked name is denied for every caller and every package, not only yours — and that is exactly why they are **native-only**: from an installed or dropped package both are dropped at load, with a warning naming the kind. Do not reach for `safety` to restrict your own tools; `permission` does that at every trust level.
224
233
  - **`permission`** — `config.allowedTools: string[]`, an allowlist scoped to the declaring package. It also filters the visible tool catalog, so a denied tool is hidden, not merely refused.
225
234
  - **`trust`** — `config.enforceInputValidation: boolean`.
226
235
 
@@ -230,4 +239,4 @@ Two rules you never write are synthesized for every package: a **trust-tier ceil
230
239
 
231
240
  ---
232
241
 
233
- Public reference: [connectors](https://docs.neuralisapp.com/package-system/connectors) · [URI policies](https://docs.neuralisapp.com/package-system/uri-policies) · [sources and connectors in the brain](https://docs.neuralisapp.com/brain-core/sources-and-connectors)
242
+ Public reference: [connectors](https://docs.neuralisapp.com/package-system/connectors) · [URI policies](https://docs.neuralisapp.com/package-system/uri-policies) · [sources and connectors in the brain](https://docs.neuralisapp.com/brain-core/connectors)
@@ -91,7 +91,7 @@ Four skill layouts are recognised, not one — `skills/<name>/SKILL.md`, `<root-
91
91
 
92
92
  ## Trust and runtime
93
93
 
94
- **Trust is assigned by where the package came from, never declared.** `access.trust` is `first-party | trusted | untrusted`. A package installed as a dependency of the host is made `first-party` by the host after its manifest is read; a project-dropped package is pinned `untrusted` on its seed *before* the manifest merge, and the seed wins. Wherever the host assigns nothing, an **absent value means `untrusted`** — so `"access": {"trust": "first-party"}` in a package the host did not install as a dependency changes nothing.
94
+ **Trust is assigned by where the package came from, never declared.** `access.trust` is `native | trusted | untrusted`. A package installed as a dependency of the host is made `native` by the host after its manifest is read; a project-dropped package is pinned `untrusted` on its seed *before* the manifest merge, and the seed wins. Wherever the host assigns nothing, an **absent value means `untrusted`** — so `"access": {"trust": "native"}` in a package the host did not install as a dependency changes nothing.
95
95
 
96
96
  Untrusted implies, all at once: rules physically moved into the `docs` array (so they never inject into the system prompt), `activation.target: prompt-context` rewritten to `workspace`, `overwrite` forced false, `skillScripts` restricted to `"none"`, no `permissions.exec`, no `net: "full"`, no `fs: "full"`, no `seed: "auto"` sources.
97
97
 
@@ -101,15 +101,15 @@ Untrusted implies, all at once: rules physically moved into the `docs` array (so
101
101
 
102
102
  The three differ on two axes — LANGUAGE and CONFINEMENT — and only one of them gives a dropped package the second:
103
103
 
104
- - **`node`** — in-process, **first-party only**.
105
- - **`wasm`** — JS/TS compiled into an Extism sandbox. **The only code runtime available below first-party**, and what a dropped package declares to run code.
106
- - **`mcp`** — any language, as an stdio subprocess. Also **first-party only**: the child runs as the host user, with the host's filesystem and network reach, from the `entry.command` and `entry.args` your manifest names. It is a LANGUAGE escape hatch, never a confinement one. Pair it with `entry.command` or you get a warning.
104
+ - **`node`** — in-process, **native only**.
105
+ - **`wasm`** — JS/TS compiled into an Extism sandbox. **The only code runtime available below native**, and what a dropped package declares to run code.
106
+ - **`mcp`** — any language, as an stdio subprocess. Also **native only**: the child runs as the host user, with the host's filesystem and network reach, from the `entry.command` and `entry.args` your manifest names. It is a LANGUAGE escape hatch, never a confinement one. Pair it with `entry.command` or you get a warning.
107
107
 
108
- **Neither `node` nor `mcp` is rejected below first-party — both are DEMOTED.** The package warns and loads `partial`, reason `untrusted-node` or `untrusted-mcp`: declarative contributions register normally, no subprocess is spawned, and every tool and route handler returns a `code-runtime-unavailable` error. So if you are writing a project drop and you need to run code, the answer is `wasm` — declaring `mcp` to get a non-JS language will load the package and silently run none of it.
108
+ **Neither `node` nor `mcp` is rejected below native — both are DEMOTED.** The package warns and loads `partial`, reason `untrusted-node` or `untrusted-mcp`: declarative contributions register normally, no subprocess is spawned, and every tool and route handler returns a `code-runtime-unavailable` error. So if you are writing a project drop and you need to run code, the answer is `wasm` — declaring `mcp` to get a non-JS language will load the package and silently run none of it.
109
109
 
110
- **If you need an existing MCP server, do not reach for this runtime at all — but check WHERE that server runs before you plan around a connector either.** Declare an `{ "type": "mcp" }` **connector** (`connectors[]` — a different field and a different discriminator) when the server is reachable **over HTTP**: give it a `url`, and once connected it is dialed into the agent's MCP session with zero code and zero schema of yours. **A local stdio server (`command`) is not dialed in-host at any tier** — the transport factory refuses stdio and the session factory skips the assignment with a warning, so only `url` servers are reached. Two consequences worth stating plainly: a `"type": "mcp"` connector that omits `transport` **defaults to `stdio`**, i.e. to the refused one, so name `transport` explicitly for an HTTP server; and a **local** non-JS server has no working route below first-party today, by this path or by `runtime.type: "mcp"`. The intended shape for that case is a managed sidecar, which does not exist yet.
110
+ **If you need an existing MCP server, do not reach for this runtime at all — but check WHERE that server runs before you plan around a connector either.** Declare an `{ "type": "mcp" }` **connector** (`connectors[]` — a different field and a different discriminator) when the server is reachable **over HTTP**: give it a `url`, and once connected it is dialed into the agent's MCP session with zero code and zero schema of yours. **A local stdio server (`command`) is not dialed in-host at any tier** — the transport factory refuses stdio and the session factory skips the assignment with a warning, so only `url` servers are reached. Two consequences worth stating plainly: a `"type": "mcp"` connector that omits `transport` **defaults to `stdio`**, i.e. to the refused one, so name `transport` explicitly for an HTTP server; and a **local** non-JS server has no working route below native today, by this path or by `runtime.type: "mcp"`. The intended shape for that case is a managed sidecar, which does not exist yet.
111
111
 
112
- `runtime.binding: "embedded"` is the one true hard reject — a non-first-party package declaring it is marked `error` with `embedded binding requires first-party trust`; nothing registers.
112
+ `runtime.binding: "embedded"` is the one true hard reject — a non-native package declaring it is marked `error` with `embedded binding requires native trust`; nothing registers.
113
113
 
114
114
  **`runtime.skillScripts`** is `host | wasm-only | none`. An untrusted manifest declaring anything other than `"none"` fails validation (omitting it is also fine). Beyond that declaration-time check the value is **advertisement**: rendered as a tag in the package overview, enforcing nothing at runtime — do not plan around it blocking a spawn. Separately, `${SKILL_DIR}` resolves to a sentinel string only when a skill has **no host-side directory at all** (a source-contributed skill whose connector gives no container path); installed packages and project drops both resolve a real directory.
115
115
 
@@ -150,7 +150,7 @@ The three differ on two axes — LANGUAGE and CONFINEMENT — and only one of th
150
150
 
151
151
  **`meta.families`** groups tools for UI and feature gating. **`meta.distribution`** has exactly four keys — `installRoot`, `gitRepository`, `gitRef`, `npm`; no `homepage`, `repository` or `bugs` key exists there.
152
152
 
153
- **`source.kind`** records provenance — thirteen values: `neuralis`, `local-dir`, `mounted-dir`, `git`, `npm`, `archive`, `mcp-server`, plus the imported-ecosystem kinds `claude-skill`, `cursor-skill`, `gemini-extension`, `openclaw-plugin`, `openai-app`, `m365-agent`. Two rules bite: `git` **requires** `meta.distribution.gitRepository` or validation fails; `neuralis` is the marker the loader reads to treat a package as a host-owned builtin and select full in-process discovery — a project drop must never claim it.
153
+ **`source.kind`** records provenance — thirteen values: `neuralis`, `local-dir`, `mounted-dir`, `git`, `npm`, `archive`, `mcp-server`, plus the imported-ecosystem kinds `claude-skill`, `cursor-skill`, `gemini-extension`, `openclaw-plugin`, `openai-app`, `m365-agent`. Two rules bite: `git` **requires** `meta.distribution.gitRepository` or validation fails; `neuralis` is never authored: the host stamps it — with `native` trust — on every package of its install slots (its own dependencies and the packages installed while it runs), and only that stamped pair lets a package's code be imported; a manifest that declares it is ignored (the validator warns), and a project drop can never reach it.
154
154
 
155
155
  **Not in this contract — do not invent them:** no `category` enum, no curated keyword vocabulary beyond free-form `tags`, no `engines`/compatibility field, no manifest-level deprecation or yank key (`version` is metadata, not an update trigger — pulling a published version is a registry-side operation over the signed revocation feed, never a field you declare here).
156
156
 
@@ -169,13 +169,13 @@ Each of `tools`, `prompts`, `resources` takes `none | selected | all`; `selected
169
169
 
170
170
  ### A tool name is global: a collision is SHADOWED, not renamed
171
171
 
172
- A tool name is one key for the whole deployment, so two packages — or a package and one of the platform's own tools, or an MCP server — can claim the same one. **Nothing is renamed.** Each agent answers the name with ONE claimant, chosen by rule, never by load order: the **first-party** claimant wins if there is one (the platform's own tools included), otherwise the lexically-smallest `packageId`, and any package before an MCP server. A claimant the caller cannot use — its package switched off for that agent, out of scope, or its tool feature-gated for the caller — drops out BEFORE the rule, so it never takes the name from anyone. The losing package keeps every one of its OTHER tools.
172
+ A tool name is one key for the whole deployment, so two packages — or a package and one of the platform's own tools, or an MCP server — can claim the same one. **Nothing is renamed.** Each agent answers the name with ONE claimant, chosen by rule, never by load order: the **native** claimant wins if there is one (the platform's own tools included), otherwise the lexically-smallest `packageId`, and any package before an MCP server. A claimant the caller cannot use — its package switched off for that agent, out of scope, or its tool feature-gated for the caller — drops out BEFORE the rule, so it never takes the name from anyone. The losing package keeps every one of its OTHER tools.
173
173
 
174
174
  > **Symptom:** a call to your tool answers from another package. The package is healthy; the NAME is contested. An owner can pick your package for that name per agent in Tool Access, but by default the rule decides — rename your tool so nobody has to choose.
175
175
 
176
176
  Where to look: the boot log carries a `Namespace collisions detected` line naming the owner and the shadowed package ids, and `GET tools/catalog` returns a `contestedTools` row (`{name, owner, claimants, preferred?}`) for each name contested for that agent.
177
177
 
178
- So **pick a name nobody else will pick**. Prefix by domain, not by convenience — `acme_release_status`, not `status`. The rule is the ONLY protection, and it applies to every install class alike: the platform's own packages, an admin's `neuralis pkg add`'ed dependency and a project `_packages/` drop all fight for the same key. Trust decides who WINS the fight, never whether there is one — a host dependency is stamped `first-party` by the host regardless of its scope, so `@acme/*` next to `@neuralis/*` is a lexical tie-break, not a rescue. Nothing anywhere refuses to start over a collision: a taken name shadows, it never takes the deployment down.
178
+ So **pick a name nobody else will pick**. Prefix by domain, not by convenience — `acme_release_status`, not `status`. The rule is the ONLY protection, and it applies to every install class alike: the platform's own packages, an admin's `neuralis pkg add`'ed dependency and a project `_packages/` drop all fight for the same key. Trust decides who WINS the fight, never whether there is one — a host dependency is stamped `native` by the host regardless of its scope, so `@acme/*` next to `@neuralis/*` is a lexical tie-break, not a rescue. Nothing anywhere refuses to start over a collision: a taken name shadows, it never takes the deployment down.
179
179
 
180
180
  ## `dataLayout` — say where you keep your files
181
181
 
@@ -187,9 +187,9 @@ If your package writes under its own `data://` zone, declare the first-level dir
187
187
 
188
188
  `"machineWritten": [{ "path": "*/stats/*.json", "class": "metrics" }]` (inside `dataLayout`) names the files your package writes on its own — never rendered into the prompt. `path` is a glob relative to your zone (`*` one segment, `**` any depth; a leading `/`, an empty or `..` segment, or any character outside `[A-Za-z0-9._*-]` rejects the manifest); `class` is `metrics` (numbers only), `log` or `runtime-text` (runtime state a person may search for). A NEW project's `data` source leaves `metrics` files out of its index from the start; existing projects keep their settings. Declarations from untrusted packages are ignored.
189
189
 
190
- **The rest of the block is owned elsewhere:** `sources[]` / `connectors[]` / `uriPolicies` → `connectors-and-uri-policies.md` (a `uriPolicies` pattern may name only `packages://<self>/…` and `data://<self>/…`; a foreign namespace rejects the whole manifest — and a `connectors[]` entry registers into exactly ONE project partition, or into none at all when the package is neither first-party nor owned by a resolvable project), `credentials[]` / `configSettings[]` → `config-and-credentials.md`, `app.surfaces[]` → `surfaces-and-design.md`, `team[]` / workflows → `team-and-workflows.md` (note that `team[]` is VALIDATED fail-closed at load: a bad slug or a template path that leaves the package rejects the whole manifest).
190
+ **The rest of the block is owned elsewhere:** `sources[]` / `connectors[]` / `uriPolicies` → `connectors-and-uri-policies.md` (a `uriPolicies` pattern may name only `packages://<self>/…` and `data://<self>/…`; a foreign namespace rejects the whole manifest — and a `connectors[]` entry registers into exactly ONE project partition, or into none at all when the package is neither native nor owned by a resolvable project), `credentials[]` / `configSettings[]` → `config-and-credentials.md`, `app.surfaces[]` → `surfaces-and-design.md`, `team[]` / workflows → `team-and-workflows.md` (note that `team[]` is VALIDATED fail-closed at load: a bad slug or a template path that leaves the package rejects the whole manifest).
191
191
 
192
- ## `events[]` — notifications from your package (first-party only)
192
+ ## `events[]` — notifications from your package (native only)
193
193
 
194
194
  A package the host installs as a dependency can declare the moments a person should hear about — a run finished, a sync failed. The platform delivers them: a badge on your dock entry, a row in the user's inbox, per-person mute and follow. You build none of that UI. Any other install class has the field dropped at load with a warning.
195
195