primitive-admin 1.0.61 → 1.0.62

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 (300) hide show
  1. package/README.md +125 -69
  2. package/assets/skill/skills/primitive-platform/SKILL.md +336 -37
  3. package/dist/bin/primitive.js +25 -14
  4. package/dist/bin/primitive.js.map +1 -1
  5. package/dist/src/commands/analytics.js +36 -16
  6. package/dist/src/commands/analytics.js.map +1 -1
  7. package/dist/src/commands/apps.js +49 -188
  8. package/dist/src/commands/apps.js.map +1 -1
  9. package/dist/src/commands/blob-buckets.js +13 -153
  10. package/dist/src/commands/blob-buckets.js.map +1 -1
  11. package/dist/src/commands/collection-type-configs.js +14 -100
  12. package/dist/src/commands/collection-type-configs.js.map +1 -1
  13. package/dist/src/commands/collections.js +47 -8
  14. package/dist/src/commands/collections.js.map +1 -1
  15. package/dist/src/commands/config.d.ts +46 -0
  16. package/dist/src/commands/config.js +479 -0
  17. package/dist/src/commands/config.js.map +1 -0
  18. package/dist/src/commands/connections.js +12 -7
  19. package/dist/src/commands/connections.js.map +1 -1
  20. package/dist/src/commands/cron-triggers.js +84 -176
  21. package/dist/src/commands/cron-triggers.js.map +1 -1
  22. package/dist/src/commands/database-type-configs.d.ts +2 -0
  23. package/dist/src/commands/database-type-configs.js +171 -0
  24. package/dist/src/commands/database-type-configs.js.map +1 -0
  25. package/dist/src/commands/database-types.js +4 -4
  26. package/dist/src/commands/database-types.js.map +1 -1
  27. package/dist/src/commands/databases.d.ts +63 -0
  28. package/dist/src/commands/databases.js +649 -87
  29. package/dist/src/commands/databases.js.map +1 -1
  30. package/dist/src/commands/documents.js +869 -12
  31. package/dist/src/commands/documents.js.map +1 -1
  32. package/dist/src/commands/email-templates.js +18 -125
  33. package/dist/src/commands/email-templates.js.map +1 -1
  34. package/dist/src/commands/env.d.ts +12 -1
  35. package/dist/src/commands/env.js +98 -25
  36. package/dist/src/commands/env.js.map +1 -1
  37. package/dist/src/commands/feature-flags.d.ts +14 -0
  38. package/dist/src/commands/feature-flags.js +116 -0
  39. package/dist/src/commands/feature-flags.js.map +1 -0
  40. package/dist/src/commands/group-type-configs.js +14 -109
  41. package/dist/src/commands/group-type-configs.js.map +1 -1
  42. package/dist/src/commands/init.d.ts +9 -1
  43. package/dist/src/commands/init.js +1056 -277
  44. package/dist/src/commands/init.js.map +1 -1
  45. package/dist/src/commands/integrations.js +136 -421
  46. package/dist/src/commands/integrations.js.map +1 -1
  47. package/dist/src/commands/metadata-category-configs.d.ts +12 -0
  48. package/dist/src/commands/metadata-category-configs.js +112 -0
  49. package/dist/src/commands/metadata-category-configs.js.map +1 -0
  50. package/dist/src/commands/metadata.js +33 -141
  51. package/dist/src/commands/metadata.js.map +1 -1
  52. package/dist/src/commands/prompts.js +206 -563
  53. package/dist/src/commands/prompts.js.map +1 -1
  54. package/dist/src/commands/rule-sets.d.ts +1 -1
  55. package/dist/src/commands/rule-sets.js +16 -132
  56. package/dist/src/commands/rule-sets.js.map +1 -1
  57. package/dist/src/commands/scripts.js +67 -234
  58. package/dist/src/commands/scripts.js.map +1 -1
  59. package/dist/src/commands/sessions.js +17 -5
  60. package/dist/src/commands/sessions.js.map +1 -1
  61. package/dist/src/commands/sync-app-settings.d.ts +113 -70
  62. package/dist/src/commands/sync-app-settings.js +193 -242
  63. package/dist/src/commands/sync-app-settings.js.map +1 -1
  64. package/dist/src/commands/sync.d.ts +1932 -49
  65. package/dist/src/commands/sync.js +9521 -1769
  66. package/dist/src/commands/sync.js.map +1 -1
  67. package/dist/src/commands/tokens.js +8 -2
  68. package/dist/src/commands/tokens.js.map +1 -1
  69. package/dist/src/commands/users.js +92 -1
  70. package/dist/src/commands/users.js.map +1 -1
  71. package/dist/src/commands/vars.js +44 -58
  72. package/dist/src/commands/vars.js.map +1 -1
  73. package/dist/src/commands/webhooks.js +318 -156
  74. package/dist/src/commands/webhooks.js.map +1 -1
  75. package/dist/src/commands/workflows.d.ts +49 -12
  76. package/dist/src/commands/workflows.js +652 -1086
  77. package/dist/src/commands/workflows.js.map +1 -1
  78. package/dist/src/lib/access-rule-display.d.ts +21 -0
  79. package/dist/src/lib/access-rule-display.js +34 -0
  80. package/dist/src/lib/access-rule-display.js.map +1 -0
  81. package/dist/src/lib/api-client.d.ts +541 -61
  82. package/dist/src/lib/api-client.js +559 -102
  83. package/dist/src/lib/api-client.js.map +1 -1
  84. package/dist/src/lib/app-settings-descriptor.d.ts +180 -25
  85. package/dist/src/lib/app-settings-descriptor.js +403 -82
  86. package/dist/src/lib/app-settings-descriptor.js.map +1 -1
  87. package/dist/src/lib/canonical-json.d.ts +12 -0
  88. package/dist/src/lib/canonical-json.js +35 -0
  89. package/dist/src/lib/canonical-json.js.map +1 -0
  90. package/dist/src/lib/cli-manifest.d.ts +8 -0
  91. package/dist/src/lib/cli-manifest.js +1 -0
  92. package/dist/src/lib/cli-manifest.js.map +1 -1
  93. package/dist/src/lib/codegen-shared/generatedFiles.d.ts +6 -2
  94. package/dist/src/lib/codegen-shared/generatedFiles.js +9 -2
  95. package/dist/src/lib/codegen-shared/generatedFiles.js.map +1 -1
  96. package/dist/src/lib/codegen-shared/resolveCodegenSourceDir.d.ts +6 -6
  97. package/dist/src/lib/codegen-shared/resolveCodegenSourceDir.js +8 -8
  98. package/dist/src/lib/codegen-shared/resolveCodegenSourceDir.js.map +1 -1
  99. package/dist/src/lib/config-object-descriptor.d.ts +127 -0
  100. package/dist/src/lib/config-object-descriptor.js +658 -0
  101. package/dist/src/lib/config-object-descriptor.js.map +1 -0
  102. package/dist/src/lib/config-payload.d.ts +85 -0
  103. package/dist/src/lib/config-payload.js +116 -0
  104. package/dist/src/lib/config-payload.js.map +1 -0
  105. package/dist/src/lib/config-surface.d.ts +130 -0
  106. package/dist/src/lib/config-surface.js +300 -0
  107. package/dist/src/lib/config-surface.js.map +1 -0
  108. package/dist/src/lib/credentials-store.d.ts +10 -0
  109. package/dist/src/lib/credentials-store.js +23 -0
  110. package/dist/src/lib/credentials-store.js.map +1 -1
  111. package/dist/src/lib/data-input.d.ts +23 -0
  112. package/dist/src/lib/data-input.js +50 -0
  113. package/dist/src/lib/data-input.js.map +1 -0
  114. package/dist/src/lib/db-codegen/dbTemplates.js +1 -1
  115. package/dist/src/lib/db-codegen/dbTemplates.js.map +1 -1
  116. package/dist/src/lib/db-codegen/dbTypeIR.d.ts +1 -1
  117. package/dist/src/lib/env-resolver-core.d.ts +147 -0
  118. package/dist/src/lib/env-resolver-core.js +265 -0
  119. package/dist/src/lib/env-resolver-core.js.map +1 -0
  120. package/dist/src/lib/env-resolver.d.ts +28 -6
  121. package/dist/src/lib/env-resolver.js +44 -32
  122. package/dist/src/lib/env-resolver.js.map +1 -1
  123. package/dist/src/lib/generated-allowlist.js +12 -0
  124. package/dist/src/lib/generated-allowlist.js.map +1 -1
  125. package/dist/src/lib/generated-config-surfaces.d.ts +682 -0
  126. package/dist/src/lib/generated-config-surfaces.js +4058 -0
  127. package/dist/src/lib/generated-config-surfaces.js.map +1 -0
  128. package/dist/src/lib/generated-template-lint.d.ts +212 -0
  129. package/dist/src/lib/generated-template-lint.js +624 -0
  130. package/dist/src/lib/generated-template-lint.js.map +1 -0
  131. package/dist/src/lib/init-adopt.d.ts +16 -0
  132. package/dist/src/lib/init-adopt.js +34 -0
  133. package/dist/src/lib/init-adopt.js.map +1 -0
  134. package/dist/src/lib/init-assets.d.ts +39 -0
  135. package/dist/src/lib/init-assets.js +97 -0
  136. package/dist/src/lib/init-assets.js.map +1 -0
  137. package/dist/src/lib/init-config.d.ts +44 -5
  138. package/dist/src/lib/init-config.js +80 -7
  139. package/dist/src/lib/init-config.js.map +1 -1
  140. package/dist/src/lib/init-ios-links.d.ts +50 -0
  141. package/dist/src/lib/init-ios-links.js +153 -0
  142. package/dist/src/lib/init-ios-links.js.map +1 -0
  143. package/dist/src/lib/init-plan.d.ts +80 -0
  144. package/dist/src/lib/init-plan.js +95 -0
  145. package/dist/src/lib/init-plan.js.map +1 -0
  146. package/dist/src/lib/init-production-env.d.ts +48 -0
  147. package/dist/src/lib/init-production-env.js +59 -0
  148. package/dist/src/lib/init-production-env.js.map +1 -0
  149. package/dist/src/lib/init-schema.d.ts +74 -0
  150. package/dist/src/lib/init-schema.js +358 -0
  151. package/dist/src/lib/init-schema.js.map +1 -0
  152. package/dist/src/lib/init-xcode.d.ts +33 -0
  153. package/dist/src/lib/init-xcode.js +114 -0
  154. package/dist/src/lib/init-xcode.js.map +1 -0
  155. package/dist/src/lib/integration-request-config.d.ts +30 -0
  156. package/dist/src/lib/integration-request-config.js +145 -0
  157. package/dist/src/lib/integration-request-config.js.map +1 -0
  158. package/dist/src/lib/local-state.d.ts +55 -0
  159. package/dist/src/lib/local-state.js +167 -0
  160. package/dist/src/lib/local-state.js.map +1 -0
  161. package/dist/src/lib/log-inspection.d.ts +568 -0
  162. package/dist/src/lib/log-inspection.js +639 -0
  163. package/dist/src/lib/log-inspection.js.map +1 -0
  164. package/dist/src/lib/migration-nag.d.ts +2 -2
  165. package/dist/src/lib/migration-nag.js +3 -3
  166. package/dist/src/lib/object-status-filter.d.ts +22 -0
  167. package/dist/src/lib/object-status-filter.js +45 -0
  168. package/dist/src/lib/object-status-filter.js.map +1 -0
  169. package/dist/src/lib/output.d.ts +24 -1
  170. package/dist/src/lib/output.js +42 -1
  171. package/dist/src/lib/output.js.map +1 -1
  172. package/dist/src/lib/package-manager.d.ts +140 -0
  173. package/dist/src/lib/package-manager.js +305 -0
  174. package/dist/src/lib/package-manager.js.map +1 -0
  175. package/dist/src/lib/paginate.d.ts +50 -0
  176. package/dist/src/lib/paginate.js +53 -0
  177. package/dist/src/lib/paginate.js.map +1 -1
  178. package/dist/src/lib/platform-owned.d.ts +29 -3
  179. package/dist/src/lib/platform-owned.js +42 -3
  180. package/dist/src/lib/platform-owned.js.map +1 -1
  181. package/dist/src/lib/project-config.js +13 -5
  182. package/dist/src/lib/project-config.js.map +1 -1
  183. package/dist/src/lib/query-operators.d.ts +1 -1
  184. package/dist/src/lib/query-operators.js +1 -1
  185. package/dist/src/lib/record-filter.d.ts +18 -0
  186. package/dist/src/lib/record-filter.js +55 -0
  187. package/dist/src/lib/record-filter.js.map +1 -0
  188. package/dist/src/lib/resolve-init-dev-port.d.ts +56 -0
  189. package/dist/src/lib/resolve-init-dev-port.js +55 -0
  190. package/dist/src/lib/resolve-init-dev-port.js.map +1 -0
  191. package/dist/src/lib/resolve-init-server.d.ts +64 -0
  192. package/dist/src/lib/resolve-init-server.js +77 -0
  193. package/dist/src/lib/resolve-init-server.js.map +1 -0
  194. package/dist/src/lib/resolve-platform.d.ts +43 -14
  195. package/dist/src/lib/resolve-platform.js +74 -12
  196. package/dist/src/lib/resolve-platform.js.map +1 -1
  197. package/dist/src/lib/run-status.d.ts +19 -0
  198. package/dist/src/lib/run-status.generated.d.ts +39 -0
  199. package/dist/src/lib/run-status.generated.js +66 -0
  200. package/dist/src/lib/run-status.generated.js.map +1 -0
  201. package/dist/src/lib/run-status.js +19 -0
  202. package/dist/src/lib/run-status.js.map +1 -0
  203. package/dist/src/lib/server-text-normalization.d.ts +51 -0
  204. package/dist/src/lib/server-text-normalization.js +90 -0
  205. package/dist/src/lib/server-text-normalization.js.map +1 -0
  206. package/dist/src/lib/server-url.d.ts +22 -0
  207. package/dist/src/lib/server-url.js +33 -0
  208. package/dist/src/lib/server-url.js.map +1 -0
  209. package/dist/src/lib/signing-secret-status.d.ts +81 -0
  210. package/dist/src/lib/signing-secret-status.js +116 -0
  211. package/dist/src/lib/signing-secret-status.js.map +1 -0
  212. package/dist/src/lib/skill-installer.js +6 -3
  213. package/dist/src/lib/skill-installer.js.map +1 -1
  214. package/dist/src/lib/snapshots.d.ts +2 -2
  215. package/dist/src/lib/snapshots.js +2 -2
  216. package/dist/src/lib/swift-codegen/dbGenerator.d.ts +15 -2
  217. package/dist/src/lib/swift-codegen/dbGenerator.js +250 -18
  218. package/dist/src/lib/swift-codegen/dbGenerator.js.map +1 -1
  219. package/dist/src/lib/swift-codegen/generator.d.ts +11 -2
  220. package/dist/src/lib/swift-codegen/generator.js +181 -7
  221. package/dist/src/lib/swift-codegen/generator.js.map +1 -1
  222. package/dist/src/lib/swift-codegen/siblingSymbols.d.ts +7 -3
  223. package/dist/src/lib/swift-codegen/siblingSymbols.js +4 -1
  224. package/dist/src/lib/swift-codegen/siblingSymbols.js.map +1 -1
  225. package/dist/src/lib/sync-dir-selector.d.ts +21 -0
  226. package/dist/src/lib/sync-dir-selector.js +30 -0
  227. package/dist/src/lib/sync-dir-selector.js.map +1 -0
  228. package/dist/src/lib/sync-paths.d.ts +39 -0
  229. package/dist/src/lib/sync-paths.js +70 -2
  230. package/dist/src/lib/sync-paths.js.map +1 -1
  231. package/dist/src/lib/sync-resource-types.d.ts +138 -31
  232. package/dist/src/lib/sync-resource-types.js +241 -47
  233. package/dist/src/lib/sync-resource-types.js.map +1 -1
  234. package/dist/src/lib/sync-selectors.d.ts +95 -0
  235. package/dist/src/lib/sync-selectors.js +228 -0
  236. package/dist/src/lib/sync-selectors.js.map +1 -0
  237. package/dist/src/lib/template.d.ts +62 -4
  238. package/dist/src/lib/template.js +147 -39
  239. package/dist/src/lib/template.js.map +1 -1
  240. package/dist/src/lib/test-case-keys.d.ts +29 -0
  241. package/dist/src/lib/test-case-keys.js +55 -0
  242. package/dist/src/lib/test-case-keys.js.map +1 -0
  243. package/dist/src/lib/test-case-variables.d.ts +15 -0
  244. package/dist/src/lib/test-case-variables.js +29 -0
  245. package/dist/src/lib/test-case-variables.js.map +1 -0
  246. package/dist/src/lib/toml-database-config.d.ts +4 -4
  247. package/dist/src/lib/toml-database-config.js +27 -34
  248. package/dist/src/lib/toml-database-config.js.map +1 -1
  249. package/dist/src/lib/toml-metadata-config.d.ts +9 -5
  250. package/dist/src/lib/toml-metadata-config.js +40 -45
  251. package/dist/src/lib/toml-metadata-config.js.map +1 -1
  252. package/dist/src/lib/toml-native-form.d.ts +1 -1
  253. package/dist/src/lib/toml-native-form.js +1 -1
  254. package/dist/src/lib/toml-params-validator.d.ts +1 -1
  255. package/dist/src/lib/toml-params-validator.js +1 -1
  256. package/dist/src/lib/toml-scalar-edit.d.ts +43 -0
  257. package/dist/src/lib/toml-scalar-edit.js +283 -0
  258. package/dist/src/lib/toml-scalar-edit.js.map +1 -0
  259. package/dist/src/lib/user-selector.d.ts +24 -0
  260. package/dist/src/lib/user-selector.js +33 -0
  261. package/dist/src/lib/user-selector.js.map +1 -0
  262. package/dist/src/lib/version-check.d.ts +25 -0
  263. package/dist/src/lib/version-check.js +77 -8
  264. package/dist/src/lib/version-check.js.map +1 -1
  265. package/dist/src/lib/watch.d.ts +121 -0
  266. package/dist/src/lib/watch.js +169 -0
  267. package/dist/src/lib/watch.js.map +1 -0
  268. package/dist/src/lib/workflow-apply.d.ts +69 -45
  269. package/dist/src/lib/workflow-apply.js +99 -72
  270. package/dist/src/lib/workflow-apply.js.map +1 -1
  271. package/dist/src/lib/workflow-codegen/generator.js +4 -4
  272. package/dist/src/lib/workflow-codegen/generator.js.map +1 -1
  273. package/dist/src/lib/workflow-codegen/invokerIR.d.ts +11 -0
  274. package/dist/src/lib/workflow-codegen/invokerIR.js +5 -0
  275. package/dist/src/lib/workflow-codegen/invokerIR.js.map +1 -1
  276. package/dist/src/lib/workflow-config-apply.d.ts +70 -0
  277. package/dist/src/lib/workflow-config-apply.js +137 -0
  278. package/dist/src/lib/workflow-config-apply.js.map +1 -0
  279. package/dist/src/lib/workflow-config-sidecar.d.ts +63 -0
  280. package/dist/src/lib/workflow-config-sidecar.js +96 -0
  281. package/dist/src/lib/workflow-config-sidecar.js.map +1 -0
  282. package/dist/src/lib/workflow-defaults.d.ts +29 -0
  283. package/dist/src/lib/workflow-defaults.js +41 -0
  284. package/dist/src/lib/workflow-defaults.js.map +1 -0
  285. package/dist/src/lib/workflow-include-preserve.d.ts +76 -0
  286. package/dist/src/lib/workflow-include-preserve.js +286 -0
  287. package/dist/src/lib/workflow-include-preserve.js.map +1 -0
  288. package/dist/src/lib/workflow-payload.d.ts +31 -20
  289. package/dist/src/lib/workflow-payload.js +100 -110
  290. package/dist/src/lib/workflow-payload.js.map +1 -1
  291. package/dist/src/lib/workflow-toml-validator.d.ts +37 -16
  292. package/dist/src/lib/workflow-toml-validator.js +141 -16
  293. package/dist/src/lib/workflow-toml-validator.js.map +1 -1
  294. package/dist/src/types/index.d.ts +78 -22
  295. package/dist/src/validators.d.ts +7 -7
  296. package/dist/src/validators.js +6 -6
  297. package/package.json +11 -6
  298. package/dist/src/commands/settings.d.ts +0 -15
  299. package/dist/src/commands/settings.js +0 -102
  300. package/dist/src/commands/settings.js.map +0 -1
