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,488 @@
|
|
|
1
|
+
"""Tests for the sqlserver schema-extract / schema-diff / migrate actions.
|
|
2
|
+
|
|
3
|
+
No live DB and no pyodbc: extraction runs against a FAKE cursor returning canned
|
|
4
|
+
catalog rows, dispatch injects a ``conn_factory``, and the diff dir-vs-dir path
|
|
5
|
+
needs no connection at all. The migrate ``list`` path uses a fake connection that
|
|
6
|
+
returns canned applied rows; the apply-without-``--apply`` guard is asserted.
|
|
7
|
+
"""
|
|
8
|
+
from __future__ import annotations
|
|
9
|
+
|
|
10
|
+
import pytest
|
|
11
|
+
|
|
12
|
+
from tools._lib import dbschema
|
|
13
|
+
from tools.sqlserver import main, schema
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
# --- programmable fake cursor/connection ------------------------------------
|
|
17
|
+
|
|
18
|
+
class FakeCursor:
|
|
19
|
+
"""Replays a queue of (description, rows) results across execute() calls.
|
|
20
|
+
|
|
21
|
+
Each execute() advances to the next queued result; description/fetchall
|
|
22
|
+
reflect the most recent execute. This models pyodbc's behaviour where the
|
|
23
|
+
same cursor is reused for several queries (as schema._emit_table does).
|
|
24
|
+
"""
|
|
25
|
+
|
|
26
|
+
def __init__(self, results):
|
|
27
|
+
self._results = list(results) # list[(description, rows)]
|
|
28
|
+
self._i = -1
|
|
29
|
+
self.executed = []
|
|
30
|
+
|
|
31
|
+
def execute(self, sql, *params):
|
|
32
|
+
self.executed.append((sql, params))
|
|
33
|
+
if self._i + 1 < len(self._results):
|
|
34
|
+
self._i += 1
|
|
35
|
+
|
|
36
|
+
@property
|
|
37
|
+
def description(self):
|
|
38
|
+
if self._i < 0:
|
|
39
|
+
return None
|
|
40
|
+
return self._results[self._i][0]
|
|
41
|
+
|
|
42
|
+
def fetchall(self):
|
|
43
|
+
if self._i < 0:
|
|
44
|
+
return []
|
|
45
|
+
return list(self._results[self._i][1])
|
|
46
|
+
|
|
47
|
+
def fetchone(self):
|
|
48
|
+
rows = self.fetchall()
|
|
49
|
+
return rows[0] if rows else None
|
|
50
|
+
|
|
51
|
+
def close(self):
|
|
52
|
+
pass
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
class FakeConn:
|
|
56
|
+
"""Hands out a queued cursor on each .cursor() call."""
|
|
57
|
+
|
|
58
|
+
def __init__(self, cursor_queue):
|
|
59
|
+
self._queue = list(cursor_queue)
|
|
60
|
+
self.cursors = []
|
|
61
|
+
self.closed = False
|
|
62
|
+
|
|
63
|
+
def cursor(self):
|
|
64
|
+
cur = self._queue.pop(0)
|
|
65
|
+
self.cursors.append(cur)
|
|
66
|
+
return cur
|
|
67
|
+
|
|
68
|
+
def close(self):
|
|
69
|
+
self.closed = True
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
def _desc(*names):
|
|
73
|
+
return [(n, None) for n in names]
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
# --- a profile must exist for needs_conn actions ----------------------------
|
|
77
|
+
|
|
78
|
+
@pytest.fixture
|
|
79
|
+
def one_profile(tmp_path, monkeypatch):
|
|
80
|
+
from tools._lib import dbprofiles
|
|
81
|
+
|
|
82
|
+
pfile = tmp_path / "profiles.json"
|
|
83
|
+
monkeypatch.setattr(main, "PROFILES_PATH", pfile)
|
|
84
|
+
monkeypatch.setattr(dbprofiles.creds, "has", lambda *a: False)
|
|
85
|
+
monkeypatch.setattr(dbprofiles.creds, "get_optional", lambda *a: None)
|
|
86
|
+
main._store().add("default", {"server": "h", "database": "d", "username": "u"})
|
|
87
|
+
return pfile
|
|
88
|
+
|
|
89
|
+
|
|
90
|
+
# ===========================================================================
|
|
91
|
+
# extract_objects against a fake cursor
|
|
92
|
+
# ===========================================================================
|
|
93
|
+
|
|
94
|
+
# canned module rows: a proc, a scalar function, a view, a trigger, plus an
|
|
95
|
+
# is_ms_shipped-style row already excluded by SQL, and an encrypted (NULL body).
|
|
96
|
+
_MODULE_DESC = _desc("schema_name", "object_name", "type_code", "type_desc", "body")
|
|
97
|
+
_MODULE_ROWS = [
|
|
98
|
+
("dbo", "GetCustomer", "P ", "SQL_STORED_PROCEDURE",
|
|
99
|
+
"CREATE PROCEDURE dbo.GetCustomer AS SELECT 1\r\n"),
|
|
100
|
+
("dbo", "fnTax", "FN", "SQL_SCALAR_FUNCTION",
|
|
101
|
+
"CREATE FUNCTION dbo.fnTax() RETURNS int AS BEGIN RETURN 1 END"),
|
|
102
|
+
("dbo", "vCustomer", "V", "VIEW", "CREATE VIEW dbo.vCustomer AS SELECT 1 AS x"),
|
|
103
|
+
("dbo", "trAudit", "TR", "SQL_TRIGGER", "CREATE TRIGGER dbo.trAudit ON dbo.t AFTER INSERT AS SELECT 1"),
|
|
104
|
+
("dbo", "secret", "P", "SQL_STORED_PROCEDURE", None), # encrypted -> NULL body
|
|
105
|
+
]
|
|
106
|
+
|
|
107
|
+
|
|
108
|
+
def _modules_only_conn():
|
|
109
|
+
return FakeConn([FakeCursor([(_MODULE_DESC, _MODULE_ROWS)])])
|
|
110
|
+
|
|
111
|
+
|
|
112
|
+
def test_extract_modules_verbatim_and_labels():
|
|
113
|
+
recs = schema.extract_modules(_modules_only_conn())
|
|
114
|
+
by_name = {r["name"]: r for r in recs}
|
|
115
|
+
assert by_name["GetCustomer"]["type"] == "Procedures"
|
|
116
|
+
assert by_name["fnTax"]["type"] == "Functions"
|
|
117
|
+
assert by_name["vCustomer"]["type"] == "Views"
|
|
118
|
+
assert by_name["trAudit"]["type"] == "Triggers"
|
|
119
|
+
# CRLF normalised to LF, verbatim body preserved
|
|
120
|
+
assert by_name["GetCustomer"]["definition"] == "CREATE PROCEDURE dbo.GetCustomer AS SELECT 1\n"
|
|
121
|
+
# encrypted object surfaces a NOTE placeholder rather than being dropped
|
|
122
|
+
assert "definition unavailable" in by_name["secret"]["definition"]
|
|
123
|
+
|
|
124
|
+
|
|
125
|
+
# --- table DDL generation ---------------------------------------------------
|
|
126
|
+
|
|
127
|
+
_TABLES_DESC = _desc("object_id", "schema_name", "table_name")
|
|
128
|
+
_TABLES_ROWS = [(10, "dbo", "Customer")]
|
|
129
|
+
|
|
130
|
+
_COLUMNS_DESC = _desc(
|
|
131
|
+
"column_id", "column_name", "type_name", "max_length", "precision", "scale",
|
|
132
|
+
"is_nullable", "is_identity", "seed_value", "increment_value", "collation_name",
|
|
133
|
+
"computed_definition", "is_persisted", "default_definition", "default_name",
|
|
134
|
+
"is_computed",
|
|
135
|
+
)
|
|
136
|
+
_COLUMNS_ROWS = [
|
|
137
|
+
# Id INT IDENTITY(1,1) NOT NULL
|
|
138
|
+
(1, "Id", "int", 4, 10, 0, 0, 1, "1", "1", None, None, 0, None, None, 0),
|
|
139
|
+
# Name nvarchar(100) NOT NULL with a default
|
|
140
|
+
(2, "Name", "nvarchar", 200, 0, 0, 0, 0, None, None, "Latin1_General_CI_AS",
|
|
141
|
+
None, 0, "('x')", "DF_Customer_Name", 0),
|
|
142
|
+
# Notes nvarchar(MAX) NULL
|
|
143
|
+
(3, "Notes", "nvarchar", -1, 0, 0, 1, 0, None, None, "Latin1_General_CI_AS",
|
|
144
|
+
None, 0, None, None, 0),
|
|
145
|
+
]
|
|
146
|
+
|
|
147
|
+
_PK_DESC = _desc("constraint_name", "type_desc", "column_name", "is_descending_key", "key_ordinal")
|
|
148
|
+
_PK_ROWS = [("PK_Customer", "CLUSTERED", "Id", 0, 1)]
|
|
149
|
+
|
|
150
|
+
_INDEX_DESC = _desc("index_id", "index_name", "type_desc", "is_unique",
|
|
151
|
+
"filter_definition", "column_name", "is_descending_key",
|
|
152
|
+
"is_included_column", "key_ordinal")
|
|
153
|
+
_INDEX_ROWS = [(2, "IX_Customer_Name", "NONCLUSTERED", 0, None, "Name", 0, 0, 1)]
|
|
154
|
+
|
|
155
|
+
_FK_DESC = _desc("fk_name", "ref_schema", "ref_table", "parent_column", "ref_column",
|
|
156
|
+
"delete_referential_action_desc", "update_referential_action_desc",
|
|
157
|
+
"constraint_column_id")
|
|
158
|
+
_FK_ROWS = [("FK_Customer_Region", "dbo", "Region", "RegionId", "Id",
|
|
159
|
+
"NO_ACTION", "NO_ACTION", 1)]
|
|
160
|
+
|
|
161
|
+
_CHECK_DESC = _desc("constraint_name", "definition", "is_disabled")
|
|
162
|
+
_CHECK_ROWS = []
|
|
163
|
+
|
|
164
|
+
|
|
165
|
+
def _tables_conn():
|
|
166
|
+
# extract_tables: 1 cursor for the TABLES list, then one cursor reused for the
|
|
167
|
+
# five per-table queries (columns, pk, index, fk, check).
|
|
168
|
+
tables_cur = FakeCursor([(_TABLES_DESC, _TABLES_ROWS)])
|
|
169
|
+
table_detail_cur = FakeCursor([
|
|
170
|
+
(_COLUMNS_DESC, _COLUMNS_ROWS),
|
|
171
|
+
(_PK_DESC, _PK_ROWS),
|
|
172
|
+
(_INDEX_DESC, _INDEX_ROWS),
|
|
173
|
+
(_FK_DESC, _FK_ROWS),
|
|
174
|
+
(_CHECK_DESC, _CHECK_ROWS),
|
|
175
|
+
])
|
|
176
|
+
return FakeConn([tables_cur, table_detail_cur])
|
|
177
|
+
|
|
178
|
+
|
|
179
|
+
def test_extract_tables_generates_create_ddl():
|
|
180
|
+
recs = schema.extract_tables(_tables_conn())
|
|
181
|
+
assert len(recs) == 1
|
|
182
|
+
rec = recs[0]
|
|
183
|
+
assert rec["type"] == "Tables"
|
|
184
|
+
assert rec["schema"] == "dbo" and rec["name"] == "Customer"
|
|
185
|
+
ddl = rec["definition"]
|
|
186
|
+
assert "CREATE TABLE [dbo].[Customer]" in ddl
|
|
187
|
+
assert "[Id] int IDENTITY(1,1) NOT NULL" in ddl
|
|
188
|
+
assert "[Name] nvarchar(100)" in ddl # 200 bytes / 2 = 100 chars
|
|
189
|
+
# nvarchar(MAX), nullable, with collation between type and nullability
|
|
190
|
+
assert "[Notes] nvarchar(MAX)" in ddl
|
|
191
|
+
assert "[Notes] nvarchar(MAX) COLLATE Latin1_General_CI_AS NULL" in ddl
|
|
192
|
+
assert "CONSTRAINT [PK_Customer] PRIMARY KEY CLUSTERED ([Id])" in ddl
|
|
193
|
+
assert "CREATE NONCLUSTERED INDEX [IX_Customer_Name]" in ddl
|
|
194
|
+
assert "ADD CONSTRAINT [FK_Customer_Region] FOREIGN KEY ([RegionId])" in ddl
|
|
195
|
+
assert "REFERENCES [dbo].[Region] ([Id])" in ddl
|
|
196
|
+
|
|
197
|
+
|
|
198
|
+
def test_extract_objects_types_filter_modules_only():
|
|
199
|
+
# only modules cursor needed when U is excluded
|
|
200
|
+
recs = schema.extract_objects(_modules_only_conn(), types=["P", "V"])
|
|
201
|
+
labels = {r["type"] for r in recs}
|
|
202
|
+
# Procedures + Views kept; Functions/Triggers dropped by the family filter
|
|
203
|
+
assert "Procedures" in labels and "Views" in labels
|
|
204
|
+
assert "Functions" not in labels and "Triggers" not in labels
|
|
205
|
+
assert "Tables" not in labels
|
|
206
|
+
|
|
207
|
+
|
|
208
|
+
# ===========================================================================
|
|
209
|
+
# schema-extract dispatch -> writes a mirror under tmp_path
|
|
210
|
+
# ===========================================================================
|
|
211
|
+
|
|
212
|
+
def test_dispatch_schema_extract_writes_mirror(one_profile, tmp_path):
|
|
213
|
+
out = tmp_path / "mirror"
|
|
214
|
+
conn = _modules_only_conn()
|
|
215
|
+
result = main.dispatch(
|
|
216
|
+
"schema-extract",
|
|
217
|
+
["--profile", "default", "--types", "P,V,FN,TR", "--out", str(out)],
|
|
218
|
+
conn_factory=lambda _p: conn,
|
|
219
|
+
)
|
|
220
|
+
assert result["profile"] == "default"
|
|
221
|
+
# proc, fn, view, trigger + the encrypted "secret" proc (NULL body -> NOTE placeholder,
|
|
222
|
+
# still a record). --types P,V,FN,TR keeps all 5 module objects.
|
|
223
|
+
assert result["written"] == 5
|
|
224
|
+
assert (out / "_manifest.json").is_file()
|
|
225
|
+
proc = out / "schema" / "Procedures" / "dbo.GetCustomer.sql"
|
|
226
|
+
assert proc.is_file()
|
|
227
|
+
assert proc.read_text(encoding="utf-8").startswith("CREATE PROCEDURE")
|
|
228
|
+
assert conn.closed is True
|
|
229
|
+
|
|
230
|
+
|
|
231
|
+
def test_dispatch_schema_extract_dry_run_writes_nothing(one_profile, tmp_path):
|
|
232
|
+
out = tmp_path / "mirror"
|
|
233
|
+
result = main.dispatch(
|
|
234
|
+
"schema-extract",
|
|
235
|
+
["--profile", "default", "--types", "P", "--out", str(out), "--dry-run"],
|
|
236
|
+
conn_factory=lambda _p: _modules_only_conn(),
|
|
237
|
+
)
|
|
238
|
+
assert result["dry_run"] is True
|
|
239
|
+
assert not out.exists()
|
|
240
|
+
|
|
241
|
+
|
|
242
|
+
# ===========================================================================
|
|
243
|
+
# schema-diff dir-vs-dir (no DB)
|
|
244
|
+
# ===========================================================================
|
|
245
|
+
|
|
246
|
+
def _make_mirror(root, files):
|
|
247
|
+
schema_root = root / "schema"
|
|
248
|
+
for rel, text in files.items():
|
|
249
|
+
p = schema_root / rel
|
|
250
|
+
p.parent.mkdir(parents=True, exist_ok=True)
|
|
251
|
+
p.write_text(text, encoding="utf-8")
|
|
252
|
+
|
|
253
|
+
|
|
254
|
+
def test_dispatch_schema_diff_dirs(tmp_path):
|
|
255
|
+
left = tmp_path / "left"
|
|
256
|
+
right = tmp_path / "right"
|
|
257
|
+
_make_mirror(left, {
|
|
258
|
+
"Procedures/dbo.A.sql": "CREATE PROC A AS SELECT 1\n",
|
|
259
|
+
"Views/dbo.Gone.sql": "CREATE VIEW Gone AS SELECT 1\n",
|
|
260
|
+
})
|
|
261
|
+
_make_mirror(right, {
|
|
262
|
+
"Procedures/dbo.A.sql": "CREATE PROC A AS SELECT 2\n", # changed
|
|
263
|
+
"Views/dbo.New.sql": "CREATE VIEW New AS SELECT 1\n", # added
|
|
264
|
+
})
|
|
265
|
+
result = main.dispatch("schema-diff", ["--left", str(left), "--right", str(right)])
|
|
266
|
+
assert result["summary"] == {"added": 1, "removed": 1, "changed": 1}
|
|
267
|
+
assert "schema/Views/dbo.New.sql" in result["added"]
|
|
268
|
+
assert "schema/Views/dbo.Gone.sql" in result["removed"]
|
|
269
|
+
assert result["changed"][0]["relpath"] == "schema/Procedures/dbo.A.sql"
|
|
270
|
+
assert "diff" in result["changed"][0] # unified diff present by default
|
|
271
|
+
|
|
272
|
+
|
|
273
|
+
def test_dispatch_schema_diff_no_diff_text(tmp_path):
|
|
274
|
+
left = tmp_path / "l"
|
|
275
|
+
right = tmp_path / "r"
|
|
276
|
+
_make_mirror(left, {"Procedures/dbo.A.sql": "x\n"})
|
|
277
|
+
_make_mirror(right, {"Procedures/dbo.A.sql": "y\n"})
|
|
278
|
+
result = main.dispatch(
|
|
279
|
+
"schema-diff",
|
|
280
|
+
["--left", str(left), "--right", str(right), "--no-diff-text"],
|
|
281
|
+
)
|
|
282
|
+
assert result["changed"][0]["relpath"] == "schema/Procedures/dbo.A.sql"
|
|
283
|
+
assert "diff" not in result["changed"][0]
|
|
284
|
+
|
|
285
|
+
|
|
286
|
+
def test_dispatch_schema_diff_profile_side_extracts(one_profile, tmp_path):
|
|
287
|
+
# left is a live profile (extracted via the fake cursor), right is an empty dir
|
|
288
|
+
right = tmp_path / "right"
|
|
289
|
+
(right / "schema").mkdir(parents=True)
|
|
290
|
+
result = main.dispatch(
|
|
291
|
+
"schema-diff",
|
|
292
|
+
["--left", "profile:default", "--right", str(right), "--types", "P,V,FN,TR"],
|
|
293
|
+
conn_factory=lambda _p: _modules_only_conn(),
|
|
294
|
+
)
|
|
295
|
+
# everything in the extracted left is "removed" relative to the empty right
|
|
296
|
+
assert result["summary"]["added"] == 0
|
|
297
|
+
assert result["summary"]["removed"] >= 4
|
|
298
|
+
|
|
299
|
+
|
|
300
|
+
# ===========================================================================
|
|
301
|
+
# migrate
|
|
302
|
+
# ===========================================================================
|
|
303
|
+
|
|
304
|
+
class MigrateConn:
|
|
305
|
+
"""Fake connection for migrate: ensure-table is a no-op execute, then a SELECT
|
|
306
|
+
on the tracking table returns canned applied rows."""
|
|
307
|
+
|
|
308
|
+
def __init__(self, applied_rows, exists=True):
|
|
309
|
+
self._applied_rows = applied_rows
|
|
310
|
+
self._exists = exists
|
|
311
|
+
self.executed = []
|
|
312
|
+
|
|
313
|
+
def cursor(self):
|
|
314
|
+
return self # the conn is its own cursor for simplicity
|
|
315
|
+
|
|
316
|
+
def execute(self, sql, *params):
|
|
317
|
+
self.executed.append((sql, params))
|
|
318
|
+
self._last = sql
|
|
319
|
+
|
|
320
|
+
def fetchall(self):
|
|
321
|
+
if "SELECT migration_id" in self._last:
|
|
322
|
+
return list(self._applied_rows)
|
|
323
|
+
return []
|
|
324
|
+
|
|
325
|
+
def fetchone(self):
|
|
326
|
+
# tracking_table_exists probes sys.tables; report existence per self._exists.
|
|
327
|
+
if "sys.tables" in self._last:
|
|
328
|
+
return (1,) if self._exists else None
|
|
329
|
+
return None
|
|
330
|
+
|
|
331
|
+
def close(self):
|
|
332
|
+
pass
|
|
333
|
+
|
|
334
|
+
|
|
335
|
+
def _write_migrations(d, files):
|
|
336
|
+
d.mkdir(parents=True, exist_ok=True)
|
|
337
|
+
for name, text in files.items():
|
|
338
|
+
(d / name).write_text(text, encoding="utf-8")
|
|
339
|
+
|
|
340
|
+
|
|
341
|
+
def test_migrate_list_applied_and_pending(one_profile, tmp_path):
|
|
342
|
+
mig_dir = tmp_path / "migrations"
|
|
343
|
+
_write_migrations(mig_dir, {
|
|
344
|
+
"001_init.sql": "CREATE TABLE dbo.A (id int);\n",
|
|
345
|
+
"002_drop.sql": "DROP TABLE dbo.A;\n",
|
|
346
|
+
})
|
|
347
|
+
# 001 already applied (matching sha so no drift); 002 pending
|
|
348
|
+
sha001 = dbschema.sha256_file(mig_dir / "001_init.sql")
|
|
349
|
+
applied = [("001_init", sha001, "001_init.sql", "2026-01-01T00:00:00")]
|
|
350
|
+
result = main.dispatch(
|
|
351
|
+
"migrate",
|
|
352
|
+
["--profile", "default", "--dir", str(mig_dir), "--mode", "list"],
|
|
353
|
+
conn_factory=lambda _p: MigrateConn(applied),
|
|
354
|
+
)
|
|
355
|
+
assert result["mode"] == "list"
|
|
356
|
+
assert [a["migration_id"] for a in result["applied"]] == ["001_init"]
|
|
357
|
+
assert [p["migration_id"] for p in result["pending"]] == ["002_drop"]
|
|
358
|
+
assert result["drift"] == []
|
|
359
|
+
# the pending DROP migration carries a danger warning
|
|
360
|
+
assert any("destructive" in w for w in result["pending"][0]["danger_warnings"])
|
|
361
|
+
|
|
362
|
+
|
|
363
|
+
def test_migrate_list_is_read_only_even_without_tracking_table(one_profile, tmp_path):
|
|
364
|
+
"""`list` must NEVER create the tracking table (read-only on production DBs)."""
|
|
365
|
+
mig_dir = tmp_path / "migrations"
|
|
366
|
+
_write_migrations(mig_dir, {"001_init.sql": "SELECT 1;\n"})
|
|
367
|
+
conn = MigrateConn([], exists=False) # tracking table does not exist
|
|
368
|
+
result = main.dispatch(
|
|
369
|
+
"migrate", ["--profile", "default", "--dir", str(mig_dir), "--mode", "list"],
|
|
370
|
+
conn_factory=lambda _p: conn)
|
|
371
|
+
assert result["applied"] == [] and len(result["pending"]) == 1
|
|
372
|
+
assert not any("CREATE TABLE" in sql.upper() for sql, _ in conn.executed)
|
|
373
|
+
|
|
374
|
+
|
|
375
|
+
def test_migrate_list_detects_drift(one_profile, tmp_path):
|
|
376
|
+
mig_dir = tmp_path / "migrations"
|
|
377
|
+
_write_migrations(mig_dir, {"001_init.sql": "SELECT 1;\n"})
|
|
378
|
+
applied = [("001_init", "deadbeef" * 8, "001_init.sql", "2026-01-01T00:00:00")]
|
|
379
|
+
result = main.dispatch(
|
|
380
|
+
"migrate",
|
|
381
|
+
["--profile", "default", "--dir", str(mig_dir), "--mode", "list"],
|
|
382
|
+
conn_factory=lambda _p: MigrateConn(applied),
|
|
383
|
+
)
|
|
384
|
+
assert len(result["drift"]) == 1
|
|
385
|
+
assert result["drift"][0]["migration_id"] == "001_init"
|
|
386
|
+
|
|
387
|
+
|
|
388
|
+
def test_migrate_apply_requires_apply_flag(one_profile, tmp_path):
|
|
389
|
+
mig_dir = tmp_path / "migrations"
|
|
390
|
+
_write_migrations(mig_dir, {"001_init.sql": "SELECT 1;\n"})
|
|
391
|
+
with pytest.raises(main.UsageError, match="--apply"):
|
|
392
|
+
main.dispatch(
|
|
393
|
+
"migrate",
|
|
394
|
+
["--profile", "default", "--dir", str(mig_dir), "--mode", "apply"],
|
|
395
|
+
conn_factory=lambda _p: MigrateConn([]),
|
|
396
|
+
)
|
|
397
|
+
|
|
398
|
+
|
|
399
|
+
def test_migrate_apply_runs_pending(one_profile, tmp_path):
|
|
400
|
+
mig_dir = tmp_path / "migrations"
|
|
401
|
+
_write_migrations(mig_dir, {
|
|
402
|
+
"001_init.sql": "CREATE TABLE dbo.A (id int);\nGO\nINSERT INTO dbo.A VALUES (1);\n",
|
|
403
|
+
})
|
|
404
|
+
conn = MigrateConn([])
|
|
405
|
+
result = main.dispatch(
|
|
406
|
+
"migrate",
|
|
407
|
+
["--profile", "default", "--dir", str(mig_dir), "--mode", "apply", "--apply"],
|
|
408
|
+
conn_factory=lambda _p: conn,
|
|
409
|
+
)
|
|
410
|
+
assert result["applied_now"] == 1
|
|
411
|
+
assert result["results"][0]["status"] == "applied"
|
|
412
|
+
assert result["results"][0]["batches"] == 2 # GO split into 2 batches
|
|
413
|
+
# a tracking INSERT was issued
|
|
414
|
+
assert any("INSERT INTO" in sql and "__schema_migrations" in sql
|
|
415
|
+
for sql, _ in conn.executed)
|
|
416
|
+
|
|
417
|
+
|
|
418
|
+
def test_migrate_apply_dry_run_does_not_record(one_profile, tmp_path):
|
|
419
|
+
mig_dir = tmp_path / "migrations"
|
|
420
|
+
_write_migrations(mig_dir, {"001_init.sql": "SELECT 1;\n"})
|
|
421
|
+
conn = MigrateConn([])
|
|
422
|
+
result = main.dispatch(
|
|
423
|
+
"migrate",
|
|
424
|
+
["--profile", "default", "--dir", str(mig_dir),
|
|
425
|
+
"--mode", "apply", "--apply", "--dry-run"],
|
|
426
|
+
conn_factory=lambda _p: conn,
|
|
427
|
+
)
|
|
428
|
+
assert result["dry_run"] is True
|
|
429
|
+
assert result["results"][0]["status"] == "dry-run-ok"
|
|
430
|
+
# no tracking INSERT in dry-run
|
|
431
|
+
assert not any("INSERT INTO" in sql and "__schema_migrations" in sql
|
|
432
|
+
for sql, _ in conn.executed)
|
|
433
|
+
# but a ROLLBACK was issued for the file's transaction
|
|
434
|
+
assert any("ROLLBACK" in sql for sql, _ in conn.executed)
|
|
435
|
+
|
|
436
|
+
|
|
437
|
+
class BatchCursor:
|
|
438
|
+
"""Fake connection + cursor for apply_migration_sql. execute() opens a batch; the
|
|
439
|
+
results that follow its first one are listed per marker found in the SQL, and an
|
|
440
|
+
Exception among them is raised when nextset() reaches it, as pyodbc does."""
|
|
441
|
+
|
|
442
|
+
def __init__(self, later_results_by_marker):
|
|
443
|
+
self._by_marker = later_results_by_marker
|
|
444
|
+
self._pending = []
|
|
445
|
+
self.executed = []
|
|
446
|
+
|
|
447
|
+
def cursor(self):
|
|
448
|
+
return self
|
|
449
|
+
|
|
450
|
+
def execute(self, sql, *params):
|
|
451
|
+
self.executed.append(sql)
|
|
452
|
+
self._pending = list(next((r for m, r in self._by_marker.items() if m in sql), []))
|
|
453
|
+
|
|
454
|
+
def nextset(self):
|
|
455
|
+
if not self._pending:
|
|
456
|
+
return False
|
|
457
|
+
nxt = self._pending.pop(0)
|
|
458
|
+
if isinstance(nxt, Exception):
|
|
459
|
+
raise nxt
|
|
460
|
+
return True
|
|
461
|
+
|
|
462
|
+
def close(self):
|
|
463
|
+
pass
|
|
464
|
+
|
|
465
|
+
|
|
466
|
+
def test_apply_migration_sql_surfaces_an_error_after_a_row_count():
|
|
467
|
+
# The INSERT answers "1 row affected" first, the THROW after it. Undrained, XACT_ABORT
|
|
468
|
+
# rolled the file back on the server while the tool reported it applied.
|
|
469
|
+
conn = BatchCursor({"INSERT dbo.T": [RuntimeError("check failed (51120)")]})
|
|
470
|
+
with pytest.raises(RuntimeError, match="51120"):
|
|
471
|
+
schema.apply_migration_sql(conn, "INSERT dbo.T VALUES (1);\n;THROW 51120, 'check failed', 1;\n")
|
|
472
|
+
assert any("ROLLBACK" in sql for sql in conn.executed)
|
|
473
|
+
assert not any("COMMIT" in sql for sql in conn.executed)
|
|
474
|
+
|
|
475
|
+
|
|
476
|
+
def test_apply_migration_sql_commits_after_draining_a_clean_batch():
|
|
477
|
+
conn = BatchCursor({"INSERT dbo.T": ["1 row affected"]})
|
|
478
|
+
assert schema.apply_migration_sql(conn, "INSERT dbo.T VALUES (1);\nINSERT dbo.T VALUES (2);\n") == 1
|
|
479
|
+
assert conn.executed[-1] == "IF @@TRANCOUNT > 0 COMMIT TRANSACTION;"
|
|
480
|
+
|
|
481
|
+
|
|
482
|
+
def test_tracking_table_is_unicode_with_a_named_primary_key():
|
|
483
|
+
# Databases that hold only nvarchar must not get a varchar column from the tool itself, and a
|
|
484
|
+
# system-named PK (PK____schema__<hash>) differs per database and breaks a parity compare.
|
|
485
|
+
import re
|
|
486
|
+
ddl = schema._ENSURE_TABLE_SQL
|
|
487
|
+
assert not re.search(r"(?<![N\w])(VAR)?CHAR\s*\(", ddl, re.I)
|
|
488
|
+
assert "CONSTRAINT PK___schema_migrations PRIMARY KEY" in ddl
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
name: sqlserver
|
|
2
|
+
description: Read-only SQL Server queries over pyodbc with named connection profiles. SELECT-only by default (--write to override); returns rows as JSON; schema/table introspection.
|
|
3
|
+
version: 0.1.0
|
|
4
|
+
runtime: python
|
|
5
|
+
entrypoint: main.py
|
|
6
|
+
|
|
7
|
+
# Secrets are PER-PROFILE and dynamic, so none are declared here.
|
|
8
|
+
# Each profile's password lives in Windows Credential Manager under
|
|
9
|
+
# agents-and-tools:sqlserver:<profile-name> and is read at runtime via
|
|
10
|
+
# tools._lib.creds.get("sqlserver", <profile>). Set one with:
|
|
11
|
+
# python scripts/set-credential.py sqlserver <profile>
|
|
12
|
+
# Non-secret profile config (server/database/username/driver/tls) lives in
|
|
13
|
+
# this tool's profiles.json — never the password.
|
|
14
|
+
secrets: []
|
|
15
|
+
|
|
16
|
+
routing:
|
|
17
|
+
triggers:
|
|
18
|
+
- run a SQL Server query
|
|
19
|
+
- query a SQL Server / MSSQL database
|
|
20
|
+
- read a table from SQL Server
|
|
21
|
+
- list SQL Server tables or columns
|
|
22
|
+
primary_action: query
|
|
23
|
+
example: sqlserver query --profile default --sql "SELECT TOP 10 * FROM dbo.Customer"
|
|
24
|
+
|
|
25
|
+
actions:
|
|
26
|
+
- name: profiles
|
|
27
|
+
description: List configured connection profiles (no passwords).
|
|
28
|
+
args: []
|
|
29
|
+
output_schema: '{ "count": N, "profiles": [ {name, server, database, ..., has_password} ] }'
|
|
30
|
+
|
|
31
|
+
- name: add-profile
|
|
32
|
+
description: Store a connection profile (config only; set the password separately via set-credential).
|
|
33
|
+
args:
|
|
34
|
+
- {name: name, type: string, required: true, description: Profile name (also the credential name)}
|
|
35
|
+
- {name: server, type: string, required: true, description: "Host, host\\instance, or fqdn"}
|
|
36
|
+
- {name: database, type: string, description: "Default database (optional; one profile can serve many DBs - pick per call with --database)"}
|
|
37
|
+
- {name: username, type: string, description: SQL login (omit for a trusted/Windows connection)}
|
|
38
|
+
- {name: port, type: integer, description: "TCP port (appended as server,port)"}
|
|
39
|
+
- {name: driver, type: string, description: ODBC driver name (default = newest ODBC Driver for SQL Server installed on this machine)}
|
|
40
|
+
- {name: encrypt, type: string, description: Encrypt the connection - yes or no (default yes)}
|
|
41
|
+
- {name: trust-server-certificate, type: string, description: Trust a self-signed cert - yes or no (default no)}
|
|
42
|
+
- {name: connect-timeout, type: integer, description: Connect timeout seconds (default 30)}
|
|
43
|
+
- {name: statement-timeout, type: integer, description: "Statement timeout seconds, 0=unbounded (default 300)"}
|
|
44
|
+
- {name: overwrite, type: boolean, description: Replace an existing profile}
|
|
45
|
+
output_schema: '{ "name": "...", "server": "...", "database": "...", "has_password": false, "note": "..." }'
|
|
46
|
+
|
|
47
|
+
- name: test-connection
|
|
48
|
+
description: Connect and return the masked connection string + server version (never the password).
|
|
49
|
+
args:
|
|
50
|
+
- {name: profile, type: string, required: true, description: Profile name}
|
|
51
|
+
output_schema: '{ "profile": "...", "connection_string": "...PWD=***...", "server_version": "...", "connected": true }'
|
|
52
|
+
|
|
53
|
+
- name: query
|
|
54
|
+
description: Run read-only SQL (SELECT by default; --write allows non-SELECT). Params bound via ? placeholders, never interpolated.
|
|
55
|
+
args:
|
|
56
|
+
- {name: profile, type: string, required: true, description: Profile name}
|
|
57
|
+
- {name: sql, type: string, required: true, description: SQL statement}
|
|
58
|
+
- {name: params, type: string, description: "Parameter values as a JSON array, bound via ? placeholders"}
|
|
59
|
+
- {name: max-rows, type: integer, description: Cap rows returned (default 1000; 0=unbounded)}
|
|
60
|
+
- {name: write, type: boolean, description: Allow a non-SELECT/DDL/multi statement (off by default)}
|
|
61
|
+
- {name: database, type: string, description: Run against this database instead of the profile's}
|
|
62
|
+
- {name: no-normalize-eol, type: boolean, description: "Keep SQL line endings as-is (default: normalize to CRLF so CREATE/ALTER object definitions store consistent EOLs and SSMS does not flag inconsistent line endings)"}
|
|
63
|
+
output_schema: '{ "columns": [...], "rows": [ {...} ], "row_count": N, "truncated": false, "write": false, "eol_normalized": true }'
|
|
64
|
+
|
|
65
|
+
- name: tables
|
|
66
|
+
description: List tables and views, optionally restricted to one schema.
|
|
67
|
+
args:
|
|
68
|
+
- {name: profile, type: string, required: true, description: Profile name}
|
|
69
|
+
- {name: database, type: string, description: List tables from this database instead of the profile's}
|
|
70
|
+
- {name: schema, type: string, description: Restrict to one schema}
|
|
71
|
+
output_schema: '{ "profile": "...", "count": N, "tables": [ {TABLE_SCHEMA, TABLE_NAME, TABLE_TYPE} ] }'
|
|
72
|
+
|
|
73
|
+
- name: columns
|
|
74
|
+
description: List a table's columns (name, type, nullable, length, default).
|
|
75
|
+
args:
|
|
76
|
+
- {name: profile, type: string, required: true, description: Profile name}
|
|
77
|
+
- {name: database, type: string, description: Read columns from this database instead of the profile's}
|
|
78
|
+
- {name: table, type: string, required: true, description: Table name (schema.table or table)}
|
|
79
|
+
output_schema: '{ "profile": "...", "table": "...", "count": N, "columns": [ {COLUMN_NAME, DATA_TYPE, IS_NULLABLE, ...} ] }'
|
|
80
|
+
|
|
81
|
+
- name: schema-extract
|
|
82
|
+
description: Mirror all DB objects to local .sql files (one per object; incremental; read-only).
|
|
83
|
+
args:
|
|
84
|
+
- {name: profile, type: string, required: true, description: Profile name}
|
|
85
|
+
- {name: database, type: string, description: Extract this database instead of the profile's}
|
|
86
|
+
- {name: out, type: string, description: "Mirror output directory (default ./db-mirror/<profile>)"}
|
|
87
|
+
- {name: types, type: string, description: "Comma-separated type letters to extract (P,FN,TF,IF,V,TR,U); default all"}
|
|
88
|
+
- {name: full, type: boolean, description: Wipe the mirror and re-extract everything}
|
|
89
|
+
- {name: dry-run, type: boolean, description: Report what would change without writing}
|
|
90
|
+
output_schema: '{ "profile": "...", "database": "...", "out": "...", "written": N, "unchanged": N, "removed": N, "total": N, "by_type": {}, "dry_run": false }'
|
|
91
|
+
|
|
92
|
+
- name: schema-diff
|
|
93
|
+
description: Diff two schema mirrors or live profiles (objects added/removed/changed + unified diffs). Read-only.
|
|
94
|
+
args:
|
|
95
|
+
- {name: left, type: string, required: true, description: "Mirror directory OR profile:NAME for the left side"}
|
|
96
|
+
- {name: right, type: string, required: true, description: "Mirror directory OR profile:NAME for the right side"}
|
|
97
|
+
- {name: database-left, type: string, description: Database override when --left is a profile}
|
|
98
|
+
- {name: database-right, type: string, description: Database override when --right is a profile}
|
|
99
|
+
- {name: types, type: string, description: "Comma-separated type letters to extract for profile sides (P,FN,TF,IF,V,TR,U); default all"}
|
|
100
|
+
- {name: no-diff-text, type: boolean, description: Only list added/removed/changed names (omit unified diffs)}
|
|
101
|
+
output_schema: '{ "added": [...], "removed": [...], "changed": [ {relpath, diff} ], "unchanged": N, "identical": false, "summary": {added, removed, changed} }'
|
|
102
|
+
|
|
103
|
+
- name: migrate
|
|
104
|
+
description: List or apply versioned .sql migrations (forward-only; tracking table; apply gated behind --apply). list is read-only and the default.
|
|
105
|
+
args:
|
|
106
|
+
- {name: profile, type: string, required: true, description: Profile name}
|
|
107
|
+
- {name: database, type: string, description: Migrate this database instead of the profile's}
|
|
108
|
+
- {name: dir, type: string, description: "Migrations directory (default ./db-migrations/<profile>)"}
|
|
109
|
+
- {name: mode, type: string, description: "list (read-only; default) or apply (writes)"}
|
|
110
|
+
- {name: dry-run, type: boolean, description: Apply each pending file in a rolled-back transaction (no persist)}
|
|
111
|
+
- {name: apply, type: boolean, description: "Required confirmation for --mode apply (this writes)"}
|
|
112
|
+
- {name: accept-drift, type: boolean, description: Proceed with apply even if applied files drifted on disk}
|
|
113
|
+
output_schema: '{ "profile": "...", "mode": "list", "applied": [...], "pending": [ {migration_id, filename, danger_warnings} ], "drift": [...], "results": [...] }'
|
|
114
|
+
|
|
115
|
+
requires:
|
|
116
|
+
- name: odbc-sqlserver
|
|
117
|
+
kind: driver
|
|
118
|
+
why: >
|
|
119
|
+
pyodbc ships in the venv but the Microsoft ODBC driver does not; without it
|
|
120
|
+
every DB action fails with missing_dependency while the tool still loads.
|
|
121
|
+
check: >-
|
|
122
|
+
{python} -c "import pyodbc,sys; sys.exit(0 if [d for d in pyodbc.drivers() if 'SQL Server' in d] else 1)"
|
|
123
|
+
install: winget install --id Microsoft.msodbcsql.18 -e --silent
|