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,54 @@
|
|
|
1
|
+
"""JSON I/O contract for tools.
|
|
2
|
+
|
|
3
|
+
Success: emit({...}) -> one JSON object to stdout, exit 0
|
|
4
|
+
Failure: fail("code", "msg") -> error envelope to stdout, non-zero exit
|
|
5
|
+
Logs: log(...) -> stderr only (never pollutes stdout)
|
|
6
|
+
"""
|
|
7
|
+
from __future__ import annotations
|
|
8
|
+
|
|
9
|
+
import json
|
|
10
|
+
import sys
|
|
11
|
+
from typing import Any, NoReturn
|
|
12
|
+
|
|
13
|
+
# Windows terminals default to cp1252. Force UTF-8 so tools can emit
|
|
14
|
+
# non-ASCII (Ryver messages, calendar titles, names) without mojibake.
|
|
15
|
+
try:
|
|
16
|
+
sys.stdout.reconfigure(encoding="utf-8")
|
|
17
|
+
sys.stderr.reconfigure(encoding="utf-8")
|
|
18
|
+
except (AttributeError, ValueError):
|
|
19
|
+
pass
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
def emit(data: dict[str, Any]) -> NoReturn:
|
|
23
|
+
"""Print one JSON object to stdout and exit 0."""
|
|
24
|
+
json.dump(data, sys.stdout, ensure_ascii=False)
|
|
25
|
+
sys.stdout.write("\n")
|
|
26
|
+
sys.stdout.flush()
|
|
27
|
+
sys.exit(0)
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
def fail(
|
|
31
|
+
code: str,
|
|
32
|
+
message: str,
|
|
33
|
+
details: dict[str, Any] | None = None,
|
|
34
|
+
exit_code: int = 1,
|
|
35
|
+
) -> NoReturn:
|
|
36
|
+
"""Print error envelope to stdout and exit non-zero."""
|
|
37
|
+
json.dump(
|
|
38
|
+
{"error": {"code": code, "message": message, "details": details or {}}},
|
|
39
|
+
sys.stdout,
|
|
40
|
+
ensure_ascii=False,
|
|
41
|
+
)
|
|
42
|
+
sys.stdout.write("\n")
|
|
43
|
+
sys.stdout.flush()
|
|
44
|
+
sys.exit(exit_code)
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
def log(*args: Any) -> None:
|
|
48
|
+
"""Write to stderr. Use for progress, debug, anything non-JSON."""
|
|
49
|
+
print(*args, file=sys.stderr, flush=True)
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
def read_stdin_json() -> dict[str, Any]:
|
|
53
|
+
"""For tools that accept JSON on stdin instead of CLI args."""
|
|
54
|
+
return json.load(sys.stdin)
|
|
@@ -0,0 +1,297 @@
|
|
|
1
|
+
"""Tool and agent manifest loading + validation."""
|
|
2
|
+
from __future__ import annotations
|
|
3
|
+
|
|
4
|
+
from datetime import date
|
|
5
|
+
from pathlib import Path
|
|
6
|
+
from typing import Any, Literal
|
|
7
|
+
|
|
8
|
+
import yaml
|
|
9
|
+
from pydantic import BaseModel, ConfigDict, Field
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class ArgSpec(BaseModel):
|
|
13
|
+
model_config = ConfigDict(extra="forbid", populate_by_name=True)
|
|
14
|
+
|
|
15
|
+
name: str
|
|
16
|
+
type: Literal["string", "integer", "number", "boolean", "array", "object"] = "string"
|
|
17
|
+
required: bool = False
|
|
18
|
+
description: str = ""
|
|
19
|
+
default: Any = None
|
|
20
|
+
# JSON Schema for an arg that carries a STRUCTURED payload (a config, a DTO). A
|
|
21
|
+
# one-line `help=` can say an arg takes "a JSON object" but not what has to be in
|
|
22
|
+
# it, so a caller that only has the manifest has to reverse-engineer the shape from
|
|
23
|
+
# validation errors, one layer per attempt. Populate it from the schema the tool
|
|
24
|
+
# already validates against, never a hand-written copy, so the two cannot drift.
|
|
25
|
+
# Aliased: the manifest key stays `schema`, but a field literally named `schema`
|
|
26
|
+
# shadows BaseModel.schema() and pydantic warns on every import.
|
|
27
|
+
json_schema: dict | None = Field(default=None, alias="schema")
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
class SecretSpec(BaseModel):
|
|
31
|
+
model_config = ConfigDict(extra="forbid")
|
|
32
|
+
|
|
33
|
+
name: str
|
|
34
|
+
description: str = ""
|
|
35
|
+
optional: bool = False
|
|
36
|
+
"""True when the tool works without this secret and only one branch of it
|
|
37
|
+
needs the value. Such a secret must not count against readiness: showing a
|
|
38
|
+
fully working tool as red teaches people to ignore the colour, and the next
|
|
39
|
+
genuinely missing credential reads the same as this one. The dashboard and
|
|
40
|
+
`list-tools` still surface it, as an optional extra rather than a blocker."""
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
class RoutingSpec(BaseModel):
|
|
44
|
+
"""Optional request-routing hint, consumed by scripts/build-router.py to
|
|
45
|
+
build the Capability Router in CLAUDE.md. Lets a tool declare, in its own
|
|
46
|
+
manifest (the source of truth), the natural-language asks that should map to
|
|
47
|
+
it and the action to reach for first. When absent, the router falls back to
|
|
48
|
+
the tool description and a heuristic primary action."""
|
|
49
|
+
model_config = ConfigDict(extra="forbid")
|
|
50
|
+
|
|
51
|
+
triggers: list[str] = Field(default_factory=list)
|
|
52
|
+
primary_action: str = ""
|
|
53
|
+
example: str = ""
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
class HealthcheckSpec(BaseModel):
|
|
57
|
+
"""Optional live-credential probe, consumed by the dashboard's validation
|
|
58
|
+
layer (and any 'is this actually connected' check). Declares a cheap,
|
|
59
|
+
read-only, side-effect-free call whose success proves the stored credential
|
|
60
|
+
is currently authorized - not merely present in Credential Manager.
|
|
61
|
+
|
|
62
|
+
- `action`: the action name to invoke on a dispatch tool. Empty for a flat
|
|
63
|
+
tool (the tool is run with no action positional).
|
|
64
|
+
- `args`: arg-name -> value, forwarded as `--name value` to the tool.
|
|
65
|
+
- `label`: optional human label for what the probe does (e.g. 'list 1 user').
|
|
66
|
+
|
|
67
|
+
When absent, the dashboard falls back to the tool's own `auth-status` action
|
|
68
|
+
(a soft convention), then to presence-only. MUST be read-only: it runs
|
|
69
|
+
unattended on every dashboard load."""
|
|
70
|
+
model_config = ConfigDict(extra="forbid")
|
|
71
|
+
|
|
72
|
+
action: str = ""
|
|
73
|
+
args: dict[str, Any] = Field(default_factory=dict)
|
|
74
|
+
label: str = ""
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
class WebSessionSpec(BaseModel):
|
|
78
|
+
"""Declares that a tool works by driving a saved browser login (the `web`
|
|
79
|
+
tool's session) rather than an API credential. Lets the dashboard show a
|
|
80
|
+
per-tool 'Connect login' button prefilled with the right name/URL, and count
|
|
81
|
+
a missing session as 'needs setup' - so a colleague never has to guess a
|
|
82
|
+
session name or login URL.
|
|
83
|
+
|
|
84
|
+
- `name`: the session name the tool opens (matches `web save-session --name`).
|
|
85
|
+
- `login_url`: the URL to open for the human to log in.
|
|
86
|
+
- `persistent`: capture a persistent profile (IndexedDB-auth sites, e.g.
|
|
87
|
+
WhatsApp) instead of a storageState snapshot.
|
|
88
|
+
- `channel`: a real browser channel ('chrome'/'msedge'), e.g. for Google-SSO.
|
|
89
|
+
"""
|
|
90
|
+
model_config = ConfigDict(extra="forbid")
|
|
91
|
+
|
|
92
|
+
name: str
|
|
93
|
+
login_url: str = ""
|
|
94
|
+
persistent: bool = False
|
|
95
|
+
channel: str = ""
|
|
96
|
+
label: str = ""
|
|
97
|
+
|
|
98
|
+
|
|
99
|
+
class RequirementSpec(BaseModel):
|
|
100
|
+
"""Something that must exist ON THE MACHINE - not a Python dependency.
|
|
101
|
+
|
|
102
|
+
`uv sync` installs the venv; it does not install a browser engine, a database
|
|
103
|
+
driver or a codec. Those were previously discovered one incident at a time and
|
|
104
|
+
then hard-coded into the onboarding brief from memory, which is exactly how a
|
|
105
|
+
fresh install ends up looking healthy and failing at the user's first real
|
|
106
|
+
call: `list-tools` reports ready, the test suite passes, and the browser tools
|
|
107
|
+
die on their first action because the Playwright binary was never downloaded.
|
|
108
|
+
|
|
109
|
+
Declaring them makes the gap machine-checkable
|
|
110
|
+
(`python scripts/check-requirements.py`) instead of remembered.
|
|
111
|
+
|
|
112
|
+
- `name`: short id, e.g. `playwright-chromium`, `ffmpeg`, `odbc-sqlserver`.
|
|
113
|
+
- `kind`: what sort of thing it is (drives how it's presented, not logic).
|
|
114
|
+
- `why`: what breaks without it - written for the person reading the failure.
|
|
115
|
+
- `check`: a cheap shell command that exits 0 when the thing is present.
|
|
116
|
+
- `install`: how to get it (a winget id, a documented command).
|
|
117
|
+
- `auto`: the tool installs it itself on first use, so a missing one is a
|
|
118
|
+
warning rather than a blocker (ffmpeg does this via tools/_lib/ffmpeg.py).
|
|
119
|
+
"""
|
|
120
|
+
model_config = ConfigDict(extra="forbid")
|
|
121
|
+
|
|
122
|
+
name: str
|
|
123
|
+
kind: Literal["binary", "browser", "driver", "service", "runtime"] = "binary"
|
|
124
|
+
why: str = ""
|
|
125
|
+
check: str = ""
|
|
126
|
+
install: str = ""
|
|
127
|
+
auto: bool = False
|
|
128
|
+
|
|
129
|
+
|
|
130
|
+
class ActionSpec(BaseModel):
|
|
131
|
+
"""One action of a multi-action (dispatch) tool.
|
|
132
|
+
|
|
133
|
+
Action-based tools take the action name as the first positional arg;
|
|
134
|
+
each action has its own arg set. Flat tools use `args` at the top level.
|
|
135
|
+
"""
|
|
136
|
+
model_config = ConfigDict(extra="forbid")
|
|
137
|
+
|
|
138
|
+
name: str
|
|
139
|
+
description: str = ""
|
|
140
|
+
args: list[ArgSpec] = Field(default_factory=list)
|
|
141
|
+
output_schema: str = ""
|
|
142
|
+
examples: list[dict] = Field(default_factory=list)
|
|
143
|
+
|
|
144
|
+
|
|
145
|
+
class ToolManifest(BaseModel):
|
|
146
|
+
model_config = ConfigDict(extra="forbid")
|
|
147
|
+
|
|
148
|
+
name: str
|
|
149
|
+
description: str
|
|
150
|
+
version: str = "0.1.0"
|
|
151
|
+
runtime: Literal["python"] = "python"
|
|
152
|
+
entrypoint: str = "main.py"
|
|
153
|
+
# Catalog tier for the multi-tenant PROCESIO module (spec P0.0-06 / D11):
|
|
154
|
+
# official - platform-owned, shared, users can't change (IsProcesio)
|
|
155
|
+
# template - a shipped default every workspace starts from, copy-on-write
|
|
156
|
+
# custom - workspace-authored
|
|
157
|
+
# Default 'template': a shipped tool is a default a workspace may fork. Ignored
|
|
158
|
+
# entirely by the local single-tenant runtime, so it changes nothing locally.
|
|
159
|
+
tier: Literal["official", "template", "custom"] = "template"
|
|
160
|
+
args: list[ArgSpec] = Field(default_factory=list)
|
|
161
|
+
actions: list[ActionSpec] = Field(default_factory=list)
|
|
162
|
+
secrets: list[SecretSpec] = Field(default_factory=list)
|
|
163
|
+
routing: RoutingSpec | None = None
|
|
164
|
+
healthcheck: HealthcheckSpec | None = None
|
|
165
|
+
web_session: WebSessionSpec | None = None
|
|
166
|
+
requires: list[RequirementSpec] = Field(default_factory=list)
|
|
167
|
+
output_schema: str = ""
|
|
168
|
+
examples: list[dict] = Field(default_factory=list)
|
|
169
|
+
# path is filled by the loader; not part of the YAML
|
|
170
|
+
path: Path | None = None
|
|
171
|
+
|
|
172
|
+
def is_action_based(self) -> bool:
|
|
173
|
+
return len(self.actions) > 0
|
|
174
|
+
|
|
175
|
+
def action_names(self) -> list[str]:
|
|
176
|
+
return [a.name for a in self.actions]
|
|
177
|
+
|
|
178
|
+
def get_action(self, name: str) -> ActionSpec | None:
|
|
179
|
+
for a in self.actions:
|
|
180
|
+
if a.name == name:
|
|
181
|
+
return a
|
|
182
|
+
return None
|
|
183
|
+
|
|
184
|
+
|
|
185
|
+
def load_tool(manifest_path: Path) -> ToolManifest:
|
|
186
|
+
raw = yaml.safe_load(manifest_path.read_text(encoding="utf-8"))
|
|
187
|
+
if not isinstance(raw, dict):
|
|
188
|
+
raise ValueError(f"{manifest_path}: top-level YAML must be a mapping")
|
|
189
|
+
m = ToolManifest(**raw)
|
|
190
|
+
m.path = manifest_path.parent
|
|
191
|
+
return m
|
|
192
|
+
|
|
193
|
+
|
|
194
|
+
class AgentManifest(BaseModel):
|
|
195
|
+
"""Manifest for a registered agent.
|
|
196
|
+
|
|
197
|
+
An agent is invoked exactly like an action-dispatch tool (action name as the
|
|
198
|
+
first positional arg, JSON in / JSON out, secrets via Credential Manager), so
|
|
199
|
+
it shares ToolManifest's shape. It additionally declares `tools`: the names of
|
|
200
|
+
registered tools it orchestrates. The runtime resolves those via the registry,
|
|
201
|
+
never a hardcoded list.
|
|
202
|
+
"""
|
|
203
|
+
model_config = ConfigDict(extra="forbid")
|
|
204
|
+
|
|
205
|
+
name: str
|
|
206
|
+
description: str
|
|
207
|
+
version: str = "0.1.0"
|
|
208
|
+
runtime: Literal["python"] = "python"
|
|
209
|
+
entrypoint: str = "main.py"
|
|
210
|
+
# Catalog tier (spec P0.0-06 / D11); see ToolManifest.tier. Default 'template'.
|
|
211
|
+
tier: Literal["official", "template", "custom"] = "template"
|
|
212
|
+
tools: list[str] = Field(default_factory=list)
|
|
213
|
+
args: list[ArgSpec] = Field(default_factory=list)
|
|
214
|
+
actions: list[ActionSpec] = Field(default_factory=list)
|
|
215
|
+
secrets: list[SecretSpec] = Field(default_factory=list)
|
|
216
|
+
routing: RoutingSpec | None = None
|
|
217
|
+
healthcheck: HealthcheckSpec | None = None
|
|
218
|
+
output_schema: str = ""
|
|
219
|
+
examples: list[dict] = Field(default_factory=list)
|
|
220
|
+
# path is filled by the loader; not part of the YAML
|
|
221
|
+
path: Path | None = None
|
|
222
|
+
|
|
223
|
+
def is_action_based(self) -> bool:
|
|
224
|
+
return len(self.actions) > 0
|
|
225
|
+
|
|
226
|
+
def action_names(self) -> list[str]:
|
|
227
|
+
return [a.name for a in self.actions]
|
|
228
|
+
|
|
229
|
+
def get_action(self, name: str) -> ActionSpec | None:
|
|
230
|
+
for a in self.actions:
|
|
231
|
+
if a.name == name:
|
|
232
|
+
return a
|
|
233
|
+
return None
|
|
234
|
+
|
|
235
|
+
|
|
236
|
+
def load_agent(manifest_path: Path) -> AgentManifest:
|
|
237
|
+
raw = yaml.safe_load(manifest_path.read_text(encoding="utf-8"))
|
|
238
|
+
if not isinstance(raw, dict):
|
|
239
|
+
raise ValueError(f"{manifest_path}: top-level YAML must be a mapping")
|
|
240
|
+
m = AgentManifest(**raw)
|
|
241
|
+
m.path = manifest_path.parent
|
|
242
|
+
return m
|
|
243
|
+
|
|
244
|
+
|
|
245
|
+
class SkillManifest(BaseModel):
|
|
246
|
+
"""Manifest for a registered skill.
|
|
247
|
+
|
|
248
|
+
A skill is instruction/reference content (not an executable), so its native
|
|
249
|
+
`SKILL.md` YAML frontmatter IS its manifest — no separate file, no duplicated
|
|
250
|
+
metadata. The frontmatter always carries `name` + `description`; it may also
|
|
251
|
+
carry native keys we don't model (`license`, `allowed-tools`, etc.), so unlike
|
|
252
|
+
tool/agent manifests this is lenient (`extra="ignore"`) — skills are imported
|
|
253
|
+
artifacts we keep portable, not author from scratch.
|
|
254
|
+
|
|
255
|
+
An optional `routing:` block lets a skill curate its Capability-Router line,
|
|
256
|
+
exactly like a tool. When absent, the router falls back to the description.
|
|
257
|
+
|
|
258
|
+
Skills that opt into the governance discipline also carry `owner`,
|
|
259
|
+
`last_verified`, `baseline_version`, `eval_suite`, and `source_policy`
|
|
260
|
+
(the marker `check-skill-governance.py` scopes on). Imported/portable skills
|
|
261
|
+
omit them and default; `extra="ignore"` keeps any other native key portable.
|
|
262
|
+
"""
|
|
263
|
+
model_config = ConfigDict(extra="ignore")
|
|
264
|
+
|
|
265
|
+
name: str
|
|
266
|
+
description: str
|
|
267
|
+
version: str = "0.1.0"
|
|
268
|
+
tier: Literal["official", "template", "custom"] = "template"
|
|
269
|
+
routing: RoutingSpec | None = None
|
|
270
|
+
owner: str = ""
|
|
271
|
+
last_verified: date | None = None
|
|
272
|
+
baseline_version: str = ""
|
|
273
|
+
eval_suite: str = ""
|
|
274
|
+
source_policy: Literal["generated", "timestamped", "static"] | None = None
|
|
275
|
+
# path is filled by the loader; not part of the frontmatter
|
|
276
|
+
path: Path | None = None
|
|
277
|
+
|
|
278
|
+
|
|
279
|
+
def _split_frontmatter(text: str) -> dict:
|
|
280
|
+
"""Parse the leading `---`-delimited YAML frontmatter from a SKILL.md body."""
|
|
281
|
+
lines = text.splitlines()
|
|
282
|
+
if not lines or lines[0].strip() != "---":
|
|
283
|
+
raise ValueError("SKILL.md is missing its '---' YAML frontmatter")
|
|
284
|
+
for i in range(1, len(lines)):
|
|
285
|
+
if lines[i].strip() == "---":
|
|
286
|
+
raw = yaml.safe_load("\n".join(lines[1:i]))
|
|
287
|
+
if not isinstance(raw, dict):
|
|
288
|
+
raise ValueError("SKILL.md frontmatter must be a YAML mapping")
|
|
289
|
+
return raw
|
|
290
|
+
raise ValueError("SKILL.md frontmatter is not terminated by a closing '---'")
|
|
291
|
+
|
|
292
|
+
|
|
293
|
+
def load_skill(skill_md_path: Path) -> SkillManifest:
|
|
294
|
+
raw = _split_frontmatter(skill_md_path.read_text(encoding="utf-8"))
|
|
295
|
+
m = SkillManifest(**raw)
|
|
296
|
+
m.path = skill_md_path.parent
|
|
297
|
+
return m
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
"""Read-only correspondence check for a Gate 5 commit and current skill bytes.
|
|
2
|
+
|
|
3
|
+
Historical fingerprints cover the entire committed skills subtree, exactly as the
|
|
4
|
+
series launcher exports it. Live correspondence covers published packages and the
|
|
5
|
+
behavioral/threshold contract, excluding the ledger (which must record new proof).
|
|
6
|
+
This verifies content identity, not the authenticity or quality of a test verdict.
|
|
7
|
+
Release targets must be clean source exports: bytecode/cache artifacts are rejected,
|
|
8
|
+
not silently ignored. Never delete a possibly active developer cache to pass a gate.
|
|
9
|
+
"""
|
|
10
|
+
from __future__ import annotations
|
|
11
|
+
|
|
12
|
+
import hashlib
|
|
13
|
+
import re
|
|
14
|
+
import subprocess
|
|
15
|
+
from pathlib import Path, PurePosixPath
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
EXPERIMENT_FILES = {"evals/behavioral.json", "evals/gate5-thresholds.json"}
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
def _finding(code: str, message: str) -> list[dict[str, str]]:
|
|
22
|
+
return [{"skill": "<repository>", "code": code, "message": message}]
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
def _git(repo: Path, *args: str) -> bytes:
|
|
26
|
+
result = subprocess.run(["git", "-C", str(repo), *args], capture_output=True, check=False)
|
|
27
|
+
if result.returncode:
|
|
28
|
+
# Git diagnostics may include machine-local paths; never echo raw output.
|
|
29
|
+
raise ValueError("evaluated Git commit/tree is unavailable")
|
|
30
|
+
return result.stdout
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
def _norm(data: bytes) -> bytes:
|
|
34
|
+
"""Content, made newline-agnostic. SVN materialises CRLF where Git keeps LF, so
|
|
35
|
+
a fingerprint over raw bytes reads the same corpus as tampered on one VCS and
|
|
36
|
+
intact on the other (the recorded values are the LF hashes). Normalise CRLF -> LF
|
|
37
|
+
for text; leave binary (anything with a NUL) untouched, so a font or image is
|
|
38
|
+
compared byte-for-byte as before."""
|
|
39
|
+
return data if b"\x00" in data else data.replace(b"\r\n", b"\n")
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
def _snapshot(repo: Path, commit: str) -> dict[str, bytes]:
|
|
43
|
+
if _git(repo, "cat-file", "-t", commit).strip() != b"commit":
|
|
44
|
+
raise ValueError("evaluated identity must be a commit, not a tree or tag")
|
|
45
|
+
entries = _git(repo, "ls-tree", "-r", "-z", commit, "--", "skills").split(b"\0")
|
|
46
|
+
files: dict[str, bytes] = {}
|
|
47
|
+
for entry in filter(None, entries):
|
|
48
|
+
metadata, raw_path = entry.split(b"\t", 1)
|
|
49
|
+
mode, kind, oid = metadata.decode("ascii").split()
|
|
50
|
+
path = PurePosixPath(raw_path.decode("utf-8"))
|
|
51
|
+
if mode not in {"100644", "100755"} or kind != "blob":
|
|
52
|
+
raise ValueError("evaluated skills tree contains an unsupported entry")
|
|
53
|
+
if path.is_absolute() or ".." in path.parts or path.parts[0] != "skills":
|
|
54
|
+
raise ValueError("evaluated tree contains an unsafe path")
|
|
55
|
+
files[path.relative_to("skills").as_posix()] = _norm(_git(repo, "cat-file", "blob", oid))
|
|
56
|
+
if not files:
|
|
57
|
+
raise ValueError("evaluated skills tree is empty")
|
|
58
|
+
return files
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
def _digest(files: dict[str, bytes]) -> str:
|
|
62
|
+
digest = hashlib.sha256()
|
|
63
|
+
# Match sorted(Path.rglob()) in the frozen series launcher, not raw string
|
|
64
|
+
# ordering: a directory's children sort before a similarly prefixed sibling.
|
|
65
|
+
for name in sorted(files, key=PurePosixPath):
|
|
66
|
+
digest.update(name.encode("utf-8") + b"\0" + files[name] + b"\0")
|
|
67
|
+
return digest.hexdigest()
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
def _packages(files: dict[str, bytes]) -> set[str]:
|
|
71
|
+
return {name.split("/")[0] for name in files
|
|
72
|
+
if len(PurePosixPath(name).parts) == 2 and name.endswith("/SKILL.md")}
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
def _projection(files: dict[str, bytes]) -> dict[str, bytes]:
|
|
76
|
+
packages = _packages(files)
|
|
77
|
+
return {name: data for name, data in files.items()
|
|
78
|
+
if name.split("/")[0] in packages or name in EXPERIMENT_FILES}
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
def _live(root: Path) -> dict[str, bytes]:
|
|
82
|
+
if root.is_symlink() or not root.is_dir():
|
|
83
|
+
raise ValueError("current skill root is missing or symlinked")
|
|
84
|
+
files: dict[str, bytes] = {}
|
|
85
|
+
for folder in root.iterdir():
|
|
86
|
+
if folder.is_symlink():
|
|
87
|
+
raise ValueError("current skills contain a symlinked directory")
|
|
88
|
+
if not folder.is_dir() or not (folder / "SKILL.md").exists():
|
|
89
|
+
continue
|
|
90
|
+
for path in folder.rglob("*"):
|
|
91
|
+
rel = path.relative_to(root)
|
|
92
|
+
if path.is_symlink():
|
|
93
|
+
raise ValueError("current skill package contains a symlink")
|
|
94
|
+
if "__pycache__" in rel.parts or path.suffix.lower() in {".pyc", ".pyo"}:
|
|
95
|
+
raise ValueError("release binding requires a clean source export without bytecode")
|
|
96
|
+
if path.is_file():
|
|
97
|
+
files[rel.as_posix()] = _norm(path.read_bytes())
|
|
98
|
+
for name in EXPERIMENT_FILES:
|
|
99
|
+
path = root / name
|
|
100
|
+
if path.parent.is_symlink() or path.is_symlink():
|
|
101
|
+
raise ValueError("current experiment contract contains a symlink")
|
|
102
|
+
if path.is_file():
|
|
103
|
+
files[name] = _norm(path.read_bytes())
|
|
104
|
+
return files
|
|
105
|
+
|
|
106
|
+
|
|
107
|
+
def check_release_binding(repo_root: Path, skills_root: Path, commit: object,
|
|
108
|
+
fingerprint: object) -> list[dict[str, str]]:
|
|
109
|
+
if (not isinstance(commit, str) or not re.fullmatch(r"[0-9a-f]{40}", commit)
|
|
110
|
+
or not isinstance(fingerprint, str)
|
|
111
|
+
or not re.fullmatch(r"[0-9a-f]{64}", fingerprint)):
|
|
112
|
+
return _finding("invalid-release-binding", "Gate 5 needs an exact commit and SHA-256 fingerprint")
|
|
113
|
+
try:
|
|
114
|
+
frozen = _snapshot(repo_root, commit)
|
|
115
|
+
except (OSError, ValueError, UnicodeError):
|
|
116
|
+
return _finding("unavailable-release-snapshot", "Cannot read a safe evaluated skills tree")
|
|
117
|
+
if _digest(frozen) != fingerprint:
|
|
118
|
+
return _finding("release-snapshot-mismatch", "Recorded fingerprint does not match evaluated Git tree")
|
|
119
|
+
try:
|
|
120
|
+
live = _live(skills_root)
|
|
121
|
+
except (OSError, ValueError):
|
|
122
|
+
return _finding("unsafe-release-content", "Require readable source packages without symlinks or bytecode/cache artifacts; use a clean export")
|
|
123
|
+
expected = _projection(frozen)
|
|
124
|
+
if not _packages(expected) or _packages(live) != _packages(expected) or live != expected:
|
|
125
|
+
changed = sum(live.get(name) != expected.get(name) for name in live.keys() | expected.keys())
|
|
126
|
+
return _finding("release-content-drift", f"Current packages/experiment differ from evaluated content ({changed} paths)")
|
|
127
|
+
return []
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
"""Safe indexing and retrieval for bundled Agent Skill resources."""
|
|
2
|
+
from __future__ import annotations
|
|
3
|
+
|
|
4
|
+
import mimetypes
|
|
5
|
+
from pathlib import Path, PurePosixPath
|
|
6
|
+
from typing import Any
|
|
7
|
+
|
|
8
|
+
RESOURCE_CATEGORIES = ("references", "scripts", "assets")
|
|
9
|
+
MAX_TEXT_BYTES = 512_000
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class SkillResourceError(ValueError):
|
|
13
|
+
code = "invalid_skill_resource"
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
class SkillResourceNotFound(SkillResourceError):
|
|
17
|
+
code = "skill_resource_not_found"
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
class SkillResourceNotText(SkillResourceError):
|
|
21
|
+
code = "skill_resource_not_text"
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
def _media_type(path: Path) -> str:
|
|
25
|
+
guessed, _ = mimetypes.guess_type(path.name)
|
|
26
|
+
if guessed:
|
|
27
|
+
return guessed
|
|
28
|
+
if path.suffix.lower() in {".md", ".markdown"}:
|
|
29
|
+
return "text/markdown"
|
|
30
|
+
return "text/plain"
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
def _resource_paths(root: Path, category: str) -> list[Path]:
|
|
34
|
+
folder = root / category
|
|
35
|
+
if not folder.is_dir():
|
|
36
|
+
return []
|
|
37
|
+
paths: list[Path] = []
|
|
38
|
+
for path in folder.rglob("*"):
|
|
39
|
+
if not path.is_file():
|
|
40
|
+
continue
|
|
41
|
+
try:
|
|
42
|
+
resolved = path.resolve(strict=True)
|
|
43
|
+
except (FileNotFoundError, OSError):
|
|
44
|
+
continue
|
|
45
|
+
if root != resolved and root not in resolved.parents:
|
|
46
|
+
continue
|
|
47
|
+
paths.append(path)
|
|
48
|
+
return sorted(paths)
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
def resource_index(root: Path) -> dict[str, Any]:
|
|
52
|
+
"""Return a bounded metadata index without loading resource contents."""
|
|
53
|
+
root = root.resolve()
|
|
54
|
+
categories: dict[str, list[str]] = {}
|
|
55
|
+
resources: list[dict[str, Any]] = []
|
|
56
|
+
for category in RESOURCE_CATEGORIES:
|
|
57
|
+
paths = _resource_paths(root, category)
|
|
58
|
+
rels = [path.relative_to(root).as_posix() for path in paths]
|
|
59
|
+
categories[category] = rels
|
|
60
|
+
for path, rel in zip(paths, rels):
|
|
61
|
+
resources.append({
|
|
62
|
+
"path": rel,
|
|
63
|
+
"category": category,
|
|
64
|
+
"size": path.stat().st_size,
|
|
65
|
+
"media_type": _media_type(path),
|
|
66
|
+
})
|
|
67
|
+
return {**categories, "resources": resources}
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
def _requested_path(requested: str) -> PurePosixPath:
|
|
71
|
+
value = str(requested or "").strip().replace("\\", "/")
|
|
72
|
+
if not value:
|
|
73
|
+
raise SkillResourceError("resource path is required")
|
|
74
|
+
path = PurePosixPath(value)
|
|
75
|
+
if path.is_absolute() or ".." in path.parts:
|
|
76
|
+
raise SkillResourceError("resource path must stay inside the skill")
|
|
77
|
+
if len(path.parts) < 2 or path.parts[0] not in RESOURCE_CATEGORIES:
|
|
78
|
+
allowed = ", ".join(f"{item}/" for item in RESOURCE_CATEGORIES)
|
|
79
|
+
raise SkillResourceError(f"resource path must start with one of: {allowed}")
|
|
80
|
+
return path
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
def read_text_resource(root: Path, requested: str,
|
|
84
|
+
max_bytes: int = MAX_TEXT_BYTES) -> dict[str, Any]:
|
|
85
|
+
"""Read one UTF-8 resource, rejecting traversal, symlink escape, and huge files."""
|
|
86
|
+
relative = _requested_path(requested)
|
|
87
|
+
if "\x00" in str(relative):
|
|
88
|
+
raise SkillResourceError("resource path contains a null byte")
|
|
89
|
+
try:
|
|
90
|
+
root_resolved = root.resolve()
|
|
91
|
+
candidate = root_resolved.joinpath(*relative.parts)
|
|
92
|
+
resolved = candidate.resolve(strict=True)
|
|
93
|
+
if root_resolved != resolved and root_resolved not in resolved.parents:
|
|
94
|
+
raise SkillResourceError("resource resolves outside the skill root")
|
|
95
|
+
if not resolved.is_file():
|
|
96
|
+
raise SkillResourceNotFound(f"resource is not a file: {relative.as_posix()}")
|
|
97
|
+
size = resolved.stat().st_size
|
|
98
|
+
if size > max_bytes:
|
|
99
|
+
raise SkillResourceError(
|
|
100
|
+
f"resource is {size} bytes; maximum retrievable size is {max_bytes}"
|
|
101
|
+
)
|
|
102
|
+
content = resolved.read_text(encoding="utf-8")
|
|
103
|
+
except FileNotFoundError as exc:
|
|
104
|
+
raise SkillResourceNotFound(f"resource not found: {relative.as_posix()}") from exc
|
|
105
|
+
except UnicodeDecodeError as exc:
|
|
106
|
+
raise SkillResourceNotText(
|
|
107
|
+
f"resource is not UTF-8 text: {relative.as_posix()}"
|
|
108
|
+
) from exc
|
|
109
|
+
except OSError as exc:
|
|
110
|
+
# OS messages may contain absolute installation paths; never emit them.
|
|
111
|
+
raise SkillResourceError("resource could not be read") from exc
|
|
112
|
+
return {
|
|
113
|
+
"path": relative.as_posix(),
|
|
114
|
+
"category": relative.parts[0],
|
|
115
|
+
"size": size,
|
|
116
|
+
"media_type": _media_type(resolved),
|
|
117
|
+
"content": content,
|
|
118
|
+
}
|