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.
Files changed (647) hide show
  1. procesio_cli/__init__.py +18 -0
  2. procesio_cli/_cli.py +71 -0
  3. procesio_cli/agents/__init__.py +0 -0
  4. procesio_cli/agents/_lib/__init__.py +0 -0
  5. procesio_cli/agents/_lib/actiondef.py +24 -0
  6. procesio_cli/agents/_lib/errors.py +40 -0
  7. procesio_cli/agents/_lib/reversibility.py +236 -0
  8. procesio_cli/agents/_lib/toolrunner.py +141 -0
  9. procesio_cli/agents/connector-builder/CONNECTOR-BUILDER-PLAYBOOK.md +62 -0
  10. procesio_cli/agents/connector-builder/CONNECTOR-BUILDER-PROCESIO-INTEROP.md +76 -0
  11. procesio_cli/agents/connector-builder/CONNECTOR-BUILDER-TROUBLESHOOTING.md +60 -0
  12. procesio_cli/agents/connector-builder/README.md +51 -0
  13. procesio_cli/agents/connector-builder/agent.yaml +61 -0
  14. procesio_cli/agents/connector-builder/context.py +19 -0
  15. procesio_cli/agents/connector-builder/handlers/__init__.py +1 -0
  16. procesio_cli/agents/connector-builder/handlers/checklist.py +71 -0
  17. procesio_cli/agents/connector-builder/handlers/guidance.py +37 -0
  18. procesio_cli/agents/connector-builder/handlers/nextstep.py +221 -0
  19. procesio_cli/agents/connector-builder/handlers/status.py +35 -0
  20. procesio_cli/agents/connector-builder/knowledge.py +47 -0
  21. procesio_cli/agents/connector-builder/main.py +93 -0
  22. procesio_cli/agents/connector-builder/tests/conftest.py +95 -0
  23. procesio_cli/agents/connector-builder/tests/test_cba_agent.py +148 -0
  24. procesio_cli/agents/orchestrator/__init__.py +0 -0
  25. procesio_cli/agents/orchestrator/bootstraplib.py +166 -0
  26. procesio_cli/agents/procesio/IMPLEMENTATION-PATTERNS/00-INDEX.md +60 -0
  27. procesio_cli/agents/procesio/IMPLEMENTATION-PATTERNS/01-PROCESSES.md +230 -0
  28. procesio_cli/agents/procesio/IMPLEMENTATION-PATTERNS/02-FORMS.md +287 -0
  29. procesio_cli/agents/procesio/IMPLEMENTATION-PATTERNS/03-INTEGRATIONS.md +384 -0
  30. procesio_cli/agents/procesio/IMPLEMENTATION-PATTERNS/04-DATABASE.md +293 -0
  31. procesio_cli/agents/procesio/PROCESIO-API-RELIABILITY-DOCTRINE.md +113 -0
  32. procesio_cli/agents/procesio/PROCESIO-BEST-PRACTICES.md +316 -0
  33. procesio_cli/agents/procesio/PROCESIO-BUILD-AND-TEST-PLAYBOOK.md +217 -0
  34. procesio_cli/agents/procesio/PROCESIO-DATASTORE.md +72 -0
  35. procesio_cli/agents/procesio/PROCESIO-ENVIRONMENTS.md +62 -0
  36. procesio_cli/agents/procesio/PROCESIO-SCHEDULING.md +47 -0
  37. procesio_cli/agents/procesio/PROCESIO-VISUAL-ORGANIZATION.md +175 -0
  38. procesio_cli/agents/procesio/README.md +97 -0
  39. procesio_cli/agents/procesio/__init__.py +0 -0
  40. procesio_cli/agents/procesio/agent.yaml +73 -0
  41. procesio_cli/agents/procesio/audit.py +226 -0
  42. procesio_cli/agents/procesio/checklist.py +135 -0
  43. procesio_cli/agents/procesio/context.py +19 -0
  44. procesio_cli/agents/procesio/handlers/__init__.py +0 -0
  45. procesio_cli/agents/procesio/handlers/audit.py +39 -0
  46. procesio_cli/agents/procesio/handlers/checklist.py +34 -0
  47. procesio_cli/agents/procesio/handlers/guidance.py +36 -0
  48. procesio_cli/agents/procesio/handlers/status.py +33 -0
  49. procesio_cli/agents/procesio/handlers/verify.py +39 -0
  50. procesio_cli/agents/procesio/knowledge.py +115 -0
  51. procesio_cli/agents/procesio/main.py +89 -0
  52. procesio_cli/agents/procesio/tests/__init__.py +0 -0
  53. procesio_cli/agents/procesio/tests/conftest.py +62 -0
  54. procesio_cli/agents/procesio/tests/test_audit.py +91 -0
  55. procesio_cli/agents/procesio/tests/test_checklist.py +28 -0
  56. procesio_cli/agents/procesio/tests/test_guidance.py +78 -0
  57. procesio_cli/agents/procesio/tests/test_manifest_sync.py +48 -0
  58. procesio_cli/agents/procesio/tests/test_verify.py +134 -0
  59. procesio_cli/agents/procesio/tests/test_workspace_scope.py +97 -0
  60. procesio_cli/agents/procesio/verifylib.py +222 -0
  61. procesio_cli/dashboard/README.md +117 -0
  62. procesio_cli/dashboard/__init__.py +18 -0
  63. procesio_cli/dashboard/serve.py +98 -0
  64. procesio_cli/dashboard/server/__init__.py +1 -0
  65. procesio_cli/dashboard/server/config_schemas.py +92 -0
  66. procesio_cli/dashboard/server/google.py +103 -0
  67. procesio_cli/dashboard/server/handler.py +160 -0
  68. procesio_cli/dashboard/server/inventory.py +213 -0
  69. procesio_cli/dashboard/server/jobs.py +118 -0
  70. procesio_cli/dashboard/server/llmtest.py +181 -0
  71. procesio_cli/dashboard/server/procesio_env.py +94 -0
  72. procesio_cli/dashboard/server/routes.py +74 -0
  73. procesio_cli/dashboard/server/runner.py +150 -0
  74. procesio_cli/dashboard/server/security.py +29 -0
  75. procesio_cli/dashboard/server/setup.py +211 -0
  76. procesio_cli/dashboard/server/validate.py +152 -0
  77. procesio_cli/dashboard/tests/conftest.py +16 -0
  78. procesio_cli/dashboard/tests/test_dashboard.py +225 -0
  79. procesio_cli/dashboard/tests/test_procesio_env.py +159 -0
  80. procesio_cli/dashboard/web/actions.js +274 -0
  81. procesio_cli/dashboard/web/api.js +79 -0
  82. procesio_cli/dashboard/web/app.js +385 -0
  83. procesio_cli/dashboard/web/copilot.js +72 -0
  84. procesio_cli/dashboard/web/google.js +121 -0
  85. procesio_cli/dashboard/web/index.html +67 -0
  86. procesio_cli/dashboard/web/procesio_env.js +187 -0
  87. procesio_cli/dashboard/web/styles.css +207 -0
  88. procesio_cli/registry.py +370 -0
  89. procesio_cli/scripts/build-router.py +249 -0
  90. procesio_cli/scripts/build-tool-skill.py +202 -0
  91. procesio_cli/scripts/check-requirements.py +131 -0
  92. procesio_cli/scripts/check-skill-governance.py +174 -0
  93. procesio_cli/scripts/evaluate-skill-routing.py +217 -0
  94. procesio_cli/scripts/evaluate-skills.py +316 -0
  95. procesio_cli/scripts/get-skill.py +122 -0
  96. procesio_cli/scripts/list-skills.py +68 -0
  97. procesio_cli/scripts/list-tools.py +73 -0
  98. procesio_cli/scripts/run-agent.py +59 -0
  99. procesio_cli/scripts/run-tool.py +123 -0
  100. procesio_cli/scripts/secret_scan.py +584 -0
  101. procesio_cli/scripts/set-credential.py +126 -0
  102. procesio_cli/scripts/validate-skills.py +530 -0
  103. procesio_cli/skills/PORTFOLIO.md +134 -0
  104. procesio_cli/skills/__init__.py +6 -0
  105. procesio_cli/skills/agent-skill-engineer/SKILL.md +226 -0
  106. procesio_cli/skills/agent-skill-engineer/evals/evals.json +422 -0
  107. procesio_cli/skills/agent-skill-engineer/references/authoring-standard.md +178 -0
  108. procesio_cli/skills/agent-skill-engineer/references/decision-framework.md +107 -0
  109. procesio_cli/skills/agent-skill-engineer/references/domain-evidence-protocol.md +248 -0
  110. procesio_cli/skills/agent-skill-engineer/references/evaluation-standard.md +191 -0
  111. procesio_cli/skills/agent-skill-engineer/references/expert-lenses.md +167 -0
  112. procesio_cli/skills/agent-skill-engineer/references/field-gate-standard.md +231 -0
  113. procesio_cli/skills/agent-skill-engineer/references/optimization-protocol.md +233 -0
  114. procesio_cli/skills/agent-skill-engineer/references/optimizer-contract.md +268 -0
  115. procesio_cli/skills/agent-skill-engineer/references/portability-standard.md +99 -0
  116. procesio_cli/skills/agent-skill-engineer/references/research-basis.md +128 -0
  117. procesio_cli/skills/agent-skill-engineer/references/review-standard.md +143 -0
  118. procesio_cli/skills/agent-skill-engineer/scripts/audit_skill.py +959 -0
  119. procesio_cli/skills/agent-skill-engineer/scripts/optimize_skill.py +891 -0
  120. procesio_cli/skills/agent-skill-engineer/scripts/scaffold_skill.py +397 -0
  121. procesio_cli/skills/evals/baseline-catalog.json +14 -0
  122. procesio_cli/skills/evals/baseline-routing-v2.json +38 -0
  123. procesio_cli/skills/evals/baseline.json +37 -0
  124. procesio_cli/skills/evals/behavioral.json +367 -0
  125. procesio_cli/skills/evals/field-boundary-development-v1.json +126 -0
  126. procesio_cli/skills/evals/field-closeout-correction-development-v1.json +23 -0
  127. procesio_cli/skills/evals/field-closeout-development-v1.json +89 -0
  128. procesio_cli/skills/evals/portfolio-pressure-training-v1.json +83 -0
  129. procesio_cli/skills/evals/routing.json +363 -0
  130. procesio_cli/skills/evals/validation-baseline.json +4 -0
  131. procesio_cli/skills/procesio-cli/SKILL.md +134 -0
  132. procesio_cli/skills/procesio-cli/evals/evals.json +111 -0
  133. procesio_cli/skills/procesio-cli/evals/workflows.json +16 -0
  134. procesio_cli/skills/procesio-cli/references/connector-lifecycle.md +47 -0
  135. procesio_cli/skills/procesio-cli/references/credentials-admin.md +113 -0
  136. procesio_cli/skills/procesio-cli/references/data-verification.md +71 -0
  137. procesio_cli/skills/procesio-cli/references/documents-files.md +44 -0
  138. procesio_cli/skills/procesio-cli/references/form-e2e.md +57 -0
  139. procesio_cli/skills/procesio-cli/references/operation-contract.md +138 -0
  140. procesio_cli/skills/procesio-cli/references/process-debugging.md +65 -0
  141. procesio_cli/skills/procesio-cli/references/process-lifecycle.md +88 -0
  142. procesio_cli/skills/procesio-cli/references/schedules-webhooks.md +58 -0
  143. procesio_cli/skills/procesio-cli/references/transport-environments.md +53 -0
  144. procesio_cli/skills/procesio-cli-maintainer/SKILL.md +84 -0
  145. procesio_cli/skills/procesio-cli-maintainer/evals/evals.json +116 -0
  146. procesio_cli/skills/procesio-cli-maintainer/references/change-contract.md +34 -0
  147. procesio_cli/skills/procesio-cli-maintainer/references/mcp-compatibility.md +13 -0
  148. procesio_cli/skills/procesio-cli-maintainer/references/skill-authoring.md +51 -0
  149. procesio_cli/skills/procesio-platform-advisor/SKILL.md +82 -0
  150. procesio_cli/skills/procesio-platform-advisor/evals/evals.json +116 -0
  151. procesio_cli/skills/procesio-platform-advisor/references/capability-map.md +22 -0
  152. procesio_cli/skills/procesio-platform-advisor/references/fit-framework.md +35 -0
  153. procesio_cli/skills/procesio-platform-advisor/references/freshness-policy.md +25 -0
  154. procesio_cli/skills/procesio-platform-advisor/references/sizing-method.md +70 -0
  155. procesio_cli/skills/procesio-platform-advisor/scripts/estimate_capacity.py +99 -0
  156. procesio_cli/skills/procesio-setup/SKILL.md +180 -0
  157. procesio_cli/skills/sql-server-optimizer/SKILL.md +86 -0
  158. procesio_cli/skills/sql-server-optimizer/evals/evals.json +116 -0
  159. procesio_cli/skills/sql-server-optimizer/references/db-context.md +44 -0
  160. procesio_cli/skills/sql-server-optimizer/references/generic-mode.md +32 -0
  161. procesio_cli/skills/sql-server-optimizer/references/procesio-mode.md +40 -0
  162. procesio_cli/skills/sql-server-optimizer/references/sql-rules.md +43 -0
  163. procesio_cli/skills/sql-server-optimizer/scripts/export-indexes.sql +178 -0
  164. procesio_cli/skills/sql-server-optimizer/scripts/export-procs-and-functions.sql +118 -0
  165. procesio_cli/skills/sql-server-optimizer/scripts/export-tables.sql +367 -0
  166. procesio_cli/skills/tests/__init__.py +0 -0
  167. procesio_cli/skills/tests/test_agent_skill_engineer.py +240 -0
  168. procesio_cli/skills/tests/test_auth_failure_stop.py +25 -0
  169. procesio_cli/skills/tests/test_capacity_estimator.py +85 -0
  170. procesio_cli/skills/tests/test_field_boundary_learning.py +100 -0
  171. procesio_cli/skills/tests/test_field_closeout_learning.py +123 -0
  172. procesio_cli/skills/tests/test_field_gate_standard.py +76 -0
  173. procesio_cli/skills/tests/test_operational_playbooks.py +51 -0
  174. procesio_cli/skills/tests/test_portfolio_pressure_training.py +35 -0
  175. procesio_cli/skills/tests/test_process_lifecycle_single_run.py +25 -0
  176. procesio_cli/skills/tests/test_skill_evaluator.py +67 -0
  177. procesio_cli/skills/tests/test_skill_optimizer.py +473 -0
  178. procesio_cli/skills/tests/test_skill_portfolio_review.py +70 -0
  179. procesio_cli/skills/tests/test_skill_release_binding.py +204 -0
  180. procesio_cli/skills/tests/test_skill_routing.py +74 -0
  181. procesio_cli/skills/tests/test_skill_scaffold_v2.py +116 -0
  182. procesio_cli/skills/tests/test_validate_skills.py +115 -0
  183. procesio_cli/tools/__init__.py +0 -0
  184. procesio_cli/tools/_lib/README.md +119 -0
  185. procesio_cli/tools/_lib/__init__.py +0 -0
  186. procesio_cli/tools/_lib/accounting.py +120 -0
  187. procesio_cli/tools/_lib/contacts.py +544 -0
  188. procesio_cli/tools/_lib/creds.py +83 -0
  189. procesio_cli/tools/_lib/creds_backends.py +578 -0
  190. procesio_cli/tools/_lib/dbprofiles.py +147 -0
  191. procesio_cli/tools/_lib/dbquery.py +286 -0
  192. procesio_cli/tools/_lib/dbschema.py +225 -0
  193. procesio_cli/tools/_lib/io.py +54 -0
  194. procesio_cli/tools/_lib/manifest.py +297 -0
  195. procesio_cli/tools/_lib/skill_release.py +127 -0
  196. procesio_cli/tools/_lib/skill_resources.py +118 -0
  197. procesio_cli/tools/_lib/userdata.py +228 -0
  198. procesio_cli/tools/_lib/webserialize/__init__.py +16 -0
  199. procesio_cli/tools/_lib/webserialize/admin.py +61 -0
  200. procesio_cli/tools/_lib/webserialize/client.py +264 -0
  201. procesio_cli/tools/_lib/webserialize/config.py +96 -0
  202. procesio_cli/tools/_lib/webserialize/errors.py +27 -0
  203. procesio_cli/tools/_lib/webserialize/framing.py +45 -0
  204. procesio_cli/tools/_lib/webserialize/registry.py +47 -0
  205. procesio_cli/tools/_lib/webserialize/runtime.py +61 -0
  206. procesio_cli/tools/_lib/webserialize/server.py +510 -0
  207. procesio_cli/tools/_lib/websession.py +194 -0
  208. procesio_cli/tools/connector-builder/CONNECTOR-BUILDER-API-NOTES.md +91 -0
  209. procesio_cli/tools/connector-builder/README.md +101 -0
  210. procesio_cli/tools/connector-builder/SKILL.md +248 -0
  211. procesio_cli/tools/connector-builder/__init__.py +7 -0
  212. procesio_cli/tools/connector-builder/actiondef.py +24 -0
  213. procesio_cli/tools/connector-builder/client.py +251 -0
  214. procesio_cli/tools/connector-builder/errors.py +44 -0
  215. procesio_cli/tools/connector-builder/gen_manifest.py +142 -0
  216. procesio_cli/tools/connector-builder/handlers/__init__.py +1 -0
  217. procesio_cli/tools/connector-builder/handlers/admin.py +182 -0
  218. procesio_cli/tools/connector-builder/handlers/auth.py +74 -0
  219. procesio_cli/tools/connector-builder/handlers/builds.py +396 -0
  220. procesio_cli/tools/connector-builder/handlers/common.py +104 -0
  221. procesio_cli/tools/connector-builder/handlers/files.py +111 -0
  222. procesio_cli/tools/connector-builder/handlers/raw.py +38 -0
  223. procesio_cli/tools/connector-builder/handlers/telemetry.py +39 -0
  224. procesio_cli/tools/connector-builder/main.py +94 -0
  225. procesio_cli/tools/connector-builder/tests/conftest.py +146 -0
  226. procesio_cli/tools/connector-builder/tests/test_cb_client.py +86 -0
  227. procesio_cli/tools/connector-builder/tests/test_cb_dispatch.py +105 -0
  228. procesio_cli/tools/connector-builder/tests/test_cb_manifest_sync.py +76 -0
  229. procesio_cli/tools/connector-builder/tests/test_cb_wait.py +123 -0
  230. procesio_cli/tools/connector-builder/tool.yaml +671 -0
  231. procesio_cli/tools/framework-map/.gitattributes +2 -0
  232. procesio_cli/tools/framework-map/README.md +98 -0
  233. procesio_cli/tools/framework-map/SKILL.md +30 -0
  234. procesio_cli/tools/framework-map/app.js +188 -0
  235. procesio_cli/tools/framework-map/fm_builder.py +476 -0
  236. procesio_cli/tools/framework-map/fm_catalog.py +19 -0
  237. procesio_cli/tools/framework-map/fm_ro_catalog.py +94 -0
  238. procesio_cli/tools/framework-map/fm_strings.py +101 -0
  239. procesio_cli/tools/framework-map/main.py +95 -0
  240. procesio_cli/tools/framework-map/styles.css +214 -0
  241. procesio_cli/tools/framework-map/tests/conftest.py +33 -0
  242. procesio_cli/tools/framework-map/tests/test_fm_build.py +126 -0
  243. procesio_cli/tools/framework-map/tests/test_fm_manifest_sync.py +63 -0
  244. procesio_cli/tools/framework-map/tests/test_fm_store_tree.py +75 -0
  245. procesio_cli/tools/framework-map/tool.yaml +61 -0
  246. procesio_cli/tools/mysql/MOVED-TO-CENTRAL.md +29 -0
  247. procesio_cli/tools/mysql/README.md +196 -0
  248. procesio_cli/tools/mysql/SKILL.md +37 -0
  249. procesio_cli/tools/mysql/__init__.py +0 -0
  250. procesio_cli/tools/mysql/connection.py +191 -0
  251. procesio_cli/tools/mysql/main.py +487 -0
  252. procesio_cli/tools/mysql/profiles.template.json +1 -0
  253. procesio_cli/tools/mysql/schema.py +434 -0
  254. procesio_cli/tools/mysql/tests/__init__.py +0 -0
  255. procesio_cli/tools/mysql/tests/conftest.py +21 -0
  256. procesio_cli/tools/mysql/tests/test_manifest_sync.py +68 -0
  257. procesio_cli/tools/mysql/tests/test_mysql.py +201 -0
  258. procesio_cli/tools/mysql/tests/test_mysql_schema.py +337 -0
  259. procesio_cli/tools/mysql/tool.yaml +112 -0
  260. procesio_cli/tools/procesio/DTO-SUBTOOLS-NOTE.md +360 -0
  261. procesio_cli/tools/procesio/FORM-DEV-GUIDE/00-INDEX.md +67 -0
  262. procesio_cli/tools/procesio/FORM-DEV-GUIDE/01-ANATOMY.md +209 -0
  263. procesio_cli/tools/procesio/FORM-DEV-GUIDE/02-CODE-INJECTION.md +309 -0
  264. procesio_cli/tools/procesio/FORM-DEV-GUIDE/03-DOM-CONTRACT.md +370 -0
  265. procesio_cli/tools/procesio/FORM-DEV-GUIDE/04-INTERACTION-RECIPES.md +600 -0
  266. procesio_cli/tools/procesio/FORM-DEV-GUIDE/05-STEPPER-AND-MOTION.md +426 -0
  267. procesio_cli/tools/procesio/FORM-DEV-GUIDE/06-PROCESS-INTEGRATION.md +347 -0
  268. procesio_cli/tools/procesio/FORM-DEV-GUIDE/07-DEPLOY-WORKFLOW.md +294 -0
  269. procesio_cli/tools/procesio/FORM-DEV-GUIDE/08-PITFALLS.md +569 -0
  270. procesio_cli/tools/procesio/FORM-DEV-GUIDE/09-NAVIGATION-AND-HOSTING.md +308 -0
  271. procesio_cli/tools/procesio/PHASE4-E2E-NOTES.md +594 -0
  272. procesio_cli/tools/procesio/PROCESIO-API-CORRECTIONS.md +295 -0
  273. procesio_cli/tools/procesio/PROCESIO-API-NOTES.md +6976 -0
  274. procesio_cli/tools/procesio/PROCESIO-AUTH-NOTES.md +226 -0
  275. procesio_cli/tools/procesio/PROCESIO-CARD-BUILD-NOTES.md +183 -0
  276. procesio_cli/tools/procesio/PROCESIO-CONNECTORS-NOTES.md +141 -0
  277. procesio_cli/tools/procesio/PROCESIO-CUSTOM-ACTION-NOTES.md +179 -0
  278. procesio_cli/tools/procesio/PROCESIO-DOCS-FIX-REPORT.md +123 -0
  279. procesio_cli/tools/procesio/PROCESIO-ENVIRONMENTS-NOTES.md +94 -0
  280. procesio_cli/tools/procesio/PROCESIO-FE-VALIDATION-NOTES.md +107 -0
  281. procesio_cli/tools/procesio/PROCESIO-FOREACH-NOTES.md +199 -0
  282. procesio_cli/tools/procesio/PROCESIO-FORM-API-HANG-NOTE.md +101 -0
  283. procesio_cli/tools/procesio/PROCESIO-FORM-SUBMISSION-NOTES.md +172 -0
  284. procesio_cli/tools/procesio/PROCESIO-HTML-TO-DOCX-NOTES.md +110 -0
  285. procesio_cli/tools/procesio/PROCESIO-INSTANCE-HISTORY-NOTES.md +242 -0
  286. procesio_cli/tools/procesio/PROCESIO-METERING-NOTES.md +201 -0
  287. procesio_cli/tools/procesio/PROCESIO-NODE-CODE-NOTES.md +279 -0
  288. procesio_cli/tools/procesio/PROCESIO-NODE-MODULE-WHITELIST.md +113 -0
  289. procesio_cli/tools/procesio/PROCESIO-PYTHON-ACTION-NOTES.md +165 -0
  290. procesio_cli/tools/procesio/PROCESIO-QUERY-STORE-NOTES.md +826 -0
  291. procesio_cli/tools/procesio/PROCESIO-RECONCILIATION-PATTERNS.md +104 -0
  292. procesio_cli/tools/procesio/PROCESIO-RESOURCE-MODEL-NOTES.md +1100 -0
  293. procesio_cli/tools/procesio/PROCESIO-SEND-EMAIL-CRED-OPTIONALITY.md +45 -0
  294. procesio_cli/tools/procesio/PROCESIO-SEND-EMAIL-NOTES.md +252 -0
  295. procesio_cli/tools/procesio/PROCESIO-SQL-ACTIONS-NOTES.md +284 -0
  296. procesio_cli/tools/procesio/PROCESIO-USAGE-GUIDE.md +219 -0
  297. procesio_cli/tools/procesio/README.md +341 -0
  298. procesio_cli/tools/procesio/SCHEDULE-INPUT-SECURITY-NOTES.md +63 -0
  299. procesio_cli/tools/procesio/SKILL.md +694 -0
  300. procesio_cli/tools/procesio/__init__.py +1 -0
  301. procesio_cli/tools/procesio/actiondef.py +27 -0
  302. procesio_cli/tools/procesio/assets/html2docx/html2docx.js +2155 -0
  303. procesio_cli/tools/procesio/auth.py +354 -0
  304. procesio_cli/tools/procesio/autogen.py +121 -0
  305. procesio_cli/tools/procesio/client.py +355 -0
  306. procesio_cli/tools/procesio/config.py +96 -0
  307. procesio_cli/tools/procesio/data/endpoints.json +2901 -0
  308. procesio_cli/tools/procesio/docs_info/API-DOCUMENTATION/01-authentication.md +180 -0
  309. procesio_cli/tools/procesio/docs_info/API-DOCUMENTATION/02-conventions.md +116 -0
  310. procesio_cli/tools/procesio/docs_info/API-DOCUMENTATION/ANONYMOUS-SURFACE.md +51 -0
  311. procesio_cli/tools/procesio/docs_info/API-DOCUMENTATION/README.md +104 -0
  312. procesio_cli/tools/procesio/docs_info/API-DOCUMENTATION/SYMBOL-INDEX.md +444 -0
  313. procesio_cli/tools/procesio/docs_info/API-DOCUMENTATION/endpoints/03-auth-users-workspaces.md +731 -0
  314. procesio_cli/tools/procesio/docs_info/API-DOCUMENTATION/endpoints/04-processes.md +913 -0
  315. procesio_cli/tools/procesio/docs_info/API-DOCUMENTATION/endpoints/05-actions.md +605 -0
  316. procesio_cli/tools/procesio/docs_info/API-DOCUMENTATION/endpoints/06-files.md +237 -0
  317. procesio_cli/tools/procesio/docs_info/API-DOCUMENTATION/endpoints/07-forms-documents.md +985 -0
  318. procesio_cli/tools/procesio/docs_info/API-DOCUMENTATION/endpoints/08-credentials.md +532 -0
  319. procesio_cli/tools/procesio/docs_info/API-DOCUMENTATION/endpoints/09-datastore-datatypes.md +830 -0
  320. procesio_cli/tools/procesio/docs_info/API-DOCUMENTATION/endpoints/10-custom-urls.md +319 -0
  321. procesio_cli/tools/procesio/docs_info/API-DOCUMENTATION/endpoints/11-subscriptions-resources-analytics.md +455 -0
  322. procesio_cli/tools/procesio/docs_info/API-DOCUMENTATION/endpoints/12-webhooks-notifications-misc.md +519 -0
  323. procesio_cli/tools/procesio/docs_info/API-DOCUMENTATION/endpoints/13-realtime-signalr.md +153 -0
  324. procesio_cli/tools/procesio/docs_info/API-DOCUMENTATION/endpoints/99-internal-and-other-services.md +52 -0
  325. procesio_cli/tools/procesio/docs_info/FormBuilder mock.ts +5725 -0
  326. procesio_cli/tools/procesio/docs_info/Procesio Platform Actions.json +30219 -0
  327. procesio_cli/tools/procesio/docs_info/form-config-enums.ts +92 -0
  328. procesio_cli/tools/procesio/docs_info/form-theme.ts +1603 -0
  329. procesio_cli/tools/procesio/docs_info/process-validation-reference-1.md +2739 -0
  330. procesio_cli/tools/procesio/dto/__init__.py +13 -0
  331. procesio_cli/tools/procesio/dto/credential/builder.py +179 -0
  332. procesio_cli/tools/procesio/dto/credential/config.schema.json +19 -0
  333. procesio_cli/tools/procesio/dto/credential/description.md +193 -0
  334. procesio_cli/tools/procesio/dto/credential/fixtures/rest.config.json +11 -0
  335. procesio_cli/tools/procesio/dto/credential/fixtures/rest.dto.json +28 -0
  336. procesio_cli/tools/procesio/dto/credential/fixtures/rest.template.json +44 -0
  337. procesio_cli/tools/procesio/dto/credential/template.dto.json +16 -0
  338. procesio_cli/tools/procesio/dto/data/_refresh.py +147 -0
  339. procesio_cli/tools/procesio/dto/data/action_catalog.json +30825 -0
  340. procesio_cli/tools/procesio/dto/data/action_families.json +55 -0
  341. procesio_cli/tools/procesio/dto/data/platform_types.json +182 -0
  342. procesio_cli/tools/procesio/dto/datatype/builder.py +223 -0
  343. procesio_cli/tools/procesio/dto/datatype/config.schema.json +47 -0
  344. procesio_cli/tools/procesio/dto/datatype/description.md +85 -0
  345. procesio_cli/tools/procesio/dto/datatype/fixtures/customer.config.json +41 -0
  346. procesio_cli/tools/procesio/dto/datatype/fixtures/customer.dto.json +164 -0
  347. procesio_cli/tools/procesio/dto/datatype/template.dto.json +37 -0
  348. procesio_cli/tools/procesio/dto/document/builder.py +193 -0
  349. procesio_cli/tools/procesio/dto/document/config.schema.json +33 -0
  350. procesio_cli/tools/procesio/dto/document/description.md +124 -0
  351. procesio_cli/tools/procesio/dto/document/fixtures/invoice.config.json +16 -0
  352. procesio_cli/tools/procesio/dto/document/fixtures/invoice.dto.json +32 -0
  353. procesio_cli/tools/procesio/dto/document/template.dto.json +14 -0
  354. procesio_cli/tools/procesio/dto/form/FORM-STYLING-NOTES.md +142 -0
  355. procesio_cli/tools/procesio/dto/form/GOLDEN-DRIFT-NOTES.md +72 -0
  356. procesio_cli/tools/procesio/dto/form/RUN-PROCESS-RESULT-NOTES.md +80 -0
  357. procesio_cli/tools/procesio/dto/form/addelement.py +277 -0
  358. procesio_cli/tools/procesio/dto/form/builder.py +1009 -0
  359. procesio_cli/tools/procesio/dto/form/capture_goldens.py +106 -0
  360. procesio_cli/tools/procesio/dto/form/code_cipher.py +67 -0
  361. procesio_cli/tools/procesio/dto/form/config.schema.json +76 -0
  362. procesio_cli/tools/procesio/dto/form/data_shell.json +1 -0
  363. procesio_cli/tools/procesio/dto/form/description.md +346 -0
  364. procesio_cli/tools/procesio/dto/form/elements/approval.json +259 -0
  365. procesio_cli/tools/procesio/dto/form/elements/assignee.json +137 -0
  366. procesio_cli/tools/procesio/dto/form/elements/button.json +125 -0
  367. procesio_cli/tools/procesio/dto/form/elements/chart.json +341 -0
  368. procesio_cli/tools/procesio/dto/form/elements/chat.json +199 -0
  369. procesio_cli/tools/procesio/dto/form/elements/checkbox.json +153 -0
  370. procesio_cli/tools/procesio/dto/form/elements/column.json +77 -0
  371. procesio_cli/tools/procesio/dto/form/elements/columns.json +78 -0
  372. procesio_cli/tools/procesio/dto/form/elements/datetime-input.json +304 -0
  373. procesio_cli/tools/procesio/dto/form/elements/divider.json +54 -0
  374. procesio_cli/tools/procesio/dto/form/elements/dropdown.json +130 -0
  375. procesio_cli/tools/procesio/dto/form/elements/dynamic-table-row.json +253 -0
  376. procesio_cli/tools/procesio/dto/form/elements/file-upload.json +196 -0
  377. procesio_cli/tools/procesio/dto/form/elements/file-viewer.json +169 -0
  378. procesio_cli/tools/procesio/dto/form/elements/heading.json +79 -0
  379. procesio_cli/tools/procesio/dto/form/elements/icon.json +107 -0
  380. procesio_cli/tools/procesio/dto/form/elements/image.json +174 -0
  381. procesio_cli/tools/procesio/dto/form/elements/input.json +206 -0
  382. procesio_cli/tools/procesio/dto/form/elements/list.json +202 -0
  383. procesio_cli/tools/procesio/dto/form/elements/number-input.json +202 -0
  384. procesio_cli/tools/procesio/dto/form/elements/paragraph.json +79 -0
  385. procesio_cli/tools/procesio/dto/form/elements/radiobox.json +174 -0
  386. procesio_cli/tools/procesio/dto/form/elements/section.json +114 -0
  387. procesio_cli/tools/procesio/dto/form/elements/select.json +217 -0
  388. procesio_cli/tools/procesio/dto/form/elements/side-panel.json +146 -0
  389. procesio_cli/tools/procesio/dto/form/elements/signature-pad.json +141 -0
  390. procesio_cli/tools/procesio/dto/form/elements/static-table-row.json +84 -0
  391. procesio_cli/tools/procesio/dto/form/elements/step.json +105 -0
  392. procesio_cli/tools/procesio/dto/form/elements/stepper.json +126 -0
  393. procesio_cli/tools/procesio/dto/form/elements/tab.json +77 -0
  394. procesio_cli/tools/procesio/dto/form/elements/table.json +279 -0
  395. procesio_cli/tools/procesio/dto/form/elements/tabs.json +114 -0
  396. procesio_cli/tools/procesio/dto/form/elements/textarea.json +213 -0
  397. procesio_cli/tools/procesio/dto/form/enum_map.json +68 -0
  398. procesio_cli/tools/procesio/dto/form/fieldpath.py +284 -0
  399. procesio_cli/tools/procesio/dto/form/fixtures/reg.config.json +32 -0
  400. procesio_cli/tools/procesio/dto/form/fixtures/reg.elements.json +638 -0
  401. procesio_cli/tools/procesio/dto/form/sync_from_mock.py +386 -0
  402. procesio_cli/tools/procesio/dto/framework.py +125 -0
  403. procesio_cli/tools/procesio/dto/process/builder.py +1991 -0
  404. procesio_cli/tools/procesio/dto/process/config.schema.json +159 -0
  405. procesio_cli/tools/procesio/dto/process/description.md +218 -0
  406. procesio_cli/tools/procesio/dto/process/fixtures/greet.config.json +32 -0
  407. procesio_cli/tools/procesio/dto/process/fixtures/greet.dto.json +317 -0
  408. procesio_cli/tools/procesio/dto/process/naming.py +305 -0
  409. procesio_cli/tools/procesio/dto/process/normalize.py +74 -0
  410. procesio_cli/tools/procesio/dto/process/template.dto.json +32 -0
  411. procesio_cli/tools/procesio/dto/refdata.py +87 -0
  412. procesio_cli/tools/procesio/dto/registry.py +27 -0
  413. procesio_cli/tools/procesio/dto/webhook/builder.py +142 -0
  414. procesio_cli/tools/procesio/dto/webhook/config.schema.json +25 -0
  415. procesio_cli/tools/procesio/dto/webhook/description.md +92 -0
  416. procesio_cli/tools/procesio/dto/webhook/fixtures/order.config.json +10 -0
  417. procesio_cli/tools/procesio/dto/webhook/fixtures/order.dto.json +25 -0
  418. procesio_cli/tools/procesio/dto/webhook/template.dto.json +14 -0
  419. procesio_cli/tools/procesio/environments.py +264 -0
  420. procesio_cli/tools/procesio/errors.py +166 -0
  421. procesio_cli/tools/procesio/flowmodel/README.md +37 -0
  422. procesio_cli/tools/procesio/flowmodel/__init__.py +14 -0
  423. procesio_cli/tools/procesio/flowmodel/digest.py +223 -0
  424. procesio_cli/tools/procesio/flowmodel/families.py +34 -0
  425. procesio_cli/tools/procesio/flowmodel/fevalidation.py +1098 -0
  426. procesio_cli/tools/procesio/flowmodel/formdigest.py +232 -0
  427. procesio_cli/tools/procesio/flowmodel/inspect.py +78 -0
  428. procesio_cli/tools/procesio/flowmodel/model.py +82 -0
  429. procesio_cli/tools/procesio/flowmodel/nodeparam.py +871 -0
  430. procesio_cli/tools/procesio/flowmodel/reader.py +191 -0
  431. procesio_cli/tools/procesio/flowmodel/sqlparam.py +410 -0
  432. procesio_cli/tools/procesio/form_code_keys.py +50 -0
  433. procesio_cli/tools/procesio/formlint.py +292 -0
  434. procesio_cli/tools/procesio/gen_manifest.py +118 -0
  435. procesio_cli/tools/procesio/handlers/__init__.py +1 -0
  436. procesio_cli/tools/procesio/handlers/auth_actions.py +103 -0
  437. procesio_cli/tools/procesio/handlers/catalog.py +147 -0
  438. procesio_cli/tools/procesio/handlers/common.py +90 -0
  439. procesio_cli/tools/procesio/handlers/customaction_ops.py +146 -0
  440. procesio_cli/tools/procesio/handlers/datastore_ops.py +482 -0
  441. procesio_cli/tools/procesio/handlers/datatype_ops.py +275 -0
  442. procesio_cli/tools/procesio/handlers/dto_actions.py +258 -0
  443. procesio_cli/tools/procesio/handlers/environment_admin.py +146 -0
  444. procesio_cli/tools/procesio/handlers/fevalidate.py +236 -0
  445. procesio_cli/tools/procesio/handlers/files.py +141 -0
  446. procesio_cli/tools/procesio/handlers/flowgraph.py +229 -0
  447. procesio_cli/tools/procesio/handlers/flowlint.py +269 -0
  448. procesio_cli/tools/procesio/handlers/form_chains.py +336 -0
  449. procesio_cli/tools/procesio/handlers/form_code.py +277 -0
  450. procesio_cli/tools/procesio/handlers/form_element.py +199 -0
  451. procesio_cli/tools/procesio/handlers/form_events.py +441 -0
  452. procesio_cli/tools/procesio/handlers/form_update.py +270 -0
  453. procesio_cli/tools/procesio/handlers/formprocess.py +211 -0
  454. procesio_cli/tools/procesio/handlers/generic.py +135 -0
  455. procesio_cli/tools/procesio/handlers/layout.py +137 -0
  456. procesio_cli/tools/procesio/handlers/nodeparams.py +1018 -0
  457. procesio_cli/tools/procesio/handlers/process_layout.py +189 -0
  458. procesio_cli/tools/procesio/handlers/process_naming.py +213 -0
  459. procesio_cli/tools/procesio/handlers/processes.py +416 -0
  460. procesio_cli/tools/procesio/handlers/profile_admin.py +184 -0
  461. procesio_cli/tools/procesio/handlers/resource_ops.py +447 -0
  462. procesio_cli/tools/procesio/handlers/schedules.py +320 -0
  463. procesio_cli/tools/procesio/handlers/sqlactions.py +232 -0
  464. procesio_cli/tools/procesio/handlers/transport.py +463 -0
  465. procesio_cli/tools/procesio/handlers/usageguide.py +222 -0
  466. procesio_cli/tools/procesio/layout/README.md +196 -0
  467. procesio_cli/tools/procesio/layout/__init__.py +11 -0
  468. procesio_cli/tools/procesio/layout/adapter.py +736 -0
  469. procesio_cli/tools/procesio/layout/cycles.py +186 -0
  470. procesio_cli/tools/procesio/layout/dispatch.py +39 -0
  471. procesio_cli/tools/procesio/layout/elk/elk_runner.mjs +50 -0
  472. procesio_cli/tools/procesio/layout/elk/package-lock.json +21 -0
  473. procesio_cli/tools/procesio/layout/elk/package.json +11 -0
  474. procesio_cli/tools/procesio/layout/elk_engine.py +568 -0
  475. procesio_cli/tools/procesio/layout/engine.py +1311 -0
  476. procesio_cli/tools/procesio/layout/report.py +187 -0
  477. procesio_cli/tools/procesio/main.py +179 -0
  478. procesio_cli/tools/procesio/profiles.py +193 -0
  479. procesio_cli/tools/procesio/reliability.py +193 -0
  480. procesio_cli/tools/procesio/sqlformat.py +167 -0
  481. procesio_cli/tools/procesio/swagger.py +51 -0
  482. procesio_cli/tools/procesio/tests/__init__.py +0 -0
  483. procesio_cli/tools/procesio/tests/conftest.py +129 -0
  484. procesio_cli/tools/procesio/tests/test_auth.py +200 -0
  485. procesio_cli/tools/procesio/tests/test_autogen.py +78 -0
  486. procesio_cli/tools/procesio/tests/test_builder_attrpath_sqlbind.py +180 -0
  487. procesio_cli/tools/procesio/tests/test_builder_custom_action_catalog.py +72 -0
  488. procesio_cli/tools/procesio/tests/test_client.py +114 -0
  489. procesio_cli/tools/procesio/tests/test_client_reliability.py +139 -0
  490. procesio_cli/tools/procesio/tests/test_customaction.py +103 -0
  491. procesio_cli/tools/procesio/tests/test_customaction_test.py +80 -0
  492. procesio_cli/tools/procesio/tests/test_cycles.py +69 -0
  493. procesio_cli/tools/procesio/tests/test_datastore.py +378 -0
  494. procesio_cli/tools/procesio/tests/test_datastore_node.py +94 -0
  495. procesio_cli/tools/procesio/tests/test_dispatch.py +170 -0
  496. procesio_cli/tools/procesio/tests/test_document_page_size.py +19 -0
  497. procesio_cli/tools/procesio/tests/test_dto.py +734 -0
  498. procesio_cli/tools/procesio/tests/test_edit_dryrun_preview.py +96 -0
  499. procesio_cli/tools/procesio/tests/test_elk_layout.py +221 -0
  500. procesio_cli/tools/procesio/tests/test_environments.py +214 -0
  501. procesio_cli/tools/procesio/tests/test_fevalidate_gate.py +104 -0
  502. procesio_cli/tools/procesio/tests/test_fevalidation.py +317 -0
  503. procesio_cli/tools/procesio/tests/test_fieldpath_variables.py +87 -0
  504. procesio_cli/tools/procesio/tests/test_files.py +72 -0
  505. procesio_cli/tools/procesio/tests/test_flow_digest.py +202 -0
  506. procesio_cli/tools/procesio/tests/test_flowlint.py +114 -0
  507. procesio_cli/tools/procesio/tests/test_flowmodel.py +158 -0
  508. procesio_cli/tools/procesio/tests/test_form_add_element.py +256 -0
  509. procesio_cli/tools/procesio/tests/test_form_approval_gaps.py +319 -0
  510. procesio_cli/tools/procesio/tests/test_form_auto_names.py +60 -0
  511. procesio_cli/tools/procesio/tests/test_form_chains.py +217 -0
  512. procesio_cli/tools/procesio/tests/test_form_code_actions.py +188 -0
  513. procesio_cli/tools/procesio/tests/test_form_code_keys.py +92 -0
  514. procesio_cli/tools/procesio/tests/test_form_code_style.py +178 -0
  515. procesio_cli/tools/procesio/tests/test_form_delete_element.py +99 -0
  516. procesio_cli/tools/procesio/tests/test_form_element_config.py +141 -0
  517. procesio_cli/tools/procesio/tests/test_form_event_maps.py +135 -0
  518. procesio_cli/tools/procesio/tests/test_form_event_ops.py +376 -0
  519. procesio_cli/tools/procesio/tests/test_form_event_replace.py +86 -0
  520. procesio_cli/tools/procesio/tests/test_form_events.py +92 -0
  521. procesio_cli/tools/procesio/tests/test_form_parity.py +171 -0
  522. procesio_cli/tools/procesio/tests/test_form_select_source.py +74 -0
  523. procesio_cli/tools/procesio/tests/test_form_sync.py +35 -0
  524. procesio_cli/tools/procesio/tests/test_form_update.py +133 -0
  525. procesio_cli/tools/procesio/tests/test_formlint.py +155 -0
  526. procesio_cli/tools/procesio/tests/test_formlint_css_scope.py +38 -0
  527. procesio_cli/tools/procesio/tests/test_formlint_field_names.py +83 -0
  528. procesio_cli/tools/procesio/tests/test_guards.py +110 -0
  529. procesio_cli/tools/procesio/tests/test_hidden_setting_types.py +39 -0
  530. procesio_cli/tools/procesio/tests/test_html2docx_asset.py +132 -0
  531. procesio_cli/tools/procesio/tests/test_key_handle_terminology.py +45 -0
  532. procesio_cli/tools/procesio/tests/test_layout.py +574 -0
  533. procesio_cli/tools/procesio/tests/test_layout_report.py +88 -0
  534. procesio_cli/tools/procesio/tests/test_manifest_sync.py +68 -0
  535. procesio_cli/tools/procesio/tests/test_nodedelete.py +151 -0
  536. procesio_cli/tools/procesio/tests/test_nodeparam.py +826 -0
  537. procesio_cli/tools/procesio/tests/test_normalize.py +70 -0
  538. procesio_cli/tools/procesio/tests/test_payload_docs.py +86 -0
  539. procesio_cli/tools/procesio/tests/test_process_action_naming.py +170 -0
  540. procesio_cli/tools/procesio/tests/test_process_call_api_seed.py +46 -0
  541. procesio_cli/tools/procesio/tests/test_process_ext.py +373 -0
  542. procesio_cli/tools/procesio/tests/test_process_invariants.py +183 -0
  543. procesio_cli/tools/procesio/tests/test_process_layout.py +117 -0
  544. procesio_cli/tools/procesio/tests/test_process_naming.py +188 -0
  545. procesio_cli/tools/procesio/tests/test_process_query_store.py +172 -0
  546. procesio_cli/tools/procesio/tests/test_processinfo_variable.py +56 -0
  547. procesio_cli/tools/procesio/tests/test_profiles.py +127 -0
  548. procesio_cli/tools/procesio/tests/test_put_projects.py +41 -0
  549. procesio_cli/tools/procesio/tests/test_reliability.py +107 -0
  550. procesio_cli/tools/procesio/tests/test_removal_gate.py +95 -0
  551. procesio_cli/tools/procesio/tests/test_resource_ops.py +173 -0
  552. procesio_cli/tools/procesio/tests/test_save_validity.py +207 -0
  553. procesio_cli/tools/procesio/tests/test_schedule_cron_shape.py +111 -0
  554. procesio_cli/tools/procesio/tests/test_schedules.py +309 -0
  555. procesio_cli/tools/procesio/tests/test_sqlconvert.py +234 -0
  556. procesio_cli/tools/procesio/tests/test_sqlformat.py +83 -0
  557. procesio_cli/tools/procesio/tests/test_sqlparam.py +187 -0
  558. procesio_cli/tools/procesio/tests/test_superseded_actions.py +54 -0
  559. procesio_cli/tools/procesio/tests/test_surgical_concurrency.py +156 -0
  560. procesio_cli/tools/procesio/tests/test_tier4.py +123 -0
  561. procesio_cli/tools/procesio/tests/test_transport.py +147 -0
  562. procesio_cli/tools/procesio/tests/test_transport_data_stores.py +168 -0
  563. procesio_cli/tools/procesio/tests/test_transport_mapper_repair.py +150 -0
  564. procesio_cli/tools/procesio/tests/test_transport_webhook_strip.py +253 -0
  565. procesio_cli/tools/procesio/tests/test_usage_guide.py +96 -0
  566. procesio_cli/tools/procesio/tool.yaml +12486 -0
  567. procesio_cli/tools/sqlserver/MOVED-TO-CENTRAL.md +29 -0
  568. procesio_cli/tools/sqlserver/README.md +192 -0
  569. procesio_cli/tools/sqlserver/SKILL.md +37 -0
  570. procesio_cli/tools/sqlserver/SQLSERVER-SCHEMA-NOTES.md +284 -0
  571. procesio_cli/tools/sqlserver/__init__.py +0 -0
  572. procesio_cli/tools/sqlserver/connection.py +242 -0
  573. procesio_cli/tools/sqlserver/main.py +521 -0
  574. procesio_cli/tools/sqlserver/profiles.template.json +1 -0
  575. procesio_cli/tools/sqlserver/schema.py +600 -0
  576. procesio_cli/tools/sqlserver/tests/__init__.py +0 -0
  577. procesio_cli/tools/sqlserver/tests/conftest.py +21 -0
  578. procesio_cli/tools/sqlserver/tests/test_connection.py +75 -0
  579. procesio_cli/tools/sqlserver/tests/test_dbprofiles.py +92 -0
  580. procesio_cli/tools/sqlserver/tests/test_dbquery.py +220 -0
  581. procesio_cli/tools/sqlserver/tests/test_manifest_sync.py +68 -0
  582. procesio_cli/tools/sqlserver/tests/test_sqlserver.py +326 -0
  583. procesio_cli/tools/sqlserver/tests/test_sqlserver_schema.py +488 -0
  584. procesio_cli/tools/sqlserver/tool.yaml +123 -0
  585. procesio_cli/tools/web/README.md +381 -0
  586. procesio_cli/tools/web/SKILL.md +37 -0
  587. procesio_cli/tools/web/WEB-AUTOMATION-NOTES.md +277 -0
  588. procesio_cli/tools/web/__init__.py +21 -0
  589. procesio_cli/tools/web/actiondef.py +24 -0
  590. procesio_cli/tools/web/api.py +444 -0
  591. procesio_cli/tools/web/brokered.py +107 -0
  592. procesio_cli/tools/web/driver.py +839 -0
  593. procesio_cli/tools/web/drivercontract.py +44 -0
  594. procesio_cli/tools/web/errors.py +54 -0
  595. procesio_cli/tools/web/handlers/__init__.py +1 -0
  596. procesio_cli/tools/web/handlers/archive.py +367 -0
  597. procesio_cli/tools/web/handlers/browse.py +182 -0
  598. procesio_cli/tools/web/handlers/contacts.py +74 -0
  599. procesio_cli/tools/web/handlers/sessmgmt.py +120 -0
  600. procesio_cli/tools/web/main.py +128 -0
  601. procesio_cli/tools/web/sessions.py +253 -0
  602. procesio_cli/tools/web/steps.py +162 -0
  603. procesio_cli/tools/web/tests/__init__.py +0 -0
  604. procesio_cli/tools/web/tests/conftest.py +197 -0
  605. procesio_cli/tools/web/tests/test_api.py +330 -0
  606. procesio_cli/tools/web/tests/test_archive.py +190 -0
  607. procesio_cli/tools/web/tests/test_brokered.py +138 -0
  608. procesio_cli/tools/web/tests/test_dispatch.py +132 -0
  609. procesio_cli/tools/web/tests/test_errors.py +60 -0
  610. procesio_cli/tools/web/tests/test_manifest_sync.py +76 -0
  611. procesio_cli/tools/web/tests/test_page_contacts.py +68 -0
  612. procesio_cli/tools/web/tests/test_sessions.py +145 -0
  613. procesio_cli/tools/web/tests/test_steps.py +210 -0
  614. procesio_cli/tools/web/tool.yaml +184 -0
  615. procesio_cli/tools/xlsx/README.md +34 -0
  616. procesio_cli/tools/xlsx/SKILL.md +28 -0
  617. procesio_cli/tools/xlsx/__init__.py +0 -0
  618. procesio_cli/tools/xlsx/main.py +129 -0
  619. procesio_cli/tools/xlsx/reader.py +91 -0
  620. procesio_cli/tools/xlsx/tests/__init__.py +0 -0
  621. procesio_cli/tools/xlsx/tests/conftest.py +39 -0
  622. procesio_cli/tools/xlsx/tests/test_xlsx.py +103 -0
  623. procesio_cli/tools/xlsx/tool.yaml +30 -0
  624. procesio_cli/webplatform/aat_mcp/AAT-MCP-NOTES.md +244 -0
  625. procesio_cli/webplatform/aat_mcp/README.md +78 -0
  626. procesio_cli/webplatform/aat_mcp/bridge.py +705 -0
  627. procesio_cli/webplatform/aat_mcp/chat_server.py +194 -0
  628. procesio_cli/webplatform/aat_mcp/chat_surface.snapshot.json +668 -0
  629. procesio_cli/webplatform/aat_mcp/chat_surface.yaml +372 -0
  630. procesio_cli/webplatform/aat_mcp/gate.py +68 -0
  631. procesio_cli/webplatform/aat_mcp/http_server.py +139 -0
  632. procesio_cli/webplatform/aat_mcp/protocol.py +175 -0
  633. procesio_cli/webplatform/aat_mcp/server.py +306 -0
  634. procesio_cli/webplatform/aat_mcp/tests/conftest.py +8 -0
  635. procesio_cli/webplatform/aat_mcp/tests/test_aat_mcp.py +255 -0
  636. procesio_cli/webplatform/aat_mcp/tests/test_chat_surface.py +247 -0
  637. procesio_cli/webplatform/aat_mcp/tests/test_discovery.py +489 -0
  638. procesio_cli/webplatform/aat_mcp/tests/test_multiuser.py +86 -0
  639. procesio_cli/webplatform/aat_mcp/tests/test_progressive_discovery.py +89 -0
  640. procesio_cli/webplatform/aat_mcp/tests/test_protocol.py +180 -0
  641. procesio_cli/webplatform/aat_mcp/tests/test_skill_discovery.py +23 -0
  642. procesio_cli-0.1.1.dist-info/METADATA +467 -0
  643. procesio_cli-0.1.1.dist-info/RECORD +647 -0
  644. procesio_cli-0.1.1.dist-info/WHEEL +4 -0
  645. procesio_cli-0.1.1.dist-info/entry_points.txt +7 -0
  646. procesio_cli-0.1.1.dist-info/licenses/LICENSE +201 -0
  647. procesio_cli-0.1.1.dist-info/licenses/NOTICE +5 -0
