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,255 @@
|
|
|
1
|
+
"""Tests for the aat-mcp bridge + stdio JSON-RPC server + reversibility gate.
|
|
2
|
+
|
|
3
|
+
Protocol dispatch, the reversibility gate, and the anti-thrash argv guarantee are
|
|
4
|
+
tested with fakes - no real subprocess, no credential access.
|
|
5
|
+
"""
|
|
6
|
+
from __future__ import annotations
|
|
7
|
+
|
|
8
|
+
import json
|
|
9
|
+
|
|
10
|
+
import bridge
|
|
11
|
+
import gate
|
|
12
|
+
import server
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
def _call(name, arguments, _id=1):
|
|
16
|
+
return server.handle({"jsonrpc": "2.0", "id": _id, "method": "tools/call",
|
|
17
|
+
"params": {"name": name, "arguments": arguments}})
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
# --- protocol dispatch ---------------------------------------------------
|
|
21
|
+
|
|
22
|
+
def test_initialize_echoes_protocol_and_serverinfo():
|
|
23
|
+
resp = server.handle({"jsonrpc": "2.0", "id": 1, "method": "initialize",
|
|
24
|
+
"params": {"protocolVersion": "2024-11-05"}})
|
|
25
|
+
assert resp["result"]["serverInfo"]["name"] == "aat-mcp"
|
|
26
|
+
assert resp["result"]["protocolVersion"] == "2024-11-05"
|
|
27
|
+
assert "tools" in resp["result"]["capabilities"]
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
def test_initialize_defaults_protocol_when_absent():
|
|
31
|
+
resp = server.handle({"jsonrpc": "2.0", "id": 1, "method": "initialize",
|
|
32
|
+
"params": {}})
|
|
33
|
+
assert resp["result"]["protocolVersion"] == server.DEFAULT_PROTOCOL
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
def test_notifications_get_no_response():
|
|
37
|
+
assert server.handle({"jsonrpc": "2.0", "method": "notifications/initialized"}) is None
|
|
38
|
+
assert server.handle({"jsonrpc": "2.0", "method": "notifications/cancelled"}) is None
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
def test_ping():
|
|
42
|
+
assert server.handle({"jsonrpc": "2.0", "id": 7, "method": "ping"})["result"] == {}
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
def test_tools_list_exposes_the_six_tools():
|
|
46
|
+
resp = server.handle({"jsonrpc": "2.0", "id": 2, "method": "tools/list"})
|
|
47
|
+
names = {t["name"] for t in resp["result"]["tools"]}
|
|
48
|
+
assert names == {"capabilities", "run_tool", "run_tool_confirmed",
|
|
49
|
+
"run_agent", "run_agent_confirmed", "get_skill"}
|
|
50
|
+
assert all("inputSchema" in t for t in resp["result"]["tools"])
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
def test_unknown_method_is_jsonrpc_error():
|
|
54
|
+
resp = server.handle({"jsonrpc": "2.0", "id": 9, "method": "does/not/exist"})
|
|
55
|
+
assert resp["error"]["code"] == -32601
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
def test_unknown_notification_is_swallowed():
|
|
59
|
+
assert server.handle({"jsonrpc": "2.0", "method": "does/not/exist"}) is None
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
# --- reversibility gate --------------------------------------------------
|
|
63
|
+
|
|
64
|
+
def test_reversible_action_runs_on_plain_tool(monkeypatch):
|
|
65
|
+
called = {}
|
|
66
|
+
monkeypatch.setattr(server.bridge, "run_tool",
|
|
67
|
+
lambda t, a, args: called.update(t=t, a=a) or
|
|
68
|
+
{"ok": True, "data": {"x": 1}, "error": None})
|
|
69
|
+
resp = _call("run_tool", {"tool": "google-mail", "action": "list-messages"})
|
|
70
|
+
assert resp["result"]["isError"] is False
|
|
71
|
+
assert called == {"t": "google-mail", "a": "list-messages"}
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
def test_irreversible_action_refused_on_plain_tool(monkeypatch):
|
|
75
|
+
# bridge.run_tool must NOT be called - the gate refuses before execution.
|
|
76
|
+
monkeypatch.setattr(server.bridge, "run_tool",
|
|
77
|
+
lambda *a, **k: (_ for _ in ()).throw(AssertionError("executed!")))
|
|
78
|
+
resp = _call("run_tool", {"tool": "google-mail", "action": "send-message",
|
|
79
|
+
"args": {"to": "a@example.com"}})
|
|
80
|
+
payload = json.loads(resp["result"]["content"][0]["text"])
|
|
81
|
+
assert "approval_required" in payload
|
|
82
|
+
assert payload["approval_required"]["verb"] == "send"
|
|
83
|
+
assert payload["approval_required"]["blast_class"] == "message-sent"
|
|
84
|
+
assert "run_tool_confirmed" in payload["approval_required"]["next"]
|
|
85
|
+
|
|
86
|
+
|
|
87
|
+
def test_irreversible_action_runs_on_confirmed_tool(monkeypatch):
|
|
88
|
+
called = {}
|
|
89
|
+
monkeypatch.setattr(server.bridge, "run_tool",
|
|
90
|
+
lambda t, a, args: called.update(t=t, a=a, args=args) or
|
|
91
|
+
{"ok": True, "data": {"id": "m1"}, "error": None})
|
|
92
|
+
resp = _call("run_tool_confirmed", {"tool": "google-mail", "action": "send-message",
|
|
93
|
+
"args": {"to": "a@example.com"}})
|
|
94
|
+
assert resp["result"]["isError"] is False
|
|
95
|
+
assert called["t"] == "google-mail" and called["a"] == "send-message"
|
|
96
|
+
|
|
97
|
+
|
|
98
|
+
def test_confirmed_denied_when_headless_env_set(monkeypatch):
|
|
99
|
+
monkeypatch.setattr(gate, "deny_irreversible_env", lambda: True)
|
|
100
|
+
monkeypatch.setattr(server.bridge, "run_tool",
|
|
101
|
+
lambda *a, **k: (_ for _ in ()).throw(AssertionError("executed!")))
|
|
102
|
+
resp = _call("run_tool_confirmed", {"tool": "google-mail", "action": "send-message"})
|
|
103
|
+
assert resp["result"]["isError"] is True
|
|
104
|
+
payload = json.loads(resp["result"]["content"][0]["text"])
|
|
105
|
+
assert "refused" in payload
|
|
106
|
+
|
|
107
|
+
|
|
108
|
+
def test_agent_intake_is_reversible_and_runs(monkeypatch):
|
|
109
|
+
called = {}
|
|
110
|
+
monkeypatch.setattr(server.bridge, "run_agent",
|
|
111
|
+
lambda ag, a, args: called.update(ag=ag, a=a) or
|
|
112
|
+
{"ok": True, "data": {}, "error": None})
|
|
113
|
+
resp = _call("run_agent", {"agent": "orchestrator", "action": "intake",
|
|
114
|
+
"args": {"request": "collect invoices"}})
|
|
115
|
+
assert resp["result"]["isError"] is False
|
|
116
|
+
assert called == {"ag": "orchestrator", "a": "intake"}
|
|
117
|
+
|
|
118
|
+
|
|
119
|
+
def test_run_tool_requires_tool_arg():
|
|
120
|
+
resp = _call("run_tool", {})
|
|
121
|
+
assert resp["result"]["isError"] is True
|
|
122
|
+
|
|
123
|
+
|
|
124
|
+
def test_call_unknown_tool_is_error():
|
|
125
|
+
resp = _call("nope", {})
|
|
126
|
+
assert resp["result"]["isError"] is True
|
|
127
|
+
|
|
128
|
+
|
|
129
|
+
def test_get_skill_keyerror_becomes_readable_error(monkeypatch):
|
|
130
|
+
def boom(name):
|
|
131
|
+
raise KeyError("skill not found: ghost")
|
|
132
|
+
monkeypatch.setattr(server.bridge, "get_skill", boom)
|
|
133
|
+
resp = _call("get_skill", {"name": "ghost"})
|
|
134
|
+
assert resp["result"]["isError"] is True
|
|
135
|
+
assert "ghost" in resp["result"]["content"][0]["text"]
|
|
136
|
+
|
|
137
|
+
|
|
138
|
+
# --- gate classifier -----------------------------------------------------
|
|
139
|
+
|
|
140
|
+
def test_gate_classify_verbs():
|
|
141
|
+
assert gate.classify("google-mail", "send-message")["reversible"] is False
|
|
142
|
+
assert gate.classify("whatsapp-personal", "delete-messages")["reversible"] is False
|
|
143
|
+
assert gate.classify("fgo", "issue-invoice")["reversible"] is False
|
|
144
|
+
assert gate.classify("google-mail", "list-messages")["reversible"] is True
|
|
145
|
+
assert gate.classify("apollo", "search-people")["reversible"] is True
|
|
146
|
+
assert gate.classify("hello-world", None)["reversible"] is True
|
|
147
|
+
|
|
148
|
+
|
|
149
|
+
def test_gate_ignores_arg_values_only_action_and_name():
|
|
150
|
+
# The gate classifies on name + action, never arg values - so a subject line
|
|
151
|
+
# that contains "send" does not trip it (that is the caller's job to pass action).
|
|
152
|
+
assert gate.classify("google-mail", "create-draft")["reversible"] is True
|
|
153
|
+
|
|
154
|
+
|
|
155
|
+
# --- the anti-thrash guarantee ------------------------------------------
|
|
156
|
+
|
|
157
|
+
def test_bridge_encodes_json_args_as_single_argv_element(monkeypatch):
|
|
158
|
+
seen = {}
|
|
159
|
+
|
|
160
|
+
def fake_run_tool(tool, argv, **k):
|
|
161
|
+
seen.update(tool=tool, argv=argv)
|
|
162
|
+
return {"ok": True, "data": {}, "error": None}
|
|
163
|
+
|
|
164
|
+
monkeypatch.setattr(bridge.runner, "run_tool", fake_run_tool)
|
|
165
|
+
bridge.run_tool("google-mail", "send-message",
|
|
166
|
+
{"to": "a@example.com", "cc": ["x@example.com", "z@example.com"]})
|
|
167
|
+
assert seen["argv"][0] == "send-message"
|
|
168
|
+
i = seen["argv"].index("--cc")
|
|
169
|
+
assert json.loads(seen["argv"][i + 1]) == ["x@example.com", "z@example.com"]
|
|
170
|
+
|
|
171
|
+
|
|
172
|
+
def test_bridge_omits_action_for_flat_tool(monkeypatch):
|
|
173
|
+
seen = {}
|
|
174
|
+
monkeypatch.setattr(bridge.runner, "run_tool",
|
|
175
|
+
lambda tool, argv, **k: seen.update(argv=argv) or
|
|
176
|
+
{"ok": True, "data": {}, "error": None})
|
|
177
|
+
bridge.run_tool("hello-world", None, {"name": "Z"})
|
|
178
|
+
assert seen["argv"] == ["--name", "Z"]
|
|
179
|
+
|
|
180
|
+
|
|
181
|
+
# --- host-only delegation (host-side tool-runner) ------------------------
|
|
182
|
+
|
|
183
|
+
def test_is_host_only_detects_listed_vs_plain():
|
|
184
|
+
assert bridge._is_host_only("tool", "web") is True # listed: drives a real browser profile
|
|
185
|
+
assert bridge._is_host_only("tool", "xlsx") is False # neither listed nor web_session
|
|
186
|
+
|
|
187
|
+
|
|
188
|
+
def test_run_tool_delegates_host_only_when_runner_set(monkeypatch):
|
|
189
|
+
seen = {}
|
|
190
|
+
monkeypatch.setenv("AAT_HOST_RUNNER_URL", "http://host.docker.internal:8904")
|
|
191
|
+
monkeypatch.setattr(bridge, "_delegate",
|
|
192
|
+
lambda kind, name, action, args: seen.update(kind=kind, name=name) or
|
|
193
|
+
{"ok": True, "data": {"delegated": True}})
|
|
194
|
+
monkeypatch.setattr(bridge.runner, "run_tool",
|
|
195
|
+
lambda *a, **k: (_ for _ in ()).throw(AssertionError("ran locally!")))
|
|
196
|
+
r = bridge.run_tool("web", "get-text", {"url": "https://example.com"})
|
|
197
|
+
assert r["data"]["delegated"] is True
|
|
198
|
+
assert seen == {"kind": "tool", "name": "web"}
|
|
199
|
+
|
|
200
|
+
|
|
201
|
+
def test_run_tool_runs_locally_when_not_host_only(monkeypatch):
|
|
202
|
+
monkeypatch.setenv("AAT_HOST_RUNNER_URL", "http://host.docker.internal:8904")
|
|
203
|
+
monkeypatch.setattr(bridge.runner, "run_tool",
|
|
204
|
+
lambda tool, argv, **k: {"ok": True, "data": {"local": tool}})
|
|
205
|
+
monkeypatch.setattr(bridge, "_delegate",
|
|
206
|
+
lambda *a, **k: (_ for _ in ()).throw(AssertionError("delegated!")))
|
|
207
|
+
assert bridge.run_tool("hello-world", None, {"name": "X"})["data"]["local"] == "hello-world"
|
|
208
|
+
|
|
209
|
+
|
|
210
|
+
def test_no_delegation_without_runner_url(monkeypatch):
|
|
211
|
+
monkeypatch.delenv("AAT_HOST_RUNNER_URL", raising=False)
|
|
212
|
+
monkeypatch.setattr(bridge.runner, "run_tool",
|
|
213
|
+
lambda tool, argv, **k: {"ok": True, "data": {"local": True}})
|
|
214
|
+
# a host-only tool still runs locally when no host-runner is configured (local platform)
|
|
215
|
+
assert bridge.run_tool("whatsapp-personal", "list-chats", {})["data"]["local"] is True
|
|
216
|
+
|
|
217
|
+
|
|
218
|
+
# --- tool annotations ----------------------------------------------------
|
|
219
|
+
|
|
220
|
+
def test_every_tool_declares_a_title_and_hints():
|
|
221
|
+
"""A directory listing requires both, and a client uses them for permissions."""
|
|
222
|
+
for t in server.TOOLS:
|
|
223
|
+
assert t.get("title"), f"{t['name']} has no title"
|
|
224
|
+
a = t.get("annotations") or {}
|
|
225
|
+
assert a.get("title") == t["title"]
|
|
226
|
+
for hint in ("readOnlyHint", "destructiveHint", "idempotentHint", "openWorldHint"):
|
|
227
|
+
assert isinstance(a.get(hint), bool), f"{t['name']} missing {hint}"
|
|
228
|
+
assert len(t["name"]) <= 64
|
|
229
|
+
|
|
230
|
+
|
|
231
|
+
def test_a_tool_that_dispatches_arbitrary_actions_is_never_read_only():
|
|
232
|
+
"""The rule that stops a write from running unprompted.
|
|
233
|
+
|
|
234
|
+
A readOnlyHint tool may be run by a client WITHOUT asking. Anything that takes a
|
|
235
|
+
caller-supplied action and forwards it can reach a create or an update, so it can
|
|
236
|
+
never make that claim. The check reads the input schema rather than a list of
|
|
237
|
+
names, so a dispatcher added later is caught without anyone remembering to add it.
|
|
238
|
+
"""
|
|
239
|
+
for t in server.TOOLS:
|
|
240
|
+
props = set(((t.get("inputSchema") or {}).get("properties") or {}))
|
|
241
|
+
dispatches = "action" in props and bool(props & {"tool", "agent"})
|
|
242
|
+
if dispatches:
|
|
243
|
+
a = t["annotations"]
|
|
244
|
+
assert a["readOnlyHint"] is False, (
|
|
245
|
+
f"{t['name']} forwards a caller-supplied action and claims readOnlyHint")
|
|
246
|
+
assert a["destructiveHint"] is True
|
|
247
|
+
|
|
248
|
+
|
|
249
|
+
def test_a_freeform_dispatcher_names_the_api_it_targets():
|
|
250
|
+
"""Required of any tool whose caller constructs the request."""
|
|
251
|
+
for t in server.TOOLS:
|
|
252
|
+
props = set(((t.get("inputSchema") or {}).get("properties") or {}))
|
|
253
|
+
if "action" in props and "tool" in props:
|
|
254
|
+
assert "procesio.com" in t["description"], (
|
|
255
|
+
f"{t['name']} accepts freeform actions but names no API")
|
|
@@ -0,0 +1,247 @@
|
|
|
1
|
+
"""The three gates that keep the published chat surface and the framework independent.
|
|
2
|
+
|
|
3
|
+
chat_surface.yaml declares what is published; the registry remains the source of truth
|
|
4
|
+
for what exists. They are allowed to drift - that is the point of having two of them -
|
|
5
|
+
but never silently, and never past CI.
|
|
6
|
+
|
|
7
|
+
1. conformance every declared target/argument still exists and still means the
|
|
8
|
+
same thing. Catches a renamed action, a retyped argument and, most
|
|
9
|
+
quietly of all, a NEW required argument on an action we already
|
|
10
|
+
publish - which breaks nothing until a user's first call.
|
|
11
|
+
2. snapshot the exact tools/list payload is checked in, so any change to the
|
|
12
|
+
published contract arrives as a reviewable diff instead of a
|
|
13
|
+
surprise in a directory listing. MCP clients cache tool definitions
|
|
14
|
+
at initialisation and do not refresh them, so a schema that changes
|
|
15
|
+
under a client does not error - it misleads.
|
|
16
|
+
3. isolation neither surface imports the other, and the published one reaches
|
|
17
|
+
only the shared substrate.
|
|
18
|
+
|
|
19
|
+
Regenerating the snapshot after a deliberate change:
|
|
20
|
+
python -c "import sys; sys.path.insert(0,'webplatform/aat_mcp'); \
|
|
21
|
+
import json, chat_server as c; \
|
|
22
|
+
open('webplatform/aat_mcp/chat_surface.snapshot.json','w',newline='\\n').write( \
|
|
23
|
+
json.dumps(c.build_tools(c.load_surface()), indent=2, ensure_ascii=False)+'\\n')"
|
|
24
|
+
"""
|
|
25
|
+
from __future__ import annotations
|
|
26
|
+
|
|
27
|
+
import ast
|
|
28
|
+
import json
|
|
29
|
+
from pathlib import Path
|
|
30
|
+
|
|
31
|
+
import bridge # noqa: F401 - puts the repo root on sys.path for `registry`
|
|
32
|
+
import chat_server
|
|
33
|
+
import gate
|
|
34
|
+
import registry
|
|
35
|
+
import server
|
|
36
|
+
|
|
37
|
+
_HERE = Path(__file__).resolve().parents[1]
|
|
38
|
+
SNAPSHOT = _HERE / "chat_surface.snapshot.json"
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
def _registry_index():
|
|
42
|
+
tools = {t["name"]: t for t in registry.list_tools()}
|
|
43
|
+
agents = {a["name"]: a for a in registry.list_agents(tools)}
|
|
44
|
+
return tools, agents
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
def _resolve(spec):
|
|
48
|
+
"""(entry, action_dict) for a declared tool, or (None, None)."""
|
|
49
|
+
tools, agents = _registry_index()
|
|
50
|
+
target = spec["target"]
|
|
51
|
+
who = target.get("tool") or target.get("agent")
|
|
52
|
+
entry = (tools if "tool" in target else agents).get(who)
|
|
53
|
+
if entry is None:
|
|
54
|
+
return None, None
|
|
55
|
+
action = {a["name"]: a for a in (entry.get("actions") or [])}.get(target.get("action"))
|
|
56
|
+
return entry, action
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
# --- gate 1: conformance -------------------------------------------------
|
|
60
|
+
|
|
61
|
+
def test_every_declared_target_still_exists():
|
|
62
|
+
missing = []
|
|
63
|
+
for spec in chat_server.SURFACE["tools"]:
|
|
64
|
+
entry, action = _resolve(spec)
|
|
65
|
+
if entry is None or action is None:
|
|
66
|
+
missing.append(f"{spec['name']} -> {spec['target']}")
|
|
67
|
+
assert not missing, (
|
|
68
|
+
"declared in chat_surface.yaml but not in the registry (an action was renamed "
|
|
69
|
+
f"or removed; update the declaration deliberately): {missing}")
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
def test_every_declared_argument_still_exists_with_the_declared_type():
|
|
73
|
+
problems = []
|
|
74
|
+
for spec in chat_server.SURFACE["tools"]:
|
|
75
|
+
_, action = _resolve(spec)
|
|
76
|
+
if action is None:
|
|
77
|
+
continue
|
|
78
|
+
manifest = {a["name"]: a for a in action["args"]}
|
|
79
|
+
declared = list(spec.get("args") or [])
|
|
80
|
+
declared += [chat_server.SURFACE["common_args"][k] for k in (spec.get("common") or [])]
|
|
81
|
+
for arg in declared:
|
|
82
|
+
flag = arg["flag"]
|
|
83
|
+
if flag not in manifest:
|
|
84
|
+
problems.append(f"{spec['name']}: --{flag} no longer exists")
|
|
85
|
+
continue
|
|
86
|
+
want, got = arg.get("type"), manifest[flag].get("type")
|
|
87
|
+
if want and got and want != got:
|
|
88
|
+
problems.append(f"{spec['name']}: --{flag} is {got}, declared {want}")
|
|
89
|
+
assert not problems, problems
|
|
90
|
+
|
|
91
|
+
|
|
92
|
+
def test_no_required_argument_is_left_undeclared():
|
|
93
|
+
"""The silent one. A new required argument on an action we already publish leaves
|
|
94
|
+
the published schema valid and every call failing, because the surface has no way
|
|
95
|
+
to supply it. It has to fail here instead."""
|
|
96
|
+
problems = []
|
|
97
|
+
for spec in chat_server.SURFACE["tools"]:
|
|
98
|
+
_, action = _resolve(spec)
|
|
99
|
+
if action is None:
|
|
100
|
+
continue
|
|
101
|
+
exposed = {a["flag"] for a in (spec.get("args") or [])}
|
|
102
|
+
exposed |= {chat_server.SURFACE["common_args"][k]["flag"]
|
|
103
|
+
for k in (spec.get("common") or [])}
|
|
104
|
+
for arg in action["args"]:
|
|
105
|
+
if arg.get("required") and arg["name"] not in exposed and arg.get("default") is None:
|
|
106
|
+
problems.append(f"{spec['name']}: --{arg['name']} is required by "
|
|
107
|
+
f"{spec['target']} but the surface cannot supply it")
|
|
108
|
+
assert not problems, problems
|
|
109
|
+
|
|
110
|
+
|
|
111
|
+
def test_no_published_tool_reaches_an_irreversible_action():
|
|
112
|
+
"""This surface has no confirmed-twin path, so it must carry nothing that needs one.
|
|
113
|
+
Adding a destructive action fails the build rather than growing a second, softer
|
|
114
|
+
approval route beside the one in server.py."""
|
|
115
|
+
bad = []
|
|
116
|
+
for spec in chat_server.SURFACE["tools"]:
|
|
117
|
+
t = spec["target"]
|
|
118
|
+
verdict = gate.classify(t.get("tool") or t.get("agent"), t.get("action"))
|
|
119
|
+
if not verdict["reversible"]:
|
|
120
|
+
bad.append(f"{spec['name']} ({verdict['verb']}/{verdict['blast_class']})")
|
|
121
|
+
assert not bad, bad
|
|
122
|
+
|
|
123
|
+
|
|
124
|
+
def test_read_only_entries_are_also_reversible():
|
|
125
|
+
"""read_only and reversible are different questions - process-create is reversible
|
|
126
|
+
and is not read-only - but the implication holds one way: a call that changes
|
|
127
|
+
nothing cannot be irreversible. A mislabel here would let a write run unattended."""
|
|
128
|
+
for spec in chat_server.SURFACE["tools"]:
|
|
129
|
+
if not spec["read_only"]:
|
|
130
|
+
continue
|
|
131
|
+
t = spec["target"]
|
|
132
|
+
verdict = gate.classify(t.get("tool") or t.get("agent"), t.get("action"))
|
|
133
|
+
assert verdict["reversible"], f"{spec['name']} claims read_only but the gate disagrees"
|
|
134
|
+
|
|
135
|
+
|
|
136
|
+
def test_excluded_operations_are_not_also_published():
|
|
137
|
+
"""The exclusion list is part of the contract. An entry that reappears in `tools`
|
|
138
|
+
means someone reversed a decision without reading why it was made."""
|
|
139
|
+
published = {(s["target"].get("tool") or s["target"].get("agent"), s["target"].get("action"))
|
|
140
|
+
for s in chat_server.SURFACE["tools"]}
|
|
141
|
+
for item in chat_server.SURFACE["excluded"]:
|
|
142
|
+
target = item["target"]
|
|
143
|
+
if "*" in target or "<" in target or " " in target:
|
|
144
|
+
continue # a class of actions or an argument, not one target
|
|
145
|
+
who, _, action = target.partition("/")
|
|
146
|
+
assert (who, action) not in published, f"{target} is both excluded and published"
|
|
147
|
+
assert item.get("reason", "").strip(), f"{target} is excluded with no reason"
|
|
148
|
+
|
|
149
|
+
|
|
150
|
+
# --- gate 2: snapshot ----------------------------------------------------
|
|
151
|
+
|
|
152
|
+
def test_published_surface_matches_the_checked_in_snapshot():
|
|
153
|
+
built = chat_server.build_tools(chat_server.load_surface())
|
|
154
|
+
saved = json.loads(SNAPSHOT.read_text(encoding="utf-8"))
|
|
155
|
+
assert built == saved, (
|
|
156
|
+
"the published tool list changed. If that was intended, regenerate the snapshot "
|
|
157
|
+
"(command in this module's docstring), bump surface_version, and let the diff be "
|
|
158
|
+
"reviewed - a client caches these definitions and will not notice on its own.")
|
|
159
|
+
|
|
160
|
+
|
|
161
|
+
def test_snapshot_is_the_shape_a_client_receives():
|
|
162
|
+
saved = json.loads(SNAPSHOT.read_text(encoding="utf-8"))
|
|
163
|
+
listed = chat_server.handle({"jsonrpc": "2.0", "id": 1, "method": "tools/list"})
|
|
164
|
+
assert listed["result"]["tools"] == saved
|
|
165
|
+
|
|
166
|
+
|
|
167
|
+
# --- gate 3: isolation ---------------------------------------------------
|
|
168
|
+
|
|
169
|
+
def _imports(path: Path) -> set[str]:
|
|
170
|
+
tree = ast.parse(path.read_text(encoding="utf-8"))
|
|
171
|
+
names: set[str] = set()
|
|
172
|
+
for node in ast.walk(tree):
|
|
173
|
+
if isinstance(node, ast.Import):
|
|
174
|
+
names |= {a.name.split(".")[0] for a in node.names}
|
|
175
|
+
elif isinstance(node, ast.ImportFrom) and node.module and node.level == 0:
|
|
176
|
+
names.add(node.module.split(".")[0])
|
|
177
|
+
return names
|
|
178
|
+
|
|
179
|
+
|
|
180
|
+
def test_the_two_surfaces_do_not_import_each_other():
|
|
181
|
+
assert "server" not in _imports(_HERE / "chat_server.py")
|
|
182
|
+
assert "chat_server" not in _imports(_HERE / "server.py")
|
|
183
|
+
|
|
184
|
+
|
|
185
|
+
def test_the_shared_protocol_module_imports_neither_surface():
|
|
186
|
+
"""protocol.py is shared so that negotiation has ONE implementation - two copies are how
|
|
187
|
+
both servers came to agree to any version asked for. It must stay below both surfaces:
|
|
188
|
+
if it imported one, a change to that surface would reach the other through it."""
|
|
189
|
+
assert not _imports(_HERE / "protocol.py") & {"server", "chat_server", "bridge", "gate"}
|
|
190
|
+
|
|
191
|
+
|
|
192
|
+
def test_the_published_surface_reaches_only_the_shared_substrate():
|
|
193
|
+
"""Whatever this surface imports is what a change elsewhere can reach it through.
|
|
194
|
+
Keeping the list short is the isolation; asserting it is what keeps it short."""
|
|
195
|
+
allowed = {"bridge", "gate", "protocol", "yaml", "json", "os", "sys", "pathlib", "__future__"}
|
|
196
|
+
assert _imports(_HERE / "chat_server.py") <= allowed
|
|
197
|
+
|
|
198
|
+
|
|
199
|
+
def test_a_tool_that_dispatches_arbitrary_actions_is_never_read_only():
|
|
200
|
+
"""Applied across BOTH surfaces, and derived from the schema rather than a list of
|
|
201
|
+
names, so a dispatcher added later is caught without anyone remembering this rule."""
|
|
202
|
+
for tools in (server.TOOLS, chat_server.TOOLS):
|
|
203
|
+
for t in tools:
|
|
204
|
+
props = set(((t.get("inputSchema") or {}).get("properties") or {}))
|
|
205
|
+
if "action" in props and props & {"tool", "agent"}:
|
|
206
|
+
a = t["annotations"]
|
|
207
|
+
assert a["readOnlyHint"] is False, t["name"]
|
|
208
|
+
assert a["destructiveHint"] is True, t["name"]
|
|
209
|
+
|
|
210
|
+
|
|
211
|
+
# --- the surface as a client sees it -------------------------------------
|
|
212
|
+
|
|
213
|
+
def test_initialize_reports_the_surface_version():
|
|
214
|
+
resp = chat_server.handle({"jsonrpc": "2.0", "id": 1, "method": "initialize",
|
|
215
|
+
"params": {"protocolVersion": "2024-11-05"}})
|
|
216
|
+
info = resp["result"]["serverInfo"]
|
|
217
|
+
assert info["name"] == "procesio-chat"
|
|
218
|
+
assert info["version"] == chat_server.SURFACE["surface_version"]
|
|
219
|
+
|
|
220
|
+
|
|
221
|
+
def test_every_published_tool_is_named_for_its_domain():
|
|
222
|
+
"""Namespacing: a directory client merges several servers' tools into one list, so a
|
|
223
|
+
bare `create_process` competes with every other automation product's."""
|
|
224
|
+
for t in chat_server.TOOLS:
|
|
225
|
+
assert t["name"].startswith("procesio_"), t["name"]
|
|
226
|
+
assert t["title"] and t["description"], t["name"]
|
|
227
|
+
|
|
228
|
+
|
|
229
|
+
def test_no_published_tool_accepts_an_undeclared_argument():
|
|
230
|
+
"""The schema is the contract. An argument the declaration does not name is dropped
|
|
231
|
+
rather than forwarded, so a caller cannot reach past the published surface."""
|
|
232
|
+
spec = chat_server._BY_NAME["procesio_list_processes"]
|
|
233
|
+
by_exposed = {chat_server.exposed_name(a) for a in spec["args"]}
|
|
234
|
+
assert "profile" not in by_exposed # a local installation detail, deliberately unexposed
|
|
235
|
+
|
|
236
|
+
|
|
237
|
+
def test_unknown_tool_is_an_error_payload_not_a_crash():
|
|
238
|
+
payload, is_error = chat_server.call_tool("procesio_not_a_tool", {})
|
|
239
|
+
assert is_error and "unknown tool" in payload["error"]
|
|
240
|
+
|
|
241
|
+
|
|
242
|
+
def test_an_oversized_result_is_capped_with_an_actionable_hint():
|
|
243
|
+
spec = chat_server._BY_NAME["procesio_list_processes"]
|
|
244
|
+
capped = chat_server._cap({"ok": True, "rows": ["x" * 100] * 2000}, spec)
|
|
245
|
+
assert capped["truncated"] is True
|
|
246
|
+
assert "search" in capped["hint"] # names the argument that narrows THIS tool
|
|
247
|
+
assert len(capped["preview"]) <= 2000
|