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,600 @@
|
|
|
1
|
+
"""SQL Server engine-specific schema extraction + migration helpers.
|
|
2
|
+
|
|
3
|
+
Provides the driver-touching half of the `schema-extract`, `schema-diff`, and
|
|
4
|
+
`migrate` actions; the pure, engine-agnostic machinery (mirror layout, diff,
|
|
5
|
+
migration discovery / danger / GO split) lives in ``tools/_lib/dbschema.py``.
|
|
6
|
+
|
|
7
|
+
Every function here takes a connection-like object (a real pyodbc connection or
|
|
8
|
+
a test fake) and uses ``conn.cursor()`` directly. The extract path is read-only
|
|
9
|
+
(SELECT against the system catalog). The migrate path is the only writer and is
|
|
10
|
+
gated upstream behind ``--apply``.
|
|
11
|
+
|
|
12
|
+
A "record" is the shared dbschema shape:
|
|
13
|
+
{"type": <dir label>, "schema": <str|"">, "name": <str>, "definition": <sql>}
|
|
14
|
+
|
|
15
|
+
Object types extracted (by the ``sys.objects.type`` letter):
|
|
16
|
+
P procedures -> dir "Procedures" (verbatim sys.sql_modules)
|
|
17
|
+
FN scalar functions -> dir "Functions" (verbatim)
|
|
18
|
+
IF inline TVFs -> dir "Functions" (verbatim)
|
|
19
|
+
TF table-valued functions -> dir "Functions" (verbatim)
|
|
20
|
+
V views -> dir "Views" (verbatim)
|
|
21
|
+
TR DML triggers -> dir "Triggers" (verbatim)
|
|
22
|
+
U user tables -> dir "Tables" (DDL generated from catalog)
|
|
23
|
+
|
|
24
|
+
Module objects (P/FN/IF/TF/V/TR) come VERBATIM from ``sys.sql_modules.definition``
|
|
25
|
+
so the mirror is byte-faithful to what the server stores. Tables (U) have no stored
|
|
26
|
+
"CREATE TABLE" text, so their DDL is generated from the catalog: columns (type,
|
|
27
|
+
nullability, identity, default, collation, computed), primary key, foreign keys,
|
|
28
|
+
non-PK indexes, and check constraints.
|
|
29
|
+
|
|
30
|
+
DEFERRED (v1 — not blocking; port from a sibling schema extractor when needed):
|
|
31
|
+
- CLR assemblies (sys.assemblies) and CLR procs/types
|
|
32
|
+
- user-defined types: scalar alias / table types / CLR types
|
|
33
|
+
- authored schemas (CREATE SCHEMA) and database-scope DDL triggers
|
|
34
|
+
- partitioning / filegroups / XML schema collections / full-text / sequences
|
|
35
|
+
- synonyms, Service Broker objects, extended properties
|
|
36
|
+
"""
|
|
37
|
+
from __future__ import annotations
|
|
38
|
+
|
|
39
|
+
from typing import Any
|
|
40
|
+
|
|
41
|
+
from tools._lib import dbquery, dbschema
|
|
42
|
+
|
|
43
|
+
# ---------------------------------------------------------------------------
|
|
44
|
+
# Type-letter -> readable directory label. The mirror groups objects by this
|
|
45
|
+
# label (dbschema.mirror_relpath uses it as the <Type> folder).
|
|
46
|
+
# ---------------------------------------------------------------------------
|
|
47
|
+
|
|
48
|
+
MODULE_TYPES = {
|
|
49
|
+
"P": "Procedures",
|
|
50
|
+
"FN": "Functions",
|
|
51
|
+
"IF": "Functions",
|
|
52
|
+
"TF": "Functions",
|
|
53
|
+
"V": "Views",
|
|
54
|
+
"TR": "Triggers",
|
|
55
|
+
}
|
|
56
|
+
TABLE_TYPE = "U"
|
|
57
|
+
TABLE_LABEL = "Tables"
|
|
58
|
+
|
|
59
|
+
# All type letters this engine knows how to extract.
|
|
60
|
+
ALL_TYPES = set(MODULE_TYPES) | {TABLE_TYPE}
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
# ---------------------------------------------------------------------------
|
|
64
|
+
# small cursor helpers
|
|
65
|
+
# ---------------------------------------------------------------------------
|
|
66
|
+
|
|
67
|
+
def _rows(cur) -> list[dict[str, Any]]:
|
|
68
|
+
"""Materialise the current cursor result as a list of column->value dicts."""
|
|
69
|
+
cols = [c[0] for c in cur.description]
|
|
70
|
+
return [{cols[i]: r[i] for i in range(len(cols))} for r in cur.fetchall()]
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
def _normalize(text: str) -> str:
|
|
74
|
+
"""Collapse CRLF/CR to LF so hashes are deterministic across hosts.
|
|
75
|
+
|
|
76
|
+
SQL Server returns ``sys.sql_modules.definition`` with CRLF line endings; on
|
|
77
|
+
Windows ``Path.write_text`` would translate ``\\n`` -> ``\\r\\n`` again,
|
|
78
|
+
producing ``\\r\\r\\n``. Normalising to LF here keeps the mirror clean and the
|
|
79
|
+
manifest sha stable (incremental runs short-circuit correctly).
|
|
80
|
+
"""
|
|
81
|
+
return text.replace("\r\n", "\n").replace("\r", "\n")
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
# ---------------------------------------------------------------------------
|
|
85
|
+
# Module objects (procedures / functions / views / triggers) — verbatim
|
|
86
|
+
# ---------------------------------------------------------------------------
|
|
87
|
+
|
|
88
|
+
# One catalog query pulls every module definition. A LEFT JOIN to sys.sql_modules
|
|
89
|
+
# means encrypted (WITH ENCRYPTION) or permission-denied objects come back with a
|
|
90
|
+
# NULL body — surfaced as a comment placeholder rather than dropped silently.
|
|
91
|
+
_MODULES_SQL = """
|
|
92
|
+
SELECT
|
|
93
|
+
SCHEMA_NAME(o.schema_id) AS schema_name,
|
|
94
|
+
o.name AS object_name,
|
|
95
|
+
o.type AS type_code,
|
|
96
|
+
o.type_desc AS type_desc,
|
|
97
|
+
m.definition AS body
|
|
98
|
+
FROM sys.objects o
|
|
99
|
+
LEFT JOIN sys.sql_modules m ON m.object_id = o.object_id
|
|
100
|
+
WHERE o.type IN ('P','FN','TF','IF','V','TR')
|
|
101
|
+
AND o.is_ms_shipped = 0
|
|
102
|
+
ORDER BY SCHEMA_NAME(o.schema_id), o.name;
|
|
103
|
+
"""
|
|
104
|
+
|
|
105
|
+
|
|
106
|
+
def _emit_module(obj: dict[str, Any]) -> str:
|
|
107
|
+
body = obj.get("body")
|
|
108
|
+
schema = obj.get("schema_name") or ""
|
|
109
|
+
name = obj.get("object_name")
|
|
110
|
+
if body is None:
|
|
111
|
+
return (
|
|
112
|
+
f"-- Object: {schema}.{name}\n"
|
|
113
|
+
f"-- Type: {obj.get('type_desc')}\n"
|
|
114
|
+
f"-- NOTE: definition unavailable (encrypted or permission denied)\n"
|
|
115
|
+
)
|
|
116
|
+
body = _normalize(body)
|
|
117
|
+
if not body.endswith("\n"):
|
|
118
|
+
body += "\n"
|
|
119
|
+
return body
|
|
120
|
+
|
|
121
|
+
|
|
122
|
+
def extract_modules(conn) -> list[dict[str, Any]]:
|
|
123
|
+
"""Records for every P/FN/IF/TF/V/TR object, definition VERBATIM."""
|
|
124
|
+
cur = conn.cursor()
|
|
125
|
+
cur.execute(_MODULES_SQL)
|
|
126
|
+
out: list[dict[str, Any]] = []
|
|
127
|
+
for obj in _rows(cur):
|
|
128
|
+
code = (obj.get("type_code") or "").strip()
|
|
129
|
+
label = MODULE_TYPES.get(code)
|
|
130
|
+
if not label:
|
|
131
|
+
continue
|
|
132
|
+
out.append({
|
|
133
|
+
"type": label,
|
|
134
|
+
"schema": obj.get("schema_name") or "",
|
|
135
|
+
"name": obj.get("object_name"),
|
|
136
|
+
"definition": _emit_module(obj),
|
|
137
|
+
})
|
|
138
|
+
return out
|
|
139
|
+
|
|
140
|
+
|
|
141
|
+
# ---------------------------------------------------------------------------
|
|
142
|
+
# Tables — CREATE TABLE DDL generated from the catalog
|
|
143
|
+
# ---------------------------------------------------------------------------
|
|
144
|
+
|
|
145
|
+
_TABLES_SQL = """
|
|
146
|
+
SELECT
|
|
147
|
+
t.object_id,
|
|
148
|
+
SCHEMA_NAME(t.schema_id) AS schema_name,
|
|
149
|
+
t.name AS table_name
|
|
150
|
+
FROM sys.tables t
|
|
151
|
+
WHERE t.is_ms_shipped = 0
|
|
152
|
+
ORDER BY SCHEMA_NAME(t.schema_id), t.name;
|
|
153
|
+
"""
|
|
154
|
+
|
|
155
|
+
_COLUMNS_SQL = """
|
|
156
|
+
SELECT
|
|
157
|
+
c.column_id,
|
|
158
|
+
c.name AS column_name,
|
|
159
|
+
TYPE_NAME(c.user_type_id) AS type_name,
|
|
160
|
+
c.max_length,
|
|
161
|
+
c.precision,
|
|
162
|
+
c.scale,
|
|
163
|
+
c.is_nullable,
|
|
164
|
+
c.is_identity,
|
|
165
|
+
CAST(ic.seed_value AS NVARCHAR(64)) AS seed_value,
|
|
166
|
+
CAST(ic.increment_value AS NVARCHAR(64)) AS increment_value,
|
|
167
|
+
c.collation_name,
|
|
168
|
+
cc.definition AS computed_definition,
|
|
169
|
+
cc.is_persisted,
|
|
170
|
+
dc.definition AS default_definition,
|
|
171
|
+
dc.name AS default_name,
|
|
172
|
+
c.is_computed
|
|
173
|
+
FROM sys.columns c
|
|
174
|
+
LEFT JOIN sys.identity_columns ic ON ic.object_id = c.object_id AND ic.column_id = c.column_id
|
|
175
|
+
LEFT JOIN sys.computed_columns cc ON cc.object_id = c.object_id AND cc.column_id = c.column_id
|
|
176
|
+
LEFT JOIN sys.default_constraints dc
|
|
177
|
+
ON dc.parent_object_id = c.object_id AND dc.parent_column_id = c.column_id
|
|
178
|
+
WHERE c.object_id = ?
|
|
179
|
+
ORDER BY c.column_id;
|
|
180
|
+
"""
|
|
181
|
+
|
|
182
|
+
_PK_SQL = """
|
|
183
|
+
SELECT
|
|
184
|
+
kc.name AS constraint_name,
|
|
185
|
+
i.type_desc,
|
|
186
|
+
c.name AS column_name,
|
|
187
|
+
ic.is_descending_key,
|
|
188
|
+
ic.key_ordinal
|
|
189
|
+
FROM sys.key_constraints kc
|
|
190
|
+
JOIN sys.indexes i ON i.object_id = kc.parent_object_id AND i.index_id = kc.unique_index_id
|
|
191
|
+
JOIN sys.index_columns ic ON ic.object_id = i.object_id AND ic.index_id = i.index_id
|
|
192
|
+
JOIN sys.columns c ON c.object_id = ic.object_id AND c.column_id = ic.column_id
|
|
193
|
+
WHERE kc.parent_object_id = ? AND kc.type = 'PK'
|
|
194
|
+
ORDER BY kc.name, ic.key_ordinal;
|
|
195
|
+
"""
|
|
196
|
+
|
|
197
|
+
_INDEX_SQL = """
|
|
198
|
+
SELECT
|
|
199
|
+
i.index_id,
|
|
200
|
+
i.name AS index_name,
|
|
201
|
+
i.type_desc,
|
|
202
|
+
i.is_unique,
|
|
203
|
+
i.filter_definition,
|
|
204
|
+
c.name AS column_name,
|
|
205
|
+
ic.is_descending_key,
|
|
206
|
+
ic.is_included_column,
|
|
207
|
+
ic.key_ordinal
|
|
208
|
+
FROM sys.indexes i
|
|
209
|
+
JOIN sys.index_columns ic ON ic.object_id = i.object_id AND ic.index_id = i.index_id
|
|
210
|
+
JOIN sys.columns c ON c.object_id = ic.object_id AND c.column_id = ic.column_id
|
|
211
|
+
WHERE i.object_id = ?
|
|
212
|
+
AND i.is_primary_key = 0
|
|
213
|
+
AND i.is_unique_constraint = 0
|
|
214
|
+
AND i.type > 0
|
|
215
|
+
ORDER BY i.index_id, ic.is_included_column, ic.key_ordinal;
|
|
216
|
+
"""
|
|
217
|
+
|
|
218
|
+
_FK_SQL = """
|
|
219
|
+
SELECT
|
|
220
|
+
fk.name AS fk_name,
|
|
221
|
+
SCHEMA_NAME(ref.schema_id) AS ref_schema,
|
|
222
|
+
ref.name AS ref_table,
|
|
223
|
+
pc.name AS parent_column,
|
|
224
|
+
rc.name AS ref_column,
|
|
225
|
+
fk.delete_referential_action_desc,
|
|
226
|
+
fk.update_referential_action_desc,
|
|
227
|
+
fkc.constraint_column_id
|
|
228
|
+
FROM sys.foreign_keys fk
|
|
229
|
+
JOIN sys.foreign_key_columns fkc ON fkc.constraint_object_id = fk.object_id
|
|
230
|
+
JOIN sys.columns pc ON pc.object_id = fkc.parent_object_id AND pc.column_id = fkc.parent_column_id
|
|
231
|
+
JOIN sys.columns rc ON rc.object_id = fkc.referenced_object_id AND rc.column_id = fkc.referenced_column_id
|
|
232
|
+
JOIN sys.tables ref ON ref.object_id = fk.referenced_object_id
|
|
233
|
+
WHERE fk.parent_object_id = ?
|
|
234
|
+
ORDER BY fk.name, fkc.constraint_column_id;
|
|
235
|
+
"""
|
|
236
|
+
|
|
237
|
+
_CHECK_SQL = """
|
|
238
|
+
SELECT
|
|
239
|
+
cc.name AS constraint_name,
|
|
240
|
+
cc.definition AS definition,
|
|
241
|
+
cc.is_disabled
|
|
242
|
+
FROM sys.check_constraints cc
|
|
243
|
+
WHERE cc.parent_object_id = ?
|
|
244
|
+
ORDER BY cc.name;
|
|
245
|
+
"""
|
|
246
|
+
|
|
247
|
+
_LENGTH_TYPES = {"varchar", "nvarchar", "char", "nchar", "varbinary", "binary"}
|
|
248
|
+
_PRECISION_TYPES = {"decimal", "numeric"}
|
|
249
|
+
_SCALE_TYPES = {"datetime2", "time", "datetimeoffset"}
|
|
250
|
+
_COLLATABLE = {"varchar", "nvarchar", "char", "nchar", "text", "ntext"}
|
|
251
|
+
|
|
252
|
+
|
|
253
|
+
def _format_type(type_name: str, max_length, precision, scale) -> str:
|
|
254
|
+
t = (type_name or "").lower()
|
|
255
|
+
if t in _LENGTH_TYPES:
|
|
256
|
+
if max_length == -1:
|
|
257
|
+
return f"{t}(MAX)"
|
|
258
|
+
chars = max_length // 2 if t.startswith("n") else max_length
|
|
259
|
+
return f"{t}({chars})"
|
|
260
|
+
if t in _PRECISION_TYPES:
|
|
261
|
+
return f"{t}({precision}, {scale})"
|
|
262
|
+
if t in _SCALE_TYPES:
|
|
263
|
+
return f"{t}({scale})"
|
|
264
|
+
return t
|
|
265
|
+
|
|
266
|
+
|
|
267
|
+
def _qname(schema: str, name: str) -> str:
|
|
268
|
+
return f"[{schema}].[{name}]"
|
|
269
|
+
|
|
270
|
+
|
|
271
|
+
def _emit_table(conn, obj: dict[str, Any]) -> str:
|
|
272
|
+
oid = obj["object_id"]
|
|
273
|
+
schema = obj["schema_name"]
|
|
274
|
+
name = obj["table_name"]
|
|
275
|
+
cur = conn.cursor()
|
|
276
|
+
|
|
277
|
+
cur.execute(_COLUMNS_SQL, oid)
|
|
278
|
+
columns = _rows(cur)
|
|
279
|
+
cur.execute(_PK_SQL, oid)
|
|
280
|
+
pk_rows = _rows(cur)
|
|
281
|
+
cur.execute(_INDEX_SQL, oid)
|
|
282
|
+
idx_rows = _rows(cur)
|
|
283
|
+
cur.execute(_FK_SQL, oid)
|
|
284
|
+
fk_rows = _rows(cur)
|
|
285
|
+
cur.execute(_CHECK_SQL, oid)
|
|
286
|
+
ck_rows = _rows(cur)
|
|
287
|
+
|
|
288
|
+
lines: list[str] = [f"CREATE TABLE {_qname(schema, name)} ("]
|
|
289
|
+
col_defs: list[str] = []
|
|
290
|
+
for c in columns:
|
|
291
|
+
if c.get("is_computed") and c.get("computed_definition"):
|
|
292
|
+
persist = " PERSISTED" if c.get("is_persisted") else ""
|
|
293
|
+
col_defs.append(f" [{c['column_name']}] AS {c['computed_definition']}{persist}")
|
|
294
|
+
continue
|
|
295
|
+
type_str = _format_type(c["type_name"], c["max_length"], c["precision"], c["scale"])
|
|
296
|
+
ident = ""
|
|
297
|
+
if c.get("is_identity"):
|
|
298
|
+
ident = f" IDENTITY({c.get('seed_value')},{c.get('increment_value')})"
|
|
299
|
+
nullable = "NULL" if c.get("is_nullable") else "NOT NULL"
|
|
300
|
+
default = ""
|
|
301
|
+
if c.get("default_definition"):
|
|
302
|
+
default = f" CONSTRAINT [{c['default_name']}] DEFAULT {c['default_definition']}"
|
|
303
|
+
coll = ""
|
|
304
|
+
if c.get("collation_name") and (c["type_name"] or "").lower() in _COLLATABLE:
|
|
305
|
+
coll = f" COLLATE {c['collation_name']}"
|
|
306
|
+
col_defs.append(
|
|
307
|
+
f" [{c['column_name']}] {type_str}{coll}{ident} {nullable}{default}"
|
|
308
|
+
)
|
|
309
|
+
|
|
310
|
+
if pk_rows:
|
|
311
|
+
pk_name = pk_rows[0]["constraint_name"]
|
|
312
|
+
pk_type = "CLUSTERED" if pk_rows[0]["type_desc"] == "CLUSTERED" else "NONCLUSTERED"
|
|
313
|
+
pk_cols = ", ".join(
|
|
314
|
+
f"[{r['column_name']}]{' DESC' if r.get('is_descending_key') else ''}"
|
|
315
|
+
for r in pk_rows
|
|
316
|
+
)
|
|
317
|
+
col_defs.append(f" CONSTRAINT [{pk_name}] PRIMARY KEY {pk_type} ({pk_cols})")
|
|
318
|
+
|
|
319
|
+
lines.append(",\n".join(col_defs))
|
|
320
|
+
lines.append(");")
|
|
321
|
+
lines.append("GO")
|
|
322
|
+
|
|
323
|
+
# CHECK constraints
|
|
324
|
+
for ck in ck_rows:
|
|
325
|
+
dis = " WITH NOCHECK" if ck.get("is_disabled") else ""
|
|
326
|
+
lines.append(
|
|
327
|
+
f"ALTER TABLE {_qname(schema, name)}{dis} "
|
|
328
|
+
f"ADD CONSTRAINT [{ck['constraint_name']}] CHECK {ck['definition']};"
|
|
329
|
+
)
|
|
330
|
+
lines.append("GO")
|
|
331
|
+
|
|
332
|
+
# Non-PK indexes
|
|
333
|
+
if idx_rows:
|
|
334
|
+
by_idx: dict[Any, list[dict]] = {}
|
|
335
|
+
for r in idx_rows:
|
|
336
|
+
by_idx.setdefault(r["index_id"], []).append(r)
|
|
337
|
+
for entries in by_idx.values():
|
|
338
|
+
ix = entries[0]
|
|
339
|
+
keys = sorted(
|
|
340
|
+
(e for e in entries if not e.get("is_included_column")),
|
|
341
|
+
key=lambda e: e["key_ordinal"],
|
|
342
|
+
)
|
|
343
|
+
incs = [e for e in entries if e.get("is_included_column")]
|
|
344
|
+
unique = "UNIQUE " if ix.get("is_unique") else ""
|
|
345
|
+
key_cols = ", ".join(
|
|
346
|
+
f"[{e['column_name']}]{' DESC' if e.get('is_descending_key') else ''}"
|
|
347
|
+
for e in keys
|
|
348
|
+
)
|
|
349
|
+
include = ""
|
|
350
|
+
if incs:
|
|
351
|
+
include = " INCLUDE (" + ", ".join(f"[{e['column_name']}]" for e in incs) + ")"
|
|
352
|
+
where = f" WHERE {ix['filter_definition']}" if ix.get("filter_definition") else ""
|
|
353
|
+
lines.append(
|
|
354
|
+
f"CREATE {unique}{ix['type_desc']} INDEX [{ix['index_name']}] "
|
|
355
|
+
f"ON {_qname(schema, name)} ({key_cols}){include}{where};"
|
|
356
|
+
)
|
|
357
|
+
lines.append("GO")
|
|
358
|
+
|
|
359
|
+
# Foreign keys
|
|
360
|
+
if fk_rows:
|
|
361
|
+
by_fk: dict[str, list[dict]] = {}
|
|
362
|
+
for r in fk_rows:
|
|
363
|
+
by_fk.setdefault(r["fk_name"], []).append(r)
|
|
364
|
+
for fk_name, entries in by_fk.items():
|
|
365
|
+
entries.sort(key=lambda e: e["constraint_column_id"])
|
|
366
|
+
head = entries[0]
|
|
367
|
+
parent_cols = ", ".join(f"[{e['parent_column']}]" for e in entries)
|
|
368
|
+
ref_cols = ", ".join(f"[{e['ref_column']}]" for e in entries)
|
|
369
|
+
on_del = (
|
|
370
|
+
f" ON DELETE {head['delete_referential_action_desc'].replace('_', ' ')}"
|
|
371
|
+
if head.get("delete_referential_action_desc") not in (None, "NO_ACTION") else ""
|
|
372
|
+
)
|
|
373
|
+
on_upd = (
|
|
374
|
+
f" ON UPDATE {head['update_referential_action_desc'].replace('_', ' ')}"
|
|
375
|
+
if head.get("update_referential_action_desc") not in (None, "NO_ACTION") else ""
|
|
376
|
+
)
|
|
377
|
+
lines.append(
|
|
378
|
+
f"ALTER TABLE {_qname(schema, name)} "
|
|
379
|
+
f"ADD CONSTRAINT [{fk_name}] FOREIGN KEY ({parent_cols}) "
|
|
380
|
+
f"REFERENCES {_qname(head['ref_schema'], head['ref_table'])} "
|
|
381
|
+
f"({ref_cols}){on_del}{on_upd};"
|
|
382
|
+
)
|
|
383
|
+
lines.append("GO")
|
|
384
|
+
|
|
385
|
+
return "\n".join(lines) + "\n"
|
|
386
|
+
|
|
387
|
+
|
|
388
|
+
def extract_tables(conn) -> list[dict[str, Any]]:
|
|
389
|
+
"""Records for every user table, DDL generated from the catalog."""
|
|
390
|
+
cur = conn.cursor()
|
|
391
|
+
cur.execute(_TABLES_SQL)
|
|
392
|
+
tables = _rows(cur)
|
|
393
|
+
out: list[dict[str, Any]] = []
|
|
394
|
+
for obj in tables:
|
|
395
|
+
out.append({
|
|
396
|
+
"type": TABLE_LABEL,
|
|
397
|
+
"schema": obj.get("schema_name") or "",
|
|
398
|
+
"name": obj.get("table_name"),
|
|
399
|
+
"definition": _emit_table(conn, obj),
|
|
400
|
+
})
|
|
401
|
+
return out
|
|
402
|
+
|
|
403
|
+
|
|
404
|
+
# ---------------------------------------------------------------------------
|
|
405
|
+
# Public extract entrypoint
|
|
406
|
+
# ---------------------------------------------------------------------------
|
|
407
|
+
|
|
408
|
+
def extract_objects(conn, types=None) -> list[dict[str, Any]]:
|
|
409
|
+
"""Extract all (or a filtered subset of) DB objects as dbschema records.
|
|
410
|
+
|
|
411
|
+
`types` is an optional iterable of SQL Server type letters to keep
|
|
412
|
+
(``P``, ``FN``, ``TF``, ``IF``, ``V``, ``TR``, ``U``). ``None`` extracts all.
|
|
413
|
+
The connection is autocommit + read-only; only SELECTs against the catalog
|
|
414
|
+
are issued. Returns records sorted for a stable mirror.
|
|
415
|
+
"""
|
|
416
|
+
wanted = None
|
|
417
|
+
if types is not None:
|
|
418
|
+
wanted = {t.strip().upper() for t in types if t and t.strip()}
|
|
419
|
+
|
|
420
|
+
records: list[dict[str, Any]] = []
|
|
421
|
+
want_modules = wanted is None or (wanted & set(MODULE_TYPES))
|
|
422
|
+
if want_modules:
|
|
423
|
+
for rec in extract_modules(conn):
|
|
424
|
+
# filter at the type-letter level when a subset was requested
|
|
425
|
+
if wanted is not None:
|
|
426
|
+
# map back: the dir label alone is ambiguous (Functions <- FN/IF/TF),
|
|
427
|
+
# so re-derive whether this record's letter is wanted by re-running
|
|
428
|
+
# is unnecessary — extract_modules already only yields known labels;
|
|
429
|
+
# filtering by letter happens below via _module_letter_wanted.
|
|
430
|
+
pass
|
|
431
|
+
records.append(rec)
|
|
432
|
+
if wanted is not None:
|
|
433
|
+
records = [r for r in records if _record_letters_wanted(r, wanted)]
|
|
434
|
+
|
|
435
|
+
if wanted is None or TABLE_TYPE in wanted:
|
|
436
|
+
records.extend(extract_tables(conn))
|
|
437
|
+
|
|
438
|
+
records.sort(key=lambda r: (r["type"], r.get("schema") or "", r["name"]))
|
|
439
|
+
return records
|
|
440
|
+
|
|
441
|
+
|
|
442
|
+
# Reverse map label -> set of letters that can produce it, for --types filtering.
|
|
443
|
+
_LABEL_LETTERS: dict[str, set[str]] = {}
|
|
444
|
+
for _letter, _label in MODULE_TYPES.items():
|
|
445
|
+
_LABEL_LETTERS.setdefault(_label, set()).add(_letter)
|
|
446
|
+
_LABEL_LETTERS[TABLE_LABEL] = {TABLE_TYPE}
|
|
447
|
+
|
|
448
|
+
|
|
449
|
+
def _record_letters_wanted(record: dict, wanted: set[str]) -> bool:
|
|
450
|
+
"""True if the record's dir label maps to at least one wanted type letter.
|
|
451
|
+
|
|
452
|
+
"Functions" maps to {FN, IF, TF}; if the user asked for only ``TF`` we cannot
|
|
453
|
+
distinguish from the label alone, so we keep the whole Functions group when
|
|
454
|
+
ANY of its letters is wanted. This is the documented coarse behaviour: --types
|
|
455
|
+
selects object FAMILIES (proc / function / view / trigger / table), not the
|
|
456
|
+
sub-kinds of a family.
|
|
457
|
+
"""
|
|
458
|
+
letters = _LABEL_LETTERS.get(record["type"], set())
|
|
459
|
+
return bool(letters & wanted)
|
|
460
|
+
|
|
461
|
+
|
|
462
|
+
# ===========================================================================
|
|
463
|
+
# Migration engine
|
|
464
|
+
# ===========================================================================
|
|
465
|
+
|
|
466
|
+
MIGRATIONS_SCHEMA = "dbo"
|
|
467
|
+
MIGRATIONS_TABLE = "__schema_migrations"
|
|
468
|
+
MIG_FQN = f"[{MIGRATIONS_SCHEMA}].[{MIGRATIONS_TABLE}]"
|
|
469
|
+
|
|
470
|
+
_ENSURE_TABLE_SQL = f"""
|
|
471
|
+
IF NOT EXISTS (
|
|
472
|
+
SELECT 1 FROM sys.tables t JOIN sys.schemas s ON s.schema_id = t.schema_id
|
|
473
|
+
WHERE t.name = '{MIGRATIONS_TABLE}' AND s.name = '{MIGRATIONS_SCHEMA}'
|
|
474
|
+
)
|
|
475
|
+
BEGIN
|
|
476
|
+
CREATE TABLE {MIG_FQN} (
|
|
477
|
+
migration_id NVARCHAR(200) NOT NULL
|
|
478
|
+
CONSTRAINT PK___schema_migrations PRIMARY KEY,
|
|
479
|
+
filename NVARCHAR(260) NOT NULL,
|
|
480
|
+
sha256 NCHAR(64) NOT NULL,
|
|
481
|
+
applied_at DATETIME2(0) NOT NULL
|
|
482
|
+
CONSTRAINT DF___schema_migrations_applied_at DEFAULT SYSUTCDATETIME(),
|
|
483
|
+
applied_by NVARCHAR(128) NOT NULL
|
|
484
|
+
CONSTRAINT DF___schema_migrations_applied_by DEFAULT SUSER_SNAME(),
|
|
485
|
+
duration_ms INT NULL,
|
|
486
|
+
notes NVARCHAR(MAX) NULL
|
|
487
|
+
);
|
|
488
|
+
END;
|
|
489
|
+
"""
|
|
490
|
+
|
|
491
|
+
|
|
492
|
+
def ensure_migrations_table(conn) -> None:
|
|
493
|
+
"""Create ``dbo.__schema_migrations`` if it does not already exist. This is a
|
|
494
|
+
WRITE — only the ``apply`` path calls it; ``list`` stays read-only."""
|
|
495
|
+
cur = conn.cursor()
|
|
496
|
+
cur.execute(_ENSURE_TABLE_SQL)
|
|
497
|
+
|
|
498
|
+
|
|
499
|
+
def tracking_table_exists(conn) -> bool:
|
|
500
|
+
"""Read-only: does the tracking table exist? (never creates it)."""
|
|
501
|
+
cur = conn.cursor()
|
|
502
|
+
cur.execute(
|
|
503
|
+
"SELECT 1 FROM sys.tables t JOIN sys.schemas s ON s.schema_id = t.schema_id "
|
|
504
|
+
"WHERE t.name = ? AND s.name = ?", (MIGRATIONS_TABLE, MIGRATIONS_SCHEMA))
|
|
505
|
+
return cur.fetchone() is not None
|
|
506
|
+
|
|
507
|
+
|
|
508
|
+
def fetch_applied(conn) -> dict[str, dict[str, Any]]:
|
|
509
|
+
"""Return {migration_id: {sha256, filename, applied_at}} from the tracking table.
|
|
510
|
+
|
|
511
|
+
READ-ONLY: if the tracking table does not exist yet, returns {} WITHOUT
|
|
512
|
+
creating it (only ``apply`` creates the table).
|
|
513
|
+
"""
|
|
514
|
+
if not tracking_table_exists(conn):
|
|
515
|
+
return {}
|
|
516
|
+
cur = conn.cursor()
|
|
517
|
+
cur.execute(
|
|
518
|
+
f"SELECT migration_id, sha256, filename, applied_at FROM {MIG_FQN}"
|
|
519
|
+
)
|
|
520
|
+
out: dict[str, dict[str, Any]] = {}
|
|
521
|
+
for row in cur.fetchall():
|
|
522
|
+
# Support both pyodbc Row (attribute access) and plain tuples (test fakes).
|
|
523
|
+
if hasattr(row, "migration_id"):
|
|
524
|
+
mid = row.migration_id
|
|
525
|
+
out[mid] = {
|
|
526
|
+
"sha256": row.sha256,
|
|
527
|
+
"filename": row.filename,
|
|
528
|
+
"applied_at": _to_str(row.applied_at),
|
|
529
|
+
}
|
|
530
|
+
else:
|
|
531
|
+
mid = row[0]
|
|
532
|
+
out[mid] = {
|
|
533
|
+
"sha256": row[1],
|
|
534
|
+
"filename": row[2],
|
|
535
|
+
"applied_at": _to_str(row[3]),
|
|
536
|
+
}
|
|
537
|
+
return out
|
|
538
|
+
|
|
539
|
+
|
|
540
|
+
def _to_str(value) -> Any:
|
|
541
|
+
"""JSON-safe scalar (datetimes -> isoformat, else passthrough)."""
|
|
542
|
+
if value is None:
|
|
543
|
+
return None
|
|
544
|
+
if hasattr(value, "isoformat"):
|
|
545
|
+
return value.isoformat()
|
|
546
|
+
return value
|
|
547
|
+
|
|
548
|
+
|
|
549
|
+
def record_applied(conn, mig_id: str, filename: str, sha: str,
|
|
550
|
+
duration_ms: int | None = None) -> None:
|
|
551
|
+
"""Insert a tracking row for a successfully applied migration."""
|
|
552
|
+
cur = conn.cursor()
|
|
553
|
+
cur.execute(
|
|
554
|
+
f"INSERT INTO {MIG_FQN} (migration_id, filename, sha256, duration_ms) "
|
|
555
|
+
f"VALUES (?, ?, ?, ?)",
|
|
556
|
+
(mig_id, filename, sha, duration_ms),
|
|
557
|
+
)
|
|
558
|
+
|
|
559
|
+
|
|
560
|
+
def apply_migration_sql(conn, sql: str, *, dry_run: bool = False) -> int:
|
|
561
|
+
"""Execute one migration's SQL inside a SINGLE transaction for the file.
|
|
562
|
+
|
|
563
|
+
The SQL is split into GO batches (``dbschema.split_go_batches``); each batch
|
|
564
|
+
runs via ``cursor.execute``. Our connection is autocommit=True, so we open an
|
|
565
|
+
explicit transaction with ``BEGIN TRAN`` and either ``COMMIT`` (apply) or
|
|
566
|
+
``ROLLBACK`` (dry-run / on error) — giving file-level atomicity and a no-op
|
|
567
|
+
validation mode.
|
|
568
|
+
|
|
569
|
+
Returns the number of batches executed. Re-raises on the first batch error
|
|
570
|
+
after rolling the file's transaction back.
|
|
571
|
+
|
|
572
|
+
Known limitation: ``split_go_batches`` splits on any line that is exactly
|
|
573
|
+
``GO`` — a ``GO`` alone on a line inside a string literal or block comment is
|
|
574
|
+
still treated as a batch separator (documented in dbschema.split_go_batches).
|
|
575
|
+
"""
|
|
576
|
+
batches = dbschema.split_go_batches(sql)
|
|
577
|
+
cur = conn.cursor()
|
|
578
|
+
cur.execute("SET XACT_ABORT ON; BEGIN TRANSACTION;")
|
|
579
|
+
executed = 0
|
|
580
|
+
try:
|
|
581
|
+
for batch in batches:
|
|
582
|
+
if not batch.strip():
|
|
583
|
+
continue
|
|
584
|
+
cur.execute(batch)
|
|
585
|
+
# A statement that fails after one that returned "N rows affected" raises only
|
|
586
|
+
# when the cursor reaches it. Undrained, XACT_ABORT rolls the file back on the
|
|
587
|
+
# server while this side commits nothing and reports the migration as applied.
|
|
588
|
+
dbquery.drain_results(cur)
|
|
589
|
+
executed += 1
|
|
590
|
+
except Exception:
|
|
591
|
+
try:
|
|
592
|
+
cur.execute("IF @@TRANCOUNT > 0 ROLLBACK TRANSACTION;")
|
|
593
|
+
except Exception: # noqa: BLE001
|
|
594
|
+
pass
|
|
595
|
+
raise
|
|
596
|
+
if dry_run:
|
|
597
|
+
cur.execute("IF @@TRANCOUNT > 0 ROLLBACK TRANSACTION;")
|
|
598
|
+
else:
|
|
599
|
+
cur.execute("IF @@TRANCOUNT > 0 COMMIT TRANSACTION;")
|
|
600
|
+
return executed
|
|
File without changes
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
"""Put the framework root on sys.path so `from tools...` imports work."""
|
|
2
|
+
from __future__ import annotations
|
|
3
|
+
|
|
4
|
+
import sys
|
|
5
|
+
from pathlib import Path
|
|
6
|
+
import pytest
|
|
7
|
+
|
|
8
|
+
# pyodbc is an OPTIONAL dependency (the SQL Server driver), so a plain install does not
|
|
9
|
+
# have it. These tests then FAIL, which reads as a broken repository rather
|
|
10
|
+
# than as an extra nobody asked for. Skip instead, with the reason visible.
|
|
11
|
+
#
|
|
12
|
+
# exc_type matters: pytest 9 skips only on ModuleNotFoundError by default,
|
|
13
|
+
# and a package can be installed yet unimportable - pyodbc on a runner
|
|
14
|
+
# without its native library raises a plain ImportError, which would
|
|
15
|
+
# otherwise re-raise and take collection down instead of skipping.
|
|
16
|
+
pytest.importorskip('pyodbc', reason="install the extra that provides pyodbc",
|
|
17
|
+
exc_type=ImportError)
|
|
18
|
+
|
|
19
|
+
FRAMEWORK_ROOT = Path(__file__).resolve().parents[3]
|
|
20
|
+
if str(FRAMEWORK_ROOT) not in sys.path:
|
|
21
|
+
sys.path.insert(0, str(FRAMEWORK_ROOT))
|