@@ -0,0 +1,126 @@
1
+ """Store a credential in this machine's OS credential store.
2
+
3
+ Which store that is follows the platform: Windows Credential Manager, the macOS
4
+ login Keychain, or the Linux desktop keyring (GNOME Keyring / KWallet). On a
5
+ headless machine, where no OS keyring exists, set AAT_CREDS_BACKEND=encrypted-file
6
+ (passphrase in AAT_SECRETS_PASSPHRASE) and this script writes there instead. The
7
+ identity is the same everywhere: agents-and-tools:<tool>:<secret>.
8
+
9
+ Secrets are prompted via getpass — never echoed, never written to disk in plaintext.
10
+
11
+ Usage:
12
+ python scripts/set-credential.py <tool> <secret> # set or overwrite
13
+ python scripts/set-credential.py <tool> <secret> --delete # remove
14
+ python scripts/set-credential.py <tool> <secret> --check # just check presence
15
+
16
+ Examples:
17
+ python scripts/set-credential.py ryver api-token
18
+ python scripts/set-credential.py ryver api-token --delete
19
+ """
20
+ from __future__ import annotations
21
+
22
+ import sys
23
+ from pathlib import Path
24
+
25
+ # Auto-switch to the project's .venv Python if we were launched with a different one.
26
+ _PROJECT_ROOT = Path(__file__).resolve().parents[1]
27
+ # .venv layout is per-OS: Scripts/python.exe on Windows, bin/python everywhere
28
+ # else. Hardcoding the Windows path made this a silent no-op on macOS/Linux,
29
+ # where the script then ran on whatever interpreter happened to invoke it.
30
+ _VENV_PY = (_PROJECT_ROOT / ".venv" / "Scripts" / "python.exe" if sys.platform == "win32"
31
+ else _PROJECT_ROOT / ".venv" / "bin" / "python")
32
+ if _VENV_PY.exists() and Path(sys.executable).resolve() != _VENV_PY.resolve():
33
+ import subprocess
34
+ sys.exit(subprocess.run([str(_VENV_PY), __file__, *sys.argv[1:]]).returncode)
35
+
36
+ import argparse # noqa: E402
37
+ import getpass # noqa: E402
38
+
39
+ sys.path.insert(0, str(_PROJECT_ROOT))
40
+
41
+ from tools._lib import creds # noqa: E402
42
+
43
+
44
+ def main() -> int:
45
+ p = argparse.ArgumentParser(
46
+ description="Store a credential in this machine's OS credential store "
47
+ "(Windows Credential Manager / macOS Keychain / Linux keyring).",
48
+ epilog="Target name in the store: agents-and-tools:<tool>:<secret>",
49
+ )
50
+ p.add_argument("tool", help="Tool name (matches name in tool.yaml)")
51
+ p.add_argument("secret", help="Secret name (matches a secrets[].name entry)")
52
+ g = p.add_mutually_exclusive_group()
53
+ g.add_argument("--delete", action="store_true", help="Delete instead of set")
54
+ g.add_argument("--check", action="store_true", help="Check presence; don't prompt")
55
+ g.add_argument("--from-file", help="Read the value from this file (full content, trimmed)")
56
+ g.add_argument("--stdin", action="store_true", help="Read the value from stdin (until EOF)")
57
+ args = p.parse_args()
58
+
59
+ target = f"agents-and-tools:{args.tool} / {args.secret}"
60
+
61
+ if args.check:
62
+ present = creds.has(args.tool, args.secret)
63
+ print(f"{target}: {'present' if present else 'missing'}")
64
+ return 0 if present else 1
65
+
66
+ if args.delete:
67
+ if not creds.has(args.tool, args.secret):
68
+ print(f"not found: {target}")
69
+ return 1
70
+ creds.delete(args.tool, args.secret)
71
+ print(f"deleted: {target}")
72
+ return 0
73
+
74
+ if creds.has(args.tool, args.secret):
75
+ # Skip the interactive overwrite prompt when reading non-interactively.
76
+ if not (args.from_file or args.stdin):
77
+ answer = input(f"{target} already exists. Overwrite? [y/N] ").strip().lower()
78
+ if answer != "y":
79
+ print("cancelled.")
80
+ return 0
81
+
82
+ interactive = not (args.from_file or args.stdin)
83
+ if args.from_file:
84
+ # utf-8-sig strips a BOM that Notepad/editors may prepend.
85
+ raw = Path(args.from_file).read_text(encoding="utf-8-sig")
86
+ if not raw.strip():
87
+ print(f"file is empty: {args.from_file}", file=sys.stderr)
88
+ return 1
89
+ elif args.stdin:
90
+ raw = sys.stdin.read()
91
+ if not raw.strip():
92
+ print("stdin is empty, aborting.", file=sys.stderr)
93
+ return 1
94
+ else:
95
+ raw = getpass.getpass(f"Enter value for {target}: ")
96
+ if not raw:
97
+ print("empty value, aborting.", file=sys.stderr)
98
+ return 1
99
+
100
+ # Clean pasted/typed input: drop surrounding whitespace and any non-printable
101
+ # control characters (e.g. a stray \x16 from a terminal paste).
102
+ value = "".join(c for c in raw if c.isprintable()).strip()
103
+ had_control = any((ord(c) < 32 or ord(c) == 127) for c in raw.strip())
104
+
105
+ if had_control:
106
+ print("warning: removed non-printable characters from the pasted value "
107
+ "(terminal paste corruption). Verify it stored correctly.",
108
+ file=sys.stderr)
109
+ # A 1-3 char "secret" is almost always a truncated paste (a known issue with
110
+ # getpass + paste on Windows terminals). Refuse and point to the safe path.
111
+ if len(value) < 4 and interactive:
112
+ print(f"refusing: got only {len(value)} usable char(s) — this looks like a "
113
+ "truncated paste (getpass mangles pasted secrets on some terminals).\n"
114
+ "Save the secret to a file and use --from-file instead:\n"
115
+ f" python scripts/set-credential.py {args.tool} {args.secret} "
116
+ "--from-file <path>", file=sys.stderr)
117
+ return 1
118
+
119
+ creds.set_secret(args.tool, args.secret, value)
120
+ print(f"stored: {target} ({len(value)} bytes) in the "
121
+ f"{getattr(creds._b(), 'name', 'default')} credential store")
122
+ return 0
123
+
124
+
125
+ if __name__ == "__main__":
126
+ raise SystemExit(main())
@@ -0,0 +1,530 @@
1
+ #!/usr/bin/env python3
2
+ """Validate registered Agent Skills and their repository integrations.
3
+
4
+ WHAT THIS ENFORCES
5
+ ------------------
6
+ Two guards in one script, dispatched by where a SKILL.md lives.
7
+
8
+ `skills/*/SKILL.md` (hand-written skills) get the full check: portable
9
+ frontmatter, a name that matches its folder, a bounded body, resolvable bundled
10
+ resources, shallow resource layout, and command examples that name real tools,
11
+ agents, actions, and arguments. A `--baseline` file may temporarily waive known
12
+ findings; it never hides new ones.
13
+
14
+ `tools/*/SKILL.md` and `agents/*/SKILL.md` (GENERATED manuals) get only the
15
+ loadability check: the frontmatter must parse and carry a name and description
16
+ within the length caps. The stricter skill rules are deliberately NOT applied to
17
+ them, because a generated manual legitimately declares a manifest name that can
18
+ differ from its folder and a body far longer than a hand-written skill. This is
19
+ the read-back the generated-manual pipeline never had: the generator built its
20
+ YAML frontmatter by string interpolation, so any manifest description carrying a
21
+ colon-space ended the key and produced a document no loader could read. It held
22
+ for roughly half the manuals in the tree and hit the best-described tools first.
23
+
24
+ HOOK CONTRACT
25
+ -------------
26
+ `scripts/hook-lib.sh :: hook_run_skill_validate` calls this as
27
+ `validate-skills.py --staged` and keys on the exit code: 0 pass, 1 block, 2
28
+ could-not-run (nothing checked, so nothing cleared). The staged set is
29
+ VCS-aware, exactly like `scripts/secret_scan.py`: git's staged set where there
30
+ is a `.git`, SVN's locally-modified set otherwise, because this repo is
31
+ published through both.
32
+
33
+ Spec: https://agentskills.io/specification
34
+
35
+ Usage:
36
+ python scripts/validate-skills.py # the whole tree
37
+ python scripts/validate-skills.py --staged # only changed SKILL.md (hook path)
38
+ python scripts/validate-skills.py path/to/SKILL.md ...
39
+ python scripts/validate-skills.py --json # machine-readable report
40
+
41
+ Exit codes:
42
+ 0 clean
43
+ 1 at least one blocking finding
44
+ 2 could not run (bad usage, unreadable tree, unenumerable staged set)
45
+ """
46
+ from __future__ import annotations
47
+
48
+ import argparse
49
+ import fnmatch
50
+ import json
51
+ import re
52
+ import subprocess
53
+ import sys
54
+ from dataclasses import asdict, dataclass
55
+ from datetime import date
56
+ from pathlib import Path, PurePosixPath
57
+ from typing import Any, Iterable
58
+
59
+ try:
60
+ import yaml
61
+ except ImportError: # pragma: no cover - environment problem, not a finding
62
+ print("validate-skills: PyYAML is not installed - nothing checked.", file=sys.stderr)
63
+ raise SystemExit(2)
64
+
65
+ REPO = Path(__file__).resolve().parents[1]
66
+ DEFAULT_SKILLS = REPO / "skills"
67
+ _NAME_RE = re.compile(r"^[a-z0-9]+(?:-[a-z0-9]+)*$")
68
+ _MARKDOWN_LINK_RE = re.compile(r"\[[^\]]*\]\(([^)]+)\)")
69
+ _CODE_PATH_RE = re.compile(
70
+ r"`((?:(?:references|scripts|assets)/)?[^`\n]+\.(?:md|sql|py|sh|ps1|js|ts|json|yaml|yml|html))`",
71
+ re.IGNORECASE,
72
+ )
73
+ _RUN_RE = re.compile(
74
+ r"python\s+scripts/run-(tool|agent)\.py\s+([a-z0-9-]+)(?:\s+([a-z0-9-]+))?",
75
+ re.IGNORECASE,
76
+ )
77
+ _OPTION_RE = re.compile(r"--([a-z0-9][a-z0-9-]*)", re.IGNORECASE)
78
+ _ALLOWED_FRONTMATTER = {
79
+ "name", "description", "version", "compatibility", "license", "allowed-tools",
80
+ "disable-model-invocation", "argument-hint", "routing", "metadata", "owner",
81
+ "last_verified", "baseline_version", "eval_suite", "source_policy", "tier",
82
+ }
83
+
84
+ MAX_NAME = 64
85
+ MAX_DESCRIPTION = 1024
86
+
87
+
88
+ @dataclass(frozen=True, order=True)
89
+ class Finding:
90
+ severity: str
91
+ code: str
92
+ skill: str
93
+ path: str
94
+ message: str
95
+
96
+
97
+ def _split_frontmatter(path: Path) -> tuple[dict[str, Any], str]:
98
+ text = path.read_text(encoding="utf-8")
99
+ lines = text.splitlines()
100
+ if not lines or lines[0].strip() != "---":
101
+ raise ValueError("missing opening ---")
102
+ for index in range(1, len(lines)):
103
+ if lines[index].strip() == "---":
104
+ raw = yaml.safe_load("\n".join(lines[1:index]))
105
+ if not isinstance(raw, dict):
106
+ raise ValueError("frontmatter must be a mapping")
107
+ return raw, "\n".join(lines[index + 1:])
108
+ raise ValueError("missing closing ---")
109
+
110
+
111
+ def _load_capabilities(repo: Path) -> dict[str, dict[str, dict[str, set[str]]]]:
112
+ result: dict[str, dict[str, dict[str, set[str]]]] = {"tool": {}, "agent": {}}
113
+ for kind, folder, manifest_name in (
114
+ ("tool", "tools", "tool.yaml"), ("agent", "agents", "agent.yaml")
115
+ ):
116
+ root = repo / folder
117
+ if not root.exists():
118
+ continue
119
+ for path in sorted(root.glob(f"*/{manifest_name}")):
120
+ if path.parent.name.startswith("_"):
121
+ continue
122
+ try:
123
+ raw = yaml.safe_load(path.read_text(encoding="utf-8"))
124
+ except (OSError, yaml.YAMLError):
125
+ continue
126
+ if not isinstance(raw, dict) or not raw.get("name"):
127
+ continue
128
+ actions: dict[str, set[str]] = {}
129
+ for action in raw.get("actions") or []:
130
+ if not isinstance(action, dict) or not action.get("name"):
131
+ continue
132
+ actions[str(action["name"])] = {
133
+ str(arg["name"])
134
+ for arg in (action.get("args") or [])
135
+ if isinstance(arg, dict) and arg.get("name")
136
+ }
137
+ result[kind][str(raw["name"])] = actions
138
+ return result
139
+
140
+
141
+ def _finding(code: str, skill: str, path: Path | str, message: str,
142
+ severity: str = "error") -> Finding:
143
+ return Finding(severity=severity, code=code, skill=skill,
144
+ path=str(path).replace("\\", "/"), message=message)
145
+
146
+
147
+ def _candidate_paths(raw: str, source: Path, root: Path) -> list[Path]:
148
+ cleaned = raw.strip().split("#", 1)[0].split("?", 1)[0]
149
+ posix = PurePosixPath(cleaned)
150
+ if not cleaned or cleaned.startswith(("#", "http://", "https://", "mailto:")):
151
+ return []
152
+ if posix.is_absolute() or ".." in posix.parts:
153
+ return [root.parent / "__unsafe_reference__"]
154
+ path = Path(*posix.parts)
155
+ candidates = [source.parent / path]
156
+ if len(posix.parts) == 1:
157
+ candidates += [root / path, root / "references" / path,
158
+ root / "scripts" / path, root / "assets" / path]
159
+ else:
160
+ candidates.append(root / path)
161
+ unique: list[Path] = []
162
+ seen: set[str] = set()
163
+ for candidate in candidates:
164
+ key = str(candidate)
165
+ if key not in seen:
166
+ seen.add(key)
167
+ unique.append(candidate)
168
+ return unique
169
+
170
+
171
+ def _scan_references(skill: str, root: Path, source: Path, text: str) -> list[Finding]:
172
+ findings: list[Finding] = []
173
+ refs = [match.group(1).strip().split()[0] for match in _MARKDOWN_LINK_RE.finditer(text)]
174
+ refs += [match.group(1).strip() for match in _CODE_PATH_RE.finditer(text)]
175
+ for raw in sorted(set(refs)):
176
+ if raw.startswith(("http://", "https://", "mailto:", "#")):
177
+ continue
178
+ candidates = _candidate_paths(raw, source, root)
179
+ if not candidates:
180
+ continue
181
+ if any("__unsafe_reference__" in candidate.parts for candidate in candidates):
182
+ findings.append(_finding("unsafe-reference", skill, source.relative_to(root),
183
+ f"reference escapes the skill root: {raw}"))
184
+ continue
185
+ if not any(candidate.exists() for candidate in candidates):
186
+ findings.append(_finding("missing-reference", skill, source.relative_to(root),
187
+ f"referenced resource does not exist: {raw}"))
188
+ return findings
189
+
190
+
191
+ def _scan_commands(skill: str, root: Path, source: Path, text: str,
192
+ capabilities: dict[str, dict[str, dict[str, set[str]]]]) -> list[Finding]:
193
+ findings: list[Finding] = []
194
+ for match in _RUN_RE.finditer(text):
195
+ kind, name, action = (value.lower() if value else value for value in match.groups())
196
+ catalog = capabilities[kind]
197
+ if name not in catalog:
198
+ findings.append(_finding("unknown-capability", skill, source.relative_to(root),
199
+ f"unknown {kind}: {name}"))
200
+ continue
201
+ if not action or action.startswith("<"):
202
+ continue
203
+ actions = catalog[name]
204
+ if actions and action not in actions:
205
+ findings.append(_finding("unknown-action", skill, source.relative_to(root),
206
+ f"unknown {kind} action: {name} {action}"))
207
+ continue
208
+ if action in actions:
209
+ invocation = match.string[match.start():match.string.find("\n", match.start())]
210
+ for option in _OPTION_RE.findall(invocation):
211
+ if option not in actions[action] and option not in {"help"}:
212
+ findings.append(_finding(
213
+ "unknown-argument", skill, source.relative_to(root),
214
+ f"unknown argument --{option} for {name} {action}", severity="warning"
215
+ ))
216
+ return findings
217
+
218
+
219
+ def validate_skill(skill_md: Path, repo: Path,
220
+ capabilities: dict[str, dict[str, dict[str, set[str]]]]) -> list[Finding]:
221
+ root = skill_md.parent
222
+ folder_name = root.name
223
+ findings: list[Finding] = []
224
+ try:
225
+ frontmatter, body = _split_frontmatter(skill_md)
226
+ except (OSError, UnicodeError, yaml.YAMLError, ValueError) as exc:
227
+ return [_finding("invalid-frontmatter", folder_name, "SKILL.md", str(exc))]
228
+
229
+ name = str(frontmatter.get("name") or "").strip()
230
+ description = " ".join(str(frontmatter.get("description") or "").split())
231
+ skill = name or folder_name
232
+ if not name:
233
+ findings.append(_finding("missing-name", skill, "SKILL.md", "frontmatter name is required"))
234
+ elif not _NAME_RE.fullmatch(name) or len(name) > MAX_NAME:
235
+ findings.append(_finding("invalid-name", skill, "SKILL.md",
236
+ "name must be <=64 lowercase letters, digits, and hyphens"))
237
+ if name and name != folder_name:
238
+ findings.append(_finding("folder-name-mismatch", skill, "SKILL.md",
239
+ f"folder {folder_name!r} does not match name {name!r}"))
240
+ if not description:
241
+ findings.append(_finding("missing-description", skill, "SKILL.md",
242
+ "frontmatter description is required"))
243
+ elif len(description) > MAX_DESCRIPTION:
244
+ findings.append(_finding("description-too-long", skill, "SKILL.md",
245
+ f"description is {len(description)} characters; maximum is 1024"))
246
+ body_lines = len(body.splitlines())
247
+ if body_lines > 500:
248
+ findings.append(_finding("body-too-long", skill, "SKILL.md",
249
+ f"SKILL.md body has {body_lines} lines; maximum is 500"))
250
+
251
+ for key in sorted(set(frontmatter) - _ALLOWED_FRONTMATTER):
252
+ findings.append(_finding("unknown-frontmatter-key", skill, "SKILL.md",
253
+ f"unrecognized frontmatter key: {key}", severity="warning"))
254
+
255
+ if frontmatter.get("last_verified"):
256
+ try:
257
+ date.fromisoformat(str(frontmatter["last_verified"]))
258
+ except ValueError:
259
+ findings.append(_finding("invalid-last-verified", skill, "SKILL.md",
260
+ "last_verified must be YYYY-MM-DD"))
261
+ if frontmatter.get("eval_suite"):
262
+ target = root / str(frontmatter["eval_suite"])
263
+ if not target.is_file():
264
+ findings.append(_finding("missing-eval-suite", skill, "SKILL.md",
265
+ f"eval_suite does not exist: {frontmatter['eval_suite']}"))
266
+
267
+ # Python imports performed by tests can create bytecode caches inside a
268
+ # skill's scripts directory. They are transient interpreter artifacts, not
269
+ # bundled skill resources, and must not turn test order into validation state.
270
+ files = (
271
+ path
272
+ for path in root.rglob("*")
273
+ if path.is_file()
274
+ and path.suffix.lower() != ".pyc"
275
+ and "__pycache__" not in path.relative_to(root).parts
276
+ )
277
+ for file in sorted(files):
278
+ rel = file.relative_to(root)
279
+ if rel.parts[0] in {"references", "scripts", "assets"} and len(rel.parts) > 2:
280
+ findings.append(_finding("nested-resource", skill, rel,
281
+ "bundled resources must stay one level below their category"))
282
+ if rel.parts[0] == "scripts" and file.suffix.lower() in {".html", ".svg", ".png", ".jpg", ".jpeg"}:
283
+ findings.append(_finding("asset-in-scripts", skill, rel,
284
+ "output templates and media belong under assets/"))
285
+ if rel.parts[0] == "references" and "scripts" in rel.parts[1:-1]:
286
+ findings.append(_finding("script-in-references", skill, rel,
287
+ "executable helpers belong directly under scripts/"))
288
+ if file.suffix.lower() in {".md", ".markdown"}:
289
+ try:
290
+ text = file.read_text(encoding="utf-8")
291
+ except (OSError, UnicodeError) as exc:
292
+ findings.append(_finding("unreadable-resource", skill, rel, str(exc)))
293
+ continue
294
+ findings.extend(_scan_references(skill, root, file, text))
295
+ findings.extend(_scan_commands(skill, root, file, text, capabilities))
296
+
297
+ return sorted(set(findings))
298
+
299
+
300
+ def loadability(skill_md: Path, repo: Path) -> list[Finding]:
301
+ """The generated-manual guard: the file must parse and carry a name and
302
+ description within the caps. Deliberately no folder/name, body-length, or
303
+ resource rules - a generated manual legitimately breaks those."""
304
+ try:
305
+ rel = skill_md.relative_to(repo).as_posix()
306
+ except ValueError:
307
+ rel = skill_md.name
308
+ folder = skill_md.parent.name
309
+ try:
310
+ frontmatter, _ = _split_frontmatter(skill_md)
311
+ except (OSError, UnicodeError, yaml.YAMLError, ValueError) as exc:
312
+ return [_finding("invalid-frontmatter", folder, rel, str(exc))]
313
+ findings: list[Finding] = []
314
+ name = str(frontmatter.get("name") or "").strip()
315
+ description = str(frontmatter.get("description") or "").strip()
316
+ skill = name or folder
317
+ if not name:
318
+ findings.append(_finding("missing-name", skill, rel, "frontmatter name is required"))
319
+ elif len(name) > MAX_NAME:
320
+ findings.append(_finding("invalid-name", skill, rel,
321
+ f"name is {len(name)} chars, limit {MAX_NAME}"))
322
+ if not description:
323
+ findings.append(_finding("missing-description", skill, rel,
324
+ "frontmatter description is required"))
325
+ elif len(description) > MAX_DESCRIPTION:
326
+ over = len(description) - MAX_DESCRIPTION
327
+ findings.append(_finding("description-too-long", skill, rel,
328
+ f"description is {len(description)} chars, limit "
329
+ f"{MAX_DESCRIPTION} (over by {over})"))
330
+ return findings
331
+
332
+
333
+ def validate_repo(skills_root: Path = DEFAULT_SKILLS, repo: Path = REPO) -> list[Finding]:
334
+ capabilities = _load_capabilities(repo)
335
+ findings: list[Finding] = []
336
+ for skill_md in sorted(skills_root.glob("*/SKILL.md")):
337
+ if skill_md.parent.name.startswith("_") or skill_md.parent.name == "tests":
338
+ continue
339
+ findings.extend(validate_skill(skill_md, repo, capabilities))
340
+ if not list(skills_root.glob("*/SKILL.md")):
341
+ findings.append(_finding("no-skills", "<repository>", skills_root,
342
+ "no skills/*/SKILL.md files found"))
343
+ return sorted(set(findings))
344
+
345
+
346
+ def _is_skill_path(path: Path, repo: Path) -> bool:
347
+ try:
348
+ parts = path.resolve().relative_to(repo.resolve()).parts
349
+ except ValueError:
350
+ return "skills" in path.parts
351
+ return bool(parts) and parts[0] == "skills"
352
+
353
+
354
+ def governed_folders(skills_root: Path) -> set[str]:
355
+ """Skill folders that opt into the governance/eval discipline, by the
356
+ `source_policy` marker. The full rubric (folder/name, body length, resolvable
357
+ and shallow resources, resolvable command examples) is authored for these.
358
+ Imported/portable skills and generated tool manuals omit the marker and get
359
+ only the loadability guard, so a legitimate imported skill - one that runs
360
+ long, references a repo file outside its own folder, or ships nested fonts -
361
+ is not blocked by a rubric it was never written to. In procesio-cli, whose
362
+ `skills/` IS the portfolio, every skill is governed and the two coincide."""
363
+ names: set[str] = set()
364
+ for skill_md in sorted(skills_root.glob("*/SKILL.md")):
365
+ if skill_md.parent.name.startswith("_") or skill_md.parent.name == "tests":
366
+ continue
367
+ try:
368
+ frontmatter, _ = _split_frontmatter(skill_md)
369
+ except (OSError, UnicodeError, yaml.YAMLError, ValueError):
370
+ continue
371
+ if frontmatter.get("source_policy"):
372
+ names.add(skill_md.parent.name)
373
+ return names
374
+
375
+
376
+ def check_path(path: Path, repo: Path,
377
+ capabilities: dict[str, dict[str, dict[str, set[str]]]],
378
+ governed: set[str]) -> list[Finding]:
379
+ """Dispatch one SKILL.md: the full skill rubric for a governed skill, the
380
+ loadability guard for an imported skill or a generated manual (tools/, agents/)."""
381
+ if _is_skill_path(path, repo) and path.parent.name in governed:
382
+ return validate_skill(path, repo, capabilities)
383
+ return loadability(path, repo)
384
+
385
+
386
+ def _all_manual_files(repo: Path) -> list[Path]:
387
+ manuals: list[Path] = []
388
+ for folder in ("tools", "agents"):
389
+ root = repo / folder
390
+ if root.exists():
391
+ manuals += [p for p in sorted(root.glob("*/SKILL.md"))
392
+ if not p.parent.name.startswith("_")]
393
+ return manuals
394
+
395
+
396
+ def _changed_skill_files(repo: Path) -> list[Path]:
397
+ """The SKILL.md files this commit would carry, VCS-aware (git staged set, or
398
+ SVN locally-modified set). A path that no longer exists (a delete) is skipped."""
399
+ is_git = (repo / ".git").exists()
400
+ if is_git:
401
+ cmd = ["git", "-C", str(repo), "diff", "--cached", "--name-only", "--diff-filter=ACM"]
402
+ else:
403
+ cmd = ["svn", "status", str(repo)]
404
+ try:
405
+ raw = subprocess.run(cmd, capture_output=True, text=True, encoding="utf-8",
406
+ timeout=120).stdout
407
+ except Exception as exc: # noqa: BLE001 - cannot enumerate means cannot clear
408
+ print(f"validate-skills: could not list changed files ({exc}).", file=sys.stderr)
409
+ raise SystemExit(2)
410
+
411
+ out: list[str] = []
412
+ for line in raw.splitlines():
413
+ line = line.rstrip()
414
+ if not line:
415
+ continue
416
+ if is_git:
417
+ path = line
418
+ else:
419
+ if line[:1] not in ("A", "M"):
420
+ continue
421
+ path = line[1:].strip()
422
+ if path.replace("\\", "/").endswith("SKILL.md"):
423
+ out.append(path)
424
+
425
+ files: list[Path] = []
426
+ for p in out:
427
+ candidate = Path(p)
428
+ if not candidate.is_absolute():
429
+ candidate = repo / p
430
+ if candidate.exists():
431
+ files.append(candidate)
432
+ return sorted(set(files))
433
+
434
+
435
+ def _load_waivers(path: Path | None) -> list[dict[str, str]]:
436
+ if path is None:
437
+ return []
438
+ raw = json.loads(path.read_text(encoding="utf-8"))
439
+ rows = raw.get("allow", []) if isinstance(raw, dict) else raw
440
+ if not isinstance(rows, list):
441
+ raise ValueError(f"{path}: expected an allow list")
442
+ return [{key: str(value) for key, value in row.items()} for row in rows]
443
+
444
+
445
+ def _waived(finding: Finding, waivers: Iterable[dict[str, str]]) -> bool:
446
+ payload = asdict(finding)
447
+ for waiver in waivers:
448
+ if all(fnmatch.fnmatch(payload.get(key, ""), pattern) for key, pattern in waiver.items()):
449
+ return True
450
+ return False
451
+
452
+
453
+ def _parser() -> argparse.ArgumentParser:
454
+ parser = argparse.ArgumentParser(description="Validate registered Agent Skills.")
455
+ parser.add_argument("paths", nargs="*", help="SKILL.md files (default: the whole tree)")
456
+ parser.add_argument("--staged", action="store_true",
457
+ help="check only the SKILL.md files this commit would carry")
458
+ parser.add_argument("--skills-root", type=Path, default=DEFAULT_SKILLS)
459
+ parser.add_argument("--repo", type=Path, default=REPO)
460
+ parser.add_argument("--baseline", type=Path,
461
+ help="JSON waiver file for known findings; new findings still fail")
462
+ parser.add_argument("--strict-warnings", action="store_true")
463
+ parser.add_argument("--json", action="store_true")
464
+ return parser
465
+
466
+
467
+ def main(argv: list[str] | None = None) -> int:
468
+ args = _parser().parse_args(argv)
469
+ repo = args.repo
470
+ capabilities = _load_capabilities(repo)
471
+ governed = governed_folders(args.skills_root)
472
+
473
+ if args.paths:
474
+ files = [Path(p) if Path(p).is_absolute() else repo / p for p in args.paths]
475
+ findings = [f for path in files for f in check_path(path, repo, capabilities, governed)]
476
+ elif args.staged:
477
+ files = _changed_skill_files(repo)
478
+ if not files:
479
+ print("validate-skills: no SKILL.md in scope - nothing to check.")
480
+ return 0
481
+ findings = [f for path in files for f in check_path(path, repo, capabilities, governed)]
482
+ else:
483
+ findings = []
484
+ skill_files = sorted(args.skills_root.glob("*/SKILL.md"))
485
+ for skill_md in skill_files:
486
+ if skill_md.parent.name.startswith("_") or skill_md.parent.name == "tests":
487
+ continue
488
+ findings.extend(check_path(skill_md, repo, capabilities, governed))
489
+ if not skill_files:
490
+ findings.append(_finding("no-skills", "<repository>", args.skills_root,
491
+ "no skills/*/SKILL.md files found"))
492
+ for manual in _all_manual_files(repo):
493
+ findings.extend(loadability(manual, repo))
494
+
495
+ findings = sorted(set(findings))
496
+ try:
497
+ waivers = _load_waivers(args.baseline)
498
+ except (OSError, ValueError, json.JSONDecodeError) as exc:
499
+ print(f"validate-skills: could not read baseline ({exc}).", file=sys.stderr)
500
+ return 2
501
+
502
+ rows = []
503
+ blocking = []
504
+ for finding in findings:
505
+ waived = _waived(finding, waivers)
506
+ row = {**asdict(finding), "waived": waived}
507
+ rows.append(row)
508
+ if not waived and (finding.severity == "error" or args.strict_warnings):
509
+ blocking.append(row)
510
+
511
+ if args.json:
512
+ report = {
513
+ "schema_version": 1,
514
+ "finding_count": len(rows),
515
+ "blocking_count": len(blocking),
516
+ "findings": rows,
517
+ }
518
+ print(json.dumps(report, indent=2, sort_keys=True))
519
+ elif not rows:
520
+ print("validate-skills: clean")
521
+ else:
522
+ for row in rows:
523
+ marker = "WAIVED" if row["waived"] else row["severity"].upper()
524
+ print(f"{marker}: {row['skill']}:{row['path']}: {row['code']}: {row['message']}")
525
+ print(f"{len(rows)} finding(s), {len(blocking)} blocking")
526
+ return 1 if blocking else 0
527
+
528
+
529
+ if __name__ == "__main__":
530
+ raise SystemExit(main())