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,171 @@
|
|
|
1
|
+
"""PARITY TESTS — the builder's output must match the STRUCTURE of real PROCESIO exports.
|
|
2
|
+
|
|
3
|
+
Why this file exists: every form bug we've hit (enum values, event types, RUN_PROCESS map
|
|
4
|
+
orientation) shared one shape — the builder produced a DTO that PASSED schema/dry-run
|
|
5
|
+
validation but did NOT match what the real platform produces, so it only failed when a human
|
|
6
|
+
opened the form in the designer / ran it. The real `.procesio` exports under
|
|
7
|
+
docs_info/Exports are the platform's own ground truth: the exact shape a *working* form has.
|
|
8
|
+
|
|
9
|
+
Each invariant below is checked TWICE:
|
|
10
|
+
(a) it actually holds across the real exports -> proves the invariant is real, and
|
|
11
|
+
(b) the builder's output satisfies the same invariant -> catches divergence pre-ship.
|
|
12
|
+
|
|
13
|
+
DISCIPLINE: whenever the builder learns to emit a new construct (a new event kind, a new
|
|
14
|
+
container wiring, a new mapping...), add a reality-derived invariant here. That is the
|
|
15
|
+
mechanism that removes the need for manual UI testing of structural correctness.
|
|
16
|
+
"""
|
|
17
|
+
import glob
|
|
18
|
+
import json
|
|
19
|
+
import os
|
|
20
|
+
import re
|
|
21
|
+
import uuid
|
|
22
|
+
from pathlib import Path
|
|
23
|
+
|
|
24
|
+
import pytest
|
|
25
|
+
|
|
26
|
+
from tools.procesio.dto.form import builder
|
|
27
|
+
|
|
28
|
+
EXPORTS = Path(__file__).resolve().parents[1] / "docs_info" / "Exports"
|
|
29
|
+
|
|
30
|
+
# The reality-side invariants are calibrated against the platform's own exports.
|
|
31
|
+
# That corpus is not carried into every distribution of this tool (a .procesio
|
|
32
|
+
# export names real processes and serializes credentials inline), so those tests
|
|
33
|
+
# SKIP where it is absent rather than failing, while the builder-side invariants
|
|
34
|
+
# run everywhere. Skipping is the honest outcome: without ground truth there is
|
|
35
|
+
# nothing to calibrate against, and a vacuous pass would be worse than no test.
|
|
36
|
+
requires_corpus = pytest.mark.skipif(
|
|
37
|
+
not sorted(EXPORTS.glob("*.procesio")),
|
|
38
|
+
reason="no .procesio export corpus in this checkout")
|
|
39
|
+
_GUID = re.compile(r"^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$", re.I)
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
def _is_guid(v):
|
|
43
|
+
return isinstance(v, str) and bool(_GUID.match(v))
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
def _form_datas():
|
|
47
|
+
for p in glob.glob(str(EXPORTS / "*.procesio")):
|
|
48
|
+
dd = json.loads(Path(p).read_text(encoding="utf-8"))
|
|
49
|
+
for fm in dd.get("Forms") or []:
|
|
50
|
+
v = fm.get("Data")
|
|
51
|
+
v = json.loads(v) if isinstance(v, str) else v
|
|
52
|
+
if isinstance(v, dict):
|
|
53
|
+
yield os.path.basename(p), v
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
def _iter_events(data):
|
|
57
|
+
for el in data.get("elements") or []:
|
|
58
|
+
for c in el.get("configs") or []:
|
|
59
|
+
v = c.get("value")
|
|
60
|
+
if isinstance(v, dict) and isinstance(v.get("events"), list):
|
|
61
|
+
for ev in v["events"]:
|
|
62
|
+
yield el, c.get("key"), v, ev
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
def _build_run_process_form():
|
|
66
|
+
"""Build a form whose button runs a process with one input + one output map, with the
|
|
67
|
+
process variables 'resolved' (as prepare_ctx would do live)."""
|
|
68
|
+
pid = str(uuid.uuid4())
|
|
69
|
+
in_var, out_var = str(uuid.uuid4()), str(uuid.uuid4())
|
|
70
|
+
ctx = {"new_id": lambda: str(uuid.uuid4()),
|
|
71
|
+
"process_vars": {pid: {"inText": in_var, "outText": out_var}}}
|
|
72
|
+
cfg = {"name": "P", "elements": [
|
|
73
|
+
{"type": "input", "label": "A", "name": "fieldA"},
|
|
74
|
+
{"type": "input", "label": "B", "name": "fieldB"},
|
|
75
|
+
{"type": "button", "label": "Run", "name": "runBtn", "events": [
|
|
76
|
+
{"on": "click", "do": "process", "processId": pid, "syncRun": True,
|
|
77
|
+
"inputs": [{"to": "inText", "from": "fieldA"}],
|
|
78
|
+
"outputs": [{"to": "fieldB", "from": "outText"}]}]}]}
|
|
79
|
+
dto = builder.build(cfg, ctx)
|
|
80
|
+
btn = next(e for e in dto["Data"]["elements"]
|
|
81
|
+
if any(c.get("value") == "runBtn" for c in e["configs"]))
|
|
82
|
+
cfg_ev = next(c["value"] for c in btn["configs"] if c["key"] == "onClickEvents")
|
|
83
|
+
return cfg_ev["events"][0]["config"], in_var, out_var
|
|
84
|
+
|
|
85
|
+
|
|
86
|
+
# ---------- invariant 1: RUN_PROCESS map orientation (the bug we just fixed) ----------
|
|
87
|
+
def _seg_count(v):
|
|
88
|
+
return v.count(".") + 1 if isinstance(v, str) else 0
|
|
89
|
+
|
|
90
|
+
|
|
91
|
+
def _is_proc_ref(v):
|
|
92
|
+
# a process-variable reference: a bare GUID, or {value: <guid|"">, ...}
|
|
93
|
+
if _is_guid(v):
|
|
94
|
+
return True
|
|
95
|
+
if isinstance(v, dict) and "value" in v:
|
|
96
|
+
return _is_guid(v["value"]) or v["value"] == ""
|
|
97
|
+
return False
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
@requires_corpus
|
|
101
|
+
def test_reality_run_process_left_is_never_a_form_path():
|
|
102
|
+
"""Calibrated to reality: across all real exports, a RUN_PROCESS map's `left` is the
|
|
103
|
+
PROCESS-variable side (a GUID, sometimes wrapped as {value}) and is NEVER a form field
|
|
104
|
+
value-path (4 dotted GUIDs). That is exactly the orientation our output-map bug broke."""
|
|
105
|
+
proc_ref_lefts = 0
|
|
106
|
+
for fn, data in _form_datas():
|
|
107
|
+
for _el, _k, _grp, ev in _iter_events(data):
|
|
108
|
+
if ev.get("action") != "RUN_PROCESS":
|
|
109
|
+
continue
|
|
110
|
+
cfg = ev.get("config") or {}
|
|
111
|
+
for m in (cfg.get("inputMap") or []) + (cfg.get("outputMap") or []):
|
|
112
|
+
left = m.get("left")
|
|
113
|
+
assert _seg_count(left) < 3, (
|
|
114
|
+
f"{fn}: RUN_PROCESS map 'left' is a form path (should be a process var): {left!r}")
|
|
115
|
+
if _is_proc_ref(left):
|
|
116
|
+
proc_ref_lefts += 1
|
|
117
|
+
assert proc_ref_lefts > 0, "no real RUN_PROCESS process-var lefts found to validate against"
|
|
118
|
+
|
|
119
|
+
|
|
120
|
+
def test_builder_run_process_map_matches_reality():
|
|
121
|
+
cfg, in_var, out_var = _build_run_process_form()
|
|
122
|
+
for m in cfg["inputMap"] + cfg["outputMap"]:
|
|
123
|
+
assert _is_guid(m["left"]), f"builder RUN_PROCESS map 'left' not a GUID: {m['left']!r}"
|
|
124
|
+
# process variable on the LEFT (resolved to its id); form field path on the RIGHT
|
|
125
|
+
assert cfg["inputMap"][0]["left"] == in_var
|
|
126
|
+
assert cfg["outputMap"][0]["left"] == out_var # <-- would fail with the old swap
|
|
127
|
+
assert cfg["inputMap"][0]["right"].count(".") == 3 # form value-path = 4 segments
|
|
128
|
+
assert cfg["outputMap"][0]["right"].count(".") == 3
|
|
129
|
+
|
|
130
|
+
|
|
131
|
+
# ---------- invariant 2: stored event object shape ----------
|
|
132
|
+
@requires_corpus
|
|
133
|
+
def test_reality_event_shape():
|
|
134
|
+
n = 0
|
|
135
|
+
for _fn, data in _form_datas():
|
|
136
|
+
for _el, _k, grp, ev in _iter_events(data):
|
|
137
|
+
assert {"id", "type", "action"} <= set(ev)
|
|
138
|
+
assert "events" in grp and "debounce" in grp
|
|
139
|
+
n += 1
|
|
140
|
+
assert n > 0
|
|
141
|
+
|
|
142
|
+
|
|
143
|
+
def test_builder_event_shape():
|
|
144
|
+
"""Split out of the reality test: the builder half needs no corpus, and pairing
|
|
145
|
+
them meant losing builder coverage wherever the corpus is absent."""
|
|
146
|
+
cfg, _i, _o = _build_run_process_form()
|
|
147
|
+
assert {"processId", "inputMap", "outputMap"} <= set(cfg)
|
|
148
|
+
|
|
149
|
+
|
|
150
|
+
# ---------- invariant 3: a DATA-FIELD's `value` config is canonical (exposed + EMIT_INPUT) ----------
|
|
151
|
+
# Scoped to user-data input controls (the ones whose `value` the platform's on-save compiler
|
|
152
|
+
# turns into the field value attribute). Non-field controls (assignee, table rows, approval,
|
|
153
|
+
# containers) legitimately have a different/absent value config, so they are excluded.
|
|
154
|
+
# NOTE: dropdown is an action MENU (items), not a value field -> excluded.
|
|
155
|
+
_DATA_FIELDS = {"input", "number-input", "datetime-input", "textarea", "select",
|
|
156
|
+
"radiobox", "checkbox", "file-upload"}
|
|
157
|
+
|
|
158
|
+
|
|
159
|
+
def test_data_field_value_config_canonical_in_goldens():
|
|
160
|
+
elems = Path(builder.__file__).resolve().parent / "elements"
|
|
161
|
+
checked = 0
|
|
162
|
+
for p in elems.glob("*.json"):
|
|
163
|
+
if p.stem not in _DATA_FIELDS:
|
|
164
|
+
continue
|
|
165
|
+
cfgs = json.loads(p.read_text(encoding="utf-8")).get("configs", [])
|
|
166
|
+
vc = next((c for c in cfgs if c.get("key") == "value"), None)
|
|
167
|
+
assert vc is not None, f"{p.name}: data field must have a value config"
|
|
168
|
+
assert vc.get("exposed") is True, f"{p.name}: value config must be exposed"
|
|
169
|
+
assert vc.get("events") == ["EMIT_INPUT"], f"{p.name}: value events must be [EMIT_INPUT]"
|
|
170
|
+
checked += 1
|
|
171
|
+
assert checked >= len(_DATA_FIELDS) - 1
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
"""A select's option source reaches the form's data model, in the designer's shape.
|
|
2
|
+
|
|
3
|
+
Only data-model attributes reach `ProcesioForm` in form JS. The builder used to keep
|
|
4
|
+
`sourceType` / `sourceValue` out of the data model, so a script on an API-built form
|
|
5
|
+
could never read a select's options, while a save in the designer added them. These pin
|
|
6
|
+
the shape a designer save writes, captured on 2026-10-01 from a form built here and then
|
|
7
|
+
saved and published in the designer: attribute ids equal the config ids, `sourceType` is
|
|
8
|
+
a plain string, and a static `sourceValue` is a list of Objects.
|
|
9
|
+
"""
|
|
10
|
+
from __future__ import annotations
|
|
11
|
+
|
|
12
|
+
import itertools
|
|
13
|
+
|
|
14
|
+
from tools.procesio.dto.form import addelement
|
|
15
|
+
from tools.procesio.dto.form import builder as fb
|
|
16
|
+
|
|
17
|
+
STR = "0317bfee-b2f5-4bde-bfe8-121212121214"
|
|
18
|
+
OBJECT = "0317bfee-b2f5-4bde-bfe8-121212121221"
|
|
19
|
+
|
|
20
|
+
# The designer's attribute shape, as captured. Ids differ per form; the rest is fixed.
|
|
21
|
+
DESIGNER = {
|
|
22
|
+
"sourceType": {"dataTypeId": STR, "isList": False, "isDataModel": False,
|
|
23
|
+
"isPublic": False, "isProcesio": False, "jsonProperty": None,
|
|
24
|
+
"attributes": [], "hidden": False},
|
|
25
|
+
"sourceValue": {"dataTypeId": OBJECT, "isList": True, "isDataModel": False,
|
|
26
|
+
"isPublic": False, "isProcesio": False, "jsonProperty": None,
|
|
27
|
+
"attributes": [], "hidden": False},
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
def _ctx():
|
|
32
|
+
cnt = itertools.count(1)
|
|
33
|
+
return {"new_id": lambda: f"00000000-0000-0000-0000-{next(cnt):012d}"}
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
def _built(spec):
|
|
37
|
+
dto = fb.build({"name": "F", "elements": [spec]}, _ctx())
|
|
38
|
+
data = dto["Data"]
|
|
39
|
+
el = next(e for e in data["elements"] if e.get("type") == "select")
|
|
40
|
+
fields = next(a for a in data["dataModel"]["attributes"] if a["id"] == fb._FIELDS_NS)
|
|
41
|
+
sub = next(s for s in fields["attributes"] if s["id"] == el["id"])
|
|
42
|
+
return el, {a["name"]: a for a in sub["attributes"]}
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
def _cfg(el, key):
|
|
46
|
+
return next(c for c in el["configs"] if c["key"] == key)
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
def test_a_static_select_carries_its_option_source_in_the_designer_shape():
|
|
50
|
+
el, attrs = _built({"type": "select", "label": "Pick", "name": "pick",
|
|
51
|
+
"options": ["alpha", "beta"]})
|
|
52
|
+
for key, shape in DESIGNER.items():
|
|
53
|
+
assert key in attrs, f"{key} is missing from the data model"
|
|
54
|
+
attr = attrs[key]
|
|
55
|
+
assert attr["id"] == _cfg(el, key)["id"], f"{key}: attribute id must equal the config id"
|
|
56
|
+
assert attr["parentDataTypeId"] == el["id"]
|
|
57
|
+
assert {k: attr[k] for k in shape} == shape, key
|
|
58
|
+
assert _cfg(el, "sourceValue")["value"] == [{"name": "alpha", "value": "alpha"},
|
|
59
|
+
{"name": "beta", "value": "beta"}]
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
def test_a_json_sourced_select_gets_no_guessed_source_value_attribute():
|
|
63
|
+
"""Only the static-list shape was captured from the designer."""
|
|
64
|
+
_el, attrs = _built({"type": "select", "label": "Pick", "name": "pick",
|
|
65
|
+
"optionsSource": {"type": "json", "value": "[]"}})
|
|
66
|
+
assert "sourceType" in attrs
|
|
67
|
+
assert "sourceValue" not in attrs
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
def test_form_add_element_writes_the_same_attributes_as_form_create():
|
|
71
|
+
"""The two used to carry separate copies of this rule; now they share one."""
|
|
72
|
+
el, attrs = _built({"type": "select", "label": "Pick", "name": "pick", "options": ["a"]})
|
|
73
|
+
spliced = addelement._sub_model(el, fb._FIELDS_NS, {})
|
|
74
|
+
assert {a["name"]: a for a in spliced["attributes"]} == attrs
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
"""Guard: the form-control goldens must stay in sync with FormBuilder mock.ts.
|
|
2
|
+
|
|
3
|
+
Mirrors test_manifest_sync.py's intent for the form layer. If this fails, either a
|
|
4
|
+
golden was hand-edited or the mock changed without regenerating — run
|
|
5
|
+
`python tools/procesio/dto/form/sync_from_mock.py --write`.
|
|
6
|
+
"""
|
|
7
|
+
from tools.procesio.dto.form import sync_from_mock as s
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
def test_all_goldens_match_mock():
|
|
11
|
+
goldens, _stats, _res = s.build_goldens()
|
|
12
|
+
drift = []
|
|
13
|
+
for t, g in goldens.items():
|
|
14
|
+
path = s.ELEMENTS / f"{t}.json"
|
|
15
|
+
if not path.exists():
|
|
16
|
+
drift.append(f"{t} (missing on disk)")
|
|
17
|
+
elif path.read_text(encoding="utf-8").strip() != s._dump(g).strip():
|
|
18
|
+
drift.append(t)
|
|
19
|
+
assert not drift, (
|
|
20
|
+
"form goldens out of sync with FormBuilder mock.ts: "
|
|
21
|
+
f"{drift} — run sync_from_mock.py --write")
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
def test_every_mock_control_has_a_golden():
|
|
25
|
+
goldens, _stats, _res = s.build_goldens()
|
|
26
|
+
on_disk = {p.stem for p in s.ELEMENTS.glob("*.json")}
|
|
27
|
+
assert set(goldens) <= on_disk, f"mock controls with no golden: {set(goldens) - on_disk}"
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
def test_soundness_no_enum_contradictions():
|
|
31
|
+
# build_goldens resolves every enum; a wrong mapping would change a value that an
|
|
32
|
+
# existing golden already had. The --check path asserts this; here we just confirm
|
|
33
|
+
# the generator runs and produces the full set.
|
|
34
|
+
goldens, _stats, _res = s.build_goldens()
|
|
35
|
+
assert len(goldens) >= 33
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
"""form-update: safe GET->deep-merge->PUT of a live form.
|
|
2
|
+
|
|
3
|
+
Verifies the accepted PascalCase envelope, deep-merge semantics (nested merge,
|
|
4
|
+
array/scalar replace), top-level overrides (rename/publish), dry-run, and usage
|
|
5
|
+
errors. CustomUrl is ECHOED from the GET (main's behaviour; the PUT ignores it
|
|
6
|
+
either way — verified live). HTTP via FakeSession (no live API)."""
|
|
7
|
+
from __future__ import annotations
|
|
8
|
+
|
|
9
|
+
import pytest
|
|
10
|
+
|
|
11
|
+
from tools.procesio import errors, main
|
|
12
|
+
from tools.procesio.client import ProcesioClient
|
|
13
|
+
from tools.procesio.handlers.form_code import build_put_body
|
|
14
|
+
from tools.procesio.tests.conftest import FakeResp, FakeSession
|
|
15
|
+
|
|
16
|
+
APIKEY = {"type": "apikey", "key": "N", "value": "V"}
|
|
17
|
+
ENVELOPE = {"Id", "Name", "IsPrivate", "Type", "Status", "State", "Assignees", "Data", "CustomUrl"}
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
def _call(action, argv, session):
|
|
21
|
+
builder = lambda prof: ProcesioClient(profile=APIKEY, name="t", session=session)
|
|
22
|
+
return main.dispatch(action, argv, client_builder=builder)
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
def _form(*, status=1, state=True, data=None):
|
|
26
|
+
"""A GET echo (camelCase) with server metadata that must be dropped from the PUT.
|
|
27
|
+
No updatedOn/version field, so the concurrency guard is inert (GET + PUT only)."""
|
|
28
|
+
d = data or {
|
|
29
|
+
"code": "ENC", "elements": [{"id": "el1"}], "theme": [], "hideBranding": False,
|
|
30
|
+
"images": {"logo": None, "header": "H"},
|
|
31
|
+
}
|
|
32
|
+
return {
|
|
33
|
+
"id": "F1", "name": "Overview", "isPrivate": False, "type": 1,
|
|
34
|
+
"status": status, "state": state, "assignees": [],
|
|
35
|
+
"customUrl": {"tinyUrl": "t"}, # separate entity — echoed, PUT ignores it
|
|
36
|
+
"createdBy": "server-meta", "workspaceName": "server-meta", # server metadata, dropped
|
|
37
|
+
"data": d,
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
def test_scalar_patch_builds_accepted_envelope_and_preserves_data():
|
|
42
|
+
s = FakeSession(queue=[FakeResp(200, _form()), FakeResp(200, {})])
|
|
43
|
+
out = _call("form-update", ["--id", "F1", "--data", '{"hideBranding": true}'], s)
|
|
44
|
+
|
|
45
|
+
assert out["applied"] is True and out["patched_keys"] == ["hideBranding"]
|
|
46
|
+
get, put = s.calls
|
|
47
|
+
assert get["method"] == "GET" and get["url"].endswith("/api/FormTemplate/F1")
|
|
48
|
+
assert put["method"] == "PUT" and put["url"].endswith("/api/FormTemplate")
|
|
49
|
+
body = put["json"]
|
|
50
|
+
# PascalCase top level only, no server metadata, CustomUrl echoed
|
|
51
|
+
assert set(body) == ENVELOPE
|
|
52
|
+
assert body["Id"] == "F1" and body["Name"] == "Overview"
|
|
53
|
+
assert body["CustomUrl"] == {"tinyUrl": "t"}
|
|
54
|
+
# patched key applied; everything else in Data round-trips untouched
|
|
55
|
+
assert body["Data"]["hideBranding"] is True
|
|
56
|
+
assert body["Data"]["elements"] == [{"id": "el1"}]
|
|
57
|
+
assert body["Data"]["code"] == "ENC"
|
|
58
|
+
assert body["Data"]["images"] == {"logo": None, "header": "H"}
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
def test_nested_merge_and_array_replace():
|
|
62
|
+
s = FakeSession(queue=[FakeResp(200, _form()), FakeResp(200, {})])
|
|
63
|
+
_call("form-update",
|
|
64
|
+
["--id", "F1", "--data", '{"images": {"logo": "X"}, "elements": [{"id": "new"}]}'], s)
|
|
65
|
+
data = s.calls[1]["json"]["Data"]
|
|
66
|
+
assert data["images"] == {"logo": "X", "header": "H"} # nested dict merges (header kept)
|
|
67
|
+
assert data["elements"] == [{"id": "new"}] # array replaces wholesale
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
def test_top_level_overrides_publish_a_draft():
|
|
71
|
+
s = FakeSession(queue=[FakeResp(200, _form(status=0, state=False)), FakeResp(200, {})])
|
|
72
|
+
out = _call("form-update",
|
|
73
|
+
["--id", "F1", "--name", "ENG/ Overview", "--status", "1", "--state", "true"], s)
|
|
74
|
+
body = s.calls[1]["json"]
|
|
75
|
+
assert body["Name"] == "ENG/ Overview" and body["Status"] == 1 and body["State"] is True
|
|
76
|
+
assert out["name"] == "ENG/ Overview" and out["status"] == 1 and out["state"] is True
|
|
77
|
+
assert out["patched_keys"] == [] # no Data patch given
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
def test_dry_run_gets_only_and_returns_dto():
|
|
81
|
+
s = FakeSession(queue=[FakeResp(200, _form())])
|
|
82
|
+
out = _call("form-update", ["--id", "F1", "--data", '{"hideBranding": true}', "--dry-run"], s)
|
|
83
|
+
assert out["applied"] is False and out["dry_run"] is True
|
|
84
|
+
assert out["dto"]["Data"]["hideBranding"] is True
|
|
85
|
+
assert len(s.calls) == 1 and s.calls[0]["method"] == "GET"
|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
def test_usage_errors():
|
|
89
|
+
with pytest.raises(errors.UsageError): # nothing to update (no patch, no override) -> no GET
|
|
90
|
+
_call("form-update", ["--id", "F1"], FakeSession(queue=[]))
|
|
91
|
+
with pytest.raises(errors.UsageError): # invalid JSON, rejected before any HTTP call
|
|
92
|
+
_call("form-update", ["--id", "F1", "--data", "{bad"], FakeSession(queue=[]))
|
|
93
|
+
with pytest.raises(errors.UsageError): # patch must be an object, not an array
|
|
94
|
+
_call("form-update", ["--id", "F1", "--data", "[1, 2]"], FakeSession(queue=[]))
|
|
95
|
+
|
|
96
|
+
|
|
97
|
+
def test_build_put_body_transform_contract():
|
|
98
|
+
"""The single canonical transform: camelCase echo -> PascalCase envelope, CustomUrl echoed."""
|
|
99
|
+
echo = _form(status=0, state=False)
|
|
100
|
+
body = build_put_body(echo, data={"k": 1}, name="R", status=1, state=True)
|
|
101
|
+
assert set(body) == ENVELOPE
|
|
102
|
+
assert body["Name"] == "R" and body["Status"] == 1 and body["State"] is True
|
|
103
|
+
assert body["Data"] == {"k": 1} and body["CustomUrl"] == {"tinyUrl": "t"}
|
|
104
|
+
# omitted overrides fall back to the echo's values
|
|
105
|
+
keep = build_put_body(echo)
|
|
106
|
+
assert keep["Name"] == "Overview" and keep["Status"] == 0 and keep["State"] is False
|
|
107
|
+
# missing required echo key is refused
|
|
108
|
+
with pytest.raises(errors.UsageError):
|
|
109
|
+
build_put_body({"id": "X", "name": "Y"}) # no 'data'
|
|
110
|
+
|
|
111
|
+
|
|
112
|
+
# --------------------------------------------------------------- IsPrivate (publishing switch)
|
|
113
|
+
|
|
114
|
+
def test_is_private_is_echoed_untouched_when_not_asked_for():
|
|
115
|
+
"""Reachability is a publishing decision: an unrelated save must never flip it."""
|
|
116
|
+
form = {"id": "f1", "name": "F", "data": {"elements": []}, "isPrivate": True,
|
|
117
|
+
"type": 1, "status": 1, "state": True, "assignees": [], "customUrl": None}
|
|
118
|
+
body = build_put_body(form, name="Renamed")
|
|
119
|
+
assert body["IsPrivate"] is True
|
|
120
|
+
|
|
121
|
+
|
|
122
|
+
def test_is_private_false_is_what_opens_a_form_to_an_anonymous_visitor():
|
|
123
|
+
form = {"id": "f1", "name": "F", "data": {"elements": []}, "isPrivate": True,
|
|
124
|
+
"type": 1, "status": 1, "state": True, "assignees": [], "customUrl": None}
|
|
125
|
+
body = build_put_body(form, is_private=False)
|
|
126
|
+
assert body["IsPrivate"] is False
|
|
127
|
+
assert body["Status"] == 1, "publishing also needs Status 1, which must survive untouched"
|
|
128
|
+
|
|
129
|
+
|
|
130
|
+
def test_is_private_can_be_put_back():
|
|
131
|
+
form = {"id": "f1", "name": "F", "data": {"elements": []}, "isPrivate": False,
|
|
132
|
+
"type": 1, "status": 1, "state": True, "assignees": [], "customUrl": None}
|
|
133
|
+
assert build_put_body(form, is_private=True)["IsPrivate"] is True
|
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
"""DTO safety lints (warnings, never blockers) — red/green for each check."""
|
|
2
|
+
from __future__ import annotations
|
|
3
|
+
|
|
4
|
+
import pytest
|
|
5
|
+
|
|
6
|
+
from tools.procesio import formlint
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
def _el(el_id, parent=None, configs=None):
|
|
10
|
+
return {"id": el_id, "parentId": parent, "configs": configs or []}
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
def _cfg(key, value):
|
|
14
|
+
return {"key": key, "value": value}
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
# -- (a) phantom parentId ---------------------------------------------------
|
|
18
|
+
|
|
19
|
+
def test_phantom_parent_flagged():
|
|
20
|
+
data = {"elements": [
|
|
21
|
+
_el("tab1"),
|
|
22
|
+
_el("child", parent="GHOST"), # references no element
|
|
23
|
+
]}
|
|
24
|
+
warns = formlint.lint_phantom_parent(data)
|
|
25
|
+
assert len(warns) == 1
|
|
26
|
+
assert "GHOST" in warns[0] and "NO pane" in warns[0]
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
def test_valid_parent_not_flagged():
|
|
30
|
+
data = {"elements": [_el("tab1"), _el("child", parent="tab1")]}
|
|
31
|
+
assert formlint.lint_phantom_parent(data) == []
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
def test_null_parent_not_flagged():
|
|
35
|
+
data = {"elements": [_el("top", parent=None)]}
|
|
36
|
+
assert formlint.lint_phantom_parent(data) == []
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
# -- (b) duplicate id/name configs ------------------------------------------
|
|
40
|
+
|
|
41
|
+
def test_duplicate_name_config_flagged():
|
|
42
|
+
data = {"elements": [
|
|
43
|
+
_el("a", configs=[_cfg("name", "email")]),
|
|
44
|
+
_el("b", configs=[_cfg("name", "email")]),
|
|
45
|
+
]}
|
|
46
|
+
warns = formlint.lint_duplicate_configs(data)
|
|
47
|
+
assert any("name" in w and "email" in w for w in warns)
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
def test_unique_configs_not_flagged():
|
|
51
|
+
data = {"elements": [
|
|
52
|
+
_el("a", configs=[_cfg("name", "email"), _cfg("id", "e1")]),
|
|
53
|
+
_el("b", configs=[_cfg("name", "phone"), _cfg("id", "e2")]),
|
|
54
|
+
]}
|
|
55
|
+
assert formlint.lint_duplicate_configs(data) == []
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
# -- (c) patch-key wrapping mistake -----------------------------------------
|
|
59
|
+
|
|
60
|
+
def test_patch_data_wrapping_mistake_flagged():
|
|
61
|
+
existing = {"hideBranding": False, "elements": []}
|
|
62
|
+
warns = formlint.lint_patch_keys(existing, {"Data": {"hideBranding": True}})
|
|
63
|
+
assert len(warns) == 1 and "wrapping mistake" in warns[0]
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
def test_patch_unknown_key_flagged_as_addition():
|
|
67
|
+
existing = {"hideBranding": False}
|
|
68
|
+
warns = formlint.lint_patch_keys(existing, {"hideBrandng": True}) # typo
|
|
69
|
+
assert len(warns) == 1 and "not an existing Data field" in warns[0]
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
def test_patch_known_key_not_flagged():
|
|
73
|
+
existing = {"hideBranding": False}
|
|
74
|
+
assert formlint.lint_patch_keys(existing, {"hideBranding": True}) == []
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
# -- (d) multiple-select without isList -------------------------------------
|
|
78
|
+
|
|
79
|
+
def test_multiple_select_missing_islist_flagged():
|
|
80
|
+
data = {"elements": [_el("s1", configs=[
|
|
81
|
+
_cfg("multiple", True),
|
|
82
|
+
{"key": "value", "isList": False},
|
|
83
|
+
])]}
|
|
84
|
+
warns = formlint.lint_multiple_select_islist(data)
|
|
85
|
+
assert len(warns) == 1 and "isList" in warns[0]
|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
def test_multiple_select_with_islist_ok():
|
|
89
|
+
data = {"elements": [_el("s1", configs=[
|
|
90
|
+
_cfg("multiple", True),
|
|
91
|
+
{"key": "value", "isList": True},
|
|
92
|
+
])]}
|
|
93
|
+
assert formlint.lint_multiple_select_islist(data) == []
|
|
94
|
+
|
|
95
|
+
|
|
96
|
+
def test_single_select_not_flagged():
|
|
97
|
+
data = {"elements": [_el("s1", configs=[
|
|
98
|
+
_cfg("multiple", False),
|
|
99
|
+
{"key": "value", "isList": False},
|
|
100
|
+
])]}
|
|
101
|
+
assert formlint.lint_multiple_select_islist(data) == []
|
|
102
|
+
|
|
103
|
+
|
|
104
|
+
# -- IS_TRUE / IS_FALSE on a Boolean variable whose default is a STRING ------
|
|
105
|
+
|
|
106
|
+
def _cond(left, op, right=""):
|
|
107
|
+
return {"operator": op, "leftOperator": {"value": left}, "rightOperator": {"value": right}}
|
|
108
|
+
|
|
109
|
+
|
|
110
|
+
def _form_with_condition(default, op="IS_TRUE", left="var-pj"):
|
|
111
|
+
return {
|
|
112
|
+
"variables": [{"id": "var-pj", "name": "isPJ", "defaultValue": default}],
|
|
113
|
+
"elements": [_el("btn", configs=[
|
|
114
|
+
_cfg("name", "confirm"),
|
|
115
|
+
_cfg("onClickEvents", {"events": [{"action": "MAP_FORM_DATA", "config": {
|
|
116
|
+
"mapping": [], "conditions": [_cond(left, op)]}}]}),
|
|
117
|
+
])],
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
|
|
121
|
+
@pytest.mark.parametrize("default", ["False", "false"])
|
|
122
|
+
def test_is_true_on_text_false_default_flagged(default):
|
|
123
|
+
# measured live: IS_TRUE passes on both spellings, because any non-empty text is true
|
|
124
|
+
warns = formlint.lint_string_boolean_conditions(_form_with_condition(default))
|
|
125
|
+
assert len(warns) == 1
|
|
126
|
+
assert "isPJ IS_TRUE" in warns[0] and repr(default) in warns[0] and "'confirm'" in warns[0]
|
|
127
|
+
assert "PASSES" in warns[0]
|
|
128
|
+
assert warns[0] in formlint.lint_form_data(_form_with_condition(default))
|
|
129
|
+
|
|
130
|
+
|
|
131
|
+
def test_is_false_on_text_false_default_flagged_as_never_passing():
|
|
132
|
+
warns = formlint.lint_string_boolean_conditions(_form_with_condition("False", op="IS_FALSE"))
|
|
133
|
+
assert len(warns) == 1 and "never passes" in warns[0]
|
|
134
|
+
|
|
135
|
+
|
|
136
|
+
def test_text_true_default_is_not_flagged():
|
|
137
|
+
# "True" evaluates the way it reads, in both directions
|
|
138
|
+
assert formlint.lint_string_boolean_conditions(_form_with_condition("True")) == []
|
|
139
|
+
assert formlint.lint_string_boolean_conditions(_form_with_condition("True", op="IS_FALSE")) == []
|
|
140
|
+
|
|
141
|
+
|
|
142
|
+
def test_null_default_equals_operator_and_field_operand_not_flagged():
|
|
143
|
+
assert formlint.lint_string_boolean_conditions(_form_with_condition(None)) == []
|
|
144
|
+
assert formlint.lint_string_boolean_conditions(_form_with_condition("False", op="EQUALS")) == []
|
|
145
|
+
field = "root.11223344-5566-7788-99aa-aabbccddeeff.el.cfg"
|
|
146
|
+
assert formlint.lint_string_boolean_conditions(_form_with_condition("False", left=field)) == []
|
|
147
|
+
|
|
148
|
+
|
|
149
|
+
def test_form_level_events_are_checked_too():
|
|
150
|
+
data = {"variables": [{"id": "v", "name": "flag", "defaultValue": "False"}],
|
|
151
|
+
"events": [{"action": "MAP_FORM_DATA",
|
|
152
|
+
"config": {"mapping": [], "conditions": [_cond("v", "IS_TRUE")]}}],
|
|
153
|
+
"elements": []}
|
|
154
|
+
warns = formlint.lint_string_boolean_conditions(data)
|
|
155
|
+
assert len(warns) == 1 and warns[0].startswith("form-level event")
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
"""Form custom CSS is scoped to the form container, so code that styles or mounts UI outside it
|
|
2
|
+
needs the scope attribute copied onto <html>; the lint says so, and stays quiet otherwise."""
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from tools.procesio import formlint
|
|
6
|
+
|
|
7
|
+
FIX = ("var host = document.querySelector('[data-form-css-scope]');"
|
|
8
|
+
"document.documentElement.setAttribute('data-form-css-scope',"
|
|
9
|
+
" host.getAttribute('data-form-css-scope'));")
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
def test_ui_mounted_on_body_without_the_attribute_is_warned():
|
|
13
|
+
w = formlint.lint_form_code_scope(".card{color:red}", "document.body.appendChild(el);")
|
|
14
|
+
assert len(w) == 1 and "document.body" in w[0] and "<html>" in w[0]
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
def test_page_level_css_without_the_attribute_is_warned():
|
|
18
|
+
w = formlint.lint_form_code_scope(":root{--brand:#123} html, body{margin:0} .x{}", "")
|
|
19
|
+
assert len(w) == 1 and ":root / body / html" in w[0]
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
def test_a_framework_mounted_on_body_is_warned():
|
|
23
|
+
assert formlint.lint_form_code_scope("", "createApp(App).mount(document.body)")
|
|
24
|
+
assert formlint.lint_form_code_scope("", "app.mount('body')")
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
def test_code_that_propagates_the_attribute_is_not_warned():
|
|
28
|
+
assert formlint.lint_form_code_scope(":root{--a:1}", FIX + "document.body.appendChild(el);") == []
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
def test_ui_that_stays_inside_the_form_is_not_warned():
|
|
32
|
+
css = ".card{color:red} @media (max-width:600px){.card{color:blue}} /* body{} */"
|
|
33
|
+
assert formlint.lint_form_code_scope(css, "document.querySelector('.card').append(x);") == []
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
def test_body_inside_another_selector_is_not_a_page_rule():
|
|
37
|
+
# `.tbody` / `.html-preview` are classes, not the html/body elements.
|
|
38
|
+
assert formlint.lint_form_code_scope(".tbody td{} .html-preview{}", "") == []
|