@@ -4,7 +4,7 @@ description: >
4
4
  Expert guide for building applications on the Primitive platform. MUST be used whenever the user
5
5
  is writing code that uses js-bao, js-bao-wss-client, primitive-app components, or any Primitive
6
6
  platform feature (documents, databases, workflows, prompts, integrations, blobs, authentication,
7
- users/groups). Also trigger whenever about to run any `primitive` CLI command (e.g., primitive sync, primitive integrations, primitive apps, primitive env) to ensure Step 0 CLI verification is performed first. After writing or modifying code that touches Primitive
7
+ users/groups). Also trigger whenever about to run any `primitive` CLI command (e.g., primitive config, primitive integrations, primitive apps, primitive env) to ensure Step 0 CLI verification is performed first. After writing or modifying code that touches Primitive
8
8
  APIs, this skill cross-references the implementation against official guides and automatically
9
9
  corrects common mistakes. Use this skill even if the user doesn't explicitly ask for it —
10
10
  any Primitive-related code should be validated against current best practices. Also use it
@@ -48,8 +48,15 @@ The two branches below are not equivalent — pick the one that matches reality
48
48
  The active environment is resolved in this order:
49
49
  1. `--env <name>` flag on the command
50
50
  2. `PRIMITIVE_ENV` environment variable
