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,199 @@
1
+ """Surgical read/write of ONE element's plain configs on a live form.
2
+
3
+ Third member of the surgical family, after form_code.py (Data.code) and
4
+ form_events.py (one element's event handlers), and it exists for the same reason:
5
+ `form-edit` is a DESIRED-STATE editor that rebuilds the whole DTO from a config,
6
+ so using it to change one paragraph's HTML on a large hand-authored form means
7
+ re-declaring every element or losing them.
8
+
9
+ What this pair covers that the other two do not: the SEMANTIC configs — `label`,
10
+ `placeholder`, `required`, `regex`, `visible`, `tooltip`, `info-text`,
11
+ `defaultValue`. Content and per-field rules belong in the DTO, not in the
12
+ form-level JS layer: a paragraph rewritten from JavaScript is invisible in the
13
+ designer, has to be re-applied on every render, and fights the runtime's own
14
+ MutationObserver.
15
+
16
+ Two invariants this handler holds, both load-bearing (see FORM-DEV-GUIDE/01):
17
+
18
+ 1. **It only ever overwrites configs that already exist.** Adding a config key
19
+ would also require a matching data-model attribute whose id equals the new
20
+ config's id; without it the process designer renders raw guids and values
21
+ never flow. Refusing the write is the honest failure — silently creating a
22
+ half-wired config is not.
23
+ 2. **Config ids are preserved.** The data-model mirror addresses each attribute
24
+ by the element's own config id, so a fresh id on a rewritten config breaks
25
+ every value path that points at it.
26
+
27
+ `form-set-element-config` always returns the PREVIOUS value of every config it
28
+ touched, so an overwrite is recoverable from the tool output alone.
29
+ """
30
+ from __future__ import annotations
31
+
32
+ import argparse
33
+ import copy
34
+ import json
35
+
36
+ from tools.procesio.actiondef import ActionDef
37
+ from tools.procesio.dto.form.builder import reconcile_assignees
38
+ from tools.procesio.errors import UsageError
39
+ from tools.procesio.handlers.common import add_force_arg, add_profile_arg, guard_unchanged
40
+ from tools.procesio.handlers.form_code import _fetch, build_put_body
41
+ from tools.procesio.handlers.form_events import _cfg, _find_element
42
+
43
+ # Event configs are a different shape (`{debounce, events:[…]}`) with their own
44
+ # resolution rules — process-variable names to guids, one event per trigger. They
45
+ # go through form-set-element-event, which knows those rules; routing them here
46
+ # would let a caller write a mapping row the designer cannot render.
47
+ def _is_event_key(key: str) -> bool:
48
+ return key.startswith("on") and key.endswith("Events")
49
+
50
+
51
+ def _parse_value(raw: str):
52
+ """JSON first, plain string as the fallback.
53
+
54
+ `--set required=true` should store the boolean, and `--set label=<p>Hi</p>`
55
+ the string. Trying JSON first and falling back covers both without asking the
56
+ caller to quote every scalar.
57
+ """
58
+ try:
59
+ return json.loads(raw)
60
+ except (ValueError, TypeError):
61
+ return raw
62
+
63
+
64
+ def _split_assignment(item: str, label: str) -> tuple[str, str]:
65
+ if "=" not in item:
66
+ raise UsageError(f"--{label} expects key=value, got {item!r}")
67
+ key, _, value = item.partition("=")
68
+ key = key.strip()
69
+ if not key:
70
+ raise UsageError(f"--{label} expects a config key before '=', got {item!r}")
71
+ return key, value
72
+
73
+
74
+ # -- actions -----------------------------------------------------------------
75
+
76
+ def get_element(client, args) -> dict:
77
+ form = _fetch(client, args.id)
78
+ elements = form["data"].get("elements") or []
79
+ el = _find_element(elements, args.element)
80
+ configs = el.get("configs") or []
81
+ wanted = set(args.key or [])
82
+ return {
83
+ "form_id": args.id,
84
+ "element_id": el.get("id"),
85
+ "type": el.get("type"),
86
+ "parent_id": el.get("parentId"),
87
+ "section": el.get("section"),
88
+ "configs": {
89
+ c.get("key"): c.get("value")
90
+ for c in configs
91
+ if not wanted or c.get("key") in wanted
92
+ },
93
+ "config_keys": [c.get("key") for c in configs],
94
+ }
95
+
96
+
97
+ def set_element_config(client, args) -> dict:
98
+ updates: dict[str, object] = {}
99
+ for item in args.set or []:
100
+ key, raw = _split_assignment(item, "set")
101
+ updates[key] = _parse_value(raw)
102
+ for item in args.set_file or []:
103
+ key, path = _split_assignment(item, "set-file")
104
+ with open(path, encoding="utf-8") as f:
105
+ updates[key] = f.read()
106
+ if not updates:
107
+ raise UsageError("nothing to set: pass --set key=value and/or --set-file key=path")
108
+
109
+ bad = sorted(k for k in updates if _is_event_key(k))
110
+ if bad:
111
+ raise UsageError(
112
+ f"{', '.join(bad)} are event configs; wire them with form-set-element-event, "
113
+ f"which resolves process-variable names to guids and enforces one event per trigger")
114
+
115
+ form = _fetch(client, args.id)
116
+ elements = form["data"].get("elements") or []
117
+ el = _find_element(elements, args.element)
118
+
119
+ # Refuse BEFORE writing anything: a config this element does not carry has no
120
+ # data-model attribute behind it, and creating one here would wire it only
121
+ # half-way (see the module docstring).
122
+ missing = sorted(k for k in updates if _cfg(el, k) is None)
123
+ if missing:
124
+ raise UsageError(
125
+ f"element {args.element!r} has no config {', '.join(missing)}; "
126
+ f"it carries {', '.join(c.get('key') for c in el.get('configs') or [])}")
127
+
128
+ before = copy.deepcopy(elements)
129
+ previous = {}
130
+ for key, value in updates.items():
131
+ c = _cfg(el, key)
132
+ previous[key] = c.get("value")
133
+ c["value"] = value # the config's own id is preserved
134
+
135
+ # Changing an assignee/approver (or a dynamic row's approval steps) changes who the form
136
+ # routes to; the designer would re-derive the top-level Assignees on save, so do the same.
137
+ assignees, routing = reconcile_assignees(form.get("assignees") or [], before, elements)
138
+
139
+ result = {
140
+ "form_id": args.id,
141
+ "element_id": el.get("id"),
142
+ "type": el.get("type"),
143
+ "set": updates,
144
+ "previous": previous,
145
+ "elements": len(elements),
146
+ }
147
+ if routing:
148
+ result["assignees"] = routing
149
+ if args.dry_run:
150
+ return {"dry_run": True, **result}
151
+
152
+ guard = guard_unchanged(lambda: _fetch(client, args.id), form, force=args.force)
153
+ client.put("/api/FormTemplate", build_put_body(form, data=form["data"],
154
+ assignees=assignees if routing else None))
155
+ return {"updated": True, "concurrency": guard, **result}
156
+
157
+
158
+ def _get_args(p: argparse.ArgumentParser) -> None:
159
+ add_profile_arg(p)
160
+ p.add_argument("--id", required=True, help="form template id")
161
+ p.add_argument("--element", required=True,
162
+ help="element id, or its `name` config as the designer shows it")
163
+ p.add_argument("--key", action="append",
164
+ help="only return this config key (repeatable; default: all)")
165
+
166
+
167
+ def _set_args(p: argparse.ArgumentParser) -> None:
168
+ add_profile_arg(p)
169
+ p.add_argument("--id", required=True, help="form template id")
170
+ p.add_argument("--element", required=True,
171
+ help="element id, or its `name` config as the designer shows it")
172
+ p.add_argument("--set", action="append",
173
+ help="key=value to write (repeatable); the value is parsed as JSON "
174
+ "when it parses, otherwise stored as a plain string. A value that "
175
+ "LOOKS like JSON (true/42/[..]) is stored as that type — for a "
176
+ "literal string that looks like JSON, use --set-file (always a string)")
177
+ p.add_argument("--set-file", dest="set_file", action="append",
178
+ help="key=path to write a config's value from a file (repeatable) — "
179
+ "for long HTML labels")
180
+ p.add_argument("--dry-run", dest="dry_run", action="store_true",
181
+ help="report the change (and the previous values) without writing")
182
+ add_force_arg(p)
183
+
184
+
185
+ ACTIONS = {
186
+ "form-get-element": ActionDef(
187
+ func=get_element, add_args=_get_args, needs_client=True,
188
+ description="Read one element's configs from a live form (id or name).",
189
+ ),
190
+ "form-set-element-config": ActionDef(
191
+ func=set_element_config, add_args=_set_args, needs_client=True,
192
+ description="Set one element's plain configs in place (surgical: only that "
193
+ "element's config values change, ids preserved; returns the previous "
194
+ "values). Event configs go through form-set-element-event. Changing who "
195
+ "works or approves a step (assignee/approver configs, a dynamic row's "
196
+ "approvalSteps) re-derives the form's top-level Assignees as the designer "
197
+ "would, reported under `assignees`; any other change leaves it untouched.",
198
+ ),
199
+ }
@@ -0,0 +1,441 @@
1
+ """Surgical read/write of ONE element's event list on a live form.
2
+
3
+ Companion to form_code.py, and it exists for the same reason: `form-edit` is a
4
+ DESIRED-STATE editor that rebuilds the whole DTO from a config, so using it to
5
+ wire a single button or upload on a large hand-authored form means re-declaring
6
+ every element or losing them. These actions do a read-modify-write on the LIVE
7
+ DTO and touch ONLY the target element's event config.
8
+
9
+ The event model (see PROCESIO-RESOURCE-MODEL-NOTES.md): each element carries
10
+ per-trigger configs — `onClickEvents`, `onInputEvents`, `onStepChangeEvents`,
11
+ `onPaginationChangedEvents` — whose value is `{debounce, events:[…]}`. A fresh
12
+ element has the key present with a `null` value, which is what "no handler" looks
13
+ like; it is not an error and not a missing field.
14
+
15
+ The trap this action exists to prevent: in a RUN_PROCESS `inputMap`/`outputMap`
16
+ the PROCESS VARIABLE GUID belongs on the LEFT and the form value-path on the
17
+ right. A variable NAME on the left is accepted by the API but the designer then
18
+ renders raw guids and the launch 400s, so names are resolved to guids here and an
19
+ unknown name fails before anything is written.
20
+ """
21
+ from __future__ import annotations
22
+
23
+ import argparse
24
+ import copy
25
+ import json
26
+ import uuid
27
+
28
+ from tools.procesio.actiondef import ActionDef
29
+ from tools.procesio.client import VARIABLES_ONLY
30
+ from tools.procesio.errors import UsageError
31
+ from tools.procesio.handlers.common import add_force_arg, add_profile_arg, guard_unchanged
32
+ from tools.procesio.handlers.form_code import _fetch, build_put_body
33
+
34
+ # Trigger -> (config key, event type) comes from the DTO builder's own maps, which
35
+ # were verified against the ui-builder source. Re-deriving them here would let the
36
+ # two drift, and a wrong event type is silently accepted by the API.
37
+ from tools.procesio.dto.form.builder import _EVENT_KEY, _EVENT_TYPE, _golden # noqa: E402
38
+
39
+ # The value-path rule itself is shared with the builder, so the action that CHECKS a path and
40
+ # the one that WRITES one cannot disagree.
41
+ from tools.procesio.dto.form import fieldpath # noqa: E402
42
+
43
+ ACTIONS_ALLOWED = ("RUN_PROCESS", "RUN_JAVASCRIPT", "RUN_DATA_STORE_OPERATION")
44
+
45
+ # EventAction.RUN_DATA_STORE_OPERATION (ui-builder model/config/events/index.ts): a
46
+ # form element triggers a Data Store operation, the same way RUN_PROCESS triggers a
47
+ # process. config = EventRunDataStoreOperationConfig {dataStoreId, operation, inputMap,
48
+ # outputMap, filters?, areFiltersConfigured?}. operation = DataStoreOperation
49
+ # READ/ADD/UPDATE/DELETE; filters apply to every op except ADD
50
+ # (dataStoreOperationSupportsFilters). The operation wire encoding (string vs numeric)
51
+ # must be re-verified live — pass a numeric operation via --config if the platform
52
+ # rejects the name. See PROCESIO-RESOURCE-MODEL-NOTES.md.
53
+ _DATA_STORE_OPS = ("READ", "ADD", "UPDATE", "DELETE")
54
+
55
+
56
+ def _normalize_op(raw):
57
+ """Accept an operation as a DataStoreOperation name (case-insensitive) or a raw
58
+ value; return the name upper-cased, or the value unchanged if not a known name."""
59
+ if isinstance(raw, str):
60
+ up = raw.strip().upper()
61
+ return up if up in _DATA_STORE_OPS else raw.strip()
62
+ return raw
63
+
64
+
65
+ def _resolve_trigger(on: str) -> tuple[str, str]:
66
+ key = on.strip()
67
+ friendly = key.lower().replace("-", "").replace("_", "")
68
+ if friendly in _EVENT_KEY:
69
+ return _EVENT_KEY[friendly], _EVENT_TYPE[friendly]
70
+ raise UsageError(
71
+ f"unknown trigger {on!r}; use one of {', '.join(sorted(_EVENT_KEY))}")
72
+
73
+
74
+ def _cfg(element: dict, key: str):
75
+ for c in element.get("configs") or []:
76
+ if c.get("key") == key:
77
+ return c
78
+ return None
79
+
80
+
81
+ def _template_slot(el_type: str, key: str):
82
+ """(index, config) of `key` in the element type's golden template, or (None, None)."""
83
+ try:
84
+ template = _golden(str(el_type))
85
+ except UsageError:
86
+ return None, None
87
+ for i, c in enumerate(template.get("configs") or []):
88
+ if c.get("key") == key:
89
+ return i, c
90
+ return None, None
91
+
92
+
93
+ def _backfill_slot(element: dict, key: str) -> dict:
94
+ """Add a missing trigger slot to `element`, the way the runtime does on load.
95
+
96
+ An element saved before a trigger existed (every approval control saved before ~Sep
97
+ 2025 has no onBefore*/onAfter* slots) carries no config for it. The form runtime
98
+ back-fills missing configs from the element template on every load
99
+ (ui-builder utils/formBuilder/elements.ts::actualizeElements) and the designer persists
100
+ them on its next save, so an absent slot means "old element", not "cannot raise this
101
+ trigger". Only when the TEMPLATE lacks the key is the trigger really unavailable.
102
+ """
103
+ index, template = _template_slot(element.get("type"), key)
104
+ configs = element.setdefault("configs", [])
105
+ if template is None:
106
+ raise UsageError(
107
+ f"element type {element.get('type')!r} has no {key!r} config, so it cannot raise "
108
+ f"that trigger; available: "
109
+ f"{', '.join(c.get('key', '') for c in configs if 'vent' in c.get('key', ''))}")
110
+ slot = copy.deepcopy(template)
111
+ slot["id"] = str(uuid.uuid4())
112
+ slot["value"] = None
113
+ configs.insert(min(index, len(configs)), slot)
114
+ return slot
115
+
116
+
117
+ def _find_element(elements: list, ref: str) -> dict:
118
+ """Match by element id first, then by its `name` config (what the designer shows)."""
119
+ for e in elements:
120
+ if e.get("id") == ref:
121
+ return e
122
+ hits = []
123
+ for e in elements:
124
+ c = _cfg(e, "name")
125
+ if c and str(c.get("value") or "").strip() == ref:
126
+ hits.append(e)
127
+ if len(hits) == 1:
128
+ return hits[0]
129
+ if not hits:
130
+ raise UsageError(f"no element with id or name {ref!r} on this form")
131
+ raise UsageError(f"{len(hits)} elements are named {ref!r}; pass the element id instead")
132
+
133
+
134
+ def _process_vars(client, process_id: str) -> dict:
135
+ """{variable name: the variable DTO}. The whole DTO, not just the id, because a map row also
136
+ has to know whether the variable is a LIST - see _is_list_of."""
137
+ body = client.get(f"/api/Projects/{process_id}", VARIABLES_ONLY)
138
+ if isinstance(body, dict) and "flow" not in body and isinstance(body.get("result"), dict):
139
+ body = body["result"]
140
+ flow = body.get("flow") if isinstance(body, dict) else None
141
+ src = flow if isinstance(flow, dict) else (body if isinstance(body, dict) else {})
142
+ return {v.get("name"): v for v in (src.get("variables") or []) if v.get("name")}
143
+
144
+
145
+ def _path_of(side):
146
+ """The attribute chain a caller supplied on this side, if any.
147
+
148
+ A model-typed process variable is mapped one ATTRIBUTE at a time, and the
149
+ chain lives in the row's `path`. Rebuilding the slot without carrying it over
150
+ silently maps the whole object into a single text field instead.
151
+ """
152
+ return side.get("path") if isinstance(side, dict) else None
153
+
154
+
155
+ def _slot(value, is_left: bool, path=None, is_list: bool = False) -> dict:
156
+ """One side of a map row, in the shape the DESIGNER writes.
157
+
158
+ Verified against a live form: each side is an OBJECT, not a bare string —
159
+ `{"value": …, "isList": …, "path": …}` — and the two sides differ, the
160
+ process side carrying `path: {}` and the form side `path: null`. Writing bare
161
+ strings produces a row the API accepts but the designer cannot render.
162
+
163
+ `isList` is NOT cosmetic: a list-valued variable mapped with `isList: false` binds the whole
164
+ result set into a single scalar slot, so the form receives nothing and there is no error to
165
+ read. It is taken from the caller when given, else from the process variable being mapped.
166
+ """
167
+ if isinstance(value, dict) and "value" in value:
168
+ return value # already in wire shape
169
+ default = {} if is_left else None
170
+ return {"value": value, "isList": bool(is_list),
171
+ "path": default if path is None else path}
172
+
173
+
174
+ def _is_list_of(side, variable: dict | None) -> bool:
175
+ """Whether this side of a map row carries a LIST.
176
+
177
+ A caller that states `isList` wins — it may be mapping one attribute out of a list. Otherwise
178
+ the process variable's own `isList` decides, which is what the designer would have written.
179
+ """
180
+ if isinstance(side, dict) and "isList" in side:
181
+ return bool(side["isList"])
182
+ return bool((variable or {}).get("isList"))
183
+
184
+
185
+ def _plain(value):
186
+ return value.get("value") if isinstance(value, dict) else value
187
+
188
+
189
+ def _resolve_maps(config: dict, client, form: dict | None = None) -> dict:
190
+ """Turn a map's two sides into the designer's object shape, resolving BOTH.
191
+
192
+ Left is a process variable: a NAME becomes its GUID. Right is a form field, and it used
193
+ to pass through untouched — which is why every caller that guessed the value-path format
194
+ wrote a row the platform accepted, the designer rendered, and the control silently
195
+ ignored. With `form` given, the right side is resolved the same way as the left: a field
196
+ NAME is built into its value path, a path is CHECKED against the live form, and anything
197
+ else is refused before a single byte is written.
198
+ """
199
+ pid = config.get("processId")
200
+ if not pid:
201
+ raise UsageError("RUN_PROCESS config needs a 'processId'")
202
+ names = _process_vars(client, pid)
203
+ live = fieldpath.LiveForm(form) if form is not None else None
204
+ by_id = {v.get("id"): v for v in names.values() if v.get("id")}
205
+ out = dict(config)
206
+ for side in ("inputMap", "outputMap"):
207
+ rows = out.get(side) or []
208
+ fixed = []
209
+ for i, row in enumerate(rows):
210
+ row = dict(row)
211
+ left = _plain(row.get("left"))
212
+ if left in by_id:
213
+ variable = by_id[left] # already a guid
214
+ elif left in names:
215
+ variable = names[left]
216
+ left = variable.get("id")
217
+ else:
218
+ raise UsageError(
219
+ f"{side}: {left!r} is neither a variable id nor a variable name on "
220
+ f"process {pid}. Known variables: {', '.join(sorted(names)) or '(none)'}")
221
+ # Both sides of a row describe the SAME value, so one list-ness governs the pair: the
222
+ # form variable on the right holds whatever the process variable on the left produced.
223
+ is_list = _is_list_of(row.get("left"), variable) or _is_list_of(row.get("right"), variable)
224
+ right = _plain(row.get("right"))
225
+ if live is not None:
226
+ right = live.resolve(right, f"{side} row {i}")
227
+ row["left"] = _slot(left, True, _path_of(row.get("left")), is_list)
228
+ # a form VARIABLE side carries `path: {}` like the process side (as the designer saves it)
229
+ rpath = {} if live is not None and live.is_variable(right) and _path_of(row.get("right")) is None \
230
+ else _path_of(row.get("right"))
231
+ row["right"] = _slot(right, False, rpath, is_list)
232
+ row["id"] = row.get("id", i)
233
+ fixed.append(row)
234
+ out[side] = fixed
235
+ return out
236
+
237
+
238
+ def set_element_event(client, args) -> dict:
239
+ cfg_key, default_type = _resolve_trigger(args.on)
240
+ action = args.action.strip().upper()
241
+ if action not in ACTIONS_ALLOWED:
242
+ raise UsageError(f"--action must be one of {', '.join(ACTIONS_ALLOWED)}")
243
+
244
+ raw = args.config
245
+ if args.config_file:
246
+ with open(args.config_file, encoding="utf-8") as f:
247
+ raw = f.read()
248
+ if raw:
249
+ try:
250
+ ev_config = json.loads(raw)
251
+ except json.JSONDecodeError as e:
252
+ raise UsageError(f"--config must be valid JSON: {e}") from e
253
+ if not isinstance(ev_config, dict):
254
+ raise UsageError("--config must be a JSON object")
255
+ elif action == "RUN_DATA_STORE_OPERATION":
256
+ ev_config = {} # may be fully specified via --data-store-id / --operation
257
+ else:
258
+ raise UsageError("provide --config '<json>' or --config-file <path>")
259
+
260
+ form = _fetch(client, args.id)
261
+ elements = form["data"].get("elements") or []
262
+ element = _find_element(elements, args.element)
263
+
264
+ if action == "RUN_PROCESS":
265
+ # `form` is the live DTO fetched above: passing it is what lets the form side of each
266
+ # row be resolved and checked, not merely copied.
267
+ ev_config = _resolve_maps(ev_config, client, form) # fails loudly before any write
268
+ # Backfill the canonical RUN_PROCESS config the DTO builder always emits, so a
269
+ # hand-written minimal {processId, inputMap, outputMap} renders configured in the
270
+ # designer and launches — the designer reads these keys and a missing
271
+ # areConditionsConfigured/conditions leaves the event half-wired. setdefault, so a
272
+ # caller that passes its own value always wins.
273
+ ev_config.setdefault("syncRun", True)
274
+ ev_config.setdefault("mapLatestTriggerOnly", False)
275
+ ev_config.setdefault("conditions", [])
276
+ ev_config.setdefault("areConditionsConfigured", True)
277
+ elif action == "RUN_DATA_STORE_OPERATION":
278
+ if getattr(args, "data_store_id", None):
279
+ ev_config["dataStoreId"] = args.data_store_id
280
+ if getattr(args, "operation", None):
281
+ ev_config["operation"] = _normalize_op(args.operation)
282
+ if not ev_config.get("dataStoreId"):
283
+ raise UsageError("RUN_DATA_STORE_OPERATION needs a dataStoreId "
284
+ "(--data-store-id or in --config)")
285
+ if ev_config.get("operation") in (None, ""):
286
+ raise UsageError("RUN_DATA_STORE_OPERATION needs an operation "
287
+ "(--operation READ|ADD|UPDATE|DELETE or in --config)")
288
+ ev_config.setdefault("inputMap", [])
289
+ ev_config.setdefault("outputMap", [])
290
+ # Filters apply to every operation except ADD (dataStoreOperationSupportsFilters).
291
+ if str(ev_config.get("operation")).upper() != "ADD":
292
+ ev_config.setdefault("filters", [])
293
+ ev_config.setdefault("areFiltersConfigured", bool(ev_config.get("filters")))
294
+ elif not ev_config.get("code"):
295
+ raise UsageError("RUN_JAVASCRIPT config needs a 'code' string")
296
+
297
+ slot = _cfg(element, cfg_key)
298
+ backfilled = []
299
+ if slot is None:
300
+ slot = _backfill_slot(element, cfg_key) # refuses when the type has no such slot
301
+ backfilled.append(cfg_key)
302
+
303
+ current = slot.get("value") or {}
304
+ previous = list(current.get("events") or [])
305
+ event = {"id": str(uuid.uuid4()),
306
+ "type": (args.type or default_type),
307
+ "action": action,
308
+ "config": ev_config}
309
+
310
+ # Three ways to combine the new event with the trigger's existing events:
311
+ # --replace-action ACT : replace ONLY events whose action is ACT, keeping the
312
+ # others and their ORDER (the safe O8 recipe — an element
313
+ # commonly carries [RUN_PROCESS, RUN_JAVASCRIPT] on one
314
+ # trigger, and you rarely mean to drop the sibling).
315
+ # --replace : replace ALL events (destructive) — warns when it would
316
+ # discard more than one.
317
+ # (neither) : append.
318
+ replace_action = (args.replace_action or "").strip().upper() or None
319
+ if replace_action and args.replace:
320
+ raise UsageError(
321
+ "pass either --replace (replace ALL events) or --replace-action <ACTION> "
322
+ "(replace only that action's events) — not both")
323
+ if replace_action and replace_action not in ACTIONS_ALLOWED:
324
+ raise UsageError(f"--replace-action must be one of {', '.join(ACTIONS_ALLOWED)}")
325
+
326
+ warning = None
327
+ if replace_action:
328
+ events, inserted = [], False
329
+ for e in previous:
330
+ if str(e.get("action") or "").upper() == replace_action:
331
+ if not inserted: # new event takes the first slot of its kind
332
+ events.append(event)
333
+ inserted = True
334
+ else:
335
+ events.append(e) # a different action survives, in place
336
+ if not inserted:
337
+ events.append(event)
338
+ elif args.replace:
339
+ events = [event]
340
+ if len(previous) > 1:
341
+ discarded = ", ".join(str(e.get("action")) for e in previous)
342
+ warning = (
343
+ f"--replace discarded ALL {len(previous)} existing events on this "
344
+ f"trigger ({discarded}). Elements commonly carry [RUN_PROCESS, "
345
+ f"RUN_JAVASCRIPT] on one trigger; to replace only one action and keep "
346
+ f"the rest (and their order), use --replace-action <ACTION> instead.")
347
+ else:
348
+ events = previous + [event]
349
+
350
+ result = {
351
+ "id": args.id, "element": args.element, "elementId": element.get("id"),
352
+ "trigger": cfg_key, "action": action,
353
+ "previous_events": previous, "event_count": len(events),
354
+ "elements": len(elements),
355
+ "backfilled": backfilled,
356
+ }
357
+ if warning:
358
+ result["warning"] = warning
359
+ if backfilled:
360
+ result["note"] = (
361
+ f"{args.element!r} was saved before its {', '.join(backfilled)} slot existed, so the "
362
+ f"slot was added from the element template (the form runtime and designer do the "
363
+ f"same on load/save); every other config is unchanged.")
364
+ if args.dry_run:
365
+ return {"dry_run": True, "event": event, **result}
366
+
367
+ guard = guard_unchanged(lambda: _fetch(client, args.id), form, force=args.force)
368
+ slot["value"] = {"debounce": current.get("debounce", 0), "events": events}
369
+ client.put("/api/FormTemplate", build_put_body(form, data=form["data"]))
370
+ return {"updated": True, "event": event, "concurrency": guard, **result}
371
+
372
+
373
+ def get_element_events(client, args) -> dict:
374
+ form = _fetch(client, args.id)
375
+ element = _find_element(form["data"].get("elements") or [], args.element)
376
+ out = {}
377
+ for c in element.get("configs") or []:
378
+ k = c.get("key") or ""
379
+ if "vent" in k:
380
+ out[k] = (c.get("value") or {}).get("events") or []
381
+ return {"id": args.id, "element": args.element, "elementId": element.get("id"),
382
+ "type": element.get("type"), "events": out}
383
+
384
+
385
+ def _common(p: argparse.ArgumentParser) -> None:
386
+ add_profile_arg(p)
387
+ p.add_argument("--id", required=True, help="form template id")
388
+ p.add_argument("--element", required=True,
389
+ help="element id, or its designer 'name' (e.g. doccipf)")
390
+
391
+
392
+ def _set_args(p: argparse.ArgumentParser) -> None:
393
+ _common(p)
394
+ p.add_argument("--on", required=True,
395
+ help="trigger: " + " | ".join(sorted(_EVENT_KEY)) + " (case, '-' and '_' "
396
+ "are ignored). A slot missing from an element saved before that "
397
+ "trigger existed is added from the element template and reported "
398
+ "under `backfilled`")
399
+ p.add_argument("--action", required=True,
400
+ help="RUN_PROCESS | RUN_JAVASCRIPT | RUN_DATA_STORE_OPERATION")
401
+ p.add_argument("--config", help="event config as JSON")
402
+ p.add_argument("--data-store-id", dest="data_store_id",
403
+ help="RUN_DATA_STORE_OPERATION: the target data store id")
404
+ p.add_argument("--operation",
405
+ help="RUN_DATA_STORE_OPERATION: READ | ADD | UPDATE | DELETE")
406
+ p.add_argument("--config-file", dest="config_file", help="path to a JSON config file")
407
+ p.add_argument("--type", help="override the event type (default follows the trigger)")
408
+ p.add_argument("--replace", action="store_true",
409
+ help="replace ALL of this trigger's events instead of appending "
410
+ "(destructive; warns when it discards more than one)")
411
+ p.add_argument("--replace-action", dest="replace_action",
412
+ help="replace only this trigger's events whose action is this "
413
+ "(RUN_PROCESS/RUN_JAVASCRIPT), preserving the others and order")
414
+ p.add_argument("--dry-run", dest="dry_run", action="store_true",
415
+ help="build the event and report it without writing")
416
+ add_force_arg(p)
417
+
418
+
419
+ ACTIONS = {
420
+ "form-get-element-events": ActionDef(
421
+ func=get_element_events, add_args=_common, needs_client=True,
422
+ description="List one element's event handlers, by trigger.",
423
+ ),
424
+ "form-set-element-event": ActionDef(
425
+ func=set_element_event, add_args=_set_args, needs_client=True,
426
+ description="Wire one element's trigger to RUN_PROCESS / RUN_JAVASCRIPT / "
427
+ "RUN_DATA_STORE_OPERATION in place (surgical: only that element's event "
428
+ "config changes). In a RUN_PROCESS inputMap/outputMap BOTH sides take "
429
+ "NAMES: left = a process variable name, right = a form FIELD name, a form "
430
+ "variable (@Offer_ID), an element config (Paragraph9.label) or a data-model "
431
+ "path (instance.currentUser.email) - each "
432
+ "is resolved to the id/value-path the runtime needs. Do NOT hand-build "
433
+ "the form value path; if you pass one it is CHECKED against the live form "
434
+ "and refused when wrong, because a wrong path is saved without any error "
435
+ "and the control then launches nothing. A DataStore op takes "
436
+ "--data-store-id + --operation. An element saved before the trigger "
437
+ "existed (e.g. an approval control from before Sep 2025, no "
438
+ "onBeforeApprove slot) gets the missing slot added from the element "
439
+ "template, listed in `backfilled`.",
440
+ ),
441
+ }