procesio-cli 0.1.1__py3-none-any.whl
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.
- procesio_cli/__init__.py +18 -0
- procesio_cli/_cli.py +71 -0
- procesio_cli/agents/__init__.py +0 -0
- procesio_cli/agents/_lib/__init__.py +0 -0
- procesio_cli/agents/_lib/actiondef.py +24 -0
- procesio_cli/agents/_lib/errors.py +40 -0
- procesio_cli/agents/_lib/reversibility.py +236 -0
- procesio_cli/agents/_lib/toolrunner.py +141 -0
- procesio_cli/agents/connector-builder/CONNECTOR-BUILDER-PLAYBOOK.md +62 -0
- procesio_cli/agents/connector-builder/CONNECTOR-BUILDER-PROCESIO-INTEROP.md +76 -0
- procesio_cli/agents/connector-builder/CONNECTOR-BUILDER-TROUBLESHOOTING.md +60 -0
- procesio_cli/agents/connector-builder/README.md +51 -0
- procesio_cli/agents/connector-builder/agent.yaml +61 -0
- procesio_cli/agents/connector-builder/context.py +19 -0
- procesio_cli/agents/connector-builder/handlers/__init__.py +1 -0
- procesio_cli/agents/connector-builder/handlers/checklist.py +71 -0
- procesio_cli/agents/connector-builder/handlers/guidance.py +37 -0
- procesio_cli/agents/connector-builder/handlers/nextstep.py +221 -0
- procesio_cli/agents/connector-builder/handlers/status.py +35 -0
- procesio_cli/agents/connector-builder/knowledge.py +47 -0
- procesio_cli/agents/connector-builder/main.py +93 -0
- procesio_cli/agents/connector-builder/tests/conftest.py +95 -0
- procesio_cli/agents/connector-builder/tests/test_cba_agent.py +148 -0
- procesio_cli/agents/orchestrator/__init__.py +0 -0
- procesio_cli/agents/orchestrator/bootstraplib.py +166 -0
- procesio_cli/agents/procesio/IMPLEMENTATION-PATTERNS/00-INDEX.md +60 -0
- procesio_cli/agents/procesio/IMPLEMENTATION-PATTERNS/01-PROCESSES.md +230 -0
- procesio_cli/agents/procesio/IMPLEMENTATION-PATTERNS/02-FORMS.md +287 -0
- procesio_cli/agents/procesio/IMPLEMENTATION-PATTERNS/03-INTEGRATIONS.md +384 -0
- procesio_cli/agents/procesio/IMPLEMENTATION-PATTERNS/04-DATABASE.md +293 -0
- procesio_cli/agents/procesio/PROCESIO-API-RELIABILITY-DOCTRINE.md +113 -0
- procesio_cli/agents/procesio/PROCESIO-BEST-PRACTICES.md +316 -0
- procesio_cli/agents/procesio/PROCESIO-BUILD-AND-TEST-PLAYBOOK.md +217 -0
- procesio_cli/agents/procesio/PROCESIO-DATASTORE.md +72 -0
- procesio_cli/agents/procesio/PROCESIO-ENVIRONMENTS.md +62 -0
- procesio_cli/agents/procesio/PROCESIO-SCHEDULING.md +47 -0
- procesio_cli/agents/procesio/PROCESIO-VISUAL-ORGANIZATION.md +175 -0
- procesio_cli/agents/procesio/README.md +97 -0
- procesio_cli/agents/procesio/__init__.py +0 -0
- procesio_cli/agents/procesio/agent.yaml +73 -0
- procesio_cli/agents/procesio/audit.py +226 -0
- procesio_cli/agents/procesio/checklist.py +135 -0
- procesio_cli/agents/procesio/context.py +19 -0
- procesio_cli/agents/procesio/handlers/__init__.py +0 -0
- procesio_cli/agents/procesio/handlers/audit.py +39 -0
- procesio_cli/agents/procesio/handlers/checklist.py +34 -0
- procesio_cli/agents/procesio/handlers/guidance.py +36 -0
- procesio_cli/agents/procesio/handlers/status.py +33 -0
- procesio_cli/agents/procesio/handlers/verify.py +39 -0
- procesio_cli/agents/procesio/knowledge.py +115 -0
- procesio_cli/agents/procesio/main.py +89 -0
- procesio_cli/agents/procesio/tests/__init__.py +0 -0
- procesio_cli/agents/procesio/tests/conftest.py +62 -0
- procesio_cli/agents/procesio/tests/test_audit.py +91 -0
- procesio_cli/agents/procesio/tests/test_checklist.py +28 -0
- procesio_cli/agents/procesio/tests/test_guidance.py +78 -0
- procesio_cli/agents/procesio/tests/test_manifest_sync.py +48 -0
- procesio_cli/agents/procesio/tests/test_verify.py +134 -0
- procesio_cli/agents/procesio/tests/test_workspace_scope.py +97 -0
- procesio_cli/agents/procesio/verifylib.py +222 -0
- procesio_cli/dashboard/README.md +117 -0
- procesio_cli/dashboard/__init__.py +18 -0
- procesio_cli/dashboard/serve.py +98 -0
- procesio_cli/dashboard/server/__init__.py +1 -0
- procesio_cli/dashboard/server/config_schemas.py +92 -0
- procesio_cli/dashboard/server/google.py +103 -0
- procesio_cli/dashboard/server/handler.py +160 -0
- procesio_cli/dashboard/server/inventory.py +213 -0
- procesio_cli/dashboard/server/jobs.py +118 -0
- procesio_cli/dashboard/server/llmtest.py +181 -0
- procesio_cli/dashboard/server/procesio_env.py +94 -0
- procesio_cli/dashboard/server/routes.py +74 -0
- procesio_cli/dashboard/server/runner.py +150 -0
- procesio_cli/dashboard/server/security.py +29 -0
- procesio_cli/dashboard/server/setup.py +211 -0
- procesio_cli/dashboard/server/validate.py +152 -0
- procesio_cli/dashboard/tests/conftest.py +16 -0
- procesio_cli/dashboard/tests/test_dashboard.py +225 -0
- procesio_cli/dashboard/tests/test_procesio_env.py +159 -0
- procesio_cli/dashboard/web/actions.js +274 -0
- procesio_cli/dashboard/web/api.js +79 -0
- procesio_cli/dashboard/web/app.js +385 -0
- procesio_cli/dashboard/web/copilot.js +72 -0
- procesio_cli/dashboard/web/google.js +121 -0
- procesio_cli/dashboard/web/index.html +67 -0
- procesio_cli/dashboard/web/procesio_env.js +187 -0
- procesio_cli/dashboard/web/styles.css +207 -0
- procesio_cli/registry.py +370 -0
- procesio_cli/scripts/build-router.py +249 -0
- procesio_cli/scripts/build-tool-skill.py +202 -0
- procesio_cli/scripts/check-requirements.py +131 -0
- procesio_cli/scripts/check-skill-governance.py +174 -0
- procesio_cli/scripts/evaluate-skill-routing.py +217 -0
- procesio_cli/scripts/evaluate-skills.py +316 -0
- procesio_cli/scripts/get-skill.py +122 -0
- procesio_cli/scripts/list-skills.py +68 -0
- procesio_cli/scripts/list-tools.py +73 -0
- procesio_cli/scripts/run-agent.py +59 -0
- procesio_cli/scripts/run-tool.py +123 -0
- procesio_cli/scripts/secret_scan.py +584 -0
- procesio_cli/scripts/set-credential.py +126 -0
- procesio_cli/scripts/validate-skills.py +530 -0
- procesio_cli/skills/PORTFOLIO.md +134 -0
- procesio_cli/skills/__init__.py +6 -0
- procesio_cli/skills/agent-skill-engineer/SKILL.md +226 -0
- procesio_cli/skills/agent-skill-engineer/evals/evals.json +422 -0
- procesio_cli/skills/agent-skill-engineer/references/authoring-standard.md +178 -0
- procesio_cli/skills/agent-skill-engineer/references/decision-framework.md +107 -0
- procesio_cli/skills/agent-skill-engineer/references/domain-evidence-protocol.md +248 -0
- procesio_cli/skills/agent-skill-engineer/references/evaluation-standard.md +191 -0
- procesio_cli/skills/agent-skill-engineer/references/expert-lenses.md +167 -0
- procesio_cli/skills/agent-skill-engineer/references/field-gate-standard.md +231 -0
- procesio_cli/skills/agent-skill-engineer/references/optimization-protocol.md +233 -0
- procesio_cli/skills/agent-skill-engineer/references/optimizer-contract.md +268 -0
- procesio_cli/skills/agent-skill-engineer/references/portability-standard.md +99 -0
- procesio_cli/skills/agent-skill-engineer/references/research-basis.md +128 -0
- procesio_cli/skills/agent-skill-engineer/references/review-standard.md +143 -0
- procesio_cli/skills/agent-skill-engineer/scripts/audit_skill.py +959 -0
- procesio_cli/skills/agent-skill-engineer/scripts/optimize_skill.py +891 -0
- procesio_cli/skills/agent-skill-engineer/scripts/scaffold_skill.py +397 -0
- procesio_cli/skills/evals/baseline-catalog.json +14 -0
- procesio_cli/skills/evals/baseline-routing-v2.json +38 -0
- procesio_cli/skills/evals/baseline.json +37 -0
- procesio_cli/skills/evals/behavioral.json +367 -0
- procesio_cli/skills/evals/field-boundary-development-v1.json +126 -0
- procesio_cli/skills/evals/field-closeout-correction-development-v1.json +23 -0
- procesio_cli/skills/evals/field-closeout-development-v1.json +89 -0
- procesio_cli/skills/evals/portfolio-pressure-training-v1.json +83 -0
- procesio_cli/skills/evals/routing.json +363 -0
- procesio_cli/skills/evals/validation-baseline.json +4 -0
- procesio_cli/skills/procesio-cli/SKILL.md +134 -0
- procesio_cli/skills/procesio-cli/evals/evals.json +111 -0
- procesio_cli/skills/procesio-cli/evals/workflows.json +16 -0
- procesio_cli/skills/procesio-cli/references/connector-lifecycle.md +47 -0
- procesio_cli/skills/procesio-cli/references/credentials-admin.md +113 -0
- procesio_cli/skills/procesio-cli/references/data-verification.md +71 -0
- procesio_cli/skills/procesio-cli/references/documents-files.md +44 -0
- procesio_cli/skills/procesio-cli/references/form-e2e.md +57 -0
- procesio_cli/skills/procesio-cli/references/operation-contract.md +138 -0
- procesio_cli/skills/procesio-cli/references/process-debugging.md +65 -0
- procesio_cli/skills/procesio-cli/references/process-lifecycle.md +88 -0
- procesio_cli/skills/procesio-cli/references/schedules-webhooks.md +58 -0
- procesio_cli/skills/procesio-cli/references/transport-environments.md +53 -0
- procesio_cli/skills/procesio-cli-maintainer/SKILL.md +84 -0
- procesio_cli/skills/procesio-cli-maintainer/evals/evals.json +116 -0
- procesio_cli/skills/procesio-cli-maintainer/references/change-contract.md +34 -0
- procesio_cli/skills/procesio-cli-maintainer/references/mcp-compatibility.md +13 -0
- procesio_cli/skills/procesio-cli-maintainer/references/skill-authoring.md +51 -0
- procesio_cli/skills/procesio-platform-advisor/SKILL.md +82 -0
- procesio_cli/skills/procesio-platform-advisor/evals/evals.json +116 -0
- procesio_cli/skills/procesio-platform-advisor/references/capability-map.md +22 -0
- procesio_cli/skills/procesio-platform-advisor/references/fit-framework.md +35 -0
- procesio_cli/skills/procesio-platform-advisor/references/freshness-policy.md +25 -0
- procesio_cli/skills/procesio-platform-advisor/references/sizing-method.md +70 -0
- procesio_cli/skills/procesio-platform-advisor/scripts/estimate_capacity.py +99 -0
- procesio_cli/skills/procesio-setup/SKILL.md +180 -0
- procesio_cli/skills/sql-server-optimizer/SKILL.md +86 -0
- procesio_cli/skills/sql-server-optimizer/evals/evals.json +116 -0
- procesio_cli/skills/sql-server-optimizer/references/db-context.md +44 -0
- procesio_cli/skills/sql-server-optimizer/references/generic-mode.md +32 -0
- procesio_cli/skills/sql-server-optimizer/references/procesio-mode.md +40 -0
- procesio_cli/skills/sql-server-optimizer/references/sql-rules.md +43 -0
- procesio_cli/skills/sql-server-optimizer/scripts/export-indexes.sql +178 -0
- procesio_cli/skills/sql-server-optimizer/scripts/export-procs-and-functions.sql +118 -0
- procesio_cli/skills/sql-server-optimizer/scripts/export-tables.sql +367 -0
- procesio_cli/skills/tests/__init__.py +0 -0
- procesio_cli/skills/tests/test_agent_skill_engineer.py +240 -0
- procesio_cli/skills/tests/test_auth_failure_stop.py +25 -0
- procesio_cli/skills/tests/test_capacity_estimator.py +85 -0
- procesio_cli/skills/tests/test_field_boundary_learning.py +100 -0
- procesio_cli/skills/tests/test_field_closeout_learning.py +123 -0
- procesio_cli/skills/tests/test_field_gate_standard.py +76 -0
- procesio_cli/skills/tests/test_operational_playbooks.py +51 -0
- procesio_cli/skills/tests/test_portfolio_pressure_training.py +35 -0
- procesio_cli/skills/tests/test_process_lifecycle_single_run.py +25 -0
- procesio_cli/skills/tests/test_skill_evaluator.py +67 -0
- procesio_cli/skills/tests/test_skill_optimizer.py +473 -0
- procesio_cli/skills/tests/test_skill_portfolio_review.py +70 -0
- procesio_cli/skills/tests/test_skill_release_binding.py +204 -0
- procesio_cli/skills/tests/test_skill_routing.py +74 -0
- procesio_cli/skills/tests/test_skill_scaffold_v2.py +116 -0
- procesio_cli/skills/tests/test_validate_skills.py +115 -0
- procesio_cli/tools/__init__.py +0 -0
- procesio_cli/tools/_lib/README.md +119 -0
- procesio_cli/tools/_lib/__init__.py +0 -0
- procesio_cli/tools/_lib/accounting.py +120 -0
- procesio_cli/tools/_lib/contacts.py +544 -0
- procesio_cli/tools/_lib/creds.py +83 -0
- procesio_cli/tools/_lib/creds_backends.py +578 -0
- procesio_cli/tools/_lib/dbprofiles.py +147 -0
- procesio_cli/tools/_lib/dbquery.py +286 -0
- procesio_cli/tools/_lib/dbschema.py +225 -0
- procesio_cli/tools/_lib/io.py +54 -0
- procesio_cli/tools/_lib/manifest.py +297 -0
- procesio_cli/tools/_lib/skill_release.py +127 -0
- procesio_cli/tools/_lib/skill_resources.py +118 -0
- procesio_cli/tools/_lib/userdata.py +228 -0
- procesio_cli/tools/_lib/webserialize/__init__.py +16 -0
- procesio_cli/tools/_lib/webserialize/admin.py +61 -0
- procesio_cli/tools/_lib/webserialize/client.py +264 -0
- procesio_cli/tools/_lib/webserialize/config.py +96 -0
- procesio_cli/tools/_lib/webserialize/errors.py +27 -0
- procesio_cli/tools/_lib/webserialize/framing.py +45 -0
- procesio_cli/tools/_lib/webserialize/registry.py +47 -0
- procesio_cli/tools/_lib/webserialize/runtime.py +61 -0
- procesio_cli/tools/_lib/webserialize/server.py +510 -0
- procesio_cli/tools/_lib/websession.py +194 -0
- procesio_cli/tools/connector-builder/CONNECTOR-BUILDER-API-NOTES.md +91 -0
- procesio_cli/tools/connector-builder/README.md +101 -0
- procesio_cli/tools/connector-builder/SKILL.md +248 -0
- procesio_cli/tools/connector-builder/__init__.py +7 -0
- procesio_cli/tools/connector-builder/actiondef.py +24 -0
- procesio_cli/tools/connector-builder/client.py +251 -0
- procesio_cli/tools/connector-builder/errors.py +44 -0
- procesio_cli/tools/connector-builder/gen_manifest.py +142 -0
- procesio_cli/tools/connector-builder/handlers/__init__.py +1 -0
- procesio_cli/tools/connector-builder/handlers/admin.py +182 -0
- procesio_cli/tools/connector-builder/handlers/auth.py +74 -0
- procesio_cli/tools/connector-builder/handlers/builds.py +396 -0
- procesio_cli/tools/connector-builder/handlers/common.py +104 -0
- procesio_cli/tools/connector-builder/handlers/files.py +111 -0
- procesio_cli/tools/connector-builder/handlers/raw.py +38 -0
- procesio_cli/tools/connector-builder/handlers/telemetry.py +39 -0
- procesio_cli/tools/connector-builder/main.py +94 -0
- procesio_cli/tools/connector-builder/tests/conftest.py +146 -0
- procesio_cli/tools/connector-builder/tests/test_cb_client.py +86 -0
- procesio_cli/tools/connector-builder/tests/test_cb_dispatch.py +105 -0
- procesio_cli/tools/connector-builder/tests/test_cb_manifest_sync.py +76 -0
- procesio_cli/tools/connector-builder/tests/test_cb_wait.py +123 -0
- procesio_cli/tools/connector-builder/tool.yaml +671 -0
- procesio_cli/tools/framework-map/.gitattributes +2 -0
- procesio_cli/tools/framework-map/README.md +98 -0
- procesio_cli/tools/framework-map/SKILL.md +30 -0
- procesio_cli/tools/framework-map/app.js +188 -0
- procesio_cli/tools/framework-map/fm_builder.py +476 -0
- procesio_cli/tools/framework-map/fm_catalog.py +19 -0
- procesio_cli/tools/framework-map/fm_ro_catalog.py +94 -0
- procesio_cli/tools/framework-map/fm_strings.py +101 -0
- procesio_cli/tools/framework-map/main.py +95 -0
- procesio_cli/tools/framework-map/styles.css +214 -0
- procesio_cli/tools/framework-map/tests/conftest.py +33 -0
- procesio_cli/tools/framework-map/tests/test_fm_build.py +126 -0
- procesio_cli/tools/framework-map/tests/test_fm_manifest_sync.py +63 -0
- procesio_cli/tools/framework-map/tests/test_fm_store_tree.py +75 -0
- procesio_cli/tools/framework-map/tool.yaml +61 -0
- procesio_cli/tools/mysql/MOVED-TO-CENTRAL.md +29 -0
- procesio_cli/tools/mysql/README.md +196 -0
- procesio_cli/tools/mysql/SKILL.md +37 -0
- procesio_cli/tools/mysql/__init__.py +0 -0
- procesio_cli/tools/mysql/connection.py +191 -0
- procesio_cli/tools/mysql/main.py +487 -0
- procesio_cli/tools/mysql/profiles.template.json +1 -0
- procesio_cli/tools/mysql/schema.py +434 -0
- procesio_cli/tools/mysql/tests/__init__.py +0 -0
- procesio_cli/tools/mysql/tests/conftest.py +21 -0
- procesio_cli/tools/mysql/tests/test_manifest_sync.py +68 -0
- procesio_cli/tools/mysql/tests/test_mysql.py +201 -0
- procesio_cli/tools/mysql/tests/test_mysql_schema.py +337 -0
- procesio_cli/tools/mysql/tool.yaml +112 -0
- procesio_cli/tools/procesio/DTO-SUBTOOLS-NOTE.md +360 -0
- procesio_cli/tools/procesio/FORM-DEV-GUIDE/00-INDEX.md +67 -0
- procesio_cli/tools/procesio/FORM-DEV-GUIDE/01-ANATOMY.md +209 -0
- procesio_cli/tools/procesio/FORM-DEV-GUIDE/02-CODE-INJECTION.md +309 -0
- procesio_cli/tools/procesio/FORM-DEV-GUIDE/03-DOM-CONTRACT.md +370 -0
- procesio_cli/tools/procesio/FORM-DEV-GUIDE/04-INTERACTION-RECIPES.md +600 -0
- procesio_cli/tools/procesio/FORM-DEV-GUIDE/05-STEPPER-AND-MOTION.md +426 -0
- procesio_cli/tools/procesio/FORM-DEV-GUIDE/06-PROCESS-INTEGRATION.md +347 -0
- procesio_cli/tools/procesio/FORM-DEV-GUIDE/07-DEPLOY-WORKFLOW.md +294 -0
- procesio_cli/tools/procesio/FORM-DEV-GUIDE/08-PITFALLS.md +569 -0
- procesio_cli/tools/procesio/FORM-DEV-GUIDE/09-NAVIGATION-AND-HOSTING.md +308 -0
- procesio_cli/tools/procesio/PHASE4-E2E-NOTES.md +594 -0
- procesio_cli/tools/procesio/PROCESIO-API-CORRECTIONS.md +295 -0
- procesio_cli/tools/procesio/PROCESIO-API-NOTES.md +6976 -0
- procesio_cli/tools/procesio/PROCESIO-AUTH-NOTES.md +226 -0
- procesio_cli/tools/procesio/PROCESIO-CARD-BUILD-NOTES.md +183 -0
- procesio_cli/tools/procesio/PROCESIO-CONNECTORS-NOTES.md +141 -0
- procesio_cli/tools/procesio/PROCESIO-CUSTOM-ACTION-NOTES.md +179 -0
- procesio_cli/tools/procesio/PROCESIO-DOCS-FIX-REPORT.md +123 -0
- procesio_cli/tools/procesio/PROCESIO-ENVIRONMENTS-NOTES.md +94 -0
- procesio_cli/tools/procesio/PROCESIO-FE-VALIDATION-NOTES.md +107 -0
- procesio_cli/tools/procesio/PROCESIO-FOREACH-NOTES.md +199 -0
- procesio_cli/tools/procesio/PROCESIO-FORM-API-HANG-NOTE.md +101 -0
- procesio_cli/tools/procesio/PROCESIO-FORM-SUBMISSION-NOTES.md +172 -0
- procesio_cli/tools/procesio/PROCESIO-HTML-TO-DOCX-NOTES.md +110 -0
- procesio_cli/tools/procesio/PROCESIO-INSTANCE-HISTORY-NOTES.md +242 -0
- procesio_cli/tools/procesio/PROCESIO-METERING-NOTES.md +201 -0
- procesio_cli/tools/procesio/PROCESIO-NODE-CODE-NOTES.md +279 -0
- procesio_cli/tools/procesio/PROCESIO-NODE-MODULE-WHITELIST.md +113 -0
- procesio_cli/tools/procesio/PROCESIO-PYTHON-ACTION-NOTES.md +165 -0
- procesio_cli/tools/procesio/PROCESIO-QUERY-STORE-NOTES.md +826 -0
- procesio_cli/tools/procesio/PROCESIO-RECONCILIATION-PATTERNS.md +104 -0
- procesio_cli/tools/procesio/PROCESIO-RESOURCE-MODEL-NOTES.md +1100 -0
- procesio_cli/tools/procesio/PROCESIO-SEND-EMAIL-CRED-OPTIONALITY.md +45 -0
- procesio_cli/tools/procesio/PROCESIO-SEND-EMAIL-NOTES.md +252 -0
- procesio_cli/tools/procesio/PROCESIO-SQL-ACTIONS-NOTES.md +284 -0
- procesio_cli/tools/procesio/PROCESIO-USAGE-GUIDE.md +219 -0
- procesio_cli/tools/procesio/README.md +341 -0
- procesio_cli/tools/procesio/SCHEDULE-INPUT-SECURITY-NOTES.md +63 -0
- procesio_cli/tools/procesio/SKILL.md +694 -0
- procesio_cli/tools/procesio/__init__.py +1 -0
- procesio_cli/tools/procesio/actiondef.py +27 -0
- procesio_cli/tools/procesio/assets/html2docx/html2docx.js +2155 -0
- procesio_cli/tools/procesio/auth.py +354 -0
- procesio_cli/tools/procesio/autogen.py +121 -0
- procesio_cli/tools/procesio/client.py +355 -0
- procesio_cli/tools/procesio/config.py +96 -0
- procesio_cli/tools/procesio/data/endpoints.json +2901 -0
- procesio_cli/tools/procesio/docs_info/API-DOCUMENTATION/01-authentication.md +180 -0
- procesio_cli/tools/procesio/docs_info/API-DOCUMENTATION/02-conventions.md +116 -0
- procesio_cli/tools/procesio/docs_info/API-DOCUMENTATION/ANONYMOUS-SURFACE.md +51 -0
- procesio_cli/tools/procesio/docs_info/API-DOCUMENTATION/README.md +104 -0
- procesio_cli/tools/procesio/docs_info/API-DOCUMENTATION/SYMBOL-INDEX.md +444 -0
- procesio_cli/tools/procesio/docs_info/API-DOCUMENTATION/endpoints/03-auth-users-workspaces.md +731 -0
- procesio_cli/tools/procesio/docs_info/API-DOCUMENTATION/endpoints/04-processes.md +913 -0
- procesio_cli/tools/procesio/docs_info/API-DOCUMENTATION/endpoints/05-actions.md +605 -0
- procesio_cli/tools/procesio/docs_info/API-DOCUMENTATION/endpoints/06-files.md +237 -0
- procesio_cli/tools/procesio/docs_info/API-DOCUMENTATION/endpoints/07-forms-documents.md +985 -0
- procesio_cli/tools/procesio/docs_info/API-DOCUMENTATION/endpoints/08-credentials.md +532 -0
- procesio_cli/tools/procesio/docs_info/API-DOCUMENTATION/endpoints/09-datastore-datatypes.md +830 -0
- procesio_cli/tools/procesio/docs_info/API-DOCUMENTATION/endpoints/10-custom-urls.md +319 -0
- procesio_cli/tools/procesio/docs_info/API-DOCUMENTATION/endpoints/11-subscriptions-resources-analytics.md +455 -0
- procesio_cli/tools/procesio/docs_info/API-DOCUMENTATION/endpoints/12-webhooks-notifications-misc.md +519 -0
- procesio_cli/tools/procesio/docs_info/API-DOCUMENTATION/endpoints/13-realtime-signalr.md +153 -0
- procesio_cli/tools/procesio/docs_info/API-DOCUMENTATION/endpoints/99-internal-and-other-services.md +52 -0
- procesio_cli/tools/procesio/docs_info/FormBuilder mock.ts +5725 -0
- procesio_cli/tools/procesio/docs_info/Procesio Platform Actions.json +30219 -0
- procesio_cli/tools/procesio/docs_info/form-config-enums.ts +92 -0
- procesio_cli/tools/procesio/docs_info/form-theme.ts +1603 -0
- procesio_cli/tools/procesio/docs_info/process-validation-reference-1.md +2739 -0
- procesio_cli/tools/procesio/dto/__init__.py +13 -0
- procesio_cli/tools/procesio/dto/credential/builder.py +179 -0
- procesio_cli/tools/procesio/dto/credential/config.schema.json +19 -0
- procesio_cli/tools/procesio/dto/credential/description.md +193 -0
- procesio_cli/tools/procesio/dto/credential/fixtures/rest.config.json +11 -0
- procesio_cli/tools/procesio/dto/credential/fixtures/rest.dto.json +28 -0
- procesio_cli/tools/procesio/dto/credential/fixtures/rest.template.json +44 -0
- procesio_cli/tools/procesio/dto/credential/template.dto.json +16 -0
- procesio_cli/tools/procesio/dto/data/_refresh.py +147 -0
- procesio_cli/tools/procesio/dto/data/action_catalog.json +30825 -0
- procesio_cli/tools/procesio/dto/data/action_families.json +55 -0
- procesio_cli/tools/procesio/dto/data/platform_types.json +182 -0
- procesio_cli/tools/procesio/dto/datatype/builder.py +223 -0
- procesio_cli/tools/procesio/dto/datatype/config.schema.json +47 -0
- procesio_cli/tools/procesio/dto/datatype/description.md +85 -0
- procesio_cli/tools/procesio/dto/datatype/fixtures/customer.config.json +41 -0
- procesio_cli/tools/procesio/dto/datatype/fixtures/customer.dto.json +164 -0
- procesio_cli/tools/procesio/dto/datatype/template.dto.json +37 -0
- procesio_cli/tools/procesio/dto/document/builder.py +193 -0
- procesio_cli/tools/procesio/dto/document/config.schema.json +33 -0
- procesio_cli/tools/procesio/dto/document/description.md +124 -0
- procesio_cli/tools/procesio/dto/document/fixtures/invoice.config.json +16 -0
- procesio_cli/tools/procesio/dto/document/fixtures/invoice.dto.json +32 -0
- procesio_cli/tools/procesio/dto/document/template.dto.json +14 -0
- procesio_cli/tools/procesio/dto/form/FORM-STYLING-NOTES.md +142 -0
- procesio_cli/tools/procesio/dto/form/GOLDEN-DRIFT-NOTES.md +72 -0
- procesio_cli/tools/procesio/dto/form/RUN-PROCESS-RESULT-NOTES.md +80 -0
- procesio_cli/tools/procesio/dto/form/addelement.py +277 -0
- procesio_cli/tools/procesio/dto/form/builder.py +1009 -0
- procesio_cli/tools/procesio/dto/form/capture_goldens.py +106 -0
- procesio_cli/tools/procesio/dto/form/code_cipher.py +67 -0
- procesio_cli/tools/procesio/dto/form/config.schema.json +76 -0
- procesio_cli/tools/procesio/dto/form/data_shell.json +1 -0
- procesio_cli/tools/procesio/dto/form/description.md +346 -0
- procesio_cli/tools/procesio/dto/form/elements/approval.json +259 -0
- procesio_cli/tools/procesio/dto/form/elements/assignee.json +137 -0
- procesio_cli/tools/procesio/dto/form/elements/button.json +125 -0
- procesio_cli/tools/procesio/dto/form/elements/chart.json +341 -0
- procesio_cli/tools/procesio/dto/form/elements/chat.json +199 -0
- procesio_cli/tools/procesio/dto/form/elements/checkbox.json +153 -0
- procesio_cli/tools/procesio/dto/form/elements/column.json +77 -0
- procesio_cli/tools/procesio/dto/form/elements/columns.json +78 -0
- procesio_cli/tools/procesio/dto/form/elements/datetime-input.json +304 -0
- procesio_cli/tools/procesio/dto/form/elements/divider.json +54 -0
- procesio_cli/tools/procesio/dto/form/elements/dropdown.json +130 -0
- procesio_cli/tools/procesio/dto/form/elements/dynamic-table-row.json +253 -0
- procesio_cli/tools/procesio/dto/form/elements/file-upload.json +196 -0
- procesio_cli/tools/procesio/dto/form/elements/file-viewer.json +169 -0
- procesio_cli/tools/procesio/dto/form/elements/heading.json +79 -0
- procesio_cli/tools/procesio/dto/form/elements/icon.json +107 -0
- procesio_cli/tools/procesio/dto/form/elements/image.json +174 -0
- procesio_cli/tools/procesio/dto/form/elements/input.json +206 -0
- procesio_cli/tools/procesio/dto/form/elements/list.json +202 -0
- procesio_cli/tools/procesio/dto/form/elements/number-input.json +202 -0
- procesio_cli/tools/procesio/dto/form/elements/paragraph.json +79 -0
- procesio_cli/tools/procesio/dto/form/elements/radiobox.json +174 -0
- procesio_cli/tools/procesio/dto/form/elements/section.json +114 -0
- procesio_cli/tools/procesio/dto/form/elements/select.json +217 -0
- procesio_cli/tools/procesio/dto/form/elements/side-panel.json +146 -0
- procesio_cli/tools/procesio/dto/form/elements/signature-pad.json +141 -0
- procesio_cli/tools/procesio/dto/form/elements/static-table-row.json +84 -0
- procesio_cli/tools/procesio/dto/form/elements/step.json +105 -0
- procesio_cli/tools/procesio/dto/form/elements/stepper.json +126 -0
- procesio_cli/tools/procesio/dto/form/elements/tab.json +77 -0
- procesio_cli/tools/procesio/dto/form/elements/table.json +279 -0
- procesio_cli/tools/procesio/dto/form/elements/tabs.json +114 -0
- procesio_cli/tools/procesio/dto/form/elements/textarea.json +213 -0
- procesio_cli/tools/procesio/dto/form/enum_map.json +68 -0
- procesio_cli/tools/procesio/dto/form/fieldpath.py +284 -0
- procesio_cli/tools/procesio/dto/form/fixtures/reg.config.json +32 -0
- procesio_cli/tools/procesio/dto/form/fixtures/reg.elements.json +638 -0
- procesio_cli/tools/procesio/dto/form/sync_from_mock.py +386 -0
- procesio_cli/tools/procesio/dto/framework.py +125 -0
- procesio_cli/tools/procesio/dto/process/builder.py +1991 -0
- procesio_cli/tools/procesio/dto/process/config.schema.json +159 -0
- procesio_cli/tools/procesio/dto/process/description.md +218 -0
- procesio_cli/tools/procesio/dto/process/fixtures/greet.config.json +32 -0
- procesio_cli/tools/procesio/dto/process/fixtures/greet.dto.json +317 -0
- procesio_cli/tools/procesio/dto/process/naming.py +305 -0
- procesio_cli/tools/procesio/dto/process/normalize.py +74 -0
- procesio_cli/tools/procesio/dto/process/template.dto.json +32 -0
- procesio_cli/tools/procesio/dto/refdata.py +87 -0
- procesio_cli/tools/procesio/dto/registry.py +27 -0
- procesio_cli/tools/procesio/dto/webhook/builder.py +142 -0
- procesio_cli/tools/procesio/dto/webhook/config.schema.json +25 -0
- procesio_cli/tools/procesio/dto/webhook/description.md +92 -0
- procesio_cli/tools/procesio/dto/webhook/fixtures/order.config.json +10 -0
- procesio_cli/tools/procesio/dto/webhook/fixtures/order.dto.json +25 -0
- procesio_cli/tools/procesio/dto/webhook/template.dto.json +14 -0
- procesio_cli/tools/procesio/environments.py +264 -0
- procesio_cli/tools/procesio/errors.py +166 -0
- procesio_cli/tools/procesio/flowmodel/README.md +37 -0
- procesio_cli/tools/procesio/flowmodel/__init__.py +14 -0
- procesio_cli/tools/procesio/flowmodel/digest.py +223 -0
- procesio_cli/tools/procesio/flowmodel/families.py +34 -0
- procesio_cli/tools/procesio/flowmodel/fevalidation.py +1098 -0
- procesio_cli/tools/procesio/flowmodel/formdigest.py +232 -0
- procesio_cli/tools/procesio/flowmodel/inspect.py +78 -0
- procesio_cli/tools/procesio/flowmodel/model.py +82 -0
- procesio_cli/tools/procesio/flowmodel/nodeparam.py +871 -0
- procesio_cli/tools/procesio/flowmodel/reader.py +191 -0
- procesio_cli/tools/procesio/flowmodel/sqlparam.py +410 -0
- procesio_cli/tools/procesio/form_code_keys.py +50 -0
- procesio_cli/tools/procesio/formlint.py +292 -0
- procesio_cli/tools/procesio/gen_manifest.py +118 -0
- procesio_cli/tools/procesio/handlers/__init__.py +1 -0
- procesio_cli/tools/procesio/handlers/auth_actions.py +103 -0
- procesio_cli/tools/procesio/handlers/catalog.py +147 -0
- procesio_cli/tools/procesio/handlers/common.py +90 -0
- procesio_cli/tools/procesio/handlers/customaction_ops.py +146 -0
- procesio_cli/tools/procesio/handlers/datastore_ops.py +482 -0
- procesio_cli/tools/procesio/handlers/datatype_ops.py +275 -0
- procesio_cli/tools/procesio/handlers/dto_actions.py +258 -0
- procesio_cli/tools/procesio/handlers/environment_admin.py +146 -0
- procesio_cli/tools/procesio/handlers/fevalidate.py +236 -0
- procesio_cli/tools/procesio/handlers/files.py +141 -0
- procesio_cli/tools/procesio/handlers/flowgraph.py +229 -0
- procesio_cli/tools/procesio/handlers/flowlint.py +269 -0
- procesio_cli/tools/procesio/handlers/form_chains.py +336 -0
- procesio_cli/tools/procesio/handlers/form_code.py +277 -0
- procesio_cli/tools/procesio/handlers/form_element.py +199 -0
- procesio_cli/tools/procesio/handlers/form_events.py +441 -0
- procesio_cli/tools/procesio/handlers/form_update.py +270 -0
- procesio_cli/tools/procesio/handlers/formprocess.py +211 -0
- procesio_cli/tools/procesio/handlers/generic.py +135 -0
- procesio_cli/tools/procesio/handlers/layout.py +137 -0
- procesio_cli/tools/procesio/handlers/nodeparams.py +1018 -0
- procesio_cli/tools/procesio/handlers/process_layout.py +189 -0
- procesio_cli/tools/procesio/handlers/process_naming.py +213 -0
- procesio_cli/tools/procesio/handlers/processes.py +416 -0
- procesio_cli/tools/procesio/handlers/profile_admin.py +184 -0
- procesio_cli/tools/procesio/handlers/resource_ops.py +447 -0
- procesio_cli/tools/procesio/handlers/schedules.py +320 -0
- procesio_cli/tools/procesio/handlers/sqlactions.py +232 -0
- procesio_cli/tools/procesio/handlers/transport.py +463 -0
- procesio_cli/tools/procesio/handlers/usageguide.py +222 -0
- procesio_cli/tools/procesio/layout/README.md +196 -0
- procesio_cli/tools/procesio/layout/__init__.py +11 -0
- procesio_cli/tools/procesio/layout/adapter.py +736 -0
- procesio_cli/tools/procesio/layout/cycles.py +186 -0
- procesio_cli/tools/procesio/layout/dispatch.py +39 -0
- procesio_cli/tools/procesio/layout/elk/elk_runner.mjs +50 -0
- procesio_cli/tools/procesio/layout/elk/package-lock.json +21 -0
- procesio_cli/tools/procesio/layout/elk/package.json +11 -0
- procesio_cli/tools/procesio/layout/elk_engine.py +568 -0
- procesio_cli/tools/procesio/layout/engine.py +1311 -0
- procesio_cli/tools/procesio/layout/report.py +187 -0
- procesio_cli/tools/procesio/main.py +179 -0
- procesio_cli/tools/procesio/profiles.py +193 -0
- procesio_cli/tools/procesio/reliability.py +193 -0
- procesio_cli/tools/procesio/sqlformat.py +167 -0
- procesio_cli/tools/procesio/swagger.py +51 -0
- procesio_cli/tools/procesio/tests/__init__.py +0 -0
- procesio_cli/tools/procesio/tests/conftest.py +129 -0
- procesio_cli/tools/procesio/tests/test_auth.py +200 -0
- procesio_cli/tools/procesio/tests/test_autogen.py +78 -0
- procesio_cli/tools/procesio/tests/test_builder_attrpath_sqlbind.py +180 -0
- procesio_cli/tools/procesio/tests/test_builder_custom_action_catalog.py +72 -0
- procesio_cli/tools/procesio/tests/test_client.py +114 -0
- procesio_cli/tools/procesio/tests/test_client_reliability.py +139 -0
- procesio_cli/tools/procesio/tests/test_customaction.py +103 -0
- procesio_cli/tools/procesio/tests/test_customaction_test.py +80 -0
- procesio_cli/tools/procesio/tests/test_cycles.py +69 -0
- procesio_cli/tools/procesio/tests/test_datastore.py +378 -0
- procesio_cli/tools/procesio/tests/test_datastore_node.py +94 -0
- procesio_cli/tools/procesio/tests/test_dispatch.py +170 -0
- procesio_cli/tools/procesio/tests/test_document_page_size.py +19 -0
- procesio_cli/tools/procesio/tests/test_dto.py +734 -0
- procesio_cli/tools/procesio/tests/test_edit_dryrun_preview.py +96 -0
- procesio_cli/tools/procesio/tests/test_elk_layout.py +221 -0
- procesio_cli/tools/procesio/tests/test_environments.py +214 -0
- procesio_cli/tools/procesio/tests/test_fevalidate_gate.py +104 -0
- procesio_cli/tools/procesio/tests/test_fevalidation.py +317 -0
- procesio_cli/tools/procesio/tests/test_fieldpath_variables.py +87 -0
- procesio_cli/tools/procesio/tests/test_files.py +72 -0
- procesio_cli/tools/procesio/tests/test_flow_digest.py +202 -0
- procesio_cli/tools/procesio/tests/test_flowlint.py +114 -0
- procesio_cli/tools/procesio/tests/test_flowmodel.py +158 -0
- procesio_cli/tools/procesio/tests/test_form_add_element.py +256 -0
- procesio_cli/tools/procesio/tests/test_form_approval_gaps.py +319 -0
- procesio_cli/tools/procesio/tests/test_form_auto_names.py +60 -0
- procesio_cli/tools/procesio/tests/test_form_chains.py +217 -0
- procesio_cli/tools/procesio/tests/test_form_code_actions.py +188 -0
- procesio_cli/tools/procesio/tests/test_form_code_keys.py +92 -0
- procesio_cli/tools/procesio/tests/test_form_code_style.py +178 -0
- procesio_cli/tools/procesio/tests/test_form_delete_element.py +99 -0
- procesio_cli/tools/procesio/tests/test_form_element_config.py +141 -0
- procesio_cli/tools/procesio/tests/test_form_event_maps.py +135 -0
- procesio_cli/tools/procesio/tests/test_form_event_ops.py +376 -0
- procesio_cli/tools/procesio/tests/test_form_event_replace.py +86 -0
- procesio_cli/tools/procesio/tests/test_form_events.py +92 -0
- procesio_cli/tools/procesio/tests/test_form_parity.py +171 -0
- procesio_cli/tools/procesio/tests/test_form_select_source.py +74 -0
- procesio_cli/tools/procesio/tests/test_form_sync.py +35 -0
- procesio_cli/tools/procesio/tests/test_form_update.py +133 -0
- procesio_cli/tools/procesio/tests/test_formlint.py +155 -0
- procesio_cli/tools/procesio/tests/test_formlint_css_scope.py +38 -0
- procesio_cli/tools/procesio/tests/test_formlint_field_names.py +83 -0
- procesio_cli/tools/procesio/tests/test_guards.py +110 -0
- procesio_cli/tools/procesio/tests/test_hidden_setting_types.py +39 -0
- procesio_cli/tools/procesio/tests/test_html2docx_asset.py +132 -0
- procesio_cli/tools/procesio/tests/test_key_handle_terminology.py +45 -0
- procesio_cli/tools/procesio/tests/test_layout.py +574 -0
- procesio_cli/tools/procesio/tests/test_layout_report.py +88 -0
- procesio_cli/tools/procesio/tests/test_manifest_sync.py +68 -0
- procesio_cli/tools/procesio/tests/test_nodedelete.py +151 -0
- procesio_cli/tools/procesio/tests/test_nodeparam.py +826 -0
- procesio_cli/tools/procesio/tests/test_normalize.py +70 -0
- procesio_cli/tools/procesio/tests/test_payload_docs.py +86 -0
- procesio_cli/tools/procesio/tests/test_process_action_naming.py +170 -0
- procesio_cli/tools/procesio/tests/test_process_call_api_seed.py +46 -0
- procesio_cli/tools/procesio/tests/test_process_ext.py +373 -0
- procesio_cli/tools/procesio/tests/test_process_invariants.py +183 -0
- procesio_cli/tools/procesio/tests/test_process_layout.py +117 -0
- procesio_cli/tools/procesio/tests/test_process_naming.py +188 -0
- procesio_cli/tools/procesio/tests/test_process_query_store.py +172 -0
- procesio_cli/tools/procesio/tests/test_processinfo_variable.py +56 -0
- procesio_cli/tools/procesio/tests/test_profiles.py +127 -0
- procesio_cli/tools/procesio/tests/test_put_projects.py +41 -0
- procesio_cli/tools/procesio/tests/test_reliability.py +107 -0
- procesio_cli/tools/procesio/tests/test_removal_gate.py +95 -0
- procesio_cli/tools/procesio/tests/test_resource_ops.py +173 -0
- procesio_cli/tools/procesio/tests/test_save_validity.py +207 -0
- procesio_cli/tools/procesio/tests/test_schedule_cron_shape.py +111 -0
- procesio_cli/tools/procesio/tests/test_schedules.py +309 -0
- procesio_cli/tools/procesio/tests/test_sqlconvert.py +234 -0
- procesio_cli/tools/procesio/tests/test_sqlformat.py +83 -0
- procesio_cli/tools/procesio/tests/test_sqlparam.py +187 -0
- procesio_cli/tools/procesio/tests/test_superseded_actions.py +54 -0
- procesio_cli/tools/procesio/tests/test_surgical_concurrency.py +156 -0
- procesio_cli/tools/procesio/tests/test_tier4.py +123 -0
- procesio_cli/tools/procesio/tests/test_transport.py +147 -0
- procesio_cli/tools/procesio/tests/test_transport_data_stores.py +168 -0
- procesio_cli/tools/procesio/tests/test_transport_mapper_repair.py +150 -0
- procesio_cli/tools/procesio/tests/test_transport_webhook_strip.py +253 -0
- procesio_cli/tools/procesio/tests/test_usage_guide.py +96 -0
- procesio_cli/tools/procesio/tool.yaml +12486 -0
- procesio_cli/tools/sqlserver/MOVED-TO-CENTRAL.md +29 -0
- procesio_cli/tools/sqlserver/README.md +192 -0
- procesio_cli/tools/sqlserver/SKILL.md +37 -0
- procesio_cli/tools/sqlserver/SQLSERVER-SCHEMA-NOTES.md +284 -0
- procesio_cli/tools/sqlserver/__init__.py +0 -0
- procesio_cli/tools/sqlserver/connection.py +242 -0
- procesio_cli/tools/sqlserver/main.py +521 -0
- procesio_cli/tools/sqlserver/profiles.template.json +1 -0
- procesio_cli/tools/sqlserver/schema.py +600 -0
- procesio_cli/tools/sqlserver/tests/__init__.py +0 -0
- procesio_cli/tools/sqlserver/tests/conftest.py +21 -0
- procesio_cli/tools/sqlserver/tests/test_connection.py +75 -0
- procesio_cli/tools/sqlserver/tests/test_dbprofiles.py +92 -0
- procesio_cli/tools/sqlserver/tests/test_dbquery.py +220 -0
- procesio_cli/tools/sqlserver/tests/test_manifest_sync.py +68 -0
- procesio_cli/tools/sqlserver/tests/test_sqlserver.py +326 -0
- procesio_cli/tools/sqlserver/tests/test_sqlserver_schema.py +488 -0
- procesio_cli/tools/sqlserver/tool.yaml +123 -0
- procesio_cli/tools/web/README.md +381 -0
- procesio_cli/tools/web/SKILL.md +37 -0
- procesio_cli/tools/web/WEB-AUTOMATION-NOTES.md +277 -0
- procesio_cli/tools/web/__init__.py +21 -0
- procesio_cli/tools/web/actiondef.py +24 -0
- procesio_cli/tools/web/api.py +444 -0
- procesio_cli/tools/web/brokered.py +107 -0
- procesio_cli/tools/web/driver.py +839 -0
- procesio_cli/tools/web/drivercontract.py +44 -0
- procesio_cli/tools/web/errors.py +54 -0
- procesio_cli/tools/web/handlers/__init__.py +1 -0
- procesio_cli/tools/web/handlers/archive.py +367 -0
- procesio_cli/tools/web/handlers/browse.py +182 -0
- procesio_cli/tools/web/handlers/contacts.py +74 -0
- procesio_cli/tools/web/handlers/sessmgmt.py +120 -0
- procesio_cli/tools/web/main.py +128 -0
- procesio_cli/tools/web/sessions.py +253 -0
- procesio_cli/tools/web/steps.py +162 -0
- procesio_cli/tools/web/tests/__init__.py +0 -0
- procesio_cli/tools/web/tests/conftest.py +197 -0
- procesio_cli/tools/web/tests/test_api.py +330 -0
- procesio_cli/tools/web/tests/test_archive.py +190 -0
- procesio_cli/tools/web/tests/test_brokered.py +138 -0
- procesio_cli/tools/web/tests/test_dispatch.py +132 -0
- procesio_cli/tools/web/tests/test_errors.py +60 -0
- procesio_cli/tools/web/tests/test_manifest_sync.py +76 -0
- procesio_cli/tools/web/tests/test_page_contacts.py +68 -0
- procesio_cli/tools/web/tests/test_sessions.py +145 -0
- procesio_cli/tools/web/tests/test_steps.py +210 -0
- procesio_cli/tools/web/tool.yaml +184 -0
- procesio_cli/tools/xlsx/README.md +34 -0
- procesio_cli/tools/xlsx/SKILL.md +28 -0
- procesio_cli/tools/xlsx/__init__.py +0 -0
- procesio_cli/tools/xlsx/main.py +129 -0
- procesio_cli/tools/xlsx/reader.py +91 -0
- procesio_cli/tools/xlsx/tests/__init__.py +0 -0
- procesio_cli/tools/xlsx/tests/conftest.py +39 -0
- procesio_cli/tools/xlsx/tests/test_xlsx.py +103 -0
- procesio_cli/tools/xlsx/tool.yaml +30 -0
- procesio_cli/webplatform/aat_mcp/AAT-MCP-NOTES.md +244 -0
- procesio_cli/webplatform/aat_mcp/README.md +78 -0
- procesio_cli/webplatform/aat_mcp/bridge.py +705 -0
- procesio_cli/webplatform/aat_mcp/chat_server.py +194 -0
- procesio_cli/webplatform/aat_mcp/chat_surface.snapshot.json +668 -0
- procesio_cli/webplatform/aat_mcp/chat_surface.yaml +372 -0
- procesio_cli/webplatform/aat_mcp/gate.py +68 -0
- procesio_cli/webplatform/aat_mcp/http_server.py +139 -0
- procesio_cli/webplatform/aat_mcp/protocol.py +175 -0
- procesio_cli/webplatform/aat_mcp/server.py +306 -0
- procesio_cli/webplatform/aat_mcp/tests/conftest.py +8 -0
- procesio_cli/webplatform/aat_mcp/tests/test_aat_mcp.py +255 -0
- procesio_cli/webplatform/aat_mcp/tests/test_chat_surface.py +247 -0
- procesio_cli/webplatform/aat_mcp/tests/test_discovery.py +489 -0
- procesio_cli/webplatform/aat_mcp/tests/test_multiuser.py +86 -0
- procesio_cli/webplatform/aat_mcp/tests/test_progressive_discovery.py +89 -0
- procesio_cli/webplatform/aat_mcp/tests/test_protocol.py +180 -0
- procesio_cli/webplatform/aat_mcp/tests/test_skill_discovery.py +23 -0
- procesio_cli-0.1.1.dist-info/METADATA +467 -0
- procesio_cli-0.1.1.dist-info/RECORD +647 -0
- procesio_cli-0.1.1.dist-info/WHEEL +4 -0
- procesio_cli-0.1.1.dist-info/entry_points.txt +7 -0
- procesio_cli-0.1.1.dist-info/licenses/LICENSE +201 -0
- procesio_cli-0.1.1.dist-info/licenses/NOTICE +5 -0
|
@@ -0,0 +1,373 @@
|
|
|
1
|
+
"""Process builder: For-Each containment + Call/Trigger Subprocess mapping (Tier-2)."""
|
|
2
|
+
from __future__ import annotations
|
|
3
|
+
|
|
4
|
+
import itertools
|
|
5
|
+
|
|
6
|
+
import pytest
|
|
7
|
+
|
|
8
|
+
from tools.procesio.dto.process import builder as pb
|
|
9
|
+
from tools.procesio.errors import UsageError
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
def _ctx():
|
|
13
|
+
counter = itertools.count(1)
|
|
14
|
+
return {"new_id": lambda: f"00000000-0000-0000-0000-{next(counter):012d}"}
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
def _by_cid(dto):
|
|
18
|
+
return {a["ActionName"]: a for a in dto["Actions"]}
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
# -- For-Each containment ----------------------------------------------------
|
|
22
|
+
|
|
23
|
+
def test_foreach_body_is_parented():
|
|
24
|
+
cfg = {"title": "loop", "actions": [
|
|
25
|
+
{"id": "loop", "action": "For Each", "name": "loop"},
|
|
26
|
+
{"id": "body", "action": "Map Data", "name": "body", "parent": "loop"},
|
|
27
|
+
]}
|
|
28
|
+
dto = pb.build(cfg, _ctx())
|
|
29
|
+
nodes = _by_cid(dto)
|
|
30
|
+
loop, body = nodes["loop"], nodes["body"]
|
|
31
|
+
assert loop["CustomData"]["type"] == "area"
|
|
32
|
+
# the layout engine sizes the For-Each frame to bound its child (not the 48x48 default)
|
|
33
|
+
assert loop["CustomData"]["areaSize"]["width"] >= 48
|
|
34
|
+
assert loop["CustomData"]["areaSize"]["height"] >= 48
|
|
35
|
+
# the body action points at the For-Each node id
|
|
36
|
+
assert body["ParentId"] == loop["Id"]
|
|
37
|
+
# a normal (non-area) node keeps the small node frame
|
|
38
|
+
assert body["CustomData"]["areaSize"]["width"] == 48
|
|
39
|
+
# the built process renders correctly: body inside the loop frame, stored RELATIVE
|
|
40
|
+
from tools.procesio.layout import adapter
|
|
41
|
+
assert adapter.verify_render(dto)["ok"]
|
|
42
|
+
bp = body["CustomData"]["position"]
|
|
43
|
+
asz = loop["CustomData"]["areaSize"]
|
|
44
|
+
assert 0 <= bp["x"] <= asz["width"] and 0 <= bp["y"] <= asz["height"]
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
def test_non_parented_action_has_null_parent():
|
|
48
|
+
cfg = {"title": "t", "actions": [{"id": "g", "action": "Generate GUID"}]}
|
|
49
|
+
dto = pb.build(cfg, _ctx())
|
|
50
|
+
assert all(a["ParentId"] is None for a in dto["Actions"])
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
def test_unknown_parent_raises():
|
|
54
|
+
cfg = {"title": "t", "actions": [
|
|
55
|
+
{"id": "a", "action": "Map Data", "parent": "nope"}]}
|
|
56
|
+
with pytest.raises(UsageError):
|
|
57
|
+
pb.build(cfg, _ctx())
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
def test_nested_foreach_rejected():
|
|
61
|
+
cfg = {"title": "t", "actions": [
|
|
62
|
+
{"id": "outer", "action": "For Each"},
|
|
63
|
+
{"id": "inner", "action": "For Each", "parent": "outer"}]}
|
|
64
|
+
with pytest.raises(UsageError, match="cannot be nested"):
|
|
65
|
+
pb.build(cfg, _ctx())
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
# -- template default-valued OUTPUT slots (For Each hang) --
|
|
69
|
+
# A For Each built from the compact config must carry the two runtime-written output
|
|
70
|
+
# slots the designer materialises — `Zero based list index` (61724e="-1") and
|
|
71
|
+
# `Action start time` (808b0d=the 2010 sentinel) — or the loop iterates its body ZERO
|
|
72
|
+
# times and times out. The builder is binding-driven and used to drop them; it now
|
|
73
|
+
# materialises any `direction:2 / type:ignore` template setting carrying a scalar
|
|
74
|
+
# default that no binding supplied.
|
|
75
|
+
FE_IDX = "99e8766d-d6be-4948-8f57-1f141f61724e" # Zero based list index -> "-1"
|
|
76
|
+
FE_START = "9d2d3483-f04b-48ac-9dea-2ef7ae808b0d" # Action start time -> 2010-... sentinel
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
def _params_by_id(action):
|
|
80
|
+
return {p["TabPropertyId"]: p for p in action["Parameters"]}
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
def test_foreach_materialises_template_default_outputs():
|
|
84
|
+
cfg = {"title": "loop", "variables": [
|
|
85
|
+
{"name": "items", "type": "string", "direction": "process", "isList": True},
|
|
86
|
+
{"name": "cur", "type": "string", "direction": "process"}],
|
|
87
|
+
"actions": [
|
|
88
|
+
{"id": "loop", "action": "For Each", "name": "loop",
|
|
89
|
+
"params": {"In List": {"var": "items"}, "For Each Item": {"var": "cur"},
|
|
90
|
+
"Action timeout": 120}},
|
|
91
|
+
{"id": "body", "action": "Map Data", "name": "body", "parent": "loop"}]}
|
|
92
|
+
loop = _by_cid(pb.build(cfg, _ctx()))["loop"]
|
|
93
|
+
P = _params_by_id(loop)
|
|
94
|
+
# the three bound params AND the two template-default outputs = 5 total
|
|
95
|
+
assert len(loop["Parameters"]) == 5
|
|
96
|
+
assert FE_IDX in P and P[FE_IDX]["Value"] == "-1" and P[FE_IDX]["Variable"] == []
|
|
97
|
+
assert FE_START in P and str(P[FE_START]["Value"]).startswith("2010-01-01T00:00:00")
|
|
98
|
+
assert P[FE_START]["Variable"] == []
|
|
99
|
+
|
|
100
|
+
|
|
101
|
+
def test_foreach_default_outputs_are_append_only():
|
|
102
|
+
"""The materialised outputs are APPENDED after the bound params; the bound
|
|
103
|
+
params keep their identity and order (a transform, not a rewrite)."""
|
|
104
|
+
cfg = {"title": "loop", "variables": [
|
|
105
|
+
{"name": "items", "type": "string", "direction": "process", "isList": True},
|
|
106
|
+
{"name": "cur", "type": "string", "direction": "process"}],
|
|
107
|
+
"actions": [{"id": "loop", "action": "For Each", "name": "loop",
|
|
108
|
+
"params": {"In List": {"var": "items"}, "For Each Item": {"var": "cur"},
|
|
109
|
+
"Action timeout": 120}}]}
|
|
110
|
+
loop = _by_cid(pb.build(cfg, _ctx()))["loop"]
|
|
111
|
+
ids = [p["TabPropertyId"] for p in loop["Parameters"]]
|
|
112
|
+
# the two materialised slots come LAST, after the three bound ones
|
|
113
|
+
assert ids[-2:] == [FE_IDX, FE_START] or set(ids[-2:]) == {FE_IDX, FE_START}
|
|
114
|
+
assert ids.index(FE_IDX) >= 3 and ids.index(FE_START) >= 3
|
|
115
|
+
|
|
116
|
+
|
|
117
|
+
def test_paramless_foreach_still_gets_the_two_outputs():
|
|
118
|
+
"""Even a For Each the config binds nothing on (empty params -> the early
|
|
119
|
+
return in _action_parameters) still receives the two template defaults."""
|
|
120
|
+
cfg = {"title": "t", "actions": [{"id": "loop", "action": "For Each"}]}
|
|
121
|
+
loop = next(a for a in pb.build(cfg, _ctx())["Actions"]
|
|
122
|
+
if a["CustomData"]["type"] == "area")
|
|
123
|
+
P = _params_by_id(loop)
|
|
124
|
+
assert FE_IDX in P and FE_START in P and len(loop["Parameters"]) == 2
|
|
125
|
+
|
|
126
|
+
|
|
127
|
+
def test_non_foreach_action_gains_no_template_defaults():
|
|
128
|
+
"""An action whose template has no defaulted OUTPUT slot gains no OUTPUT default.
|
|
129
|
+
|
|
130
|
+
The INPUT half of this guard was SUPERSEDED upstream. `_ensure_input_defaults`
|
|
131
|
+
now materialises a template's input defaults deliberately: an unbound Node
|
|
132
|
+
`Timeout` was dropped, the engine ran it as 00:00:00 and the action died with
|
|
133
|
+
"value ('00:00:00') must be greater than '00:00:00'" (verified live). So a bare
|
|
134
|
+
Node legitimately carries its default "60" now, and the three tests around
|
|
135
|
+
`test_node_unbound_timeout_gets_template_default` pin that behaviour. What must
|
|
136
|
+
still never appear is an OUTPUT-side slot: that is what the For Each fix touched,
|
|
137
|
+
and its blast radius is what this test exists to hold.
|
|
138
|
+
"""
|
|
139
|
+
cfg = {"title": "t", "actions": [{"id": "n", "action": "Node", "name": "n"}]}
|
|
140
|
+
n = _by_cid(pb.build(cfg, _ctx()))["n"]
|
|
141
|
+
# the input default 177a57 ("60") is intended; nothing else may be materialised
|
|
142
|
+
assert [p["TabPropertyId"] for p in n["Parameters"]] == [
|
|
143
|
+
"d3e52aab-b9d0-2d42-911e-b0e6de177a57"]
|
|
144
|
+
|
|
145
|
+
|
|
146
|
+
def test_call_subprocess_started_flow_not_doubled():
|
|
147
|
+
"""Call Subprocess's a03fe2 started-flow slot (direction 2/ignore, default the
|
|
148
|
+
null guid) is already emitted by _build_subprocess; the materialiser must dedupe
|
|
149
|
+
it, not emit a second copy."""
|
|
150
|
+
cfg = _sub_cfg()
|
|
151
|
+
call = _by_cid(pb.build(cfg, _ctx()))["call"]
|
|
152
|
+
a03 = [p for p in call["Parameters"] if p["TabPropertyId"].endswith("a03fe2")]
|
|
153
|
+
assert len(a03) == 1 and a03[0]["Value"] == pb.NULL_GUID
|
|
154
|
+
|
|
155
|
+
|
|
156
|
+
# -- Call/Trigger Subprocess --------------------------------------------------
|
|
157
|
+
|
|
158
|
+
TARGET = "b8f1d9e7-906e-46fa-9947-8700d1602d22"
|
|
159
|
+
SUB_IN = "0f1e0ceb-6c83-4f5e-b2f3-8b013ae13865"
|
|
160
|
+
SUB_OUT = "39d984af-ba12-4e42-82be-327ef9d51648"
|
|
161
|
+
|
|
162
|
+
|
|
163
|
+
def _sub_cfg():
|
|
164
|
+
return {"title": "caller",
|
|
165
|
+
"variables": [{"name": "x", "type": "string"},
|
|
166
|
+
{"name": "y", "type": "string", "direction": "output"}],
|
|
167
|
+
"actions": [{"id": "call", "action": "Call Subprocess", "name": "call",
|
|
168
|
+
"subprocess": {"target": TARGET,
|
|
169
|
+
"inputs": {SUB_IN: {"var": "x"}},
|
|
170
|
+
"outputs": {"y": SUB_OUT}}}]}
|
|
171
|
+
|
|
172
|
+
|
|
173
|
+
def _settings_by_type(node):
|
|
174
|
+
out = {}
|
|
175
|
+
|
|
176
|
+
def walk(settings):
|
|
177
|
+
for s in settings or []:
|
|
178
|
+
out.setdefault(s.get("type"), []).append(s)
|
|
179
|
+
if isinstance(s.get("value"), list):
|
|
180
|
+
walk(s["value"])
|
|
181
|
+
for tab in node["CustomData"]["configuration"]:
|
|
182
|
+
walk(tab.get("settings", []))
|
|
183
|
+
return out
|
|
184
|
+
|
|
185
|
+
|
|
186
|
+
def test_subprocess_target_and_maps_build():
|
|
187
|
+
dto = pb.build(_sub_cfg(), _ctx())
|
|
188
|
+
call = _by_cid(dto)["call"]
|
|
189
|
+
params = {p["TabPropertyId"]: p for p in call["Parameters"]}
|
|
190
|
+
# flow-list param carries the target flow id
|
|
191
|
+
flow_vals = [p["Value"] for p in call["Parameters"] if p["Value"] == TARGET]
|
|
192
|
+
assert flow_vals == [TARGET]
|
|
193
|
+
# the designer config exposes the {subprocess, process} rows
|
|
194
|
+
by_type = _settings_by_type(call)
|
|
195
|
+
in_rows = by_type["process-inputs"][0]["value"]
|
|
196
|
+
assert in_rows and in_rows[0]["subprocess"] == SUB_IN # destination = sub input var
|
|
197
|
+
assert in_rows[0]["process"] # parent var id resolved
|
|
198
|
+
out_rows = by_type["process-outputs"][0]["value"]
|
|
199
|
+
assert out_rows and out_rows[0]["subprocess"] == SUB_OUT # source = sub output var
|
|
200
|
+
assert out_rows[0]["process"] # parent (y) var id
|
|
201
|
+
|
|
202
|
+
|
|
203
|
+
def test_subprocess_runtime_rows_match_doc_mapper_shape():
|
|
204
|
+
dto = pb.build(_sub_cfg(), _ctx())
|
|
205
|
+
call = _by_cid(dto)["call"]
|
|
206
|
+
in_param = next(p for p in call["Parameters"]
|
|
207
|
+
if isinstance(p["Value"], list) and p["Value"]
|
|
208
|
+
and p["Value"][0].get("destination", {}).get("variableId") == SUB_IN)
|
|
209
|
+
row = in_param["Value"][0]
|
|
210
|
+
assert "source" in row and "destination" in row
|
|
211
|
+
assert row["destination"]["variableId"] == SUB_IN
|
|
212
|
+
assert row["source"]["variable"][0]["variableId"] # bound to parent var x
|
|
213
|
+
|
|
214
|
+
|
|
215
|
+
def test_subprocess_unknown_output_var_raises():
|
|
216
|
+
cfg = _sub_cfg()
|
|
217
|
+
cfg["actions"][0]["subprocess"]["outputs"] = {"missing": SUB_OUT}
|
|
218
|
+
with pytest.raises(UsageError):
|
|
219
|
+
pb.build(cfg, _ctx())
|
|
220
|
+
|
|
221
|
+
|
|
222
|
+
def test_subprocess_build_passes_config_audit():
|
|
223
|
+
# build() runs _audit_config internally; a clean build means the designer would
|
|
224
|
+
# show the subprocess rows configured (not empty/invalid).
|
|
225
|
+
pb.build(_sub_cfg(), _ctx()) # must not raise
|
|
226
|
+
|
|
227
|
+
|
|
228
|
+
# -- edit-time layout: preserve existing positions + scoped relayout ----------
|
|
229
|
+
|
|
230
|
+
def _two_action_cfg():
|
|
231
|
+
return {"title": "t", "actions": [
|
|
232
|
+
{"id": "a", "action": "Generate GUID"},
|
|
233
|
+
{"id": "b", "action": "Map Data"}]}
|
|
234
|
+
|
|
235
|
+
|
|
236
|
+
_EXISTING = {"a": {"x": 999, "y": 111}, "b": {"x": 1500, "y": 222},
|
|
237
|
+
"start": {"x": 10, "y": 20}, "stop": {"x": 2000, "y": 300}}
|
|
238
|
+
|
|
239
|
+
|
|
240
|
+
def test_create_uses_engine_layout():
|
|
241
|
+
# a fresh build (no existing positions) lays out left-to-right from the margin
|
|
242
|
+
dto = pb.build(_two_action_cfg(), _ctx())
|
|
243
|
+
assert _by_cid(dto)["Start"]["CustomData"]["position"] == {"x": 80.0, "y": 80.0}
|
|
244
|
+
|
|
245
|
+
|
|
246
|
+
def test_edit_default_rearranges_the_whole_canvas(monkeypatch):
|
|
247
|
+
# an edit gets the same full arrangement as a create (classic engine + clustering),
|
|
248
|
+
# so a process edited many times never drifts into an unarranged canvas
|
|
249
|
+
monkeypatch.delenv("PROCESIO_KEEP_LAYOUT", raising=False)
|
|
250
|
+
ctx = {**_ctx(), "existing_positions": _EXISTING}
|
|
251
|
+
nodes = _by_cid(pb.build(_two_action_cfg(), ctx))
|
|
252
|
+
assert nodes["Start"]["CustomData"]["position"] == {"x": 80.0, "y": 80.0} # re-tidied
|
|
253
|
+
assert nodes["Generate GUID"]["CustomData"]["position"] != {"x": 999, "y": 111}
|
|
254
|
+
|
|
255
|
+
|
|
256
|
+
def test_edit_keep_layout_preserves_everyone_when_nothing_new():
|
|
257
|
+
ctx = {**_ctx(), "existing_positions": _EXISTING}
|
|
258
|
+
nodes = _by_cid(pb.build({**_two_action_cfg(), "relayout": "new"}, ctx))
|
|
259
|
+
assert nodes["Generate GUID"]["CustomData"]["position"] == {"x": 999, "y": 111}
|
|
260
|
+
assert nodes["Map Data"]["CustomData"]["position"] == {"x": 1500, "y": 222}
|
|
261
|
+
assert nodes["Start"]["CustomData"]["position"] == {"x": 10, "y": 20}
|
|
262
|
+
|
|
263
|
+
|
|
264
|
+
def test_edit_keep_layout_env_preserves_existing(monkeypatch):
|
|
265
|
+
monkeypatch.setenv("PROCESIO_KEEP_LAYOUT", "1")
|
|
266
|
+
ctx = {**_ctx(), "existing_positions": _EXISTING}
|
|
267
|
+
nodes = _by_cid(pb.build(_two_action_cfg(), ctx))
|
|
268
|
+
assert nodes["Start"]["CustomData"]["position"] == {"x": 10, "y": 20}
|
|
269
|
+
|
|
270
|
+
|
|
271
|
+
def test_edit_keep_layout_places_new_action_preserves_existing():
|
|
272
|
+
cfg = {"title": "t", "relayout": "new", "actions": [
|
|
273
|
+
{"id": "a", "action": "Generate GUID"},
|
|
274
|
+
{"id": "c", "action": "Add"}]} # 'c' is new (not in existing)
|
|
275
|
+
existing = {"a": {"x": 999, "y": 111}, "start": {"x": 10, "y": 20},
|
|
276
|
+
"stop": {"x": 2000, "y": 300}}
|
|
277
|
+
nodes = _by_cid(pb.build(cfg, {**_ctx(), "existing_positions": existing}))
|
|
278
|
+
assert nodes["Generate GUID"]["CustomData"]["position"] == {"x": 999, "y": 111} # stays
|
|
279
|
+
# the new action got an engine-computed position (not left at the provisional grid)
|
|
280
|
+
assert nodes["Add"]["CustomData"]["position"] != {"x": 999, "y": 111}
|
|
281
|
+
|
|
282
|
+
|
|
283
|
+
def test_edit_relayout_all_does_full_layout():
|
|
284
|
+
ctx = {**_ctx(), "existing_positions": _EXISTING}
|
|
285
|
+
cfg = {**_two_action_cfg(), "relayout": "all"}
|
|
286
|
+
nodes = _by_cid(pb.build(cfg, ctx))
|
|
287
|
+
assert nodes["Start"]["CustomData"]["position"] == {"x": 80.0, "y": 80.0} # re-tidied
|
|
288
|
+
|
|
289
|
+
|
|
290
|
+
def test_edit_relayout_subset_moves_only_that_action():
|
|
291
|
+
ctx = {**_ctx(), "existing_positions": _EXISTING}
|
|
292
|
+
cfg = {**_two_action_cfg(), "relayout": ["b"]}
|
|
293
|
+
nodes = _by_cid(pb.build(cfg, ctx))
|
|
294
|
+
assert nodes["Generate GUID"]["CustomData"]["position"] == {"x": 999, "y": 111} # stays
|
|
295
|
+
assert nodes["Start"]["CustomData"]["position"] == {"x": 10, "y": 20} # stays
|
|
296
|
+
assert nodes["Map Data"]["CustomData"]["position"] != {"x": 1500, "y": 222} # moved
|
|
297
|
+
|
|
298
|
+
|
|
299
|
+
# -- Shapes / canvasData preservation on edit (canvas-engine PRC-4391) -------
|
|
300
|
+
|
|
301
|
+
class _CanvasClient:
|
|
302
|
+
"""Serves a live flow carrying canvasData (viewport + decorative shapes) and
|
|
303
|
+
captures the PUT DTO, so we can assert an edit preserves it."""
|
|
304
|
+
def __init__(self, canvas):
|
|
305
|
+
self._flow = {"flow": {"variables": [], "actions": [], "canvasData": canvas}}
|
|
306
|
+
self.put_dto = None
|
|
307
|
+
|
|
308
|
+
def get(self, path, query=None):
|
|
309
|
+
return self._flow
|
|
310
|
+
|
|
311
|
+
def put(self, path, body=None, query=None):
|
|
312
|
+
self.put_dto = body
|
|
313
|
+
return {}
|
|
314
|
+
|
|
315
|
+
def post(self, path, body=None, query=None):
|
|
316
|
+
return {"raw_text": ""}
|
|
317
|
+
|
|
318
|
+
|
|
319
|
+
def test_edit_preserves_canvas_shapes(monkeypatch):
|
|
320
|
+
monkeypatch.setattr(pb, "_save_gate", lambda *a, **k: None) # isolate preservation
|
|
321
|
+
shapes = [{"id": "s1", "kind": "rectangle", "title": "Zone A"}]
|
|
322
|
+
canvas = {"shapes": shapes, "viewport": {"x": 5, "y": 9, "zoom": 1.2}}
|
|
323
|
+
c = _CanvasClient(canvas)
|
|
324
|
+
pb._edit(c, "P1", {"title": "t", "actions": []}, {**_ctx(), "_force": True})
|
|
325
|
+
assert c.put_dto["CanvasData"] == canvas # shapes + viewport survive the edit
|
|
326
|
+
|
|
327
|
+
|
|
328
|
+
def test_edit_without_canvas_leaves_canvasdata_none(monkeypatch):
|
|
329
|
+
monkeypatch.setattr(pb, "_save_gate", lambda *a, **k: None)
|
|
330
|
+
c = _CanvasClient(None) # live flow has no canvasData
|
|
331
|
+
pb._edit(c, "P1", {"title": "t", "actions": []}, {**_ctx(), "_force": True})
|
|
332
|
+
assert c.put_dto["CanvasData"] is None # nothing to preserve, no crash
|
|
333
|
+
|
|
334
|
+
|
|
335
|
+
# -- input-side template defaults (B-048 cluster 2) --------------------------
|
|
336
|
+
|
|
337
|
+
def _node_cfg(params):
|
|
338
|
+
return {"title": "n",
|
|
339
|
+
"variables": [{"name": "out", "type": "json", "direction": "output"}],
|
|
340
|
+
"actions": [{"id": "n", "action": "Node", "name": "nd", "params": params}]}
|
|
341
|
+
|
|
342
|
+
|
|
343
|
+
def test_node_unbound_timeout_gets_template_default():
|
|
344
|
+
# An unbound Node Timeout was dropped and the engine ran it as 00:00:00, dying with
|
|
345
|
+
# "value ('00:00:00') must be greater than '00:00:00'". The builder now materialises
|
|
346
|
+
# the template default (60), matching what the designer pre-fills. Verified live.
|
|
347
|
+
dto = pb.build(_node_cfg({"Code": {"template": "return 42;", "vars": []},
|
|
348
|
+
"Single Result": {"var": "out"}}), _ctx())
|
|
349
|
+
node = _by_cid(dto)["nd"]
|
|
350
|
+
assert "60" in [p.get("Value") for p in node["Parameters"]]
|
|
351
|
+
|
|
352
|
+
|
|
353
|
+
def test_bound_input_default_is_not_overridden_or_duplicated():
|
|
354
|
+
dto = pb.build(_node_cfg({"Code": {"template": "return 1;", "vars": []},
|
|
355
|
+
"Timeout": 120, "Single Result": {"var": "out"}}), _ctx())
|
|
356
|
+
node = _by_cid(dto)["nd"]
|
|
357
|
+
vals = [p.get("Value") for p in node["Parameters"]]
|
|
358
|
+
assert 120 in vals and "60" not in vals # user value kept, default not re-added
|
|
359
|
+
|
|
360
|
+
|
|
361
|
+
def test_ensure_input_defaults_subclass_and_skips():
|
|
362
|
+
tpl = {"name": "X", "configuration": [{"settings": [
|
|
363
|
+
{"id": "a", "direction": 1, "type": "number", "value": "7"}, # materialise
|
|
364
|
+
{"id": "b", "direction": 1, "type": "code-editor", "value": "f(){}"}, # skip: code
|
|
365
|
+
{"id": "c", "direction": 1, "type": "text", "value": ""}, # skip: empty
|
|
366
|
+
{"id": "d", "direction": 3, "type": "number", "value": "9"}, # skip: output
|
|
367
|
+
{"id": "e", "direction": 1, "type": "select", "value": "1"}, # materialise
|
|
368
|
+
]}]}
|
|
369
|
+
got = {p["TabPropertyId"]: p["Value"] for p in pb._ensure_input_defaults(tpl, [])}
|
|
370
|
+
assert got == {"a": "7", "e": "1"}
|
|
371
|
+
# an already-bound property is never re-materialised
|
|
372
|
+
got2 = pb._ensure_input_defaults(tpl, [{"TabPropertyId": "a", "Variable": [], "Value": "99"}])
|
|
373
|
+
assert [p for p in got2 if p["TabPropertyId"] == "a" and p["Value"] == "7"] == []
|
|
@@ -0,0 +1,183 @@
|
|
|
1
|
+
"""Tier-3 parity hardening: credential binding + locked builder invariants.
|
|
2
|
+
|
|
3
|
+
The invariants (shape inherited from the action; decisional fan-out unlimited) are already
|
|
4
|
+
correct in the builder — these tests lock them so a future change can't silently break them.
|
|
5
|
+
"""
|
|
6
|
+
from __future__ import annotations
|
|
7
|
+
|
|
8
|
+
import itertools
|
|
9
|
+
|
|
10
|
+
import pytest
|
|
11
|
+
|
|
12
|
+
from tools.procesio.dto.process import builder as pb
|
|
13
|
+
from tools.procesio.errors import UsageError
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
def _ctx():
|
|
17
|
+
counter = itertools.count(1)
|
|
18
|
+
return {"new_id": lambda: f"00000000-0000-0000-0000-{next(counter):012d}"}
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
def _by_name(dto):
|
|
22
|
+
return {a["ActionName"]: a for a in dto["Actions"]}
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
def _cfg_setting(node, label):
|
|
26
|
+
def walk(settings):
|
|
27
|
+
for s in settings or []:
|
|
28
|
+
if str(s.get("label", "")).lower() == label.lower():
|
|
29
|
+
return s
|
|
30
|
+
if isinstance(s.get("value"), list):
|
|
31
|
+
r = walk(s["value"])
|
|
32
|
+
if r:
|
|
33
|
+
return r
|
|
34
|
+
for tab in node["CustomData"]["configuration"]:
|
|
35
|
+
r = walk(tab.get("settings", []))
|
|
36
|
+
if r:
|
|
37
|
+
return r
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
def test_number_setting_designer_value_is_string():
|
|
41
|
+
"""A DESIGNER number input binds a STRING; a numeric config value renders EMPTY
|
|
42
|
+
and the FE range-check then reads Number("")=0 -> "value between min and max"
|
|
43
|
+
(even though the RUNTIME Parameter, which stays numeric, executes fine). So the
|
|
44
|
+
builder must mirror number-type settings (e.g. a Node's Timeout) as strings."""
|
|
45
|
+
cfg = {"title": "t",
|
|
46
|
+
"variables": [{"name": "x", "type": "json", "direction": "input"},
|
|
47
|
+
{"name": "r", "type": "json", "direction": "output"}],
|
|
48
|
+
"actions": [{"id": "n", "action": "Node", "name": "n",
|
|
49
|
+
"params": {"Code": {"template": "return <%0%>;", "vars": ["x"]},
|
|
50
|
+
"Timeout": 60, "Single Result": {"var": "r"}}}]}
|
|
51
|
+
node = _by_name(pb.build(cfg, _ctx()))["n"]
|
|
52
|
+
s = _cfg_setting(node, "Timeout")
|
|
53
|
+
assert s["value"] == "60" and isinstance(s["value"], str) # designer: string
|
|
54
|
+
assert any(p["Value"] == 60 for p in node["Parameters"]) # runtime: numeric, unchanged
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
# -- credential binding -------------------------------------------------------
|
|
58
|
+
|
|
59
|
+
CRED_GID = "45a1dd18-9d06-47cf-8a7b-7732447264af"
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
def _cred_setting(node):
|
|
63
|
+
for tab in node["CustomData"]["configuration"]:
|
|
64
|
+
for s in tab.get("settings", []):
|
|
65
|
+
if s.get("type") == "credentials":
|
|
66
|
+
return s
|
|
67
|
+
return None
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
def test_credential_binding_sets_gid_and_keeps_template():
|
|
71
|
+
cfg = {"title": "q", "variables": [{"name": "q", "type": "string"}],
|
|
72
|
+
"actions": [{"id": "eq", "action": "Execute Query", "name": "eq",
|
|
73
|
+
"params": {"Select Database Server": {"credential": CRED_GID},
|
|
74
|
+
"Query": {"var": "q"}}}]}
|
|
75
|
+
dto = pb.build(cfg, _ctx())
|
|
76
|
+
eq = _by_name(dto)["eq"]
|
|
77
|
+
# runtime Parameter carries the instance gid
|
|
78
|
+
cred_params = [p for p in eq["Parameters"] if p["Value"] == CRED_GID]
|
|
79
|
+
assert len(cred_params) == 1 and cred_params[0]["Variable"] == []
|
|
80
|
+
# designer config: value = gid AND the credential TEMPLATE id is preserved
|
|
81
|
+
s = _cred_setting(eq)
|
|
82
|
+
assert s["value"] == CRED_GID
|
|
83
|
+
assert s.get("credentialsTemplateId") # the credential TYPE, from the catalog
|
|
84
|
+
|
|
85
|
+
|
|
86
|
+
def test_credential_binding_rejects_non_guid():
|
|
87
|
+
cfg = {"title": "q", "actions": [
|
|
88
|
+
{"id": "eq", "action": "Execute Query",
|
|
89
|
+
"params": {"Select Database Server": {"credential": "not-a-guid"}}}]}
|
|
90
|
+
with pytest.raises(UsageError, match="credential"):
|
|
91
|
+
pb.build(cfg, _ctx())
|
|
92
|
+
|
|
93
|
+
|
|
94
|
+
# -- invariant: node shape is action-dictated, never hardcoded ---------------
|
|
95
|
+
|
|
96
|
+
def test_node_shape_inherited_from_action():
|
|
97
|
+
"""Every node's CustomData.type equals its catalog template's `shape` — i.e. the
|
|
98
|
+
shape is inherited from the action, never assigned per action by the builder."""
|
|
99
|
+
cfg = {"title": "shapes", "variables": [{"name": "n", "type": "integer"}],
|
|
100
|
+
"actions": [
|
|
101
|
+
{"id": "g", "action": "Generate GUID"},
|
|
102
|
+
{"id": "loop", "action": "For Each"},
|
|
103
|
+
{"id": "d", "action": "Decisional",
|
|
104
|
+
"branches": [{"to": "g", "when": [{"left": {"var": "n"}, "op": "EQUALS", "right": 1}]},
|
|
105
|
+
{"to": "loop", "default": True}]},
|
|
106
|
+
]}
|
|
107
|
+
dto = pb.build(cfg, _ctx())
|
|
108
|
+
catalog = pb.catalog_index()
|
|
109
|
+
for a in dto["Actions"]:
|
|
110
|
+
tpl = catalog.get((a["ActionTemplateName"] or "").strip().lower())
|
|
111
|
+
assert tpl is not None, f"no catalog template for {a['ActionTemplateName']!r}"
|
|
112
|
+
assert a["CustomData"]["type"] == (tpl.get("shape") or "square"), \
|
|
113
|
+
f"{a['ActionTemplateName']} shape not inherited from catalog"
|
|
114
|
+
# and the catalog genuinely carries distinct shapes (so the test isn't vacuous)
|
|
115
|
+
shapes = {a["CustomData"]["type"] for a in dto["Actions"]}
|
|
116
|
+
assert {"diamond", "area"} <= shapes
|
|
117
|
+
|
|
118
|
+
|
|
119
|
+
def test_decisional_fanout_is_unlimited():
|
|
120
|
+
# 6 cases + a default — must all be emitted (no 2-5 cap)
|
|
121
|
+
targets = [{"id": f"t{i}", "action": "Generate GUID"} for i in range(6)]
|
|
122
|
+
branches = [{"to": f"t{i}", "when": [{"left": {"var": "n"}, "op": "EQUALS", "right": i}]}
|
|
123
|
+
for i in range(6)]
|
|
124
|
+
branches.append({"to": "t0", "default": True})
|
|
125
|
+
cfg = {"title": "fan", "variables": [{"name": "n", "type": "integer"}],
|
|
126
|
+
"actions": [{"id": "d", "action": "Decisional", "branches": branches}] + targets}
|
|
127
|
+
dto = pb.build(cfg, _ctx())
|
|
128
|
+
d = _by_name(dto)["Decisional"]
|
|
129
|
+
cases_param = next(p for p in d["Parameters"] if isinstance(p["Value"], list)
|
|
130
|
+
and p["Value"] and "actionid" in p["Value"][0])
|
|
131
|
+
assert len(cases_param["Value"]) == 6 # all six cases survive (no 2-5 cap)
|
|
132
|
+
# at least the 6 case ports + 1 default port leave the decisional
|
|
133
|
+
assert sum(1 for pt in d["Ports"] if pt["SourceId"] == d["Id"]) >= 7
|
|
134
|
+
|
|
135
|
+
|
|
136
|
+
def test_decisional_no_duplicate_linear_outgoing_port():
|
|
137
|
+
# regression: with no explicit `edges` the implicit linear chain (start->...->stop)
|
|
138
|
+
# must NOT add an outgoing edge from a Decisional - its outgoing routing is its
|
|
139
|
+
# `branches` only. An extra linear port double-ports the node and the BE rejects it
|
|
140
|
+
# ("multiple incoming" / "duplicate connection").
|
|
141
|
+
cfg = {"title": "d", "variables": [{"name": "n", "type": "integer"}],
|
|
142
|
+
"actions": [
|
|
143
|
+
{"id": "d", "action": "Decisional",
|
|
144
|
+
"branches": [{"to": "a", "when": [{"left": {"var": "n"}, "op": "EQUALS", "right": 1}]},
|
|
145
|
+
{"to": "b", "default": True}]},
|
|
146
|
+
{"id": "a", "action": "Generate GUID"},
|
|
147
|
+
{"id": "b", "action": "Generate GUID"}]}
|
|
148
|
+
dto = pb.build(cfg, _ctx()) # no `edges` -> chain would have added d->a
|
|
149
|
+
d = _by_name(dto)["Decisional"]
|
|
150
|
+
outgoing = [pt for pt in d["Ports"] if pt["SourceId"] == d["Id"]]
|
|
151
|
+
assert len(outgoing) == 2 # exactly the 2 branches, no linear duplicate
|
|
152
|
+
|
|
153
|
+
|
|
154
|
+
def test_subprocess_literal_input_hoisted_to_variable():
|
|
155
|
+
# A LITERAL subprocess input must be hoisted to a synthetic process variable (default =
|
|
156
|
+
# the literal) and the binding rewritten to {var: ...}, so the mapping's parent side is
|
|
157
|
+
# a real variable id (a raw literal there makes the designer reject a Trigger Subprocess
|
|
158
|
+
# as "Mapping of required subprocess variable (X) is missing", blocking the launch).
|
|
159
|
+
cfg = {"title": "sub", "variables": [{"name": "f", "model": "FileDataModel"}],
|
|
160
|
+
"actions": [{"id": "t", "action": "Trigger Subprocess", "subprocess": {
|
|
161
|
+
"target": "d7af1675-abe3-4193-a8e6-ef6aa501f78c",
|
|
162
|
+
"inputs": {"S1": {"value": "hello.pdf"}, "S2": {"var": "f"}, "S3": 42},
|
|
163
|
+
"outputs": {}}}]}
|
|
164
|
+
out = pb._hoist_subprocess_literals(cfg)
|
|
165
|
+
inputs = out["actions"][0]["subprocess"]["inputs"]
|
|
166
|
+
# both literals ({"value":...} and a bare scalar) became {var: <synthetic>}; the var stays
|
|
167
|
+
assert set(inputs["S1"].keys()) == {"var"} and set(inputs["S3"].keys()) == {"var"}
|
|
168
|
+
assert inputs["S2"] == {"var": "f"} # var binding untouched
|
|
169
|
+
syn = {v["name"]: v for v in out["variables"] if v["name"].startswith("_sublit")}
|
|
170
|
+
assert len(syn) == 2
|
|
171
|
+
assert syn[inputs["S1"]["var"]]["default"] == "hello.pdf"
|
|
172
|
+
assert syn[inputs["S1"]["var"]]["type"] == "string"
|
|
173
|
+
assert syn[inputs["S3"]["var"]]["default"] == 42
|
|
174
|
+
assert syn[inputs["S3"]["var"]]["type"] == "integer"
|
|
175
|
+
# the original config is not mutated
|
|
176
|
+
assert cfg["actions"][0]["subprocess"]["inputs"]["S1"] == {"value": "hello.pdf"}
|
|
177
|
+
|
|
178
|
+
|
|
179
|
+
def test_subprocess_no_literals_is_noop():
|
|
180
|
+
cfg = {"title": "sub", "variables": [{"name": "f", "model": "FileDataModel"}],
|
|
181
|
+
"actions": [{"id": "t", "action": "Call Subprocess", "subprocess": {
|
|
182
|
+
"target": "x", "inputs": {"S1": {"var": "f"}}, "outputs": {}}}]}
|
|
183
|
+
assert pb._hoist_subprocess_literals(cfg) is cfg # unchanged, same object
|