@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
@@ -0,0 +1,122 @@
1
+ /**
2
+ * Graph hop assertions for expected.search (one-level related records).
3
+ *
4
+ * @fileoverview Evaluate graphDepth, relatedTypes, and related.minRows
5
+ * @author AI Fabrix Team
6
+ * @version 1.0.0
7
+ */
8
+
9
+ 'use strict';
10
+
11
+ function asObject(value) {
12
+ return value && typeof value === 'object' && !Array.isArray(value) ? value : {};
13
+ }
14
+
15
+ function relatedRows(payload, resourceType) {
16
+ const related = asObject(asObject(payload).related);
17
+ if (!Object.prototype.hasOwnProperty.call(related, resourceType)) {
18
+ return null;
19
+ }
20
+ const bundle = related[resourceType];
21
+ if (Array.isArray(bundle)) {
22
+ return bundle;
23
+ }
24
+ if (bundle && Array.isArray(bundle.data)) {
25
+ return bundle.data;
26
+ }
27
+ return [];
28
+ }
29
+
30
+ function relatedMeta(payload, resourceType) {
31
+ const bundle = asObject(asObject(payload).related)[resourceType];
32
+ return asObject(asObject(bundle).meta);
33
+ }
34
+
35
+ function evaluateGraphDepth(expectedSearch, meta) {
36
+ if (!Number.isFinite(Number(expectedSearch.graphDepth))) {
37
+ return null;
38
+ }
39
+ const expected = Number(expectedSearch.graphDepth);
40
+ const actual = Number(meta.graphDepth);
41
+ const passed = actual === expected;
42
+ return {
43
+ id: 'expected.search.graphDepth',
44
+ passed,
45
+ message: passed
46
+ ? `Search graphDepth matched ${expected}.`
47
+ : `Search graphDepth expected ${expected} but got ${Number.isFinite(actual) ? actual : 'none'}.`
48
+ };
49
+ }
50
+
51
+ function evaluateRelatedTypes(expectedTypes, meta) {
52
+ if (!Array.isArray(expectedTypes) || expectedTypes.length === 0) {
53
+ return [];
54
+ }
55
+ const observed = Array.isArray(meta.relatedTypes) ? meta.relatedTypes.map(String) : [];
56
+ return expectedTypes.map((item) => {
57
+ const key = String(item || '').trim();
58
+ const passed = Boolean(key && observed.includes(key));
59
+ return {
60
+ id: `expected.search.relatedTypes:${key}`,
61
+ passed,
62
+ message: passed
63
+ ? `Search relatedTypes included "${key}".`
64
+ : `Search relatedTypes did not include "${key}".`
65
+ };
66
+ });
67
+ }
68
+
69
+ function evaluateRelatedHop(resourceType, spec, payload) {
70
+ const assertions = [];
71
+ const rows = relatedRows(payload, resourceType);
72
+ if (Number.isFinite(Number(spec.minRows))) {
73
+ const minRows = Number(spec.minRows);
74
+ if (rows === null) {
75
+ assertions.push({
76
+ id: `expected.search.related.${resourceType}.minRows`,
77
+ passed: false,
78
+ message: `Related "${resourceType}" was omitted from the search graph.`
79
+ });
80
+ } else {
81
+ const passed = rows.length >= minRows;
82
+ assertions.push({
83
+ id: `expected.search.related.${resourceType}.minRows`,
84
+ passed,
85
+ message: passed
86
+ ? `Related "${resourceType}" returned at least ${minRows} row(s).`
87
+ : `Related "${resourceType}" returned ${rows.length} row(s); expected at least ${minRows}.`
88
+ });
89
+ }
90
+ }
91
+ if (spec.resultMode) {
92
+ const actual = String(relatedMeta(payload, resourceType).resultMode || '');
93
+ const passed = rows !== null && actual === String(spec.resultMode);
94
+ assertions.push({
95
+ id: `expected.search.related.${resourceType}.resultMode`,
96
+ passed,
97
+ message: passed
98
+ ? `Related "${resourceType}" resultMode matched "${spec.resultMode}".`
99
+ : `Related "${resourceType}" resultMode expected "${spec.resultMode}" but got "${actual || 'omitted'}".`
100
+ });
101
+ }
102
+ return assertions;
103
+ }
104
+
105
+ function evaluateSearchGraphExpectations(expectedSearch, payload, meta) {
106
+ const assertions = [];
107
+ const depth = evaluateGraphDepth(expectedSearch, meta);
108
+ if (depth) {
109
+ assertions.push(depth);
110
+ }
111
+ assertions.push(...evaluateRelatedTypes(expectedSearch.relatedTypes, meta));
112
+ const related = asObject(expectedSearch.related);
113
+ for (const resourceType of Object.keys(related)) {
114
+ const spec = asObject(related[resourceType]);
115
+ assertions.push(...evaluateRelatedHop(resourceType, spec, payload));
116
+ }
117
+ return assertions;
118
+ }
119
+
120
+ module.exports = {
121
+ evaluateSearchGraphExpectations
122
+ };
@@ -0,0 +1,247 @@
1
+ /**
2
+ * Assertions for work.skills / work.search role-assistant cases.
3
+ *
4
+ * @fileoverview Evaluate expected.search and expected.skills against Layer B results
5
+ * @author AI Fabrix Team
6
+ * @version 1.0.0
7
+ */
8
+
9
+ 'use strict';
10
+
11
+ const { operationKeys } = require('./test-runner-search');
12
+ const { skillsEnvelope } = require('../search/search-skills');
13
+ const { evaluateSearchGraphExpectations } = require('./test-cases-search-graph');
14
+
15
+ function asObject(value) {
16
+ return value && typeof value === 'object' && !Array.isArray(value) ? value : {};
17
+ }
18
+
19
+ function searchRows(payload) {
20
+ const body = asObject(payload);
21
+ if (Array.isArray(body.data)) {
22
+ return body.data;
23
+ }
24
+ return [];
25
+ }
26
+
27
+ function searchMeta(payload) {
28
+ const body = asObject(payload);
29
+ return asObject(body.meta);
30
+ }
31
+
32
+ function errorHaystack(searchObs) {
33
+ const payload = asObject(searchObs.payload);
34
+ return [
35
+ searchObs.errorText,
36
+ payload.error,
37
+ payload.detail,
38
+ payload.title,
39
+ payload.message
40
+ ]
41
+ .filter((row) => typeof row === 'string')
42
+ .join(' ');
43
+ }
44
+
45
+ function evaluateStatusCode(expectedCode, actualCode) {
46
+ if (!Number.isFinite(Number(expectedCode))) {
47
+ return null;
48
+ }
49
+ const expected = Number(expectedCode);
50
+ const actual = Number(actualCode);
51
+ const passed = actual === expected;
52
+ return {
53
+ id: 'expected.search.statusCode',
54
+ passed,
55
+ message: passed
56
+ ? `Search HTTP status matched ${expected}.`
57
+ : `Search HTTP status expected ${expected} but got ${actual}.`
58
+ };
59
+ }
60
+
61
+ function evaluateErrorContains(needle, haystack) {
62
+ if (typeof needle !== 'string' || !needle.trim()) {
63
+ return null;
64
+ }
65
+ const passed = String(haystack || '').toLowerCase().includes(needle.trim().toLowerCase());
66
+ return {
67
+ id: 'expected.search.errorContains',
68
+ passed,
69
+ message: passed
70
+ ? `Search error contained "${needle.trim()}".`
71
+ : `Search error did not contain "${needle.trim()}".`
72
+ };
73
+ }
74
+
75
+ function evaluateSearchShape(expectedSearch, searchObs) {
76
+ const assertions = [];
77
+ const meta = searchMeta(searchObs.payload);
78
+ const rows = searchRows(searchObs.payload);
79
+ if (expectedSearch.resultMode) {
80
+ const actual = String(meta.resultMode || '');
81
+ const passed = actual === String(expectedSearch.resultMode);
82
+ assertions.push({
83
+ id: 'expected.search.resultMode',
84
+ passed,
85
+ message: passed
86
+ ? `Search resultMode matched "${expectedSearch.resultMode}".`
87
+ : `Search resultMode expected "${expectedSearch.resultMode}" but got "${actual}".`
88
+ });
89
+ }
90
+ if (expectedSearch.operation) {
91
+ const actual = String(meta.operation || searchObs.arguments?.operation || '');
92
+ const passed = actual === String(expectedSearch.operation);
93
+ assertions.push({
94
+ id: 'expected.search.operation',
95
+ passed,
96
+ message: passed
97
+ ? `Search operation matched "${expectedSearch.operation}".`
98
+ : `Search operation expected "${expectedSearch.operation}" but got "${actual}".`
99
+ });
100
+ }
101
+ if (Number.isFinite(Number(expectedSearch.minRows))) {
102
+ const minRows = Number(expectedSearch.minRows);
103
+ const passed = rows.length >= minRows;
104
+ assertions.push({
105
+ id: 'expected.search.minRows',
106
+ passed,
107
+ message: passed
108
+ ? `Search returned at least ${minRows} row(s).`
109
+ : `Search returned ${rows.length} row(s); expected at least ${minRows}.`
110
+ });
111
+ }
112
+ return assertions;
113
+ }
114
+
115
+ function evaluateSearchExpectations(expectedSearch, observation) {
116
+ if (!expectedSearch || typeof expectedSearch !== 'object' || Array.isArray(expectedSearch)) {
117
+ return [];
118
+ }
119
+ const searchObs = asObject(observation.search);
120
+ const assertions = [];
121
+ const statusAssertion = evaluateStatusCode(expectedSearch.statusCode, searchObs.status);
122
+ if (statusAssertion) {
123
+ assertions.push(statusAssertion);
124
+ }
125
+ const errorAssertion = evaluateErrorContains(
126
+ expectedSearch.errorContains,
127
+ errorHaystack(searchObs)
128
+ );
129
+ if (errorAssertion) {
130
+ assertions.push(errorAssertion);
131
+ }
132
+ assertions.push(...evaluateSearchShape(expectedSearch, searchObs));
133
+ assertions.push(
134
+ ...evaluateSearchGraphExpectations(
135
+ expectedSearch,
136
+ searchObs.payload,
137
+ searchMeta(searchObs.payload)
138
+ )
139
+ );
140
+ return assertions;
141
+ }
142
+
143
+ function skillsResourceEntry(skillsPayload, resourceType) {
144
+ const root = skillsEnvelope(skillsPayload) || asObject(skillsPayload);
145
+ const rts = asObject(asObject(root).search).resourceTypes;
146
+ return asObject(asObject(rts)[resourceType]);
147
+ }
148
+
149
+ function evaluateSkillsOperations(expectedOps, spec) {
150
+ if (!Array.isArray(expectedOps) || expectedOps.length === 0) {
151
+ return [];
152
+ }
153
+ const observed = new Set(operationKeys(spec));
154
+ return expectedOps.map((operation) => {
155
+ const key = String(operation || '').trim();
156
+ const passed = observed.has(key);
157
+ return {
158
+ id: `expected.skills.operations:${key}`,
159
+ passed,
160
+ message: passed
161
+ ? `Search grammar published operation "${key}".`
162
+ : `Search grammar did not publish operation "${key}".`
163
+ };
164
+ });
165
+ }
166
+
167
+ function publishedFilterNames(spec) {
168
+ const names = new Set(Object.keys(asObject(spec.fields)));
169
+ const operations = Array.isArray(spec.operations) ? spec.operations : [];
170
+ for (const item of operations) {
171
+ const filters = item && typeof item === 'object' ? item.filters : null;
172
+ if (!Array.isArray(filters)) {
173
+ continue;
174
+ }
175
+ for (const name of filters) {
176
+ if (typeof name === 'string' && name.trim()) {
177
+ names.add(name.trim());
178
+ }
179
+ }
180
+ }
181
+ return names;
182
+ }
183
+
184
+ function evaluateSkillsFilterFields(expectedFields, spec) {
185
+ if (!Array.isArray(expectedFields) || expectedFields.length === 0) {
186
+ return [];
187
+ }
188
+ const published = publishedFilterNames(spec);
189
+ return expectedFields.map((name) => {
190
+ const key = String(name || '').trim();
191
+ const passed = Boolean(key && published.has(key));
192
+ return {
193
+ id: `expected.skills.filterFields:${key}`,
194
+ passed,
195
+ message: passed
196
+ ? `Search grammar published filter field "${key}".`
197
+ : `Search grammar did not publish filter field "${key}".`
198
+ };
199
+ });
200
+ }
201
+
202
+ function evaluateSkillsExpectations(expectedSkills, observation) {
203
+ if (!expectedSkills || typeof expectedSkills !== 'object' || Array.isArray(expectedSkills)) {
204
+ return [];
205
+ }
206
+ const skillsObs = asObject(observation.skills);
207
+ const payload = skillsObs.payload;
208
+ const resourceType = String(expectedSkills.resourceType || '').trim();
209
+ const spec = resourceType ? skillsResourceEntry(payload, resourceType) : {};
210
+ const assertions = [];
211
+ if (resourceType) {
212
+ const passed = Object.keys(spec).length > 0;
213
+ assertions.push({
214
+ id: 'expected.skills.resourceType',
215
+ passed,
216
+ message: passed
217
+ ? `work.skills published resourceType "${resourceType}".`
218
+ : `work.skills did not publish resourceType "${resourceType}".`
219
+ });
220
+ }
221
+ if (expectedSkills.operationRequired === false) {
222
+ assertions.push({
223
+ id: 'expected.skills.operationRequired',
224
+ passed: true,
225
+ skip: true,
226
+ kind: 'skip',
227
+ message: 'operationRequired is false — check skipped.'
228
+ });
229
+ } else if (expectedSkills.operationRequired === true) {
230
+ const passed = spec.operationRequired === true;
231
+ assertions.push({
232
+ id: 'expected.skills.operationRequired',
233
+ passed,
234
+ message: passed
235
+ ? 'work.skills marked operationRequired for this resourceType.'
236
+ : 'work.skills did not mark operationRequired for this resourceType.'
237
+ });
238
+ }
239
+ assertions.push(...evaluateSkillsOperations(expectedSkills.operations, spec));
240
+ assertions.push(...evaluateSkillsFilterFields(expectedSkills.filterFields, spec));
241
+ return assertions;
242
+ }
243
+
244
+ module.exports = {
245
+ evaluateSearchExpectations,
246
+ evaluateSkillsExpectations
247
+ };
@@ -8,11 +8,14 @@ const path = require('path');
8
8
  const fs = require('../internal/fs-real-sync');