51
- 3. `defaultEnvironment` in `.primitive/config.json`
52
- 4. The sole environment, if exactly one is defined
51
+ 3. This machine's selection in `.primitive/local.json` (written by `primitive env use`, gitignored)
52
+ 4. `defaultEnvironment` in `.primitive/config.json` the committed team default
53
+ 5. The sole environment, if exactly one is defined
54
+
55
+ `primitive env use <name>` does NOT edit the committed config: pointing this
56
+ machine at a different backend never shows up as a file change. `env list`
57
+ shows the resolved current environment and the committed team default
58
+ separately, and reports a corrupt or dangling selection rather than falling
59
+ back to the default.
53
60
 
54
61
  Confirm you're targeting the correct environment:
55
62
 
@@ -58,13 +65,14 @@ Confirm you're targeting the correct environment:
58
65
  2. **Inspect the project config:**
59
66
 
60
67
  ```bash
61
- primitive env list # All environments (default marked with *)
68
+ primitive env list # All environments (CURRENT and TEAM DEFAULT shown separately)
62
69
  primitive env show # Details for the currently-resolved env
63
70
  primitive whoami # Authenticated user + resolved server/app
64
71
  ```
65
72
 
66
- **To switch environments** for a one-off command, pass `--env <name>`. To change the project
67
- default, run `primitive env use <name>`. To switch the *app* an env points at, edit the env's
73
+ **To switch environments** for a one-off command, pass `--env <name>`. To point this machine at
74
+ a different environment, run `primitive env use <name>` (local state; the committed
75
+ `defaultEnvironment` is unchanged). To switch the *app* an env points at, edit the env's
68
76
  `appId` in `.primitive/config.json` (or re-run `primitive env add`). `primitive use <app>` is a
