@aifabrix/builder 2.53.1 → 2.55.0

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 (470) hide show
  1. package/README.md +8 -0
  2. package/bin/aifabrix.js +2 -2
  3. package/lib/agent-kit/apply-ops.js +82 -0
  4. package/lib/agent-kit/checksums.js +28 -0
  5. package/lib/agent-kit/classify.js +113 -0
  6. package/lib/agent-kit/claude-shim.js +61 -0
  7. package/lib/agent-kit/constants.js +55 -0
  8. package/lib/agent-kit/file-list.js +103 -0
  9. package/lib/agent-kit/host-approve.js +130 -0
  10. package/lib/agent-kit/hosting/github.js +63 -0
  11. package/lib/agent-kit/hosts.js +71 -0
  12. package/lib/agent-kit/init.js +319 -0
  13. package/lib/agent-kit/kit-root.js +17 -0
  14. package/lib/agent-kit/managed-section.js +79 -0
  15. package/lib/agent-kit/package-load.js +45 -0
  16. package/lib/agent-kit/plan-ops.js +69 -0
  17. package/lib/agent-kit/remote-prompts.js +239 -0
  18. package/lib/agent-kit/render-host-markdown.js +40 -0
  19. package/lib/agent-kit/repo-guard.js +47 -0
  20. package/lib/agent-kit/report.js +107 -0
  21. package/lib/agent-kit/run.js +82 -0
  22. package/lib/agent-kit/scm/git.js +122 -0
  23. package/lib/agent-kit/state-file.js +83 -0
  24. package/lib/agent-kit/status.js +50 -0
  25. package/lib/agent-kit/v1-detect.js +81 -0
  26. package/lib/agent-kit/validate-kit.js +87 -0
  27. package/lib/agent-kit/workspace-name.js +40 -0
  28. package/lib/agent-kit/workspace-skeleton.js +103 -0
  29. package/lib/api/assistants.api.js +8 -5
  30. package/lib/api/channel-identity.api.js +41 -0
  31. package/lib/api/evidence-authoring.api.js +5 -1
  32. package/lib/api/evidence.api.js +2 -0
  33. package/lib/api/role-assistant-test-pack.api.js +86 -0
  34. package/lib/api/types/evidence.types.js +2 -0
  35. package/lib/api/work-search.api.js +163 -0
  36. package/lib/api/work.api.js +19 -12
  37. package/lib/app/list-external-systems.js +2 -1
  38. package/lib/app/show-display.js +33 -6
  39. package/lib/app/show.js +25 -2
  40. package/lib/channels/add-channel.js +164 -126
  41. package/lib/channels/approval-guides/chatgpt.js +14 -18
  42. package/lib/channels/approval-guides/claude.js +29 -0
  43. package/lib/channels/approval-guides/index.js +88 -22
  44. package/lib/channels/approval-guides/mcp-client.js +27 -0
  45. package/lib/channels/approval-guides/microsoft-copilot.js +52 -3
  46. package/lib/channels/approval-guides/slack.js +10 -10
  47. package/lib/channels/approval-guides/teams-bot.js +8 -12
  48. package/lib/channels/channel-add-continuations.js +91 -0
  49. package/lib/channels/channel-add-ensure.js +124 -27
  50. package/lib/channels/channel-add-existing.js +160 -28
  51. package/lib/channels/channel-add-failure.js +61 -0
  52. package/lib/channels/channel-add-remaining.js +492 -0
  53. package/lib/channels/channel-add-tty.js +190 -0
  54. package/lib/channels/channel-add-wizard-config.js +138 -0
  55. package/lib/channels/channel-add-wizard.js +250 -0
  56. package/lib/channels/channel-artifact-generator.js +27 -13
  57. package/lib/channels/channel-cardinality.js +83 -0
  58. package/lib/channels/channel-catalog-icon.js +45 -0
  59. package/lib/channels/channel-cli-instructions.js +75 -0
  60. package/lib/channels/channel-configuration-map.js +213 -0
  61. package/lib/channels/channel-credential.js +11 -14
  62. package/lib/channels/channel-definition-project.js +101 -0
  63. package/lib/channels/channel-definition-registry.js +154 -0
  64. package/lib/channels/channel-definition-status.js +115 -0
  65. package/lib/channels/channel-description.js +60 -2
  66. package/lib/channels/channel-discovery.js +16 -2
  67. package/lib/channels/channel-external-system.js +86 -9
  68. package/lib/channels/channel-install-envelope-actions.js +88 -0
  69. package/lib/channels/channel-install-envelope-microsoft.js +155 -0
  70. package/lib/channels/channel-install-envelope.js +358 -0
  71. package/lib/channels/channel-install-help-md.js +172 -0
  72. package/lib/channels/channel-install-http-payload.js +62 -0
  73. package/lib/channels/channel-install-inventory.js +115 -0
  74. package/lib/channels/channel-install-profiles.js +90 -0
  75. package/lib/channels/channel-instance-collision.js +118 -0
  76. package/lib/channels/channel-instance-key.js +100 -0
  77. package/lib/channels/channel-instance-materialize.js +240 -0
  78. package/lib/channels/channel-integration-generator.js +18 -9
  79. package/lib/channels/channel-integration-template.js +101 -22
  80. package/lib/channels/channel-inventory-fetch.js +79 -0
  81. package/lib/channels/channel-oauth-preflight.js +104 -0
  82. package/lib/channels/channel-package-version.js +76 -0
  83. package/lib/channels/channel-predefined-client.js +154 -0
  84. package/lib/channels/channel-probe.js +7 -2
  85. package/lib/channels/channel-runtime-resolver.js +194 -72
  86. package/lib/channels/channel-status-display.js +86 -16
  87. package/lib/channels/channel-targets.js +132 -92
  88. package/lib/channels/chatgpt-callback.js +318 -0
  89. package/lib/channels/chatgpt-channel-add.js +229 -0
  90. package/lib/channels/chatgpt-preflight.js +396 -0
  91. package/lib/channels/chatgpt-runtime-contract.js +17 -0
  92. package/lib/channels/chatgpt-setup-values.js +124 -0
  93. package/lib/channels/claude-callback.js +67 -0
  94. package/lib/channels/claude-channel-add.js +254 -0
  95. package/lib/channels/claude-runtime-contract.js +40 -0
  96. package/lib/channels/claude-runtime.js +58 -0
  97. package/lib/channels/claude-setup-values.js +92 -0
  98. package/lib/channels/mcp-client/config-merge.js +148 -0
  99. package/lib/channels/mcp-client/ensure-client.js +231 -0
  100. package/lib/channels/mcp-client/paths.js +53 -0
  101. package/lib/channels/mcp-client/profiles.js +122 -0
  102. package/lib/channels/mcp-client/redirect-uris.js +99 -0
  103. package/lib/channels/mcp-client/runtime.js +59 -0
  104. package/lib/channels/mcp-client-channel-add.js +186 -0
  105. package/lib/channels/microsoft-copilot-channel-add.js +117 -7
  106. package/lib/channels/microsoft-copilot-entra-identifier-uris.js +187 -0
  107. package/lib/channels/microsoft-copilot-entra-sso-form.js +106 -18
  108. package/lib/channels/microsoft-copilot-entra-sso.js +31 -2
  109. package/lib/channels/microsoft-copilot-package-prior.js +107 -0
  110. package/lib/channels/microsoft-copilot-package.js +29 -28
  111. package/lib/channels/microsoft-provisioning/a365.js +80 -0
  112. package/lib/channels/microsoft-provisioning/auth-config.js +240 -0
  113. package/lib/channels/microsoft-provisioning/auth.js +179 -0
  114. package/lib/channels/microsoft-provisioning/cli.js +71 -0
  115. package/lib/channels/microsoft-provisioning/constants.js +75 -0
  116. package/lib/channels/microsoft-provisioning/errors.js +117 -0
  117. package/lib/channels/microsoft-provisioning/index.js +55 -0
  118. package/lib/channels/microsoft-provisioning/install-atk.js +158 -0
  119. package/lib/channels/microsoft-provisioning/install-teams.js +115 -0
  120. package/lib/channels/microsoft-provisioning/login-portal-device.js +236 -0
  121. package/lib/channels/microsoft-provisioning/login-portal-parse.js +71 -0
  122. package/lib/channels/microsoft-provisioning/login-portal-teams.js +193 -0
  123. package/lib/channels/microsoft-provisioning/login-portal.js +230 -0
  124. package/lib/channels/microsoft-provisioning/persist.js +110 -0
  125. package/lib/channels/microsoft-provisioning/teams-bot-args.js +119 -0
  126. package/lib/channels/microsoft-provisioning/teams-bot-controller.js +123 -0
  127. package/lib/channels/microsoft-provisioning/teams-bot-parse.js +134 -0
  128. package/lib/channels/microsoft-provisioning/teams-bot-persist.js +113 -0
  129. package/lib/channels/microsoft-provisioning/teams-bot-provision.js +234 -0
  130. package/lib/channels/microsoft-provisioning/teams-bot-secrets.js +45 -0
  131. package/lib/channels/microsoft-provisioning/teams-cli.js +82 -0
  132. package/lib/channels/runtime-tool-catalog.js +5 -2
  133. package/lib/channels/slack-channel-add-portal.js +130 -0
  134. package/lib/channels/slack-channel-add-tty-auth.js +95 -0
  135. package/lib/channels/slack-channel-add.js +311 -0
  136. package/lib/channels/slack-mcp-callback.js +51 -0
  137. package/lib/channels/slack-mcp-runtime.js +156 -0
  138. package/lib/channels/slack-provisioning/apps.js +181 -0
  139. package/lib/channels/slack-provisioning/auth-store.js +110 -0
  140. package/lib/channels/slack-provisioning/auth-ticket.js +185 -0
  141. package/lib/channels/slack-provisioning/auth.js +115 -0
  142. package/lib/channels/slack-provisioning/callbacks.js +41 -0
  143. package/lib/channels/slack-provisioning/cli.js +226 -0
  144. package/lib/channels/slack-provisioning/constants.js +37 -0
  145. package/lib/channels/slack-provisioning/credentials.js +169 -0
  146. package/lib/channels/slack-provisioning/curl-shim.js +132 -0
  147. package/lib/channels/slack-provisioning/developer-install.js +118 -0
  148. package/lib/channels/slack-provisioning/env-file.js +120 -0
  149. package/lib/channels/slack-provisioning/errors.js +47 -0
  150. package/lib/channels/slack-provisioning/go-ca-bundle.js +137 -0
  151. package/lib/channels/slack-provisioning/index.js +250 -0
  152. package/lib/channels/slack-provisioning/install-cli.js +335 -0
  153. package/lib/channels/slack-provisioning/manifest.js +89 -0
  154. package/lib/channels/slack-provisioning/oauth-lock.js +33 -0
  155. package/lib/channels/slack-provisioning/offer-cli.js +113 -0
  156. package/lib/channels/slack-provisioning/onboard-members.js +122 -0
  157. package/lib/channels/slack-provisioning/onboard.js +89 -0
  158. package/lib/channels/slack-provisioning/persist.js +95 -0
  159. package/lib/channels/slack-provisioning/remaining-urls.js +158 -0
  160. package/lib/channels/slack-provisioning/with-curl-on-path.js +53 -0
  161. package/lib/channels/teams-bot-channel-add.js +94 -0
  162. package/lib/channels/vendor-dataplane-url.js +249 -0
  163. package/lib/cli/index.js +4 -0
  164. package/lib/cli/setup-certification-commands.js +2 -2
  165. package/lib/cli/setup-certification.help.js +5 -1
  166. package/lib/cli/setup-external-system-help.js +2 -0
  167. package/lib/cli/setup-external-system.js +1 -1
  168. package/lib/commands/agent-kit-help.js +79 -0
  169. package/lib/commands/agent-kit.js +346 -0
  170. package/lib/commands/channel-add-help.js +366 -0
  171. package/lib/commands/channel-add-setup.js +162 -80
  172. package/lib/commands/channel-configure.js +118 -0
  173. package/lib/commands/channel.js +10 -1
  174. package/lib/commands/datasource-capability-relate-cli.js +5 -4
  175. package/lib/commands/governance-upload-external.js +6 -3
  176. package/lib/commands/lifecycle-command-action.js +2 -5
  177. package/lib/commands/lifecycle-external.js +93 -21
  178. package/lib/commands/repair-auth-apply.js +1 -1
  179. package/lib/commands/repair-datasource-key-skip.js +39 -0
  180. package/lib/commands/repair-datasource-keys.js +24 -12
  181. package/lib/commands/repair-datasource-test-payload.js +4 -2
  182. package/lib/commands/repair-datasource-webhooks-sync-bridge.js +23 -2
  183. package/lib/commands/repair-datasource.js +3 -0
  184. package/lib/commands/repair-external-run.js +59 -25
  185. package/lib/commands/repair-openapi-rest-runtime.js +127 -0
  186. package/lib/commands/repair-orchestration-tag-merge.js +339 -0
  187. package/lib/commands/repair-rbac-catalog-defaults.js +96 -0
  188. package/lib/commands/repair-rbac-platform-preset.js +26 -15
  189. package/lib/commands/repair-rbac-reader-roles.js +8 -21
  190. package/lib/commands/repair-rbac.js +26 -44
  191. package/lib/commands/repair-system-permissions.js +24 -22
  192. package/lib/commands/role-assistant-copy-output.js +61 -0
  193. package/lib/commands/role-assistant-copy.js +155 -0
  194. package/lib/commands/role-assistant-test-output.js +22 -9
  195. package/lib/commands/role-assistant-test-result-rows.js +42 -0
  196. package/lib/commands/role-assistant.js +150 -43
  197. package/lib/commands/search.js +143 -0
  198. package/lib/commands/test-e2e-external.js +148 -21
  199. package/lib/commands/test-trust-external.js +7 -5
  200. package/lib/commands/upload-credential-push-log.js +2 -1
  201. package/lib/commands/upload-publish-context.js +1 -1
  202. package/lib/commands/upload-role-assistant-shell.js +124 -0
  203. package/lib/commands/upload-sidecar-followups.js +10 -4
  204. package/lib/commands/upload.js +18 -3
  205. package/lib/commands/verify-operations-skip-e2e.js +131 -0
  206. package/lib/commands/verify-operations-step-plan.js +6 -33
  207. package/lib/commands/verify-operations-steps.js +3 -1
  208. package/lib/core/secrets-docker-env.js +4 -1
  209. package/lib/core/secrets-env-content.js +17 -3
  210. package/lib/datasource/capability/capability-manifest.js +0 -3
  211. package/lib/datasource/capability/copy-test-payload.js +3 -0
  212. package/lib/datasource/capability/relate-operations.js +28 -10
  213. package/lib/datasource/capability/run-capability-relate.js +48 -25
  214. package/lib/datasource/datasource-identifier.js +13 -5
  215. package/lib/deployment/deployer-poll-run.js +117 -35
  216. package/lib/external-system/deploy-dataplane-published.js +70 -0
  217. package/lib/external-system/deploy-helpers.js +26 -1
  218. package/lib/external-system/deploy.js +22 -8
  219. package/lib/external-system/download-helpers.js +29 -2
  220. package/lib/external-system/download-role-assistant.js +109 -4
  221. package/lib/external-system/download.js +46 -30
  222. package/lib/external-system/sync-deploy-manifest.js +3 -2
  223. package/lib/external-system/upload-identity.js +42 -0
  224. package/lib/generator/index.js +19 -15
  225. package/lib/generator/split.js +13 -2
  226. package/lib/generator/wizard-datasource-key.js +54 -0
  227. package/lib/generator/wizard.js +55 -54
  228. package/lib/integration-definition/apply-datasource-keys.js +75 -0
  229. package/lib/integration-definition/apply-relationships.js +195 -0
  230. package/lib/integration-definition/apply-static-enterprise.js +229 -0
  231. package/lib/integration-definition/apply-system-file.js +71 -0
  232. package/lib/integration-definition/apply-test-endpoint.js +89 -0
  233. package/lib/integration-definition/apply-viewpoint-defaults.js +157 -0
  234. package/lib/integration-definition/apply.js +78 -59
  235. package/lib/integration-definition/enrich-openapi-operations.js +36 -10
  236. package/lib/integration-definition/enrich-openapi-pick.js +87 -0
  237. package/lib/lifecycle/role-assistant-governance.js +181 -0
  238. package/lib/lifecycle/scenario-upload.js +181 -30
  239. package/lib/programmatic/builder-api-cors.js +143 -0
  240. package/lib/programmatic/builder-api-request.js +6 -0
  241. package/lib/programmatic/builder-api-route-dispatch.js +56 -42
  242. package/lib/programmatic/builder-api-server.js +8 -1
  243. package/lib/programmatic/capability-registry.js +55 -0
  244. package/lib/programmatic/channel-install-help-resolve.js +359 -0
  245. package/lib/programmatic/channel-install-session.js +218 -0
  246. package/lib/programmatic/help-content/channel-onboarding.md +2 -0
  247. package/lib/programmatic/help-content/cip-overview.md +3 -1
  248. package/lib/programmatic/http-raw-response.js +62 -0
  249. package/lib/programmatic/index.js +2 -0
  250. package/lib/programmatic/openapi-apply-result-schemas.js +8 -0
  251. package/lib/programmatic/openapi-channel-install-bindings.js +179 -0
  252. package/lib/programmatic/openapi-channel-install-schemas.js +289 -0
  253. package/lib/programmatic/openapi-component-schemas.js +19 -1
  254. package/lib/programmatic/openapi-description-enricher.js +3 -1
  255. package/lib/programmatic/openapi-descriptions.js +80 -3
  256. package/lib/programmatic/openapi-envelope-examples.js +124 -0
  257. package/lib/programmatic/openapi-operation-bindings.js +9 -1
  258. package/lib/programmatic/openapi-request-schemas.js +5 -0
  259. package/lib/programmatic/openapi-schema-descriptions-channel.js +319 -0
  260. package/lib/programmatic/openapi-schema-descriptions-operations.js +19 -0
  261. package/lib/programmatic/openapi-spec.js +13 -8
  262. package/lib/programmatic/platform-rbac-catalog.js +36 -18
  263. package/lib/programmatic/request-timeout.js +3 -0
  264. package/lib/programmatic/route-handler-map.js +58 -1
  265. package/lib/programmatic/route-handlers-context.js +2 -1
  266. package/lib/programmatic/run-auth-permissions.js +54 -0
  267. package/lib/programmatic/run-channel-catalog.js +238 -0
  268. package/lib/programmatic/run-channel-install-artifacts.js +137 -0
  269. package/lib/programmatic/run-channel-install-copilot.js +353 -0
  270. package/lib/programmatic/run-channel-install-options.js +236 -0
  271. package/lib/programmatic/run-channel-install-teams-bot.js +204 -0
  272. package/lib/programmatic/run-channel-install.js +346 -0
  273. package/lib/programmatic/run-channel-package.js +87 -7
  274. package/lib/programmatic/run-download.js +41 -0
  275. package/lib/programmatic/workspace-context.js +2 -0
  276. package/lib/protection/auth-context.js +3 -1
  277. package/lib/protection/protection-display.js +3 -2
  278. package/lib/protection/report-exit.js +50 -0
  279. package/lib/protection/run-commands.js +2 -0
  280. package/lib/role-assistant/evidence-sync.js +4 -2
  281. package/lib/role-assistant/evidence-validation-issues.js +51 -0
  282. package/lib/role-assistant/knowledge-sync.js +10 -4
  283. package/lib/role-assistant/package-validate.js +175 -0
  284. package/lib/role-assistant/settings.js +49 -2
  285. package/lib/role-assistant/test-case-assertion-row.js +36 -0
  286. package/lib/role-assistant/test-case-copy-bind.js +77 -0
  287. package/lib/role-assistant/test-case-copy-expected.js +127 -0
  288. package/lib/role-assistant/test-case-copy-from-work.js +90 -0
  289. package/lib/role-assistant/test-case-copy-interactions.js +67 -0
  290. package/lib/role-assistant/test-case-copy.js +119 -0
  291. package/lib/role-assistant/test-case-expected-catalog.js +135 -0
  292. package/lib/role-assistant/test-case-validate.js +88 -0
  293. package/lib/role-assistant/test-cases-bid.js +117 -4
  294. package/lib/role-assistant/test-cases-evaluate.js +159 -24
  295. package/lib/role-assistant/test-cases-evidence.js +175 -0
  296. package/lib/role-assistant/test-cases-honesty.js +155 -6
  297. package/lib/role-assistant/test-cases-lifecycle.js +291 -0
  298. package/lib/role-assistant/test-cases-search-graph.js +122 -0
  299. package/lib/role-assistant/test-cases-search.js +247 -0
  300. package/lib/role-assistant/test-cases.js +71 -172
  301. package/lib/role-assistant/test-pack-map.js +180 -0
  302. package/lib/role-assistant/test-pack-sync.js +187 -0
  303. package/lib/role-assistant/test-runner-debug.js +54 -0
  304. package/lib/role-assistant/test-runner-respond-body.js +36 -0
  305. package/lib/role-assistant/test-runner-search.js +164 -0
  306. package/lib/role-assistant/test-runner-start-payload.js +63 -10
  307. package/lib/role-assistant/test-runner-workhub-answers.js +45 -16
  308. package/lib/role-assistant/test-runner-workhub-helpers.js +40 -2
  309. package/lib/role-assistant/test-runner-workhub-soft.js +9 -3
  310. package/lib/role-assistant/test-runner-workhub.js +74 -32
  311. package/lib/role-assistant/test-runner.js +66 -11
  312. package/lib/schema/external-datasource.schema.json +146 -21
  313. package/lib/schema/external-system.schema.json +177 -2
  314. package/lib/schema/mcp-client-profile.schema.json +103 -0
  315. package/lib/schema/role-assistant-test-case.schema.json +408 -0
  316. package/lib/search/dataplane-context.js +23 -0
  317. package/lib/search/search-args.js +211 -0
  318. package/lib/search/search-display.js +238 -0
  319. package/lib/search/search-errors.js +50 -0
  320. package/lib/search/search-prompts.js +119 -0
  321. package/lib/search/search-roles.js +85 -0
  322. package/lib/search/search-run.js +241 -0
  323. package/lib/search/search-skills.js +198 -0
  324. package/lib/utils/app-path-resolve.js +4 -0
  325. package/lib/utils/authentication-env-template.js +44 -6
  326. package/lib/utils/authentication-slot-show.js +153 -0
  327. package/lib/utils/credential-display.js +43 -1
  328. package/lib/utils/credential-secrets-env.js +6 -1
  329. package/lib/utils/env-copy.js +19 -7
  330. package/lib/utils/external-env-template.js +20 -2
  331. package/lib/utils/external-system-readiness-compact-blocks.js +5 -1
  332. package/lib/utils/external-system-readiness-compact-display.js +30 -1
  333. package/lib/utils/external-system-validators.js +2 -1
  334. package/lib/utils/help-builder.js +3 -1
  335. package/lib/utils/paths.js +18 -1
  336. package/lib/utils/platform-shell-package.js +69 -0
  337. package/lib/utils/port-resolver.js +50 -1
  338. package/lib/utils/rewrite-name-flag.js +20 -0
  339. package/lib/utils/role-assistant-paths.js +13 -10
  340. package/lib/utils/schema-loader.js +37 -0
  341. package/lib/utils/schema-resolver.js +11 -1
  342. package/lib/utils/secrets-helpers.js +12 -21
  343. package/lib/utils/token-manager.js +10 -5
  344. package/lib/validation/validate-external-file.js +5 -1
  345. package/lib/validation/validate.js +41 -0
  346. package/package.json +1 -1
  347. package/templates/README.md +1 -1
  348. package/templates/agent-kit/adapters/claude/nested.CLAUDE.md +1 -0
  349. package/templates/agent-kit/adapters/claude/root.CLAUDE.md +5 -0
  350. package/templates/agent-kit/adapters/cursor/commands/cust-0-plan.md +5 -0
  351. package/templates/agent-kit/adapters/cursor/commands/cust-1-validate.md +5 -0
  352. package/templates/agent-kit/adapters/cursor/commands/cust-2-build.md +5 -0
  353. package/templates/agent-kit/adapters/cursor/commands/cust-3-push.md +5 -0
  354. package/templates/agent-kit/adapters/cursor/commands/cust-biz-1-validate.md +5 -0
  355. package/templates/agent-kit/adapters/cursor/commands/cust-biz-2-build.md +5 -0
  356. package/templates/agent-kit/adapters/cursor/commands/cust-biz-3-prove.md +5 -0
  357. package/templates/agent-kit/agent-kit.yaml +45 -0
  358. package/templates/agent-kit/instructions/AGENTKIT.md +83 -0
  359. package/templates/agent-kit/instructions/integration.AGENTS.md +25 -0
  360. package/templates/agent-kit/instructions/role-assistant.AGENTS.md +22 -0
  361. package/templates/agent-kit/instructions/root.AGENTS.md +37 -0
  362. package/templates/agent-kit/parity-inventory.yaml +188 -0
  363. package/templates/agent-kit/skills/aifabrix-connected-system/SKILL.md +58 -0
  364. package/templates/agent-kit/skills/aifabrix-connected-system/references/contract-checklist.md +40 -0
  365. package/templates/agent-kit/skills/aifabrix-connected-system/references/delivery-gates.md +54 -0
  366. package/templates/agent-kit/skills/aifabrix-connected-system/references/production-safety.md +35 -0
  367. package/templates/agent-kit/skills/aifabrix-connected-system/scripts/reserved-system-key.js +19 -0
  368. package/templates/agent-kit/skills/aifabrix-plan/SKILL.md +51 -0
  369. package/templates/agent-kit/skills/aifabrix-plan/references/challenge-checklist.md +108 -0
  370. package/templates/agent-kit/skills/aifabrix-plan/references/interaction.md +34 -0
  371. package/templates/agent-kit/skills/aifabrix-plan/references/plan-template.md +182 -0
  372. package/templates/agent-kit/skills/aifabrix-prove/SKILL.md +50 -0
  373. package/templates/agent-kit/skills/aifabrix-prove/references/demo-template.md +65 -0
  374. package/templates/agent-kit/skills/aifabrix-prove/references/evidence-lifecycle.md +68 -0
  375. package/templates/agent-kit/skills/aifabrix-prove/references/learning-template.md +66 -0
  376. package/templates/agent-kit/skills/aifabrix-role-assistant/SKILL.md +42 -0
  377. package/templates/agent-kit/skills/aifabrix-role-assistant/references/package-boundary.md +21 -0
  378. package/templates/agent-kit/skills/shared/hosts.md +78 -0
  379. package/templates/agent-kit/workspace/.cursor/plans/README.md +22 -0
  380. package/templates/agent-kit/workspace/LICENSE.mit +21 -0
  381. package/templates/agent-kit/workspace/README.md +89 -0
  382. package/templates/applications/builder-api/Dockerfile +3 -1
  383. package/templates/applications/builder-api/env.template +7 -0
  384. package/templates/applications/dataplane/application.yaml +6 -5
  385. package/templates/applications/dataplane/env.template +2 -2
  386. package/templates/applications/dataplane/rbac.yaml +35 -2
  387. package/templates/applications/keycloak/Dockerfile +30 -4
  388. package/templates/applications/keycloak/application.yaml +2 -2
  389. package/templates/applications/keycloak/cimd-lenient-parse/AbstractClientIdMetadataDocumentExecutor.java +896 -0
  390. package/templates/applications/keycloak/cimd-lenient-parse/SOURCE.md +19 -0
  391. package/templates/applications/keycloak/env.template +3 -0
  392. package/templates/applications/miso-controller/application.yaml +1 -2
  393. package/templates/applications/miso-controller/env.template +10 -9
  394. package/templates/channels/README.md +5 -5
  395. package/templates/channels/chatgpt/TROUBLESHOOTING.md +51 -0
  396. package/templates/channels/chatgpt/channel.json +59 -0
  397. package/templates/channels/chatgpt/icon.svg +1 -0
  398. package/templates/channels/chatgpt/install.template.md.hbs +20 -95
  399. package/templates/channels/chatgpt/integration/README.md +1 -1
  400. package/templates/channels/chatgpt/integration/application.json +2 -2
  401. package/templates/channels/chatgpt/integration/chatgpt-system.json +49 -4
  402. package/templates/channels/chatgpt/integration/env.template +2 -4
  403. package/templates/channels/chatgpt/integration/rbac.json +13 -0
  404. package/templates/channels/claude/TROUBLESHOOTING.md +44 -0
  405. package/templates/channels/claude/channel.json +59 -0
  406. package/templates/channels/claude/icon.svg +1 -0
  407. package/templates/channels/claude/install.template.md.hbs +22 -0
  408. package/templates/channels/claude/integration/README.md +14 -0
  409. package/templates/channels/claude/integration/application.json +15 -0
  410. package/templates/channels/claude/integration/claude-system.json +59 -0
  411. package/templates/channels/claude/integration/env.template +2 -0
  412. package/templates/channels/claude/integration/rbac.json +13 -0
  413. package/templates/channels/claude/manifest.template.json.hbs +40 -0
  414. package/templates/channels/mcp-client/channel.json +72 -0
  415. package/templates/channels/mcp-client/icon.svg +1 -0
  416. package/templates/channels/mcp-client/install.template.md.hbs +24 -0
  417. package/templates/channels/mcp-client/integration/README.md +13 -0
  418. package/templates/channels/mcp-client/integration/application.json +15 -0
  419. package/templates/channels/mcp-client/integration/env.template +2 -0
  420. package/templates/channels/mcp-client/integration/mcp-client-system.json +72 -0
  421. package/templates/channels/mcp-client/integration/rbac.json +13 -0
  422. package/templates/channels/mcp-client/manifest.template.json.hbs +41 -0
  423. package/templates/channels/mcp-client/profiles/cursor.json +26 -0
  424. package/templates/channels/mcp-client/profiles/github-copilot.json +29 -0
  425. package/templates/channels/mcp-client/profiles/vscode.json +29 -0
  426. package/templates/channels/microsoft-copilot/channel.json +73 -0
  427. package/templates/channels/microsoft-copilot/declarative-agent.template.json.hbs +8 -4
  428. package/templates/channels/microsoft-copilot/entra-sso-registration.template.md.hbs +65 -5
  429. package/templates/channels/microsoft-copilot/icon.svg +1 -0
  430. package/templates/channels/microsoft-copilot/install.template.md.hbs +9 -9
  431. package/templates/channels/microsoft-copilot/integration/README.md +1 -1
  432. package/templates/channels/microsoft-copilot/integration/application.json +2 -2
  433. package/templates/channels/microsoft-copilot/integration/env.template +3 -6
  434. package/templates/channels/microsoft-copilot/integration/microsoft-copilot-system.json +63 -4
  435. package/templates/channels/microsoft-copilot/integration/rbac.json +13 -0
  436. package/templates/channels/microsoft-copilot/oauth-plugin-vault-required.template.md.hbs +5 -5
  437. package/templates/channels/slack/channel.json +234 -0
  438. package/templates/channels/slack/icon.svg +1 -0
  439. package/templates/channels/slack/install.template.md.hbs +45 -28
  440. package/templates/channels/slack/integration/README.md +245 -22
  441. package/templates/channels/slack/integration/application.json +44 -7
  442. package/templates/channels/slack/integration/env.template +15 -6
  443. package/templates/channels/slack/integration/openapi/openapi.json +126 -0
  444. package/templates/channels/slack/integration/rbac.json +84 -0
  445. package/templates/channels/slack/integration/slack-datasource-commands.json +154 -0
  446. package/templates/channels/slack/integration/slack-datasource-conversations.json +28 -3
  447. package/templates/channels/slack/integration/slack-datasource-events.json +154 -0
  448. package/templates/channels/slack/integration/slack-datasource-interactive.json +154 -0
  449. package/templates/channels/slack/integration/slack-datasource-messages.json +40 -2
  450. package/templates/channels/slack/integration/slack-system.json +161 -72
  451. package/templates/channels/slack/manifest.template.json.hbs +10 -4
  452. package/templates/channels/teams-bot/channel.json +162 -0
  453. package/templates/channels/teams-bot/icon.svg +1 -0
  454. package/templates/channels/teams-bot/install.template.md.hbs +12 -13
  455. package/templates/channels/teams-bot/integration/README.md +5 -4
  456. package/templates/channels/teams-bot/integration/application.json +6 -4
  457. package/templates/channels/teams-bot/integration/env.template +5 -4
  458. package/templates/channels/teams-bot/integration/openapi/openapi.json +68 -0
  459. package/templates/channels/teams-bot/integration/rbac.json +21 -0
  460. package/templates/channels/teams-bot/integration/teams-bot-datasource-activities.json +154 -0
  461. package/templates/channels/teams-bot/integration/teams-bot-system.json +128 -23
  462. package/templates/channels/web-embed/channel.json +60 -0
  463. package/templates/channels/web-embed/install.template.md.hbs +1 -1
  464. package/templates/channels/web-embed/integration/README.md +2 -2
  465. package/templates/channels/web-embed/integration/application.json +2 -2
  466. package/templates/channels/web-embed/integration/env.template +1 -1
  467. package/templates/channels/web-embed/integration/rbac.json +13 -0
  468. package/templates/channels/web-embed/integration/web-embed-system.json +50 -4
  469. package/templates/python/docker-compose.hbs +14 -0
  470. package/templates/typescript/docker-compose.hbs +14 -0