9
9
  const yaml = require('js-yaml');
10
10
  const { resolveExternalSystemPath } = require('../utils/app-path-resolve');
11
- const { VERDICT } = require('../lifecycle/product-model');
12
11
  const {
13
12
  buildHonestyObservation,
14
13
  evaluateHonestyExpectations
15
14
  } = require('./test-cases-honesty');
15
+ const {
16
+ SUPPORTED_LIFECYCLE_STATES,
17
+ deriveLifecycleState
18
+ } = require('./test-cases-lifecycle');
16
19
  function loadNodeFsSnapshot() {
17
20
  if (global.__AIFABRIX_NODE_FS_UNMOCKED__) {
18
21
  return global.__AIFABRIX_NODE_FS_UNMOCKED__;
@@ -22,32 +25,6 @@ function loadNodeFsSnapshot() {
22
25
  : require('node:fs');
23
26
  }
24
27
  const nodeFs = loadNodeFsSnapshot();
25
- const SUPPORTED_LIFECYCLE_STATES = new Set(['completed', 'question', 'approval-required', 'dependency', 'safe-stop', 'rejected', 'failed']);
26
- const LIFECYCLE_STATE_ALIASES = Object.freeze({
27
- completed: ['completed', 'complete', 'done', 'success', 'verified'],
28
- question: ['question', 'question_required', 'awaiting_question', 'pending_question'],
29
- 'approval-required': ['approval_required', 'awaiting_approval', 'pending_approval', 'requires_approval'],
30
- dependency: ['dependency', 'dependency_wait', 'dependency_blocked', 'awaiting_dependency'],
31
- 'safe-stop': ['safe_stop', 'safe_stopped', 'policy_blocked', 'halted', 'paused'],
32
- rejected: ['rejected', 'denied', 'declined', 'policy_rejected'],
33
- failed: ['failed', 'error', 'errored', 'timeout', 'cancelled', 'canceled']
34
- });
35
-
36
- const WORK_STATUS_TO_LIFECYCLE = Object.freeze({
37
- completed: 'completed', waiting: 'question', running: 'dependency', stopped: 'safe-stop'
38
- });
39
- const WAIT_REASON_TO_LIFECYCLE = Object.freeze({
40
- ask: 'question', approval: 'approval-required', ownerroute: 'dependency',
41
- realityconfirm: 'question', knowledgeconfirm: 'question'
42
- });
43
- const WORKER_TASK_STATUS_TO_LIFECYCLE = Object.freeze({
44
- draft: 'dependency', pendingapproval: 'approval-required', approved: 'dependency',
45
- running: 'dependency', completed: 'completed', failed: 'failed',
46
- cancelled: 'rejected', canceled: 'rejected'
47
- });
48
- const WORKER_APPROVAL_STATE_TO_LIFECYCLE = Object.freeze({
49
- pending: 'approval-required', approved: 'dependency', rejected: 'rejected'
50
- });
51
28
  function safeExistsSync(filePath) {
52
29
  // Prefer unmocked node:fs so Jest worker fs mocks cannot hide real temp files.
53
30
  return nodeFs.existsSync(filePath) || fs.existsSync(filePath);
@@ -98,21 +75,55 @@ function normalizeCaseFromFile(filePath, parsed) {
98
75
  }
99
76
  return {
100
77
  caseId,
78
+ executionPath: parsed.executionPath,
79
+ roleRef: parsed.roleRef,
80
+ businessRoleRef: parsed.businessRoleRef,
101
81
  input: parsed.input || {},
102
82
  answers: Array.isArray(parsed.answers) ? parsed.answers : [],
103
83
  approvals: Array.isArray(parsed.approvals) ? parsed.approvals : [],
104
84
  expected,
85
+ metadata: parsed.metadata && typeof parsed.metadata === 'object' ? parsed.metadata : {},
86
+ preflight: parsed.preflight && typeof parsed.preflight === 'object' ? parsed.preflight : {},
105
87
  sourceFile: filePath
106
88
  };
107
89
  }
108
90
 
109
- function listTestCaseFiles(testsDir) {
110
- if (!safeExistsSync(testsDir)) {
91
+ function listYamlFileNames(dirPath) {
92
+ if (!safeExistsSync(dirPath)) {
111
93
  return [];
112
94
  }
113
- return safeReaddirSync(testsDir)
95
+ return safeReaddirSync(dirPath)
114
96
  .filter((entry) => /\.(ya?ml)$/i.test(entry))
115
- .map((entry) => path.join(testsDir, entry));
97
+ .map((entry) => path.join(dirPath, entry));
98
+ }
99
+
100
+ function safeIsDirectory(dirPath) {
101
+ try {
102
+ if (nodeFs.existsSync(dirPath)) {
103
+ return nodeFs.statSync(dirPath).isDirectory();
104
+ }
105
+ return fs.existsSync(dirPath) && fs.statSync(dirPath).isDirectory();
106
+ } catch {
107
+ return false;
108
+ }
109
+ }
110
+
111
+ function listTestCaseFiles(testsDir) {
112
+ const files = listYamlFileNames(testsDir);
113
+ if (!safeExistsSync(testsDir)) {
114
+ return files;
115
+ }
116
+ for (const entry of safeReaddirSync(testsDir)) {
117
+ if (String(entry).startsWith('.')) {
118
+ continue;
119
+ }
120
+ const child = path.join(testsDir, entry);
121
+ if (!safeIsDirectory(child)) {
122
+ continue;
123
+ }
124
+ files.push(...listYamlFileNames(child));
125
+ }
126
+ return files;
116
127
  }
117
128
 
118
129
  function looksLikePathSelector(selector) {
@@ -169,150 +180,11 @@ function loadRoleAssistantTestCase(roleKey, selector, options = {}) {
169
180
  throw new Error(`Role assistant test case ${lookup} not found in ${testsDir}`);
170
181
  }
171
182
  const parsed = parseCaseYamlFile(filePath);
183
+ const { assertTestCaseDocument } = require('./test-case-validate');
184
+ assertTestCaseDocument(parsed, filePath);
172
185
  return normalizeCaseFromFile(filePath, parsed);
173
186
  }
174
187
 
175
- function normalizeLifecycleStateToken(value) {
176
- if (typeof value !== 'string') {
177
- return '';
178
- }
179
- return value
180
- .trim()
181
- .toLowerCase()
182
- .replace(/[^a-z0-9]+/g, '_')
183
- .replace(/^_+|_+$/g, '');
184
- }
185
-
186
- function lifecycleStateFromToken(token) {
187
- if (!token) {
188
- return null;
189
- }
190
- for (const [state, aliases] of Object.entries(LIFECYCLE_STATE_ALIASES)) {
191
- for (const alias of aliases) {
192
- if (token === alias || token.startsWith(`${alias}_`)) {
193
- return state;
194
- }
195
- }
196
- }
197
- return null;
198
- }
199
-
200
- function lifecycleStateFromSignalValue(value) {
201
- if (value === null || value === undefined) {
202
- return null;
203
- }
204
- if (typeof value === 'string') {
205
- return lifecycleStateFromToken(normalizeLifecycleStateToken(value));
206
- }
207
- if (Array.isArray(value)) {
208
- for (const row of value) {
209
- const state = lifecycleStateFromSignalValue(row);
210
- if (state) {
211
- return state;
212
- }
213
- }
214
- return null;
215
- }
216
- if (typeof value === 'object') {
217
- const fields = [
218
- 'lifecycleState',
219
- 'state',
220
- 'status',
221
- 'code',
222
- 'type',
223
- 'reason',
224
- 'kind',
225
- 'category',
226
- 'errorCode'
227
- ];
228
- for (const field of fields) {
229
- const state = lifecycleStateFromSignalValue(value[field]);
230
- if (state) {
231
- return state;
232
- }
233
- }
234
- }
235
- return null;
236
- }
237
-
238
- function mapWorkStatusFromResult(result) {
239
- const rawStatus = normalizeLifecycleStateToken(result?.status);
240
- if (rawStatus && WORK_STATUS_TO_LIFECYCLE[rawStatus]) {
241
- const waitReason = normalizeLifecycleStateToken(result?.wait?.waitReason || '');
242
- if (rawStatus === 'waiting' && waitReason && WAIT_REASON_TO_LIFECYCLE[waitReason]) {
243
- return WAIT_REASON_TO_LIFECYCLE[waitReason];
244
- }
245
- return WORK_STATUS_TO_LIFECYCLE[rawStatus];
246
- }
247
- return null;
248
- }
249
-
250
- function mapWorkerTaskStateFromResult(result) {
251
- const statusCandidates = [result?.task?.status, result?.status, result?.workerTask?.status];
252
- for (const row of statusCandidates) {
253
- const token = normalizeLifecycleStateToken(row);
254
- if (token && WORKER_TASK_STATUS_TO_LIFECYCLE[token]) {
255
- return WORKER_TASK_STATUS_TO_LIFECYCLE[token];
256
- }
257
- }
258
- const approvalCandidates = [result?.task?.approvalState, result?.approvalState, result?.workerTask?.approvalState];
259
- for (const row of approvalCandidates) {
260
- const token = normalizeLifecycleStateToken(row);
261
- if (token && WORKER_APPROVAL_STATE_TO_LIFECYCLE[token]) {
262
- return WORKER_APPROVAL_STATE_TO_LIFECYCLE[token];
263
- }
264
- }
265
- return null;
266
- }
267
-
268
- function resolveLifecycleStateFromResult(result) {
269
- const workState = mapWorkStatusFromResult(result);
270
- if (workState) {
271
- return workState;
272
- }
273
- const workerTaskState = mapWorkerTaskStateFromResult(result);
274
- if (workerTaskState) {
275
- return workerTaskState;
276
- }
277
- const topLevelCandidates = [
278
- result?.lifecycleState, result?.state, result?.status, result?.lifecycle?.state,
279
- result?.report?.lifecycleState, result?.report?.state, result?.report?.status,
280
- result?.report?.lifecycle?.state, result?.report?.runtime?.state, result?.report?.work?.state
281
- ];
282
- for (const candidate of topLevelCandidates) {
283
- const state = lifecycleStateFromSignalValue(candidate);
284
- if (state) {
285
- return state;
286
- }
287
- }
288
- const steps = Array.isArray(result?.stepsRun) ? result.stepsRun : [];
289
- for (const row of steps) {
290
- const stepCandidates = [
291
- row?.lifecycleState, row?.state, row?.status, row?.code, row?.errorCode, row?.reason,
292
- row?.kind, row?.type, row?.error, row?.failure, row?.details, row?.result
293
- ];
294
- for (const candidate of stepCandidates) {
295
- const state = lifecycleStateFromSignalValue(candidate);
296
- if (state) {
297
- return state;
298
- }
299
- }
300
- }
301
- return null;
302
- }
303
-
304
- function deriveLifecycleState(result, lifecycleVerdict) {
305
- if (lifecycleVerdict === VERDICT.VERIFIED) {
306
- return 'completed';
307
- }
308
- const structuredState = resolveLifecycleStateFromResult(result);
309
- if (structuredState) {
310
- return structuredState;
311
- }
312
- if (lifecycleVerdict === VERDICT.NOT_VERIFIED) return 'safe-stop';
313
- return 'failed';
314
- }
315
-
316
188
  function addCapabilityToken(set, value) {
317
189
  if (typeof value === 'string' && value.trim()) set.add(value.trim());
318
190
  }
@@ -328,9 +200,34 @@ function collectCapabilitiesFromWorkSteps(out, steps) {
328
200
  addCapabilityToken(out, row.executionOutcome.capabilityKey);
329
201
  addCapabilityToken(out, row.executionOutcome.capability);
330
202
  }
203
+ const execution = row.capabilityExecution;
204
+ if (execution && typeof execution === 'object') {
205
+ addCapabilityToken(out, execution.capabilityKey);
206
+ addCapabilityToken(out, execution.capability);
207
+ }
331
208
  }
332
209
  }
333
210
 
211
+ /**
212
+ * Identity-preflight CIP fallback uses operationId "operation" (or omits it).
213
+ * That is a Reality probe log, not an observed write capability.
214
+ * @param {object} row
215
+ * @returns {boolean}
216
+ */
217
+ function cipArtifactIsUnspecifiedOperation(row) {
218
+ const fingerprint = typeof row.fingerprint === 'string' ? row.fingerprint : '';
219
+ const opMatch = fingerprint.match(/(?:^|[|,])operationId=([^|,]+)/);
220
+ if (opMatch) {
221
+ const operationId = opMatch[1].trim();
222
+ return !operationId || operationId === 'operation';
223
+ }
224
+ const artifactRef = typeof row.artifactRef === 'string' ? row.artifactRef : '';
225
+ if (/^cip-log:[^:]+:[^:]+:operation:/.test(artifactRef)) {
226
+ return true;
227
+ }
228
+ return /(?:^|[|,])capabilityKey=/.test(fingerprint);
229
+ }
230
+
334
231
  /**
335
232
  * Work-result artifactIndex often carries CIP fingerprints like
336
233
  * `capabilityKey=customer.createBasic|operationId=createbasic` when steps[] is empty.
@@ -341,6 +238,7 @@ function collectCapabilitiesFromArtifactIndex(out, artifacts) {
341
238
  if (!Array.isArray(artifacts)) return;
342
239
  for (const row of artifacts) {
343
240
  if (!row || typeof row !== 'object') continue;
241
+ if (cipArtifactIsUnspecifiedOperation(row)) continue;
344
242
  addCapabilityToken(out, row.capabilityKey);
345
243
  addCapabilityToken(out, row.capability);
346
244
  const fingerprint = typeof row.fingerprint === 'string' ? row.fingerprint : '';
@@ -381,6 +279,7 @@ function collectObservedCapabilities(result) {
381
279
  module.exports = {
382
280
  SUPPORTED_LIFECYCLE_STATES,
383
281
  roleAssistantTestsDir,
282
+ listTestCaseFiles,
384
283
  loadRoleAssistantTestCase,
385
284
  deriveLifecycleState,
386
285
  collectObservedCapabilities,