69
77
  no-op when the active env already pins an `appId`.
70
78
 
@@ -109,7 +117,7 @@ dependencies.
109
117
 
110
118
  **Only fall back to global state if the user explicitly declines project setup** after you've
111
119
  recommended it. Even then, name the exact server/app the command will hit and get clear
112
- confirmation before running anything mutating (`primitive sync push`, `primitive apps create`, etc.).
120
+ confirmation before running anything mutating (`primitive config push`, `primitive apps create`, etc.).
113
121
  A read-only command (`whoami`, `guides list`) against global state is fine while you're still
114
122
  working out the config.
115
123
 
@@ -117,7 +125,7 @@ Do not rely on `.env` files like `PRIMITIVE_API_URL` to control CLI targeting
117
125
  read by the CLI in project mode, and the project config is the source of truth.
118
126
 
119
127
  **Why this matters:** If the CLI is pointed at the wrong environment (e.g., prod instead of dev),
120
- commands like `primitive sync push` will modify the wrong server. Silent fallback to global state
128
+ commands like `primitive config push` will modify the wrong server. Silent fallback to global state
121
129
  makes this exact mistake easy to commit. Setting up project config is the durable fix — verify and
122
130
  surface before running mutating operations.
123
131
 
@@ -166,7 +174,7 @@ guides. The guides contain:
166
174
  - Complete API documentation with method signatures
167
175
  - Working code examples in the requested language (e.g. TypeScript or Swift)
168
176
  - Common patterns and anti-patterns
169
- - Configuration examples (TOML files for `primitive sync`)
177
+ - Configuration examples (TOML files for `primitive config`)
170
178
  - Decision frameworks for architecture choices
171
179
 
172
180
  **Do not guess or assume API patterns.** If you're unsure about a method signature, parameter,
@@ -177,8 +185,8 @@ or pattern, fetch the guide. The guides are comprehensive and authoritative.
177
185
  When writing Primitive code:
178
186
 
179
187
  1. **Follow the patterns from the fetched guides exactly** — method names, argument order, lifecycle patterns
180
- 2. **Use `primitive sync`** for all backend configuration (workflows, prompts, integrations, databases)
181
- 3. **Configuration lives in TOML files** in version control, pushed via `primitive sync push`
188
+ 2. **Use `primitive config`** for all backend configuration (workflows, prompts, integrations, databases)
189
+ 3. **Configuration lives in TOML files** in version control, pushed via `primitive config push` — including test cases, authored as sidecars at `prompts/<key>.tests/`, `workflows/<key>.tests/`, `transforms/<name>.tests/` and `integrations/<key>.tests/` (one `[test]` file per case, with its attachments in a directory of the same name). A case file's name is its identity: `config pull` writes it back under that name and renaming it renames the case, so the checked-in tree reconciles on a fresh clone instead of duplicating
182
190
  4. **Run `pnpm codegen`** after creating or modifying js-bao models
183
191
 
184
192
  ## Step 4: Post-Code Review (Automatic)
@@ -204,14 +212,15 @@ Compare the written code against the guide content:
204
212
  - **Lifecycle management** — Are documents opened before queries? Is auth checked first?
205
213
  - **Access control** — Are CEL expressions or permissions configured properly?
206
214
  - **Anti-patterns** — Does the code do anything the guide explicitly warns against?
207
- - **Missing steps** — Does the code need `pnpm codegen`, `primitive sync push`, or other follow-up?
215
+ - **Untyped workflow invocation** — Is `client.workflows.start`/`runSync` called with a string-literal `workflowKey` and a hand-typed/cast `input`/`output` (e.g. `result.output as {...}`) instead of a generated invoker? That's a finding whenever the workflow has an `inputSchema`/`outputSchema` to generate from — regenerate with `primitive workflows codegen` (`--lang swift` for iOS/macOS) and call through the factory it emits instead, per the workflows guide's "Typed invocation (codegen)" section.
216
+ - **Missing steps** — Does the code need `pnpm codegen`, `primitive workflows codegen`, `primitive config push`, or other follow-up?
208
217
 
209
218
  ### 4c. Report and Fix
210
219
  If issues are found:
211
220
  1. **Explain the issue** — cite the specific guide section that applies
212
221
  2. **Show the fix** — provide corrected code
