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,217 @@
1
+ #!/usr/bin/env python3
2
+ """Deterministic lint for skill-description routing boundaries.
3
+
4
+ This is a cheap regression gate, not a model benchmark. It evaluates the same
5
+ versioned prompt corpus against either the live skills or a frozen catalog.
6
+ Release decisions need independently validated behavioral evidence. The optional
7
+ observation summaries in evaluate-skills.py are not an acceptance gate.
8
+ """
9
+ from __future__ import annotations
10
+
11
+ import argparse
12
+ import hashlib
13
+ import json
14
+ import re
15
+ import sys
16
+ from collections import Counter, defaultdict
17
+ from dataclasses import dataclass
18
+ from pathlib import Path
19
+ from typing import Any, Iterable
20
+
21
+ import yaml
22
+
23
+ ROOT = Path(__file__).resolve().parents[1]
24
+ DEFAULT_SKILLS = ROOT / "skills"
25
+ DEFAULT_CORPUS = DEFAULT_SKILLS / "evals" / "routing.json"
26
+ TOKEN_RE = re.compile(r"[a-z0-9]+(?:\+[a-z0-9]+|#[a-z0-9]*)?", re.I)
27
+ STOP = {
28
+ "a", "an", "and", "are", "as", "at", "be", "by", "do", "for", "from",
29
+ "how", "i", "in", "is", "it", "me", "my", "no", "not", "of", "on", "or",
30
+ "our", "please", "s", "should", "the", "their", "this", "through", "to",
31
+ "use", "user", "we", "when", "with", "you",
32
+ }
33
+ NEGATIVE_MARKERS = (
34
+ "do not use", "not when", "rather than", "instead of", "excluding", "except for",
35
+ )
36
+
37
+
38
+ @dataclass(frozen=True)
39
+ class Skill:
40
+ name: str
41
+ description: str
42
+
43
+
44
+ def _frontmatter(path: Path) -> dict[str, Any]:
45
+ lines = path.read_text(encoding="utf-8").splitlines()
46
+ if not lines or lines[0].strip() != "---":
47
+ raise ValueError(f"{path}: missing YAML frontmatter")
48
+ for index, line in enumerate(lines[1:], 1):
49
+ if line.strip() == "---":
50
+ raw = yaml.safe_load("\n".join(lines[1:index]))
51
+ if isinstance(raw, dict):
52
+ return raw
53
+ raise ValueError(f"{path}: frontmatter must be a mapping")
54
+ raise ValueError(f"{path}: unterminated YAML frontmatter")
55
+
56
+
57
+ def load_skills(root: Path) -> list[Skill]:
58
+ result = []
59
+ for path in sorted(root.glob("*/SKILL.md")):
60
+ raw = _frontmatter(path)
61
+ name = str(raw.get("name") or "").strip()
62
+ description = " ".join(str(raw.get("description") or "").split())
63
+ if not name or not description:
64
+ raise ValueError(f"{path}: name and description are required")
65
+ result.append(Skill(name, description))
66
+ if not result:
67
+ raise ValueError(f"no skills found under {root}")
68
+ return result
69
+
70
+
71
+ def load_catalog(path: Path) -> list[Skill]:
72
+ raw = json.loads(path.read_text(encoding="utf-8"))
73
+ rows = raw.get("skills") if isinstance(raw, dict) else raw
74
+ if not isinstance(rows, list) or not rows:
75
+ raise ValueError(f"{path}: expected a non-empty skills list")
76
+ return [Skill(str(row["name"]), " ".join(str(row["description"]).split())) for row in rows]
77
+
78
+
79
+ def load_cases(path: Path) -> list[dict[str, Any]]:
80
+ raw = json.loads(path.read_text(encoding="utf-8"))
81
+ rows = raw.get("cases") if isinstance(raw, dict) else raw
82
+ if not isinstance(rows, list) or not rows:
83
+ raise ValueError(f"{path}: expected a non-empty cases list")
84
+ ids = [str(row.get("id") or "") for row in rows]
85
+ if any(not item for item in ids) or len(ids) != len(set(ids)):
86
+ raise ValueError(f"{path}: case ids must be non-empty and unique")
87
+ return rows
88
+
89
+
90
+ def tokens(text: str) -> list[str]:
91
+ return [token.lower() for token in TOKEN_RE.findall(text) if token.lower() not in STOP]
92
+
93
+
94
+ def phrases(items: list[str]) -> set[str]:
95
+ return {
96
+ " ".join(items[index:index + width])
97
+ for width in (2, 3)
98
+ for index in range(max(0, len(items) - width + 1))
99
+ }
100
+
101
+
102
+ def split_description(text: str) -> tuple[str, str]:
103
+ positive, negative = [], []
104
+ for clause in re.split(r"[.;\n]+", text):
105
+ lowered = clause.lower()
106
+ cuts = [lowered.index(marker) for marker in NEGATIVE_MARKERS if marker in lowered]
107
+ if not cuts:
108
+ positive.append(clause)
109
+ continue
110
+ cut = min(cuts)
111
+ positive.append(clause[:cut])
112
+ negative.append(clause[cut:])
113
+ return " ".join(positive), " ".join(negative)
114
+
115
+
116
+ def score(prompt: str, skill: Skill) -> float:
117
+ prompt_tokens = tokens(prompt)
118
+ positive, negative = split_description(skill.description)
119
+ positive_tokens, negative_tokens = tokens(positive), tokens(negative)
120
+ if not prompt_tokens or not positive_tokens:
121
+ return 0.0
122
+ prompt_counts, positive_counts = Counter(prompt_tokens), Counter(positive_tokens)
123
+ overlap = sum(min(count, positive_counts[token]) for token, count in prompt_counts.items())
124
+ prompt_phrases = phrases(prompt_tokens)
125
+ positive_text, negative_text = " ".join(positive_tokens), " ".join(negative_tokens)
126
+ positive_phrase_hits = sum(phrase in positive_text for phrase in prompt_phrases)
127
+ negative_hits = sum(token in set(negative_tokens) for token in set(prompt_tokens))
128
+ negative_phrase_hits = sum(phrase in negative_text for phrase in prompt_phrases)
129
+ exact_bonus = 8 if " ".join(prompt_tokens) in positive_text else 0
130
+ return max(0.0, float(
131
+ overlap + 2 * positive_phrase_hits + exact_bonus
132
+ - 4 * negative_hits - 8 * negative_phrase_hits
133
+ ))
134
+
135
+
136
+ def select(prompt: str, skills: Iterable[Skill]) -> tuple[str | None, dict[str, float]]:
137
+ scores = {skill.name: score(prompt, skill) for skill in skills}
138
+ best = max(scores.values(), default=0.0)
139
+ if best <= 0:
140
+ return None, scores
141
+ return sorted(name for name, value in scores.items() if value == best)[0], scores
142
+
143
+
144
+ def evaluate(skills: list[Skill], cases: list[dict[str, Any]]) -> dict[str, Any]:
145
+ rows, confusion = [], defaultdict(Counter)
146
+ correct = collisions = 0
147
+ for case in cases:
148
+ selected, scores = select(str(case.get("prompt") or ""), skills)
149
+ expected = case.get("expected_skill")
150
+ is_correct = selected == expected
151
+ collision = selected in set(case.get("forbidden_skills") or [])
152
+ correct += int(is_correct)
153
+ collisions += int(collision)
154
+ confusion[str(expected)][str(selected)] += 1
155
+ rows.append({
156
+ "id": case["id"], "expected_skill": expected, "selected_skill": selected,
157
+ "correct": is_correct, "collision": collision,
158
+ "scores": dict(sorted(scores.items(), key=lambda item: (-item[1], item[0]))),
159
+ })
160
+ catalog = [{"name": item.name, "description": item.description} for item in skills]
161
+ fingerprint = lambda value: hashlib.sha256( # noqa: E731
162
+ json.dumps(value, sort_keys=True, separators=(",", ":")).encode("utf-8")
163
+ ).hexdigest()
164
+ total = len(cases)
165
+ return {
166
+ "schema_version": 2,
167
+ "catalog_fingerprint": fingerprint(catalog),
168
+ "corpus_fingerprint": fingerprint(cases),
169
+ "skill_count": len(skills), "case_count": total, "correct": correct,
170
+ "routing_accuracy": correct / total, "collisions": collisions,
171
+ "collision_rate": collisions / total,
172
+ "confusion": {key: dict(value) for key, value in sorted(confusion.items())},
173
+ "cases": rows,
174
+ }
175
+
176
+
177
+ def projection(report: dict[str, Any]) -> dict[str, Any]:
178
+ keys = (
179
+ "schema_version", "catalog_fingerprint", "corpus_fingerprint", "skill_count",
180
+ "case_count", "correct", "routing_accuracy", "collisions", "collision_rate", "confusion",
181
+ )
182
+ return {key: report[key] for key in keys}
183
+
184
+
185
+ def main(argv: list[str] | None = None) -> int:
186
+ parser = argparse.ArgumentParser(description=__doc__)
187
+ parser.add_argument("--skills-root", type=Path, default=DEFAULT_SKILLS)
188
+ parser.add_argument("--catalog", type=Path)
189
+ parser.add_argument("--corpus", type=Path, default=DEFAULT_CORPUS)
190
+ parser.add_argument("--verify", type=Path)
191
+ parser.add_argument("--write-report", type=Path)
192
+ parser.add_argument("--min-accuracy", type=float, default=0.0)
193
+ parser.add_argument("--max-collision-rate", type=float, default=1.0)
194
+ args = parser.parse_args(argv)
195
+
196
+ skills = load_catalog(args.catalog) if args.catalog else load_skills(args.skills_root)
197
+ report = evaluate(skills, load_cases(args.corpus))
198
+ if args.verify:
199
+ expected = json.loads(args.verify.read_text(encoding="utf-8"))
200
+ if projection(report) != expected:
201
+ print(json.dumps({"error": "report_mismatch", "expected": expected,
202
+ "actual": projection(report)}, indent=2), file=sys.stderr)
203
+ return 2
204
+ if report["routing_accuracy"] < args.min_accuracy:
205
+ return 3
206
+ if report["collision_rate"] > args.max_collision_rate:
207
+ return 4
208
+ rendered = json.dumps(report, indent=2, sort_keys=True)
209
+ if args.write_report:
210
+ args.write_report.parent.mkdir(parents=True, exist_ok=True)
211
+ args.write_report.write_text(rendered + "\n", encoding="utf-8")
212
+ print(rendered)
213
+ return 0
214
+
215
+
216
+ if __name__ == "__main__":
217
+ raise SystemExit(main())
@@ -0,0 +1,316 @@
1
+ #!/usr/bin/env python3
2
+ """Measure skill discovery against a versioned prompt corpus.
3
+
4
+ The default run evaluates the repository's current ``skills/*/SKILL.md``
5
+ frontmatter. ``--catalog`` evaluates a frozen catalog instead, which lets CI
6
+ compare a candidate corpus with the original baseline without keeping two
7
+ checkouts. ``--observations`` additionally summarizes externally supplied model/run
8
+ selections captured as JSON or JSONL; it does not authenticate those observations.
9
+
10
+ This is deliberately a measurement harness, not a claim that token overlap is a
11
+ model. The deterministic scorer catches description regressions cheaply; real
12
+ observations require independent provenance, fixed-rubric and completeness checks
13
+ before any release decision. This summary command is not an acceptance gate.
14
+ """
15
+ from __future__ import annotations
16
+
17
+ import argparse
18
+ import hashlib
19
+ import json
20
+ import re
21
+ import sys
22
+ from collections import Counter, defaultdict
23
+ from dataclasses import dataclass
24
+ from pathlib import Path
25
+ from typing import Any, Iterable
26
+
27
+ import yaml
28
+
29
+ REPO = Path(__file__).resolve().parents[1]
30
+ DEFAULT_SKILLS = REPO / "skills"
31
+ DEFAULT_CORPUS = DEFAULT_SKILLS / "evals" / "routing.json"
32
+
33
+ _TOKEN_RE = re.compile(r"[a-z0-9][a-z0-9+.#_-]*", re.IGNORECASE)
34
+ _STOP = {
35
+ "a", "an", "and", "are", "as", "at", "be", "by", "do", "for", "from",
36
+ "how", "i", "in", "is", "it", "me", "my", "of", "on", "or", "please",
37
+ "the", "this", "to", "use", "we", "with", "you",
38
+ }
39
+
40
+
41
+ @dataclass(frozen=True)
42
+ class SkillEntry:
43
+ name: str
44
+ description: str
45
+
46
+
47
+ def _frontmatter(path: Path) -> dict[str, Any]:
48
+ lines = path.read_text(encoding="utf-8").splitlines()
49
+ if not lines or lines[0].strip() != "---":
50
+ raise ValueError(f"{path}: missing YAML frontmatter")
51
+ for index in range(1, len(lines)):
52
+ if lines[index].strip() == "---":
53
+ data = yaml.safe_load("\n".join(lines[1:index]))
54
+ if not isinstance(data, dict):
55
+ raise ValueError(f"{path}: frontmatter must be a mapping")
56
+ return data
57
+ raise ValueError(f"{path}: unterminated YAML frontmatter")
58
+
59
+
60
+ def load_skills(root: Path) -> list[SkillEntry]:
61
+ entries: list[SkillEntry] = []
62
+ for skill_md in sorted(root.glob("*/SKILL.md")):
63
+ data = _frontmatter(skill_md)
64
+ name = str(data.get("name") or "").strip()
65
+ description = " ".join(str(data.get("description") or "").split())
66
+ if not name or not description:
67
+ raise ValueError(f"{skill_md}: name and description are required")
68
+ entries.append(SkillEntry(name=name, description=description))
69
+ if not entries:
70
+ raise ValueError(f"no skills found under {root}")
71
+ return entries
72
+
73
+
74
+ def load_catalog(path: Path) -> list[SkillEntry]:
75
+ raw = json.loads(path.read_text(encoding="utf-8"))
76
+ rows = raw.get("skills") if isinstance(raw, dict) else raw
77
+ if not isinstance(rows, list):
78
+ raise ValueError(f"{path}: expected a list or {{'skills': [...]}}")
79
+ entries = [
80
+ SkillEntry(name=str(row["name"]), description=" ".join(str(row["description"]).split()))
81
+ for row in rows
82
+ ]
83
+ if not entries:
84
+ raise ValueError(f"{path}: catalog is empty")
85
+ return entries
86
+
87
+
88
+ def _tokens(text: str) -> list[str]:
89
+ return [token.lower() for token in _TOKEN_RE.findall(text) if token.lower() not in _STOP]
90
+
91
+
92
+ def _phrases(tokens: list[str]) -> set[str]:
93
+ out: set[str] = set()
94
+ for width in (2, 3):
95
+ out.update(" ".join(tokens[index:index + width])
96
+ for index in range(0, max(0, len(tokens) - width + 1)))
97
+ return out
98
+
99
+
100
+ def score(prompt: str, skill: SkillEntry) -> float:
101
+ prompt_tokens = _tokens(prompt)
102
+ description_tokens = _tokens(skill.description)
103
+ if not prompt_tokens or not description_tokens:
104
+ return 0.0
105
+
106
+ prompt_counts = Counter(prompt_tokens)
107
+ description_counts = Counter(description_tokens)
108
+ overlap = sum(min(count, description_counts[token]) for token, count in prompt_counts.items())
109
+
110
+ prompt_phrases = _phrases(prompt_tokens)
111
+ description_text = " ".join(description_tokens)
112
+ phrase_hits = sum(1 for phrase in prompt_phrases if phrase in description_text)
113
+
114
+ name_tokens = set(_tokens(skill.name.replace("-", " ")))
115
+ name_hits = len(name_tokens.intersection(prompt_counts))
116
+ return float(overlap + (2 * phrase_hits) + (3 * name_hits))
117
+
118
+
119
+ def select_skill(prompt: str, skills: Iterable[SkillEntry]) -> tuple[str | None, dict[str, float]]:
120
+ scores = {skill.name: score(prompt, skill) for skill in skills}
121
+ if not scores:
122
+ return None, {}
123
+ best = max(scores.values())
124
+ if best <= 0:
125
+ return None, scores
126
+ winners = sorted(name for name, value in scores.items() if value == best)
127
+ return winners[0], scores
128
+
129
+
130
+ def _load_cases(path: Path) -> list[dict[str, Any]]:
131
+ raw = json.loads(path.read_text(encoding="utf-8"))
132
+ cases = raw.get("cases") if isinstance(raw, dict) else raw
133
+ if not isinstance(cases, list) or not cases:
134
+ raise ValueError(f"{path}: expected a non-empty cases list")
135
+ seen: set[str] = set()
136
+ for case in cases:
137
+ if not isinstance(case, dict):
138
+ raise ValueError(f"{path}: each case must be an object")
139
+ case_id = str(case.get("id") or "")
140
+ if not case_id or case_id in seen:
141
+ raise ValueError(f"{path}: case ids must be non-empty and unique")
142
+ if not str(case.get("prompt") or "").strip():
143
+ raise ValueError(f"{path}: {case_id} has no prompt")
144
+ seen.add(case_id)
145
+ return cases
146
+
147
+
148
+ def evaluate(skills: list[SkillEntry], cases: list[dict[str, Any]]) -> dict[str, Any]:
149
+ rows: list[dict[str, Any]] = []
150
+ confusion: dict[str, Counter[str]] = defaultdict(Counter)
151
+ correct = collisions = 0
152
+
153
+ for case in cases:
154
+ selected, scores = select_skill(str(case["prompt"]), skills)
155
+ expected = case.get("expected_skill")
156
+ forbidden = set(case.get("forbidden_skills") or [])
157
+ is_correct = selected == expected
158
+ collision = selected in forbidden
159
+ correct += int(is_correct)
160
+ collisions += int(collision)
161
+ confusion[str(expected)][str(selected)] += 1
162
+ rows.append({
163
+ "id": case["id"],
164
+ "kind": case.get("kind", "unspecified"),
165
+ "prompt": case["prompt"],
166
+ "expected_skill": expected,
167
+ "selected_skill": selected,
168
+ "correct": is_correct,
169
+ "collision": collision,
170
+ "scores": dict(sorted(scores.items(), key=lambda item: (-item[1], item[0]))),
171
+ })
172
+
173
+ total = len(cases)
174
+ catalog_payload = [{"name": item.name, "description": item.description} for item in skills]
175
+ catalog_fingerprint = hashlib.sha256(
176
+ json.dumps(catalog_payload, sort_keys=True, separators=(",", ":")).encode("utf-8")
177
+ ).hexdigest()
178
+ corpus_fingerprint = hashlib.sha256(
179
+ json.dumps(cases, sort_keys=True, separators=(",", ":")).encode("utf-8")
180
+ ).hexdigest()
181
+
182
+ return {
183
+ "schema_version": 1,
184
+ "catalog_fingerprint": catalog_fingerprint,
185
+ "corpus_fingerprint": corpus_fingerprint,
186
+ "skill_count": len(skills),
187
+ "case_count": total,
188
+ "correct": correct,
189
+ "routing_accuracy": correct / total,
190
+ "collisions": collisions,
191
+ "collision_rate": collisions / total,
192
+ "confusion": {expected: dict(counter) for expected, counter in sorted(confusion.items())},
193
+ "cases": rows,
194
+ }
195
+
196
+
197
+ def _load_observations(path: Path) -> list[dict[str, Any]]:
198
+ text = path.read_text(encoding="utf-8").strip()
199
+ if not text:
200
+ return []
201
+ if path.suffix == ".jsonl":
202
+ return [json.loads(line) for line in text.splitlines() if line.strip()]
203
+ raw = json.loads(text)
204
+ rows = raw.get("observations") if isinstance(raw, dict) else raw
205
+ if not isinstance(rows, list):
206
+ raise ValueError(f"{path}: observations must be a list")
207
+ return rows
208
+
209
+
210
+ def grade_observations(observations: list[dict[str, Any]], cases: list[dict[str, Any]]) -> dict[str, Any]:
211
+ by_id = {str(case["id"]): case for case in cases}
212
+ graded: list[dict[str, Any]] = []
213
+ tokens: list[int] = []
214
+ durations: list[int] = []
215
+ selection_correct = task_success = 0
216
+
217
+ for row in observations:
218
+ case_id = str(row.get("case_id") or row.get("id") or "")
219
+ if case_id not in by_id:
220
+ raise ValueError(f"observation refers to unknown case {case_id!r}")
221
+ case = by_id[case_id]
222
+ selected = row.get("selected_skill")
223
+ selection_ok = selected == case.get("expected_skill")
224
+ succeeded = row.get("task_success", False)
225
+ if type(succeeded) is not bool:
226
+ raise ValueError("task_success must be Boolean")
227
+ selection_correct += int(selection_ok)
228
+ task_success += int(succeeded)
229
+ if row.get("total_tokens") is not None:
230
+ tokens.append(int(row["total_tokens"]))
231
+ if row.get("duration_ms") is not None:
232
+ durations.append(int(row["duration_ms"]))
233
+ graded.append({
234
+ "case_id": case_id,
235
+ "expected_skill": case.get("expected_skill"),
236
+ "selected_skill": selected,
237
+ "selection_correct": selection_ok,
238
+ "task_success": succeeded,
239
+ })
240
+
241
+ total = len(graded)
242
+ return {
243
+ "observation_count": total,
244
+ "selection_accuracy": (selection_correct / total) if total else None,
245
+ "task_success_rate": (task_success / total) if total else None,
246
+ "mean_total_tokens": (sum(tokens) / len(tokens)) if tokens else None,
247
+ "mean_duration_ms": (sum(durations) / len(durations)) if durations else None,
248
+ "observations": graded,
249
+ }
250
+
251
+
252
+ def _baseline_projection(report: dict[str, Any]) -> dict[str, Any]:
253
+ keys = (
254
+ "schema_version", "catalog_fingerprint", "corpus_fingerprint", "skill_count",
255
+ "case_count", "correct", "routing_accuracy", "collisions", "collision_rate",
256
+ "confusion",
257
+ )
258
+ return {key: report[key] for key in keys}
259
+
260
+
261
+ def _parser() -> argparse.ArgumentParser:
262
+ parser = argparse.ArgumentParser(description=__doc__)
263
+ parser.add_argument("--skills-root", type=Path, default=DEFAULT_SKILLS)
264
+ parser.add_argument("--catalog", type=Path,
265
+ help="Frozen JSON catalog to evaluate instead of skills/*/SKILL.md")
266
+ parser.add_argument("--corpus", type=Path, default=DEFAULT_CORPUS)
267
+ parser.add_argument("--observations", type=Path,
268
+ help="Optional real-run JSON/JSONL selections and outcomes")
269
+ parser.add_argument("--write-report", type=Path,
270
+ help="Write the full JSON report to this path")
271
+ parser.add_argument("--verify-baseline", type=Path,
272
+ help="Compare summary fields with a committed baseline JSON")
273
+ parser.add_argument("--min-accuracy", type=float, default=0.0)
274
+ parser.add_argument("--max-collision-rate", type=float, default=1.0)
275
+ return parser
276
+
277
+
278
+ def main(argv: list[str] | None = None) -> int:
279
+ args = _parser().parse_args(argv)
280
+ skills = load_catalog(args.catalog) if args.catalog else load_skills(args.skills_root)
281
+ cases = _load_cases(args.corpus)
282
+ report = evaluate(skills, cases)
283
+ if args.observations:
284
+ report["behavioral_observations"] = grade_observations(
285
+ _load_observations(args.observations), cases
286
+ )
287
+
288
+ if args.verify_baseline:
289
+ expected = json.loads(args.verify_baseline.read_text(encoding="utf-8"))
290
+ actual = _baseline_projection(report)
291
+ if actual != expected:
292
+ print(json.dumps({"error": "baseline_mismatch", "expected": expected,
293
+ "actual": actual}, indent=2), file=sys.stderr)
294
+ return 2
295
+
296
+ if report["routing_accuracy"] < args.min_accuracy:
297
+ print(json.dumps({"error": "accuracy_below_threshold",
298
+ "actual": report["routing_accuracy"],
299
+ "minimum": args.min_accuracy}, indent=2), file=sys.stderr)
300
+ return 3
301
+ if report["collision_rate"] > args.max_collision_rate:
302
+ print(json.dumps({"error": "collision_rate_above_threshold",
303
+ "actual": report["collision_rate"],
304
+ "maximum": args.max_collision_rate}, indent=2), file=sys.stderr)
305
+ return 4
306
+
307
+ rendered = json.dumps(report, indent=2, sort_keys=True)
308
+ if args.write_report:
309
+ args.write_report.parent.mkdir(parents=True, exist_ok=True)
310
+ args.write_report.write_text(rendered + "\n", encoding="utf-8")
311
+ print(rendered)
312
+ return 0
313
+
314
+
315
+ if __name__ == "__main__":
316
+ raise SystemExit(main())
@@ -0,0 +1,122 @@
1
+ """Load a registered skill or one of its bundled resources.
2
+
3
+ A skill is instruction/reference content, not an executable. "Using" one means
4
+ loading its SKILL.md and following it, then retrieving only the referenced
5
+ resource needed for the current task.
6
+
7
+ Usage:
8
+ python scripts/get-skill.py <name> # metadata only
9
+ python scripts/get-skill.py <name> --content # body + resource index
10
+ python scripts/get-skill.py <name> --index # resource index only
11
+ python scripts/get-skill.py <name> --resource references/x.md
12
+
13
+ Output is one JSON object on stdout. Failures use the repository's stable error
14
+ envelope and a non-zero exit code.
15
+ """
16
+ from __future__ import annotations
17
+
18
+ import argparse
19
+ import sys
20
+ from pathlib import Path
21
+
22
+ # Auto-switch to the project's .venv Python if we were launched with a different one.
23
+ _PROJECT_ROOT = Path(__file__).resolve().parents[1]
24
+ # .venv layout is per-OS: Scripts/python.exe on Windows, bin/python everywhere
25
+ # else. Hardcoding the Windows path made this a silent no-op on macOS/Linux,
26
+ # where the script then ran on whatever interpreter happened to invoke it.
27
+ _VENV_PY = (_PROJECT_ROOT / ".venv" / "Scripts" / "python.exe" if sys.platform == "win32"
28
+ else _PROJECT_ROOT / ".venv" / "bin" / "python")
29
+ if _VENV_PY.exists() and Path(sys.executable).resolve() != _VENV_PY.resolve():
30
+ import subprocess
31
+ sys.exit(subprocess.run([str(_VENV_PY), __file__, *sys.argv[1:]]).returncode)
32
+
33
+ sys.path.insert(0, str(_PROJECT_ROOT))
34
+
35
+ from registry import get_skill # noqa: E402
36
+ from tools._lib.io import emit, fail # noqa: E402
37
+ from tools._lib.skill_resources import ( # noqa: E402
38
+ SkillResourceError,
39
+ SkillResourceNotFound,
40
+ SkillResourceNotText,
41
+ read_text_resource,
42
+ resource_index,
43
+ )
44
+
45
+
46
+ def _strip_frontmatter(text: str) -> str:
47
+ """Return the SKILL.md body with the leading `---`-delimited frontmatter removed."""
48
+ lines = text.splitlines(keepends=True)
49
+ if lines and lines[0].strip() == "---":
50
+ for i in range(1, len(lines)):
51
+ if lines[i].strip() == "---":
52
+ return "".join(lines[i + 1:]).lstrip("\n")
53
+ return text # no frontmatter -> return as-is
54
+
55
+
56
+ class _ArgumentParser(argparse.ArgumentParser):
57
+ def error(self, message: str) -> None:
58
+ fail("invalid_args", message, {}, exit_code=2)
59
+
60
+
61
+ def _parser() -> argparse.ArgumentParser:
62
+ parser = _ArgumentParser(description=__doc__)
63
+ parser.add_argument("name", help="registered skill name")
64
+ group = parser.add_mutually_exclusive_group()
65
+ group.add_argument("--content", action="store_true",
66
+ help="include SKILL.md body and resource index")
67
+ group.add_argument("--index", action="store_true",
68
+ help="include resource index without the body")
69
+ group.add_argument("--resource", metavar="PATH",
70
+ help="read one UTF-8 file below references/, scripts/, or assets/")
71
+ return parser
72
+
73
+
74
+ def main(argv: list[str] | None = None) -> int:
75
+ argv = sys.argv[1:] if argv is None else argv
76
+ if not argv:
77
+ print(__doc__)
78
+ return 0
79
+ args = _parser().parse_args(argv)
80
+ try:
81
+ manifest = get_skill(args.name)
82
+ except KeyError as exc:
83
+ fail("not_found", str(exc), {"name": args.name}, exit_code=2)
84
+ except ValueError as exc:
85
+ fail("invalid_skill", str(exc), {"name": args.name}, exit_code=2)
86
+
87
+ path = manifest.path
88
+ skill_md = path / "SKILL.md"
89
+ out = {
90
+ "name": manifest.name,
91
+ "description": manifest.description,
92
+ "version": manifest.version,
93
+ "ready": True,
94
+ "path": str(path),
95
+ "skill_md": str(skill_md),
96
+ }
97
+
98
+ if args.resource is not None:
99
+ try:
100
+ out["resource"] = read_text_resource(path, args.resource)
101
+ except SkillResourceNotFound as exc:
102
+ fail(exc.code, str(exc), {"name": args.name, "path": args.resource}, exit_code=2)
103
+ except SkillResourceNotText as exc:
104
+ fail(exc.code, str(exc), {"name": args.name, "path": args.resource}, exit_code=2)
105
+ except SkillResourceError as exc:
106
+ fail(exc.code, str(exc), {"name": args.name, "path": args.resource}, exit_code=2)
107
+ elif args.content or args.index:
108
+ index = resource_index(path)
109
+ # Preserve the legacy top-level lists while adding richer metadata.
110
+ out["references"] = index["references"]
111
+ out["scripts"] = index["scripts"]
112
+ out["assets"] = index["assets"]
113
+ out["resources"] = index["resources"]
114
+ if args.content:
115
+ out["body"] = _strip_frontmatter(skill_md.read_text(encoding="utf-8"))
116
+
117
+ emit(out)
118
+ return 0
119
+
120
+
121
+ if __name__ == "__main__":
122
+ raise SystemExit(main())