@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.
- package/README.md +8 -0
- package/bin/aifabrix.js +2 -2
- package/lib/agent-kit/apply-ops.js +82 -0
- package/lib/agent-kit/checksums.js +28 -0
- package/lib/agent-kit/classify.js +113 -0
- package/lib/agent-kit/claude-shim.js +61 -0
- package/lib/agent-kit/constants.js +55 -0
- package/lib/agent-kit/file-list.js +103 -0
- package/lib/agent-kit/host-approve.js +130 -0
- package/lib/agent-kit/hosting/github.js +63 -0
- package/lib/agent-kit/hosts.js +71 -0
- package/lib/agent-kit/init.js +319 -0
- package/lib/agent-kit/kit-root.js +17 -0
- package/lib/agent-kit/managed-section.js +79 -0
- package/lib/agent-kit/package-load.js +45 -0
- package/lib/agent-kit/plan-ops.js +69 -0
- package/lib/agent-kit/remote-prompts.js +239 -0
- package/lib/agent-kit/render-host-markdown.js +40 -0
- package/lib/agent-kit/repo-guard.js +47 -0
- package/lib/agent-kit/report.js +107 -0
- package/lib/agent-kit/run.js +82 -0
- package/lib/agent-kit/scm/git.js +122 -0
- package/lib/agent-kit/state-file.js +83 -0
- package/lib/agent-kit/status.js +50 -0
- package/lib/agent-kit/v1-detect.js +81 -0
- package/lib/agent-kit/validate-kit.js +87 -0
- package/lib/agent-kit/workspace-name.js +40 -0
- package/lib/agent-kit/workspace-skeleton.js +103 -0
- package/lib/api/assistants.api.js +8 -5
- package/lib/api/channel-identity.api.js +41 -0
- package/lib/api/evidence-authoring.api.js +5 -1
- package/lib/api/evidence.api.js +2 -0
- package/lib/api/role-assistant-test-pack.api.js +86 -0
- package/lib/api/types/evidence.types.js +2 -0
- package/lib/api/work-search.api.js +163 -0
- package/lib/api/work.api.js +19 -12
- package/lib/app/list-external-systems.js +2 -1
- package/lib/app/show-display.js +33 -6
- package/lib/app/show.js +25 -2
- package/lib/channels/add-channel.js +164 -126
- package/lib/channels/approval-guides/chatgpt.js +14 -18
- package/lib/channels/approval-guides/claude.js +29 -0
- package/lib/channels/approval-guides/index.js +88 -22
- package/lib/channels/approval-guides/mcp-client.js +27 -0
- package/lib/channels/approval-guides/microsoft-copilot.js +52 -3
- package/lib/channels/approval-guides/slack.js +10 -10
- package/lib/channels/approval-guides/teams-bot.js +8 -12
- package/lib/channels/channel-add-continuations.js +91 -0
- package/lib/channels/channel-add-ensure.js +124 -27
- package/lib/channels/channel-add-existing.js +160 -28
- package/lib/channels/channel-add-failure.js +61 -0
- package/lib/channels/channel-add-remaining.js +492 -0
- package/lib/channels/channel-add-tty.js +190 -0
- package/lib/channels/channel-add-wizard-config.js +138 -0
- package/lib/channels/channel-add-wizard.js +250 -0
- package/lib/channels/channel-artifact-generator.js +27 -13
- package/lib/channels/channel-cardinality.js +83 -0
- package/lib/channels/channel-catalog-icon.js +45 -0
- package/lib/channels/channel-cli-instructions.js +75 -0
- package/lib/channels/channel-configuration-map.js +213 -0
- package/lib/channels/channel-credential.js +11 -14
- package/lib/channels/channel-definition-project.js +101 -0
- package/lib/channels/channel-definition-registry.js +154 -0
- package/lib/channels/channel-definition-status.js +115 -0
- package/lib/channels/channel-description.js +60 -2
- package/lib/channels/channel-discovery.js +16 -2
- package/lib/channels/channel-external-system.js +86 -9
- package/lib/channels/channel-install-envelope-actions.js +88 -0
- package/lib/channels/channel-install-envelope-microsoft.js +155 -0
- package/lib/channels/channel-install-envelope.js +358 -0
- package/lib/channels/channel-install-help-md.js +172 -0
- package/lib/channels/channel-install-http-payload.js +62 -0
- package/lib/channels/channel-install-inventory.js +115 -0
- package/lib/channels/channel-install-profiles.js +90 -0
- package/lib/channels/channel-instance-collision.js +118 -0
- package/lib/channels/channel-instance-key.js +100 -0
- package/lib/channels/channel-instance-materialize.js +240 -0
- package/lib/channels/channel-integration-generator.js +18 -9
- package/lib/channels/channel-integration-template.js +101 -22
- package/lib/channels/channel-inventory-fetch.js +79 -0
- package/lib/channels/channel-oauth-preflight.js +104 -0
- package/lib/channels/channel-package-version.js +76 -0
- package/lib/channels/channel-predefined-client.js +154 -0
- package/lib/channels/channel-probe.js +7 -2
- package/lib/channels/channel-runtime-resolver.js +194 -72
- package/lib/channels/channel-status-display.js +86 -16
- package/lib/channels/channel-targets.js +132 -92
- package/lib/channels/chatgpt-callback.js +318 -0
- package/lib/channels/chatgpt-channel-add.js +229 -0
- package/lib/channels/chatgpt-preflight.js +396 -0
- package/lib/channels/chatgpt-runtime-contract.js +17 -0
- package/lib/channels/chatgpt-setup-values.js +124 -0
- package/lib/channels/claude-callback.js +67 -0
- package/lib/channels/claude-channel-add.js +254 -0
- package/lib/channels/claude-runtime-contract.js +40 -0
- package/lib/channels/claude-runtime.js +58 -0
- package/lib/channels/claude-setup-values.js +92 -0
- package/lib/channels/mcp-client/config-merge.js +148 -0
- package/lib/channels/mcp-client/ensure-client.js +231 -0
- package/lib/channels/mcp-client/paths.js +53 -0
- package/lib/channels/mcp-client/profiles.js +122 -0
- package/lib/channels/mcp-client/redirect-uris.js +99 -0
- package/lib/channels/mcp-client/runtime.js +59 -0
- package/lib/channels/mcp-client-channel-add.js +186 -0
- package/lib/channels/microsoft-copilot-channel-add.js +117 -7
- package/lib/channels/microsoft-copilot-entra-identifier-uris.js +187 -0
- package/lib/channels/microsoft-copilot-entra-sso-form.js +106 -18
- package/lib/channels/microsoft-copilot-entra-sso.js +31 -2
- package/lib/channels/microsoft-copilot-package-prior.js +107 -0
- package/lib/channels/microsoft-copilot-package.js +29 -28
- package/lib/channels/microsoft-provisioning/a365.js +80 -0
- package/lib/channels/microsoft-provisioning/auth-config.js +240 -0
- package/lib/channels/microsoft-provisioning/auth.js +179 -0
- package/lib/channels/microsoft-provisioning/cli.js +71 -0
- package/lib/channels/microsoft-provisioning/constants.js +75 -0
- package/lib/channels/microsoft-provisioning/errors.js +117 -0
- package/lib/channels/microsoft-provisioning/index.js +55 -0
- package/lib/channels/microsoft-provisioning/install-atk.js +158 -0
- package/lib/channels/microsoft-provisioning/install-teams.js +115 -0
- package/lib/channels/microsoft-provisioning/login-portal-device.js +236 -0
- package/lib/channels/microsoft-provisioning/login-portal-parse.js +71 -0
- package/lib/channels/microsoft-provisioning/login-portal-teams.js +193 -0
- package/lib/channels/microsoft-provisioning/login-portal.js +230 -0
- package/lib/channels/microsoft-provisioning/persist.js +110 -0
- package/lib/channels/microsoft-provisioning/teams-bot-args.js +119 -0
- package/lib/channels/microsoft-provisioning/teams-bot-controller.js +123 -0
- package/lib/channels/microsoft-provisioning/teams-bot-parse.js +134 -0
- package/lib/channels/microsoft-provisioning/teams-bot-persist.js +113 -0
- package/lib/channels/microsoft-provisioning/teams-bot-provision.js +234 -0
- package/lib/channels/microsoft-provisioning/teams-bot-secrets.js +45 -0
- package/lib/channels/microsoft-provisioning/teams-cli.js +82 -0
- package/lib/channels/runtime-tool-catalog.js +5 -2
- package/lib/channels/slack-channel-add-portal.js +130 -0
- package/lib/channels/slack-channel-add-tty-auth.js +95 -0
- package/lib/channels/slack-channel-add.js +311 -0
- package/lib/channels/slack-mcp-callback.js +51 -0
- package/lib/channels/slack-mcp-runtime.js +156 -0
- package/lib/channels/slack-provisioning/apps.js +181 -0
- package/lib/channels/slack-provisioning/auth-store.js +110 -0
- package/lib/channels/slack-provisioning/auth-ticket.js +185 -0
- package/lib/channels/slack-provisioning/auth.js +115 -0
- package/lib/channels/slack-provisioning/callbacks.js +41 -0
- package/lib/channels/slack-provisioning/cli.js +226 -0
- package/lib/channels/slack-provisioning/constants.js +37 -0
- package/lib/channels/slack-provisioning/credentials.js +169 -0
- package/lib/channels/slack-provisioning/curl-shim.js +132 -0
- package/lib/channels/slack-provisioning/developer-install.js +118 -0
- package/lib/channels/slack-provisioning/env-file.js +120 -0
- package/lib/channels/slack-provisioning/errors.js +47 -0
- package/lib/channels/slack-provisioning/go-ca-bundle.js +137 -0
- package/lib/channels/slack-provisioning/index.js +250 -0
- package/lib/channels/slack-provisioning/install-cli.js +335 -0
- package/lib/channels/slack-provisioning/manifest.js +89 -0
- package/lib/channels/slack-provisioning/oauth-lock.js +33 -0
- package/lib/channels/slack-provisioning/offer-cli.js +113 -0
- package/lib/channels/slack-provisioning/onboard-members.js +122 -0
- package/lib/channels/slack-provisioning/onboard.js +89 -0
- package/lib/channels/slack-provisioning/persist.js +95 -0
- package/lib/channels/slack-provisioning/remaining-urls.js +158 -0
- package/lib/channels/slack-provisioning/with-curl-on-path.js +53 -0
- package/lib/channels/teams-bot-channel-add.js +94 -0
- package/lib/channels/vendor-dataplane-url.js +249 -0
- package/lib/cli/index.js +4 -0
- package/lib/cli/setup-certification-commands.js +2 -2
- package/lib/cli/setup-certification.help.js +5 -1
- package/lib/cli/setup-external-system-help.js +2 -0
- package/lib/cli/setup-external-system.js +1 -1
- package/lib/commands/agent-kit-help.js +79 -0
- package/lib/commands/agent-kit.js +346 -0
- package/lib/commands/channel-add-help.js +366 -0
- package/lib/commands/channel-add-setup.js +162 -80
- package/lib/commands/channel-configure.js +118 -0
- package/lib/commands/channel.js +10 -1
- package/lib/commands/datasource-capability-relate-cli.js +5 -4
- package/lib/commands/governance-upload-external.js +6 -3
- package/lib/commands/lifecycle-command-action.js +2 -5
- package/lib/commands/lifecycle-external.js +93 -21
- package/lib/commands/repair-auth-apply.js +1 -1
- package/lib/commands/repair-datasource-key-skip.js +39 -0
- package/lib/commands/repair-datasource-keys.js +24 -12
- package/lib/commands/repair-datasource-test-payload.js +4 -2
- package/lib/commands/repair-datasource-webhooks-sync-bridge.js +23 -2
- package/lib/commands/repair-datasource.js +3 -0
- package/lib/commands/repair-external-run.js +59 -25
- package/lib/commands/repair-openapi-rest-runtime.js +127 -0
- package/lib/commands/repair-orchestration-tag-merge.js +339 -0
- package/lib/commands/repair-rbac-catalog-defaults.js +96 -0
- package/lib/commands/repair-rbac-platform-preset.js +26 -15
- package/lib/commands/repair-rbac-reader-roles.js +8 -21
- package/lib/commands/repair-rbac.js +26 -44
- package/lib/commands/repair-system-permissions.js +24 -22
- package/lib/commands/role-assistant-copy-output.js +61 -0
- package/lib/commands/role-assistant-copy.js +155 -0
- package/lib/commands/role-assistant-test-output.js +22 -9
- package/lib/commands/role-assistant-test-result-rows.js +42 -0
- package/lib/commands/role-assistant.js +150 -43
- package/lib/commands/search.js +143 -0
- package/lib/commands/test-e2e-external.js +148 -21
- package/lib/commands/test-trust-external.js +7 -5
- package/lib/commands/upload-credential-push-log.js +2 -1
- package/lib/commands/upload-publish-context.js +1 -1
- package/lib/commands/upload-role-assistant-shell.js +124 -0
- package/lib/commands/upload-sidecar-followups.js +10 -4
- package/lib/commands/upload.js +18 -3
- package/lib/commands/verify-operations-skip-e2e.js +131 -0
- package/lib/commands/verify-operations-step-plan.js +6 -33
- package/lib/commands/verify-operations-steps.js +3 -1
- package/lib/core/secrets-docker-env.js +4 -1
- package/lib/core/secrets-env-content.js +17 -3
- package/lib/datasource/capability/capability-manifest.js +0 -3
- package/lib/datasource/capability/copy-test-payload.js +3 -0
- package/lib/datasource/capability/relate-operations.js +28 -10
- package/lib/datasource/capability/run-capability-relate.js +48 -25
- package/lib/datasource/datasource-identifier.js +13 -5
- package/lib/deployment/deployer-poll-run.js +117 -35
- package/lib/external-system/deploy-dataplane-published.js +70 -0
- package/lib/external-system/deploy-helpers.js +26 -1
- package/lib/external-system/deploy.js +22 -8
- package/lib/external-system/download-helpers.js +29 -2
- package/lib/external-system/download-role-assistant.js +109 -4
- package/lib/external-system/download.js +46 -30
- package/lib/external-system/sync-deploy-manifest.js +3 -2
- package/lib/external-system/upload-identity.js +42 -0
- package/lib/generator/index.js +19 -15
- package/lib/generator/split.js +13 -2
- package/lib/generator/wizard-datasource-key.js +54 -0
- package/lib/generator/wizard.js +55 -54
- package/lib/integration-definition/apply-datasource-keys.js +75 -0
- package/lib/integration-definition/apply-relationships.js +195 -0
- package/lib/integration-definition/apply-static-enterprise.js +229 -0
- package/lib/integration-definition/apply-system-file.js +71 -0
- package/lib/integration-definition/apply-test-endpoint.js +89 -0
- package/lib/integration-definition/apply-viewpoint-defaults.js +157 -0
- package/lib/integration-definition/apply.js +78 -59
- package/lib/integration-definition/enrich-openapi-operations.js +36 -10
- package/lib/integration-definition/enrich-openapi-pick.js +87 -0
- package/lib/lifecycle/role-assistant-governance.js +181 -0
- package/lib/lifecycle/scenario-upload.js +181 -30
- package/lib/programmatic/builder-api-cors.js +143 -0
- package/lib/programmatic/builder-api-request.js +6 -0
- package/lib/programmatic/builder-api-route-dispatch.js +56 -42
- package/lib/programmatic/builder-api-server.js +8 -1
- package/lib/programmatic/capability-registry.js +55 -0
- package/lib/programmatic/channel-install-help-resolve.js +359 -0
- package/lib/programmatic/channel-install-session.js +218 -0
- package/lib/programmatic/help-content/channel-onboarding.md +2 -0
- package/lib/programmatic/help-content/cip-overview.md +3 -1
- package/lib/programmatic/http-raw-response.js +62 -0
- package/lib/programmatic/index.js +2 -0
- package/lib/programmatic/openapi-apply-result-schemas.js +8 -0
- package/lib/programmatic/openapi-channel-install-bindings.js +179 -0
- package/lib/programmatic/openapi-channel-install-schemas.js +289 -0
- package/lib/programmatic/openapi-component-schemas.js +19 -1
- package/lib/programmatic/openapi-description-enricher.js +3 -1
- package/lib/programmatic/openapi-descriptions.js +80 -3
- package/lib/programmatic/openapi-envelope-examples.js +124 -0
- package/lib/programmatic/openapi-operation-bindings.js +9 -1
- package/lib/programmatic/openapi-request-schemas.js +5 -0
- package/lib/programmatic/openapi-schema-descriptions-channel.js +319 -0
- package/lib/programmatic/openapi-schema-descriptions-operations.js +19 -0
- package/lib/programmatic/openapi-spec.js +13 -8
- package/lib/programmatic/platform-rbac-catalog.js +36 -18
- package/lib/programmatic/request-timeout.js +3 -0
- package/lib/programmatic/route-handler-map.js +58 -1
- package/lib/programmatic/route-handlers-context.js +2 -1
- package/lib/programmatic/run-auth-permissions.js +54 -0
- package/lib/programmatic/run-channel-catalog.js +238 -0
- package/lib/programmatic/run-channel-install-artifacts.js +137 -0
- package/lib/programmatic/run-channel-install-copilot.js +353 -0
- package/lib/programmatic/run-channel-install-options.js +236 -0
- package/lib/programmatic/run-channel-install-teams-bot.js +204 -0
- package/lib/programmatic/run-channel-install.js +346 -0
- package/lib/programmatic/run-channel-package.js +87 -7
- package/lib/programmatic/run-download.js +41 -0
- package/lib/programmatic/workspace-context.js +2 -0
- package/lib/protection/auth-context.js +3 -1
- package/lib/protection/protection-display.js +3 -2
- package/lib/protection/report-exit.js +50 -0
- package/lib/protection/run-commands.js +2 -0
- package/lib/role-assistant/evidence-sync.js +4 -2
- package/lib/role-assistant/evidence-validation-issues.js +51 -0
- package/lib/role-assistant/knowledge-sync.js +10 -4
- package/lib/role-assistant/package-validate.js +175 -0
- package/lib/role-assistant/settings.js +49 -2
- package/lib/role-assistant/test-case-assertion-row.js +36 -0
- package/lib/role-assistant/test-case-copy-bind.js +77 -0
- package/lib/role-assistant/test-case-copy-expected.js +127 -0
- package/lib/role-assistant/test-case-copy-from-work.js +90 -0
- package/lib/role-assistant/test-case-copy-interactions.js +67 -0
- package/lib/role-assistant/test-case-copy.js +119 -0
- package/lib/role-assistant/test-case-expected-catalog.js +135 -0
- package/lib/role-assistant/test-case-validate.js +88 -0
- package/lib/role-assistant/test-cases-bid.js +117 -4
- package/lib/role-assistant/test-cases-evaluate.js +159 -24
- package/lib/role-assistant/test-cases-evidence.js +175 -0
- package/lib/role-assistant/test-cases-honesty.js +155 -6
- package/lib/role-assistant/test-cases-lifecycle.js +291 -0
- package/lib/role-assistant/test-cases-search-graph.js +122 -0
- package/lib/role-assistant/test-cases-search.js +247 -0
- package/lib/role-assistant/test-cases.js +71 -172
- package/lib/role-assistant/test-pack-map.js +180 -0
- package/lib/role-assistant/test-pack-sync.js +187 -0
- package/lib/role-assistant/test-runner-debug.js +54 -0
- package/lib/role-assistant/test-runner-respond-body.js +36 -0
- package/lib/role-assistant/test-runner-search.js +164 -0
- package/lib/role-assistant/test-runner-start-payload.js +63 -10
- package/lib/role-assistant/test-runner-workhub-answers.js +45 -16
- package/lib/role-assistant/test-runner-workhub-helpers.js +40 -2
- package/lib/role-assistant/test-runner-workhub-soft.js +9 -3
- package/lib/role-assistant/test-runner-workhub.js +74 -32
- package/lib/role-assistant/test-runner.js +66 -11
- package/lib/schema/external-datasource.schema.json +146 -21
- package/lib/schema/external-system.schema.json +177 -2
- package/lib/schema/mcp-client-profile.schema.json +103 -0
- package/lib/schema/role-assistant-test-case.schema.json +408 -0
- package/lib/search/dataplane-context.js +23 -0
- package/lib/search/search-args.js +211 -0
- package/lib/search/search-display.js +238 -0
- package/lib/search/search-errors.js +50 -0
- package/lib/search/search-prompts.js +119 -0
- package/lib/search/search-roles.js +85 -0
- package/lib/search/search-run.js +241 -0
- package/lib/search/search-skills.js +198 -0
- package/lib/utils/app-path-resolve.js +4 -0
- package/lib/utils/authentication-env-template.js +44 -6
- package/lib/utils/authentication-slot-show.js +153 -0
- package/lib/utils/credential-display.js +43 -1
- package/lib/utils/credential-secrets-env.js +6 -1
- package/lib/utils/env-copy.js +19 -7
- package/lib/utils/external-env-template.js +20 -2
- package/lib/utils/external-system-readiness-compact-blocks.js +5 -1
- package/lib/utils/external-system-readiness-compact-display.js +30 -1
- package/lib/utils/external-system-validators.js +2 -1
- package/lib/utils/help-builder.js +3 -1
- package/lib/utils/paths.js +18 -1
- package/lib/utils/platform-shell-package.js +69 -0
- package/lib/utils/port-resolver.js +50 -1
- package/lib/utils/rewrite-name-flag.js +20 -0
- package/lib/utils/role-assistant-paths.js +13 -10
- package/lib/utils/schema-loader.js +37 -0
- package/lib/utils/schema-resolver.js +11 -1
- package/lib/utils/secrets-helpers.js +12 -21
- package/lib/utils/token-manager.js +10 -5
- package/lib/validation/validate-external-file.js +5 -1
- package/lib/validation/validate.js +41 -0
- package/package.json +1 -1
- package/templates/README.md +1 -1
- package/templates/agent-kit/adapters/claude/nested.CLAUDE.md +1 -0
- package/templates/agent-kit/adapters/claude/root.CLAUDE.md +5 -0
- package/templates/agent-kit/adapters/cursor/commands/cust-0-plan.md +5 -0
- package/templates/agent-kit/adapters/cursor/commands/cust-1-validate.md +5 -0
- package/templates/agent-kit/adapters/cursor/commands/cust-2-build.md +5 -0
- package/templates/agent-kit/adapters/cursor/commands/cust-3-push.md +5 -0
- package/templates/agent-kit/adapters/cursor/commands/cust-biz-1-validate.md +5 -0
- package/templates/agent-kit/adapters/cursor/commands/cust-biz-2-build.md +5 -0
- package/templates/agent-kit/adapters/cursor/commands/cust-biz-3-prove.md +5 -0
- package/templates/agent-kit/agent-kit.yaml +45 -0
- package/templates/agent-kit/instructions/AGENTKIT.md +83 -0
- package/templates/agent-kit/instructions/integration.AGENTS.md +25 -0
- package/templates/agent-kit/instructions/role-assistant.AGENTS.md +22 -0
- package/templates/agent-kit/instructions/root.AGENTS.md +37 -0
- package/templates/agent-kit/parity-inventory.yaml +188 -0
- package/templates/agent-kit/skills/aifabrix-connected-system/SKILL.md +58 -0
- package/templates/agent-kit/skills/aifabrix-connected-system/references/contract-checklist.md +40 -0
- package/templates/agent-kit/skills/aifabrix-connected-system/references/delivery-gates.md +54 -0
- package/templates/agent-kit/skills/aifabrix-connected-system/references/production-safety.md +35 -0
- package/templates/agent-kit/skills/aifabrix-connected-system/scripts/reserved-system-key.js +19 -0
- package/templates/agent-kit/skills/aifabrix-plan/SKILL.md +51 -0
- package/templates/agent-kit/skills/aifabrix-plan/references/challenge-checklist.md +108 -0
- package/templates/agent-kit/skills/aifabrix-plan/references/interaction.md +34 -0
- package/templates/agent-kit/skills/aifabrix-plan/references/plan-template.md +182 -0
- package/templates/agent-kit/skills/aifabrix-prove/SKILL.md +50 -0
- package/templates/agent-kit/skills/aifabrix-prove/references/demo-template.md +65 -0
- package/templates/agent-kit/skills/aifabrix-prove/references/evidence-lifecycle.md +68 -0
- package/templates/agent-kit/skills/aifabrix-prove/references/learning-template.md +66 -0
- package/templates/agent-kit/skills/aifabrix-role-assistant/SKILL.md +42 -0
- package/templates/agent-kit/skills/aifabrix-role-assistant/references/package-boundary.md +21 -0
- package/templates/agent-kit/skills/shared/hosts.md +78 -0
- package/templates/agent-kit/workspace/.cursor/plans/README.md +22 -0
- package/templates/agent-kit/workspace/LICENSE.mit +21 -0
- package/templates/agent-kit/workspace/README.md +89 -0
- package/templates/applications/builder-api/Dockerfile +3 -1
- package/templates/applications/builder-api/env.template +7 -0
- package/templates/applications/dataplane/application.yaml +6 -5
- package/templates/applications/dataplane/env.template +2 -2
- package/templates/applications/dataplane/rbac.yaml +35 -2
- package/templates/applications/keycloak/Dockerfile +30 -4
- package/templates/applications/keycloak/application.yaml +2 -2
- package/templates/applications/keycloak/cimd-lenient-parse/AbstractClientIdMetadataDocumentExecutor.java +896 -0
- package/templates/applications/keycloak/cimd-lenient-parse/SOURCE.md +19 -0
- package/templates/applications/keycloak/env.template +3 -0
- package/templates/applications/miso-controller/application.yaml +1 -2
- package/templates/applications/miso-controller/env.template +10 -9
- package/templates/channels/README.md +5 -5
- package/templates/channels/chatgpt/TROUBLESHOOTING.md +51 -0
- package/templates/channels/chatgpt/channel.json +59 -0
- package/templates/channels/chatgpt/icon.svg +1 -0
- package/templates/channels/chatgpt/install.template.md.hbs +20 -95
- package/templates/channels/chatgpt/integration/README.md +1 -1
- package/templates/channels/chatgpt/integration/application.json +2 -2
- package/templates/channels/chatgpt/integration/chatgpt-system.json +49 -4
- package/templates/channels/chatgpt/integration/env.template +2 -4
- package/templates/channels/chatgpt/integration/rbac.json +13 -0
- package/templates/channels/claude/TROUBLESHOOTING.md +44 -0
- package/templates/channels/claude/channel.json +59 -0
- package/templates/channels/claude/icon.svg +1 -0
- package/templates/channels/claude/install.template.md.hbs +22 -0
- package/templates/channels/claude/integration/README.md +14 -0
- package/templates/channels/claude/integration/application.json +15 -0
- package/templates/channels/claude/integration/claude-system.json +59 -0
- package/templates/channels/claude/integration/env.template +2 -0
- package/templates/channels/claude/integration/rbac.json +13 -0
- package/templates/channels/claude/manifest.template.json.hbs +40 -0
- package/templates/channels/mcp-client/channel.json +72 -0
- package/templates/channels/mcp-client/icon.svg +1 -0
- package/templates/channels/mcp-client/install.template.md.hbs +24 -0
- package/templates/channels/mcp-client/integration/README.md +13 -0
- package/templates/channels/mcp-client/integration/application.json +15 -0
- package/templates/channels/mcp-client/integration/env.template +2 -0
- package/templates/channels/mcp-client/integration/mcp-client-system.json +72 -0
- package/templates/channels/mcp-client/integration/rbac.json +13 -0
- package/templates/channels/mcp-client/manifest.template.json.hbs +41 -0
- package/templates/channels/mcp-client/profiles/cursor.json +26 -0
- package/templates/channels/mcp-client/profiles/github-copilot.json +29 -0
- package/templates/channels/mcp-client/profiles/vscode.json +29 -0
- package/templates/channels/microsoft-copilot/channel.json +73 -0
- package/templates/channels/microsoft-copilot/declarative-agent.template.json.hbs +8 -4
- package/templates/channels/microsoft-copilot/entra-sso-registration.template.md.hbs +65 -5
- package/templates/channels/microsoft-copilot/icon.svg +1 -0
- package/templates/channels/microsoft-copilot/install.template.md.hbs +9 -9
- package/templates/channels/microsoft-copilot/integration/README.md +1 -1
- package/templates/channels/microsoft-copilot/integration/application.json +2 -2
- package/templates/channels/microsoft-copilot/integration/env.template +3 -6
- package/templates/channels/microsoft-copilot/integration/microsoft-copilot-system.json +63 -4
- package/templates/channels/microsoft-copilot/integration/rbac.json +13 -0
- package/templates/channels/microsoft-copilot/oauth-plugin-vault-required.template.md.hbs +5 -5
- package/templates/channels/slack/channel.json +234 -0
- package/templates/channels/slack/icon.svg +1 -0
- package/templates/channels/slack/install.template.md.hbs +45 -28
- package/templates/channels/slack/integration/README.md +245 -22
- package/templates/channels/slack/integration/application.json +44 -7
- package/templates/channels/slack/integration/env.template +15 -6
- package/templates/channels/slack/integration/openapi/openapi.json +126 -0
- package/templates/channels/slack/integration/rbac.json +84 -0
- package/templates/channels/slack/integration/slack-datasource-commands.json +154 -0
- package/templates/channels/slack/integration/slack-datasource-conversations.json +28 -3
- package/templates/channels/slack/integration/slack-datasource-events.json +154 -0
- package/templates/channels/slack/integration/slack-datasource-interactive.json +154 -0
- package/templates/channels/slack/integration/slack-datasource-messages.json +40 -2
- package/templates/channels/slack/integration/slack-system.json +161 -72
- package/templates/channels/slack/manifest.template.json.hbs +10 -4
- package/templates/channels/teams-bot/channel.json +162 -0
- package/templates/channels/teams-bot/icon.svg +1 -0
- package/templates/channels/teams-bot/install.template.md.hbs +12 -13
- package/templates/channels/teams-bot/integration/README.md +5 -4
- package/templates/channels/teams-bot/integration/application.json +6 -4
- package/templates/channels/teams-bot/integration/env.template +5 -4
- package/templates/channels/teams-bot/integration/openapi/openapi.json +68 -0
- package/templates/channels/teams-bot/integration/rbac.json +21 -0
- package/templates/channels/teams-bot/integration/teams-bot-datasource-activities.json +154 -0
- package/templates/channels/teams-bot/integration/teams-bot-system.json +128 -23
- package/templates/channels/web-embed/channel.json +60 -0
- package/templates/channels/web-embed/install.template.md.hbs +1 -1
- package/templates/channels/web-embed/integration/README.md +2 -2
- package/templates/channels/web-embed/integration/application.json +2 -2
- package/templates/channels/web-embed/integration/env.template +1 -1
- package/templates/channels/web-embed/integration/rbac.json +13 -0
- package/templates/channels/web-embed/integration/web-embed-system.json +50 -4
- package/templates/python/docker-compose.hbs +14 -0
- 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
|
|
110
|
-
if (!safeExistsSync(
|
|
91
|
+
function listYamlFileNames(dirPath) {
|
|
92
|
+
if (!safeExistsSync(dirPath)) {
|
|
111
93
|
return [];
|
|
112
94
|
}
|
|
113
|
-
return safeReaddirSync(
|
|
95
|
+
return safeReaddirSync(dirPath)
|
|
114
96
|
.filter((entry) => /\.(ya?ml)$/i.test(entry))
|
|
115
|
-
.map((entry) => path.join(
|
|
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,
|