213
222
  3. **Apply the fix** — edit the file directly (don't just suggest, actually fix it)
214
- 4. **Note any CLI commands needed** — e.g., `pnpm codegen` or `primitive sync push`
223
+ 4. **Note any CLI commands needed** — e.g., `pnpm codegen` or `primitive config push`
215
224
 
216
225
  If no issues are found, briefly confirm the code follows best practices.
217
226
 
@@ -221,12 +230,12 @@ Remind users of these essential commands when relevant:
221
230
 
222
231
  ```bash
223
232
  # Verify current configuration (DO THIS FIRST)
224
- primitive env list # List environments in .primitive/config.json (default marked *)
233
+ primitive env list # List environments (CURRENT vs committed TEAM DEFAULT)
225
234
  primitive env show # Details for the currently-resolved env (api URL, app ID)
226
235
  primitive whoami # Authenticated user + resolved server/app
227
236
 
228
237
  # Switching environments
229
- primitive env use <name> # Change the project's default environment
238
+ primitive env use <name> # Select this machine's environment (gitignored local state)
230
239
  primitive --env <name> <command> # One-off override for a single command
231
240
  PRIMITIVE_ENV=<name> <command> # Override via env var (useful in scripts/CI)
232
241
 
@@ -239,7 +248,18 @@ primitive login # Authenticate (tokens s
239
248
  # Setup — brand-new project (greenfield only)
240
249
  primitive init my-new-app # Scaffolds template, creates a new app
241
250
  # on the server, runs pnpm install.
242
- # Do NOT run inside an existing repo.
251
+ primitive init my-new-app --platform web,ios # One app, a web client AND a native
252
+ # client: web/ and ios/, with the project
253
+ # config, git repo and the shared
254
+ # models/models.toml at the root.
255
+
256
+ # Setup — adding a client to an app that already exists
257
+ primitive init ios --platform ios # Run INSIDE the app's repo: adds the
258
+ # client to the app the nearest ancestor
259
+ # .primitive/config.json targets. Writes
260
+ # no nested .primitive/ or .git/ and makes
261
+ # no commit — review with `git status`.
262
+ # Read the multi-client guide first.
243
263
 
244
264
  # Guides (the most important commands for development)
245
265
  primitive guides list # See all guides: topics, descriptions, available (lang,platform) combinations
@@ -247,10 +267,26 @@ primitive guides get <topic> # Read a guide's default variant
247
267
  primitive guides get <topic> --language swift --platform ios # Read a specific language/platform variant
248
268
 
249
269
  # Configuration as Code
250
- primitive sync init --dir ./config # Initialize config directory
251
- primitive sync pull --dir ./config # Pull config from server
252
- primitive sync push --dir ./config # Push config to server
253
- primitive sync diff --dir ./config # Preview changes before push
270
+ primitive config init --dir ./config # Initialize config directory
271
+ primitive config pull --dir ./config # Pull config from server
272
+ primitive config push --dir ./config # Push config to server
273
+ primitive config diff --dir ./config # Preview changes before push
274
+
275
+ # Taking something out of service (or putting it back)
276
+ primitive workflows disable <key> # same verb pair on every type that has one
277
+ primitive cron-triggers disable <id>
278
+ primitive webhooks disable <id>
279
+ primitive integrations disable <key>
280
+ primitive prompts disable <key>
281
+ primitive users disable <user-id> # a person, not an object — reversible
282
+ primitive feature-flags disable <key> # super-admin platform toggle
283
+
284
+ # Retiring an object (soft delete; NOT the same as disable)
285
+ primitive workflows archive <key> # same verb on the five types that carry
286
+ primitive cron-triggers archive <id> # `archived`; confirms first, -y skips
287
+ primitive webhooks archive <id>
288
+ primitive integrations archive <id> # the ID column of `integrations list`
289
+ primitive prompts archive <id> # the ID column of `prompts list`
254
290
 
255
291
  # Common operations
256
292
  primitive apps list # List apps on the active env's server
@@ -258,6 +294,190 @@ primitive apps create "Name" # Create an app (does NOT auto-bind to an env
258
294
  # edit .primitive/config.json or use `env add` to bind)
259
295
  ```
260
296
 
297
+ **Availability is not configuration.** Whether a workflow, cron trigger,
298
+ webhook, integration or prompt is in service is one server-owned `status`
299
+ field, changed only by `<noun> enable|disable` (or the matching console
300
+ action) and by the delete flow, whose CLI spelling is `<noun> archive` on those
301
+ same five types. It is not a TOML key: `config pull` does not emit it,
302
+ `config push` never sends it, and a file that still carries a `status` line
303
+ fails the push with a message naming the verbs. So a push cannot put something back in service
304
+ that an operator took out of it, and a fresh environment stood up from config
305
+ has everything active. Anything newly created or pushed is active; there is no
306
+ `draft` state on any object.
307
+
308
+ **`archive` retires, `--prune` destroys.** `<noun> archive <id>` writes the
309
+ third value, `archived`: the delete lifecycle rather than availability. The row
310
+ is kept so its history still resolves, it goes on holding its key — and, for
311
+ webhooks and cron triggers, its slot against the per-app cap — `enable` refuses
312
+ it, and there is no un-archive. Reclaiming the key means a hard delete: remove
313
+ the object's TOML file and run a confirmed `primitive config push --prune`, then
314
+ re-add the file and push. There is no `--hard` flag and no per-type `delete`
315
+ verb; prune-by-push is the CLI's only hard delete. `users` and `admins` carry
316
+ `enable`/`disable` but no `archive` — people are not configuration objects.
317
+
318
+ Per-VERSION status is a different thing and stays in TOML: a prompt, workflow
319
+ or script config retires a named version with `status = "archived"` inside its
320
+ `[[configs]]` entry, which says which version is live, not whether the object
321
+ is serving.
322
+
323
+ ## Debugging and inspection
324
+
325
+ The CLI is the reference surface for inspecting a running app — reading what
326
+ happened without opening the admin UI. The inspection commands share one set of
327
+ conventions so they behave predictably across resources.
328
+
329
+ ```bash
330
+ # Workflow runs (the reference tailing command)
331
+ primitive workflows runs list <workflow-id> # recent runs
332
+ primitive workflows runs list <workflow-id> --json # normalized inspection items
333
+ primitive workflows runs list <workflow-id> --watch # re-render the list every 2s (snapshot)
334
+ primitive workflows runs list <workflow-id> --follow # append runs as they start or change (tail)
335
+ primitive workflows runs list --user-id <user-id> # one user's runs, across every workflow
336
+ primitive workflows runs steps <workflow-id> <run-id> # every step run of one run
337
+ primitive workflows runs status <workflow-id> <run-id> # one run's status + step results
338
+
339
+ # The other log-shaped views
340
+ primitive integrations logs <integration-id> # outbound calls: status, timing, actor
341
+ primitive webhooks events <webhook-id> # inbound deliveries and how they were handled
342
+ primitive analytics events # app activity events
343
+
344
+ # Per-subject analytics — one home, the analytics noun
345
+ primitive analytics workflows --window-days 7 # top workflows by runs
346
+ primitive analytics prompts --window-days 7 # top prompts by executions
347
+ primitive analytics integrations # calls, error rate, latency
348
+
349
+ # Blob storage
350
+ primitive blob-buckets list # buckets in the app (app-scoped: no selector)
351
+ primitive blob-buckets head <bucket> <key> # object metadata without downloading
352
+
353
+ # Live connections and sessions
354
+ primitive connections list --user-id <id> # active WebSocket connections
355
+ primitive sessions list --user-id <id> # auth sessions
356
+
357
+ # Database records and app documents
358
+ primitive databases records query <database> ... # read records
359
+ primitive databases records get <database> <model-name> <record-id>
360
+ primitive documents records query <document> <model-name> [--filter '{...}']
361
+ primitive documents records get <document> <model-name> <record-id>
362
+ primitive documents dump <document-id> # every model's records as JSON
363
+ primitive documents export <document-id> # dump a document's contents
364
+ primitive documents create "<title>" [--owner <user-id-or-email>] # mint a document (--owner needs a super-admin or assigned-console-admin token; app-role admins create as themselves)
365
+ primitive documents delete <document-id> [-y] [--json] # delete a document (document owner / app owner / super-admin or assigned-console-admin; app-role admins only via a containing collection's document.delete rule)
366
+
367
+ # Metadata
368
+ primitive metadata get <type> <id> <category> # resource metadata VALUES
369
+ primitive metadata-category-configs list # category DEFINITIONS (schema + read/write rules)
370
+ primitive metadata-category-configs get <type> <category>
371
+ ```
372
+
373
+ **Uniform flags across every inspection command:**
374
+
375
+ - `--app <id>` — target app (falls back to the resolved env's app).
376
+ - `--json` — the output you parse in scripts. Most commands print the endpoint
377
+ payload as-is; the log views below normalize theirs into the shared item
378
+ shape. Either way it is a JSON document, never a bare array — except the
379
+ type-config readers (`group-type-configs`, `collection-type-configs`,
380
+ `metadata-category-configs`), whose `list --json` prints the configs as a
381
+ bare array (`jq '.[]'`). Data goes to
382
+ stdout; status, warnings and the `CLI Version: …` banner go to stderr — so
383
+ even the always-JSON commands that take no `--json` flag pipe cleanly
384
+ (`primitive documents dump <doc> | jq .`).
385
+ - `--limit <n>` / `--cursor <c>` — paged reads. The response envelope is always
386
+ `{ items, hasMore, nextCursor? }`. Both `records query` verbs print that
387
+ envelope whatever shape their endpoint returns, and neither emits the
388
+ deprecated `cursor` alias — read `nextCursor`. Aggregate reads walk the
389
+ `nextCursor` chain.
390
+ - `list` always requires a **selector** (`--user-id`, `--owner`, a resource id, …)
391
+ so it never enumerates the whole app — **except** genuinely app-scoped
392
+ resources like `blob-buckets list`, which lists the app's buckets directly.
393
+ `--user-id` is the spelling on every list/inspection selector; `connections
394
+ list`, `sessions list` and `tokens list` still accept `--user` as a
395
+ deprecated alias that prints a notice on stderr.
396
+
397
+ **One `--json` item shape across the log views.** `workflows runs list`,
398
+ `workflows runs steps`, `integrations logs`, `webhooks events` and `analytics
399
+ events` all emit the same item envelope inside their endpoint's pagination
400
+ envelope — never a bare array:
401
+
402
+ ```json
403
+ {
404
+ "items": [
405
+ {
406
+ "source": "workflow-run",
407
+ "timestamp": "2026-07-24T18:03:11.204Z",
408
+ "outcome": "error",
409
+ "nativeStatus": "failed",
410
+ "correlation": { "runId": "01J…", "workflowId": "01J…", "userId": "01J…" },
411
+ "detail": { "workflowKey": "summarize", "errorMessage": "…" }
412
+ }
413
+ ],
414
+ "hasMore": false
415
+ }
416
+ ```
417
+
418
+ - `source` is the discriminator: `workflow-run`, `workflow-step`,
419
+ `integration`, `webhook`, `activity`.
420
+ - `outcome` is the normalized verdict — `ok`, `error`, `pending`, or `neutral`
421
+ — and `nativeStatus` keeps the source's own value (an HTTP integer, `failed`,
422
+ `duplicate`, …) verbatim, so filtering on the raw value stays possible. A
423
+ webhook that was accepted but matched no active workflow is `ok` with
424
+ `nativeStatus: "workflow_inactive"` — a non-dispatch, not a failure.
425
+ - `correlation` carries the pivot keys that let you follow one operation
426
+ between views (`runId`, `stepId`, `traceId`, `workflowId`, `webhookId`,
427
+ `userId`) plus the row's own id (`stepRunId`, `eventId`), so a row you
428
+ printed can always be looked up again.
429
+ - `detail` is a per-source allowlist of operator-facing fields, not the whole
430
+ stored record.
431
+ - Pagination rides alongside `items`: `hasMore` plus `nextCursor` where the
432
+ endpoint pages by cursor, `page`/`pageSize`/`totalRows` for `analytics
433
+ events`. `integrations logs` returns `{ items }` — it filters within a
434
+ bounded scan rather than paging.
435
+ - The normalization is `--json`-only: the human tables stay per-view because
436
+ each shows columns the shared shape has no room for (queue delay, inter-step
437
+ gap, token counts, event id). `--watch --json` reprints the same envelope
438
+ each tick; `--follow --json` emits one item per line (newline-delimited
439
+ JSON), since a tail has no closing bracket to wait for.
440
+
441
+ **Per-user inspection.** Two views can be keyed on a user:
442
+
443
+ ```bash
444
+ primitive workflows runs list --user-id <user-id> # every run that user started
445
+ primitive analytics events --user-id <user-id> # that user's activity events
446
+ ```
447
+
448
+ `workflows runs list --user-id` makes `<workflow-id>` optional — it lists the
449
+ user's runs across every workflow. Pass both to narrow to one workflow.
450
+ `integrations logs` and `webhooks events` have no `--user-id`: an integration
451
+ invocation records the actor but is indexed by integration, and a webhook event
452
+ carries no user identity at all. To follow a user through those, take the
453
+ `runId`/`traceId` from that user's workflow runs and match it in the
454
+ integration logs.
455
+
456
+ **`--watch` vs `--follow` (both poll — there is no server push):**
457
+
458
+ - `--watch` re-fetches the current snapshot each interval and re-renders the whole
459
+ view (a periodic re-`list`/`get`). It works on any list command with no server
460
+ change.
461
+ - `--follow` tails: it appends new/changed rows since a server-owned checkpoint,
462
+ like `tail -f`. It is offered **only** where the endpoint supports the resume
463
+ contract (today: `workflows runs list`); other commands offer only `--watch`
464
+ until their endpoint adds it. Passing `--follow` where it isn't supported fails
465
+ with a clear message.
466
+ - `--interval <seconds>` sets the poll interval (minimum 1s, default 2s).
467
+ - `--watch` and `--follow` are mutually exclusive.
468
+ - `--json --follow` emits **NDJSON** (one JSON object per new row per line) — a
469
+ tail is an unbounded stream, so it can't be one array; pipe it to `jq -c`.
470
+ `--json --watch` emits one array per redraw.
471
+ - Ctrl-C stops a tail cleanly (exit 0).
472
+
473
+ **`--follow` shows the latest observed version of a row, not every state change.**
474
+ It re-emits a run when a newer version is observed between polls, so a run you
475
+ already saw can reappear at its new position after its status changes — that is
476
+ expected, not a duplicate. Fast transitions that happen between two polls collapse
477
+ to the latest stored version. This is near-lossless observed-version tailing:
478
+ rows sharing a timestamp, or a delayed index update, can occasionally be skipped
479
+ or re-shown. Use it to watch activity, not as an exactly-once event log.
480
+
261
481
  ## When the User is Starting a New Feature
262
482
 
263
483
  If the user describes a new feature they want to build:
@@ -288,8 +508,9 @@ For any question about Primitive platform capabilities:
288
508
 
289
509
  When the user asks to upgrade the app to a newer platform version, follow this workflow.
290
510
  An upgrade is not just a version bump: after the libraries move, workarounds built for old
291
- platform bugs should come out, and new platform capabilities should be considered. The
292
- refreshed guides are the source of truth for what the platform can do now.
511
+ platform bugs should come out, the starter template the app was scaffolded from has usually
512
+ moved too, and new platform capabilities should be considered. The refreshed guides are the
513
+ source of truth for what the platform can do now.
293
514
 
294
515
  The backend is upgraded by the platform team, not by the app — the app only chooses which
295
516
  environment it points at (Step 0). A library upgrade against the production environment
@@ -349,7 +570,42 @@ Resolved. If not, keep it and note the version it was last checked against. Stal
349
570
  workarounds are a real cost — they mask platform behavior and confuse later readers —
350
571
  so default to removing them the moment they're unnecessary.
351
572
 
352
- ### 6. Adopt and suggest new features
573
+ ### 6. Adopt template updates
574
+
575
+ The app was scaffolded by `primitive init` from a starter template —
576
+ `Primitive-Labs/primitive-vue-template` for web apps, `Primitive-Labs/primitive-swift-template`
577
+ for iOS. Those templates keep moving with the platform: config, setup, and wiring fixes
578
+ land there and never reach an app generated months earlier. Scan the template the app came
579
+ from (both, if the app has a web and an iOS client) and pull forward what applies. Fetch
580
+ the branch matching the channel you're upgrading to — `main` for production, `alpha` for
581
+ alpha:
582
+
583
+ ```bash
584
+ # Vue
585
+ curl -sL https://github.com/Primitive-Labs/primitive-vue-template/archive/refs/heads/main.tar.gz \
586
+ | tar -xz -C /tmp
587
+ # Swift
588
+ gh api repos/Primitive-Labs/primitive-swift-template/tarball/main > /tmp/swift-template.tgz
589
+ ```
590
+
591
+ Then compare the template against the app file by file:
592
+
593
+ - **The app never changed it → move it over.** Where the app still carries the template's
594
+ version unchanged, take the newer one. That includes files the template has added since
595
+ the app was scaffolded. No need to ask.
596
+ - **The app removed it → leave it removed.** A file or block the app deleted was deleted
597
+ on purpose. Never restore it.
598
+ - **Both changed it → ask.** Where the app has its own edits to something the template
599
+ also changed, don't overwrite. Say what the template's change does and why it landed,
600
+ then ask whether to merge it in. Ask once per coherent change, not per hunk.
601
+
602
+ Telling those three cases apart needs a baseline: the template commit the app last synced
603
+ from, recorded in the feedback doc (below). With it, diff baseline→template to see what
604
+ the template changed and baseline→app to see what the app changed; only files in both
605
+ sets need a question. Without a stamp you can't tell an app edit from a template edit, so
606
+ treat every differing file as "ask" — and record the stamp this time.
607
+
608
+ ### 7. Adopt and suggest new features
353
609
 
354
610
  Re-run `primitive guides list` (topics appear and grow over time) and skim the refreshed
355
611
  guides for the app's feature areas. Compare against what the app actually does:
@@ -359,10 +615,11 @@ guides for the app's feature areas. Compare against what the app actually does:
359
615
  - Where a capability opens something new but needs a product decision, don't build it —
360
616
  report it as a suggestion with a pointer to the relevant guide section.
361
617
 
362
- ### 7. Verify and stamp
618
+ ### 8. Verify and stamp
363
619
 
364
620
  Run the app's tests, apply the Step 4 post-code review to everything modified, and
365
- update the feedback doc's upgrade stamp (date, channel, versions).
621
+ update the feedback doc's upgrade stamp (date, channel, versions, and the template
622
+ commit synced in Step 6).
366
623
 