@@ -86,7 +86,9 @@ async function runOperationsVerifySteps(systemKey, options) {
86
86
  }
87
87
  }
88
88
 
89
- if (!cliOptsSkipPublish(options)) {
89
+ // Upload is not publish. Verify against the already-deployed dataplane unless
90
+ // the caller opts in with upload: true (and did not pass --no-publish).
91
+ if (options.upload === true && !cliOptsSkipPublish(options)) {
90
92
  const uploadCtx = await syncLocalIfRequested(systemKey, options);
91
93
  attachUploadAuthToOptions(options, uploadCtx);
92
94
  }
@@ -10,7 +10,7 @@ const fs = require('fs');
10
10
  const yaml = require('js-yaml');
11
11
  const config = require('./config');
12
12
  const { getEnvHosts } = require('../utils/env-endpoints');
13
- const { getContainerPortFromPath } = require('../utils/port-resolver');
13
+ const { getContainerPortFromPath, isExternalAppPath } = require('../utils/port-resolver');
14
14
 
15
15
  /**
16
16
  * Gets base docker environment config
@@ -69,6 +69,9 @@ function getContainerPortFromDockerEnv(dockerEnv) {
69
69
  * @returns {Promise<string>} Updated content with PORT set
70
70
  */
71
71
  async function updatePortForDocker(resolved, variablesPath) {
72
+ if (isExternalAppPath(variablesPath)) {
73
+ return resolved;
74
+ }
72
75
  let dockerEnv = await getBaseDockerEnv();
73
76
  dockerEnv = applyDockerEnvOverride(dockerEnv);
74
77
 
@@ -29,7 +29,13 @@ const {
29
29
  applyDockerEnvOverride,
30
30
  getContainerPortFromDockerEnv
31
31
  } = require('./secrets-docker-env');
32
- const { getContainerPortFromPath, loadVariablesFromPath } = require('../utils/port-resolver');
32
+ const {
33
+ getContainerPortFromPath,
34
+ loadVariablesFromPath,
35
+ isExternalAppDoc,
36
+ isExternalAppPath,
37
+ stripListenPortEnvLines
38
+ } = require('../utils/port-resolver');
33
39
  const secretsEnsure = require('./secrets-ensure');
34
40
  const { resolveSecretsPath, getActualSecretsPath } = require('../utils/secrets-path');
35
41
  const pathsUtil = require('../utils/paths');
@@ -163,9 +169,14 @@ async function applyDockerTransformations(resolved, variablesPath) {
163
169
  envVars.REDIS_PORT = String(redisPort);
164
170
  envVars.DB_HOST = dbHost;
165
171
  envVars.DB_PORT = String(dbPort);
166
- envVars.PORT = String(containerPort);
172
+ if (!isExternalAppDoc(appDoc)) {
173
+ envVars.PORT = String(containerPort);
174
+ }
167
175
  resolved = interpolateEnvVars(resolved, envVars);
168
176
  resolved = rewriteDockerManifestPublicPortEnvLine(resolved, envVars, appDoc);
177
+ if (isExternalAppDoc(appDoc)) {
178
+ return resolved;
179
+ }
169
180
  return updatePortForDocker(resolved, variablesPath);
170
181
  }
171
182
 
@@ -389,10 +400,13 @@ function resolveEnvContentToWrite(resolved, pathToPreserve, options = {}) {
389
400
  async function writeResolvedEnv({ appName, envPath, resolved, variablesPath, secretsPath, opts }) {
390
401
  const preservePath = opts.preserveFromPath !== undefined && opts.preserveFromPath !== null ? opts.preserveFromPath : null;
391
402
  const pathToPreserve = preservePath !== null ? preservePath : envPath;
392
- const toWrite = resolveEnvContentToWrite(resolved, pathToPreserve, {
403
+ let toWrite = resolveEnvContentToWrite(resolved, pathToPreserve, {
393
404
  freshEnv: opts.freshEnv === true,
394
405
  pruneOrphanKv: opts.envOnly === true && opts.freshEnv !== true
395
406
  });
407
+ if (isExternalAppPath(variablesPath) && !/^PORT\s*=/m.test(resolved || '')) {
408
+ toWrite = stripListenPortEnvLines(toWrite);
409
+ }
396
410
  fs.writeFileSync(envPath, toWrite, { mode: 0o600 });
397
411
 
398
412
  if (!opts.skipOutputPath) {
@@ -27,11 +27,8 @@ const DEFAULT_RISK_BY_KEY = {
27
27
  };
28
28
 
29
29
  const RESOURCE_TYPE_MAP = {
30
- conversation: 'message',
31
30
  user: 'employee',
32
31
  person: 'employee',
33
- record: 'document',
34
- folder: 'document',
35
32
  country: 'organization',
36
33
  report: 'document',
37
34
  calendar: 'event',
@@ -1,5 +1,8 @@
1
1
  /**
2
2
  * Clone testPayload.scenarios rows when copying a capability.
3
+ * Deep-clones whole scenario objects and rewrites operation only. Nested row gold
4
+ * (expectedRows and related keys) is copied as-is; it may be wrong for --as —
5
+ * the author must edit after copy. Does not invent gold.
3
6
  *
4
7
  * @fileoverview Used by applyCapabilityCopy when includeTestPayload is true
5
8
  * @author AI Fabrix Team
@@ -78,23 +78,41 @@ function _buildRelationMetadataSchema({ relationName, targetDoc, resolvedTargetF
78
78
  return out;
79
79
  }
80
80
 
81
+ function relationNameFromCarrier(fields) {
82
+ const raw = String((Array.isArray(fields) && fields[0]) || '').trim();
83
+ if (!raw) {
84
+ return '';
85
+ }
86
+ if (/^[a-z][a-zA-Z0-9]*$/.test(raw)) {
87
+ return raw;
88
+ }
89
+ const camel = raw.replace(/[-_]([a-zA-Z0-9])/g, (_, ch) => String(ch).toUpperCase());
90
+ return /^[a-z][a-zA-Z0-9]*$/.test(camel) ? camel : '';
91
+ }
92
+
81
93
  /**
82
94
  * FK `name` must match schema: ^[a-z][a-zA-Z0-9]*$
95
+ * Defaults to the published carrier (fields[0]) when --relation-name is omitted.
83
96
  *
84
97
  * @param {string} raw
98
+ * @param {string[]} [fields]
85
99
  * @returns {string}
86
100
  */
87
- function normalizeRelationName(raw) {
101
+ function normalizeRelationName(raw, fields) {
88
102
  const s = String(raw || '').trim();
89
- if (!s) {
90
- throw new Error('--relation-name is required');
103
+ if (s) {
104
+ if (!/^[a-z][a-zA-Z0-9]*$/.test(s)) {
105
+ throw new Error(
106
+ `--relation-name "${s}" must match ^[a-z][a-zA-Z0-9]*$ (camelCase)`
107
+ );
108
+ }
109
+ return s;
91
110
  }
92
- if (!/^[a-z][a-zA-Z0-9]*$/.test(s)) {
93
- throw new Error(
94
- `--relation-name "${s}" must match ^[a-z][a-zA-Z0-9]*$ (camelCase)`
95
- );
111
+ const fromField = relationNameFromCarrier(fields);
112
+ if (fromField) {
113
+ return fromField;
96
114
  }
97
- return s;
115
+ throw new Error('--relation-name is required when --field is not a camelCase carrier');
98
116
  }
99
117
 
100
118
  /**
@@ -287,9 +305,9 @@ function buildForeignKeyRow(name, fields, targetDatasource, targetFields, option
287
305
  * }}
288
306
  */
289
307
  function applyCapabilityRelate(doc, opts) {
290
- const name = normalizeRelationName(opts.relationName);
291
- const targetDatasource = normalizeTargetDatasource(opts.targetDatasource);
292
308
  const { fields, targetFields } = parseRelateFields(opts);
309
+ const name = normalizeRelationName(opts.relationName, fields);
310
+ const targetDatasource = normalizeTargetDatasource(opts.targetDatasource);
293
311
 
294
312
  const d = deepClone(doc);
295
313
  if (!Array.isArray(d.foreignKeys)) {
@@ -25,13 +25,18 @@ function loadTargetDocLocal(targetDatasourceKey) {
25
25
  return localTarget.ok ? readJsonFile(localTarget.path) : null;
26
26
  }
27
27
 
28
- async function maybeFetchRemoteTargetConfig({ systemKeyForAuth, targetDatasourceKey }) {
28
+ async function maybeFetchRemoteTargetConfig({
29
+ systemKeyForAuth,
30
+ targetSystemKey,
31
+ targetDatasourceKey
32
+ }) {
29
33
  const remoteFetchMeta = { attempted: false, ok: false, notAuthenticated: false };
30
- if (!systemKeyForAuth) {
34
+ const authKey = String(targetSystemKey || systemKeyForAuth || '').trim();
35
+ if (!authKey) {
31
36
  return { remoteTargetConfig: null, remoteFetchMeta };
32
37
  }
33
38
  remoteFetchMeta.attempted = true;
34
- const remote = await tryFetchDatasourceConfig(systemKeyForAuth, targetDatasourceKey, { silent: true });
39
+ const remote = await tryFetchDatasourceConfig(authKey, targetDatasourceKey, { silent: true });
35
40
  if (remote.ok) {
36
41
  return {
37
42
  remoteTargetConfig: remote.datasourceConfig,
@@ -105,6 +110,38 @@ function applyRelateAndValidateSchema(parsed, opts, semanticWarnings, remoteVali
105
110
  return { result, validation };
106
111
  }
107
112
 
113
+ function persistOrDryRunRelate({
114
+ opts,
115
+ resolvedPath,
116
+ result,
117
+ validation,
118
+ semantic,
119
+ remoteFetchMeta
120
+ }) {
121
+ if (opts.dryRun) {
122
+ return buildRelateResultEnvelope({
123
+ dryRun: true,
124
+ resolvedPath,
125
+ result,
126
+ backupPath: null,
127
+ validation,
128
+ semanticWarnings: semantic.warnings,
129
+ remoteValidation: remoteFetchMeta
130
+ });
131
+ }
132
+ const backupPath = writeBackup(resolvedPath, Boolean(opts.noBackup));
133
+ atomicWriteJson(resolvedPath, result.doc);
134
+ return buildRelateResultEnvelope({
135
+ dryRun: false,
136
+ resolvedPath,
137
+ result,
138
+ backupPath,
139
+ validation,
140
+ semanticWarnings: semantic.warnings,
141
+ remoteValidation: remoteFetchMeta
142
+ });
143
+ }
144
+
108
145
  /**
109
146
  * @typedef {object} RunCapabilityRelateOpts
110
147
  * @property {string} fileOrKey
@@ -137,8 +174,10 @@ async function runCapabilityRelate(opts) {
137
174
 
138
175
  const targetDocLocal = loadTargetDocLocal(opts.targetDatasource);
139
176
  const systemKeyForAuth = resolveSystemKeyForAuth(parsed);
177
+ const targetSystemKey = resolveSystemKeyForAuth(targetDocLocal) || systemKeyForAuth;
140
178
  const { remoteTargetConfig, remoteFetchMeta } = await maybeFetchRemoteTargetConfig({
141
179
  systemKeyForAuth,
180
+ targetSystemKey,
142
181
  targetDatasourceKey: opts.targetDatasource
143
182
  });
144
183
  const semantic = runSemanticValidation({
@@ -159,33 +198,17 @@ async function runCapabilityRelate(opts) {
159
198
  semantic.warnings,
160
199
  remoteFetchMeta
161
200
  );
162
-
163
- if (opts.dryRun) {
164
- return buildRelateResultEnvelope({
165
- dryRun: true,
166
- resolvedPath,
167
- result,
168
- backupPath: null,
169
- validation,
170
- semanticWarnings: semantic.warnings,
171
- remoteValidation: remoteFetchMeta
172
- });
173
- }
174
-
175
- const backupPath = writeBackup(resolvedPath, Boolean(opts.noBackup));
176
- atomicWriteJson(resolvedPath, result.doc);
177
-
178
- return buildRelateResultEnvelope({
179
- dryRun: false,
201
+ return persistOrDryRunRelate({
202
+ opts,
180
203
  resolvedPath,
181
204
  result,
182
- backupPath,
183
205
  validation,
184
- semanticWarnings: semantic.warnings,
185
- remoteValidation: remoteFetchMeta
206
+ semantic,
207
+ remoteFetchMeta
186
208
  });
187
209
  }
188
210
 
189
211
  module.exports = {
190
- runCapabilityRelate
212
+ runCapabilityRelate,
213
+ resolveSystemKeyForAuth
191
214
  };
@@ -56,12 +56,20 @@ function pickIntegrationAppForDatasourceIdentifier(identifier, appNames) {
56
56
  if (!id) {
57
57
  return null;
58
58
  }
59
- const matches = appNames.filter(app => id === app || id.startsWith(`${app}-`));
60
- if (matches.length === 0) {
61
- return null;
59
+ const prefixMatches = (appNames || []).filter((app) => id === app || id.startsWith(`${app}-`));
60
+ if (prefixMatches.length > 0) {
61
+ prefixMatches.sort((a, b) => b.length - a.length);
62
+ return prefixMatches[0];
63
+ }
64
+ const keyMatches = (appNames || []).filter((app) => appHasDatasourceIdentifier(app, id));
65
+ if (keyMatches.length === 1) {
66
+ return keyMatches[0];
67
+ }
68
+ if (keyMatches.length > 1) {
69
+ keyMatches.sort((a, b) => b.length - a.length);
70
+ return keyMatches[0];
62
71
  }
63
- matches.sort((a, b) => b.length - a.length);
64
- return matches[0];
72
+ return null;
65
73
  }
66
74
 
67
75
  /**
@@ -18,52 +18,133 @@ const {
18
18
  const { resolvePollIntervalFromController } = require('./poll-interval');
19
19
  const { createDeployPollHandlers } = require('./deploy-poll-ui');
20
20
 
21
+ /** Same progress for this many polls + dataplane published → treat deploy as complete. */
22
+ const STUCK_PROGRESS_POLLS = 10;
23
+
24
+ function recordStuckProgress(state, snapshot) {
25
+ const progress = Number(snapshot && snapshot.progress);
26
+ const value = Number.isFinite(progress) ? progress : null;
27
+ if (value === state.lastProgress) {
28
+ state.stuckCount += 1;
29
+ } else {
30
+ state.lastProgress = value;
31
+ state.stuckCount = 1;
32
+ }
33
+ return state;
34
+ }
35
+
36
+ async function completeIfDataplanePublished(lastSeen, options) {
37
+ if (!lastSeen || typeof options.isDataplanePublished !== 'function') {
38
+ return null;
39
+ }
40
+ try {
41
+ if (await options.isDataplanePublished()) {
42
+ return {
43
+ ...lastSeen,
44
+ status: 'completed',
45
+ progress: 100,
46
+ completedViaDataplane: true
47
+ };
48
+ }
49
+ } catch {
50
+ return null;
51
+ }
52
+ return null;
53
+ }
54
+
21
55
  /**
22
- * Polls deployment status from controller.
23
- *
24
- * @async
25
- * @param {string} deploymentId
26
- * @param {string} controllerUrl
27
- * @param {string} envKey
28
- * @param {Object} authConfig
29
- * @param {Object} [options]
30
- * @returns {Promise<Object>}
56
+ * Poll until the controller job is terminal, or dataplane is already published.
57
+ * @param {Object} ctx
58
+ * @returns {Promise<Object|null>}
31
59
  */
60
+ async function pollUntilTerminal(ctx) {
61
+ const {
62
+ controllerUrl,
63
+ validatedEnvKey,
64
+ deploymentId,
65
+ pipelineAuthConfig,
66
+ interval,
67
+ maxAttempts,
68
+ onPollWait,
69
+ wrappedProgress,
70
+ stuckState,
71
+ options,
72
+ getLastSeen
73
+ } = ctx;
74
+ for (let attempt = 0; attempt < maxAttempts; attempt++) {
75
+ if (onPollWait) {
76
+ onPollWait(attempt, maxAttempts);
77
+ }
78
+ const response = await getPipelineDeployment(
79
+ controllerUrl,
80
+ validatedEnvKey,
81
+ deploymentId,
82
+ pipelineAuthConfig
83
+ );
84
+ const deploymentData = await processDeploymentStatusResponse(
85
+ response,
86
+ attempt,
87
+ maxAttempts,
88
+ interval,
89
+ deploymentId,
90
+ wrappedProgress
91
+ );
92
+ if (deploymentData) {
93
+ return deploymentData;
94
+ }
95
+ if (stuckState.stuckCount >= STUCK_PROGRESS_POLLS) {
96
+ const viaDataplane = await completeIfDataplanePublished(getLastSeen(), options);
97
+ if (viaDataplane) {
98
+ return viaDataplane;
99
+ }
100
+ }
101
+ }
102
+ return null;
103
+ }
104
+
32
105
  async function pollDeploymentStatus(deploymentId, controllerUrl, envKey, authConfig, options = {}) {
33
106
  const interval = options.interval || 5000;
34
107
  const maxAttempts = options.maxAttempts || 300;
35
-
36
108
  const validatedEnvKey = validateEnvironmentKey(envKey);
37
109
  const pipelineAuthConfig = convertToPipelineAuthConfig(authConfig);
38
-
39
110
  const onPollProgress = typeof options.onPollProgress === 'function' ? options.onPollProgress : null;
40
111
  const onPollWait = typeof options.onPollWait === 'function' ? options.onPollWait : null;
41
-
42
- for (let attempt = 0; attempt < maxAttempts; attempt++) {
43
- try {
44
- if (onPollWait) {
45
- onPollWait(attempt, maxAttempts);
46
- }
47
- const response = await getPipelineDeployment(controllerUrl, validatedEnvKey, deploymentId, pipelineAuthConfig);
48
- const deploymentData = await processDeploymentStatusResponse(
49
- response,
50
- attempt,
51
- maxAttempts,
52
- interval,
53
- deploymentId,
54
- onPollProgress
55
- );
56
- if (deploymentData) {
57
- return deploymentData;
58
- }
59
- } catch (error) {
60
- if (error.message && error.message.includes('not found')) {
61
- throw error;
62
- }
112
+ const stuckState = { lastProgress: undefined, stuckCount: 0 };
113
+ let lastSeen = null;
114
+ const wrappedProgress = (data, attempt, max) => {
115
+ lastSeen = data;
116
+ recordStuckProgress(stuckState, data);
117
+ if (onPollProgress) {
118
+ onPollProgress(data, attempt, max);
119
+ }
120
+ };
121
+ try {
122
+ const terminal = await pollUntilTerminal({
123
+ controllerUrl,
124
+ validatedEnvKey,
125
+ deploymentId,
126
+ pipelineAuthConfig,
127
+ interval,
128
+ maxAttempts,
129
+ onPollWait,
130
+ wrappedProgress,
131
+ stuckState,
132
+ options,
133
+ getLastSeen: () => lastSeen
134
+ });
135
+ if (terminal) {
136
+ return terminal;
137
+ }
138
+ } catch (error) {
139
+ if (error.message && error.message.includes('not found')) {
63
140
  throw error;
64
141
  }
142
+ throw error;
143
+ }
144
+ const timedOutComplete = await completeIfDataplanePublished(lastSeen, options);
145
+ if (timedOutComplete) {
146
+ return timedOutComplete;
65
147
  }
66
-
67
148
  throw new Error('Deployment timeout: Maximum polling attempts reached');
68
149
  }
69
150
 
@@ -94,7 +175,8 @@ async function pollDeployment(result, url, validatedEnvKey, authConfig, options)
94
175
  interval: resolvedInterval,
95
176
  maxAttempts,
96
177
  onPollProgress: pollUi.onPollProgress,
97
- onPollWait: pollUi.onPollWait
178
+ onPollWait: pollUi.onPollWait,
179
+ isDataplanePublished: options.isDataplanePublished
98
180
  }
99
181
  );
100
182
 
@@ -0,0 +1,70 @@
1
+ /**
2
+ * Treat a stuck controller deploy poll as complete when dataplane is already published.
3
+ *
4
+ * @fileoverview Dataplane published check for external deploy poll
5
+ */
6
+
7
+ 'use strict';
8
+
9
+ const { getExternalSystem } = require('../api/external-systems.api');
10
+ const { unwrapApiData } = require('../utils/external-system-readiness-core');
11
+ const { resolveDataplaneUrl } = require('../utils/dataplane-resolver');
12
+
13
+ /**
14
+ * @param {Object|null|undefined} system
15
+ * @returns {boolean}
16
+ */
17
+ function isDataplaneSystemPublished(system) {
18
+ const status = String((system && system.status) || '').toLowerCase();
19
+ return status === 'published' || status === 'deployed';
20
+ }
21
+
22
+ /**
23
+ * @param {string} controllerUrl
24
+ * @param {string} environment
25
+ * @param {Object} authConfig
26
+ * @param {string} systemKey
27
+ * @param {string} [dataplaneUrl]
28
+ * @returns {Promise<boolean>}
29
+ */
30
+ async function checkDataplaneSystemPublished(
31
+ controllerUrl,
32
+ environment,
33
+ authConfig,
34
+ systemKey,
35
+ dataplaneUrl
36
+ ) {
37
+ let url = dataplaneUrl;
38
+ if (!url) {
39
+ url = await resolveDataplaneUrl(controllerUrl, environment, authConfig, { silent: true });
40
+ }
41
+ const getRes = await getExternalSystem(url, systemKey, authConfig);
42
+ return isDataplaneSystemPublished(unwrapApiData(getRes));
43
+ }
44
+
45
+ /**
46
+ * @param {Object} params
47
+ * @returns {() => Promise<boolean>}
48
+ */
49
+ function createDataplanePublishedCheck(params) {
50
+ const { controllerUrl, environment, authConfig, systemKey, dataplaneUrl } = params;
51
+ return async function isDataplanePublished() {
52
+ try {
53
+ return await checkDataplaneSystemPublished(
54
+ controllerUrl,
55
+ environment,
56
+ authConfig,
57
+ systemKey,
58
+ dataplaneUrl
59
+ );
60
+ } catch {
61
+ return false;
62
+ }
63
+ };
64
+ }
65
+
66
+ module.exports = {
67
+ isDataplaneSystemPublished,
68
+ checkDataplaneSystemPublished,
69
+ createDataplanePublishedCheck
70
+ };
@@ -170,6 +170,30 @@ async function uploadDigitalWorkerIfNeeded(appName, options, _compact, manifest)
170
170
  });
171
171
  }
172
172
 
173
+ async function deployRoleAssistantShellIfNeeded(appName, options, baseDir) {
174
+ const { isRoleAssistantWorkspace } = require('../utils/platform-shell-package');
175
+ if (!isRoleAssistantWorkspace(baseDir)) {
176
+ return null;
177
+ }
178
+ const { formatSuccessParagraph } = require('../utils/cli-test-layout-chalk');
179
+ const logger = require('../utils/logger');
180
+ if (options.json !== true) {
181
+ logger.log(
182
+ formatSuccessParagraph(
183
+ 'Role Assistant deployment uses settings and Evidence upload (no Connected System publish).'
184
+ )
185
+ );
186
+ }
187
+ const { uploadExternalSystem } = require('../commands/upload');
188
+ return uploadExternalSystem(appName, {
189
+ ...options,
190
+ uploadStatus: 'published',
191
+ silentResolve: false,
192
+ suppressPipelineSpinner: false,
193
+ syncMode: false
194
+ });
195
+ }
196
+
173
197
  module.exports = {
174
198
  loadVariablesYaml,
175
199
  validateSingleSystemFile,
@@ -177,6 +201,7 @@ module.exports = {
177
201
  validateSingleDatasourceFile,
178
202
  validateDatasourceFiles,
179
203
  extractSystemKey,
180
- uploadDigitalWorkerIfNeeded
204
+ uploadDigitalWorkerIfNeeded,
205
+ deployRoleAssistantShellIfNeeded
181
206
  };
182
207
 
@@ -30,7 +30,8 @@ const { displayValidationResults } = require('../validation/validate-display');
30
30
  const { syncDeployJsonFromSources } = require('./sync-deploy-manifest');
31
31
  const { runDeployGateOrchestrator } = require('../commands/deploy-gate-orchestrator');
32
32
  const { runPostPublishDataSync } = require('../commands/run-post-publish-data-sync');
33
- const { uploadDigitalWorkerIfNeeded } = require('./deploy-helpers');
33
+ const { uploadDigitalWorkerIfNeeded, deployRoleAssistantShellIfNeeded } = require('./deploy-helpers');
34
+ const { createDataplanePublishedCheck } = require('./deploy-dataplane-published');
34
35
 
35
36
  /**
36
37
  * Validates manifest on dataplane (dry-run) before controller deploy.
@@ -194,9 +195,10 @@ const EXTERNAL_DEPLOY_POLL_INTERVAL_MS = 2000;
194
195
  /** 300 × 2s ≈ 10 minutes — must cover controller publish-job max wait with gates. */
195
196
  const EXTERNAL_DEPLOY_POLL_MAX_ATTEMPTS = 300;
196
197
 
197
- function buildExternalDeployPollOpts(options) {
198
+ function buildExternalDeployPollOpts(options, extra = {}) {
198
199
  return {
199
200
  ...options,
201
+ ...extra,
200
202
  poll: true,
201
203
  pollInterval:
202
204
  options.pollInterval !== undefined ? options.pollInterval : EXTERNAL_DEPLOY_POLL_INTERVAL_MS,
@@ -300,7 +302,15 @@ async function executeDeployAndDisplay(manifest, controllerUrl, environment, aut
300
302
  controllerUrl,
301
303
  environment,
302
304
  authConfig,
303
- buildExternalDeployPollOpts(options)
305
+ buildExternalDeployPollOpts(options, {
306
+ isDataplanePublished: createDataplanePublishedCheck({
307
+ controllerUrl,
308
+ environment,
309
+ authConfig,
310
+ systemKey: manifest.key,
311
+ dataplaneUrl: options.knownDataplaneUrl
312
+ })
313
+ })
304
314
  );
305
315
 
306
316
  const deploymentOutcome = parseControllerDeploymentOutcome(result);
@@ -412,17 +422,13 @@ async function validateDataplaneManifestForDeploy(manifest, authConfig, dataplan
412
422
  }
413
423
  }
414
424
 
415
- async function runExternalSystemDeployFlow(appName, options) {
416
- const compact = options.verbose !== true;
417
- const { appPath } = await detectAppType(appName);
418
- logOfflinePathWhenType(appPath);
425
+ async function runConnectedSystemDeployAfterDetect(appName, options, compact) {
419
426
  if (!compact) {
420
427
  logger.log(chalk.blue(`\n🚀 Deploying external system: ${appName}`));
421
428
  }
422
429
  await validateExternalSystemForDeploy(appName, options, compact);
423
430
  const gateOutcomes = await runDeployGateOrchestrator(appName, {
424
431
  ...options,
425
- // Compact deploy still shows step progress; only JSON mode stays fully quiet.
426
432
  quietDeployUi: options.json === true
427
433
  });
428
434
  await syncDeployJsonFromSources(appName);
@@ -453,6 +459,14 @@ async function runExternalSystemDeployFlow(appName, options) {
453
459
  });
454
460
  }
455
461
 
462
+ async function runExternalSystemDeployFlow(appName, options) {
463
+ const compact = options.verbose !== true;
464
+ const { appPath, baseDir } = await detectAppType(appName);
465
+ logOfflinePathWhenType(appPath);
466
+ const shellResult = await deployRoleAssistantShellIfNeeded(appName, options, baseDir);
467
+ return shellResult || runConnectedSystemDeployAfterDetect(appName, options, compact);
468
+ }
469
+
456
470
  /**
457
471
  * Deploys external system via controller pipeline (same as regular apps)
458
472
  *