367
624
  ### The platform feedback doc
368
625
 
@@ -378,6 +635,7 @@ have one, create it during the first upgrade:
378
635
  - Last upgraded: 2026-07-21
379
636
  - Channel: production
380
637
  - Versions: js-bao-wss-client 2.0.6, primitive-app 3.0.5, js-bao 0.5.1, primitive-admin 1.0.55
638
+ - Template: primitive-vue-template @ main 0f1c2d3
381
639
 
382
640
  ## Open items
383
641
  - [#1234] Symptom or missing capability. Workaround: `src/lib/foo.ts:42` (retry loop).
@@ -432,32 +690,60 @@ easy to reproduce on the first try:
432
690
 
433
691
  ```
434
692
  ## Repro steps
435
- <numbered, precise steps: exact API calls, config, versions>
693
+ <numbered, precise, minimal: exact API calls, config, versions. The test:
694
+ someone with no context reproduces it on the first try>
436
695
 
437
696
  ## Observed behavior
438
- <what actually happens, with verbatim error text>
697
+ <what actually happens, with verbatim error text / response bodies in fenced
698
+ blocks>
439
699
 
440
700
  ## Expected behavior
441
- <what should happen instead>
701
+ <what should happen instead, stated as an observable outcome — this is what
702
+ "fixed" means, and what a fix will be tested against>
703
+
704
+ ## Design review needed?
705
+ <tick any that apply; leave all unticked if the fix looks self-contained>
706
+
707
+ - [ ] Involves a critical security decision (auth, permissions, CEL, secrets, webhook
708
+ verification, DO routing)
709
+ - [ ] Risks a performance regression on a per-request, per-message or per-connection path
710
+ - [ ] Requires a data model or index change (`models.yaml`)
711
+ - [ ] Breaks an existing API contract (removes or retypes something in `openapi.json`, or
712
+ changes a `src/client` public signature non-additively)
442
713
  ```
443
714
 
444
- Labels: `type:bug` + `stage:ready-to-implement` when the repro is precise and clearly
445
- reproducible; otherwise `type:bug` + `stage:design`.
715
+ Write "Expected behavior" as the acceptance criterion: the observable outcome that
716
+ defines the bug as fixed. If prior investigation exists (an earlier thread, a
717
+ session's debugging), link it — don't inline a root-cause theory as fact.
718
+
719
+ The "Design review needed?" checkboxes decide the bug's route: any tick sends it
720
+ through the design gate; all unticked sends it straight to implementation, with
721
+ "Expected behavior" as the acceptance criteria. When unsure, leave a box unticked —
722
+ the worker re-checks against its own diff and routes itself back if one applies.
723
+
724
+ Labels: `type:bug` only.
446
725
 
447
726
  ### Features / enhancements / platform extensions
448
727
 
449
728
  ```
450
729
  ## Problem
451
- <the application-level problem being solved>
730
+ <the application-level problem being solved, and who hits it — a concrete
731
+ scenario, not an abstraction, and not a solution>
452
732
 
453
733
  ## What I tried
454
734
  <existing platform features attempted, and why each falls short — omit if none apply>
455
735
 
456
- ## Ideas
457
- <high-level directions as bullets, not specs>
736
+ ## What a solution needs to enable
737
+ <the outcomes a solution must make possible, as bullets capabilities from
738
+ the consumer's perspective, not designs>
458
739
  ```
459
740
 
460
- Labels: `type:feature` + `stage:design`.
741
+ Keep "What a solution needs to enable" outcome-shaped: "an app can resume a follow
742
+ from the last event it saw across restarts" — not "add a `resumeAfter` token to the
743
+ list endpoint". If you have a design idea worth preserving, put it in a comment,
744
+ clearly labeled as an idea — never in the body.
745
+
746
+ Labels: `type:feature` only.
461
747
 
462
748
  ### Filing
463
749
 
@@ -469,16 +755,29 @@ gh issue list --repo Primitive-Labs/js-bao-wss --search "<keywords>" --state ope
469
755
  --json number,title
470
756
  ```
471
757
 
472
- Then create the issue with labels only **no assignee** (triage assigns sponsors;
473
- unassigned is the correct starting state) and no priority labels:
758
+ Then create the issue with exactly one `type:*` label and nothing else — **no
759
+ assignee** (triage assigns sponsors; unassigned is the correct starting state), no
760
+ priority labels, no `state:*` label, and no `dispatch-v3` (state and dispatch labels
761
+ are added together by triage once it judges the filing complete — never by the
762
+ filer; an issue waiting for triage is the correct starting state):
474
763
 
475
764
  ```bash
476
765
  gh issue create --repo Primitive-Labs/js-bao-wss \
477
766
  --title "<one-line symptom or need>" \
478
- --label "type:bug,stage:design" \
767
+ --label "type:bug" \
479
768
  --body "<template body>"
480
769
  ```
481
770
 
771
+ The templates above mirror the canonical ones in the js-bao-wss repo at
772
+ `.claude/skills/_shared/templates/` (`bug-filing.md`, `feature-filing.md`,
773
+ `docs-filing.md`), which the pipeline validates against with
774
+ `.claude/skills/_shared/check-filing.sh` before an issue can be picked up — a body
775
+ missing a required section stalls in triage until a human repairs it. If the
776
+ templates here and the repo's ever disagree, the repo's win. When working inside a
777
+ js-bao-wss checkout, don't file by hand at all: use that repo's `/file-issue` skill,
778
+ which interviews for the sections, validates the draft offline, and files with the
779
+ right labels.
780
+
482
781
  ### Follow-up comments on existing issues
483
782
 
484
783
  When the duplicate search finds an issue that already covers the problem, comment
@@ -19,24 +19,25 @@ import { registerPromptsCommands } from "../src/commands/prompts.js";
19
19
  import { registerScriptsCommands } from "../src/commands/scripts.js";
20
20
  import { registerWorkflowsCommands } from "../src/commands/workflows.js";
21
21
  import { registerAdminsCommands } from "../src/commands/admins.js";
22
+ import { registerFeatureFlagsCommands } from "../src/commands/feature-flags.js";
22
23
  import { registerCatalogCommands } from "../src/commands/catalog.js";
23
24
  import { registerAnalyticsCommands } from "../src/commands/analytics.js";
24
- import { registerSyncCommands } from "../src/commands/sync.js";
25
- import { registerSettingsCommands } from "../src/commands/settings.js";
26
- import { registerLlmCommands } from "../src/commands/llm.js";
25
+ import { registerConfigSyncCommands } from "../src/commands/sync.js";
26
+ import { registerConfigCommands } from "../src/commands/config.js";
27
27
  import { registerComparisonsCommands } from "../src/commands/comparisons.js";
28
28
  import { registerTokensCommands } from "../src/commands/tokens.js";
29
29
  import { registerDatabasesCommands } from "../src/commands/databases.js";
30
30
  import { registerGroupsCommands } from "../src/commands/groups.js";
31
31
  import { registerRuleSetsCommands } from "../src/commands/rule-sets.js";
32
32
  import { registerGroupTypeConfigsCommands } from "../src/commands/group-type-configs.js";
33
- import { registerDatabaseTypesCommands } from "../src/commands/database-types.js";
33
+ import { registerDatabaseTypeConfigsCommands } from "../src/commands/database-type-configs.js";
34
34
  import { registerGuidesCommands } from "../src/commands/guides.js";
35
35
  import { registerDocumentsCommands } from "../src/commands/documents.js";
36
36
  import chalk from "chalk";
37
37
  import { registerEmailTemplatesCommands } from "../src/commands/email-templates.js";
38
38
  import { registerCollectionsCommands } from "../src/commands/collections.js";
39
39
  import { registerCollectionTypeConfigsCommands } from "../src/commands/collection-type-configs.js";
40
+ import { registerMetadataCategoryConfigsCommands } from "../src/commands/metadata-category-configs.js";
40
41
  import { error } from "../src/lib/output.js";
41
42
  import { installGlobalCrashHandlers } from "../src/lib/crash-handlers.js";
42
43
  import { buildCliManifest } from "../src/lib/cli-manifest.js";
@@ -190,8 +191,14 @@ if (!skipHeader) {
190
191
  : projectConfigPath
191
192
  ? " | Env: (none selected)"
192
193
  : "";
193
- console.log(chalk.dim(`CLI Version: ${pkg.version}${envLabel} | App: ${appInfo} | Server: ${server}`));
194
- console.log();
194
+ // The banner is a diagnostic, not data, so it goes to stderr alongside
195
+ // `info`/`warn`/`success`/`keyValue` (the stream-routing convention in
196
+ // `src/lib/output.ts`, issue #695). `skipHeader` already silences it under
197
+ // `--json`, but always-JSON commands with no `--json` flag — `documents
198
+ // dump` — were still emitting it above their payload, so `primitive
199
+ // documents dump <doc> | jq .` failed to parse (issue #2357).
200
+ console.error(chalk.dim(`CLI Version: ${pkg.version}${envLabel} | App: ${appInfo} | Server: ${server}`));
201
+ console.error();
195
202
  }
196
203
  // Nudge legacy-mode users (no .primitive/config.json, but a working
197
204
  // `~/.primitive/credentials.json` + a sync marker in CWD) to migrate.
@@ -218,7 +225,7 @@ Examples:
218
225
  $ primitive env add prod --api-url ... # Add a new environment
219
226
  $ primitive --env prod users list # Run a command against a specific env
220
227
  $ primitive login # Authenticate via browser OAuth
221
- $ primitive sync pull # Pull config (auto per-env path)
228
+ $ primitive config pull # Pull config (auto per-env path)
222
229
 
223
230
  Project configuration (.primitive/config.json):
224
231
  In a directory with a .primitive/config.json (or any subdirectory of one),
@@ -227,11 +234,12 @@ Project configuration (.primitive/config.json):
227
234
  Without a .primitive/config.json the CLI runs in legacy mode, reading
228
235
  credentials from ~/.primitive/credentials.json.
229
236
 
230
- Environment selection (project mode):
237
+ Primitive environment selection (project mode):
231
238
  1. --env <name> flag
232
239
  2. PRIMITIVE_ENV env var
233
- 3. "defaultEnvironment" in .primitive/config.json
234
- 4. The only environment, if there's exactly one
240
+ 3. This machine's selection in .primitive/local.json ('primitive env use')
241
+ 4. "defaultEnvironment" in .primitive/config.json (the committed team default)
242
+ 5. The only environment, if there's exactly one
235
243
 
236
244
  App Context:
237
245
  Bind an app to an environment via "appId" in .primitive/config.json, or
@@ -259,23 +267,26 @@ registerPromptsCommands(program);
259
267
  registerScriptsCommands(program);
260
268
  registerWorkflowsCommands(program);
261
269
  registerAdminsCommands(program);
270
+ registerFeatureFlagsCommands(program);
262
271
  registerCatalogCommands(program);
263
272
  registerAnalyticsCommands(program);
264
- registerSyncCommands(program);
265
- registerSettingsCommands(program);
266
- registerLlmCommands(program);
273
+ // One noun owns the TOML configuration tree (issue #2759): `config` carries
274
+ // the local authoring verbs and the server-reconciling verbs that used to be
275
+ // the `sync` group, so the group is created once and handed on.
276
+ registerConfigSyncCommands(registerConfigCommands(program));
267
277
  registerComparisonsCommands(program);
268
278
  registerTokensCommands(program);
269
279
  registerDatabasesCommands(program);
270
280
  registerGroupsCommands(program);
271
281
  registerRuleSetsCommands(program);
272
282
  registerGroupTypeConfigsCommands(program);
273
- registerDatabaseTypesCommands(program);
283
+ registerDatabaseTypeConfigsCommands(program);
274
284
  registerGuidesCommands(program);
275
285
  registerDocumentsCommands(program);
276
286
  registerEmailTemplatesCommands(program);
277
287
  registerCollectionsCommands(program);
278
288
  registerCollectionTypeConfigsCommands(program);
289
+ registerMetadataCategoryConfigsCommands(program);
279
290
  registerSkillCommands(program);
280
291
  registerSecretsCommands(program);
281
292
  registerVarsCommands(program);