ecoportal-api-graphql 1.3.5 → 1.3.9

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 (499) hide show
  1. checksums.yaml +4 -4
  2. data/.ai-assistance/bridge/CLAUDE.md +338 -0
  3. data/.ai-assistance/bridge/archive/.gitkeep +0 -0
  4. data/.ai-assistance/bridge/archive/oscar-a1b2c3d-gitlab-mcp-doc-update.inbox.md +29 -0
  5. data/.ai-assistance/bridge/archive/oscar-a1b2c3d-gitlab-mcp-doc-update.outbox.md +18 -0
  6. data/.ai-assistance/bridge/archive/oscar-c912c25-gemini-design-review.inbox.md +42 -0
  7. data/.ai-assistance/bridge/archive/oscar-c912c25-gemini-design-review.outbox.md +115 -0
  8. data/.ai-assistance/bridge/context/gemini-review-prompt.txt +48 -0
  9. data/.ai-assistance/bridge/context/gemini-review-response.md +104 -0
  10. data/.ai-assistance/bridge/context/project.md +42 -0
  11. data/.ai-assistance/bridge/inbox/.gitkeep +0 -0
  12. data/.ai-assistance/bridge/outbox/.gitkeep +0 -0
  13. data/.ai-assistance/bridge/outbox/request-for-standards-discovery.md +48 -0
  14. data/.ai-assistance/bridge/queue/.gitkeep +1 -0
  15. data/.ai-assistance/capabilities/CLAUDE.md +27 -0
  16. data/.ai-assistance/capabilities/assumptions-log.md +80 -0
  17. data/.ai-assistance/capabilities/code.md +47 -0
  18. data/.ai-assistance/capabilities/connectors.md +37 -0
  19. data/.ai-assistance/capabilities/cowork.md +55 -0
  20. data/.ai-assistance/code/OVERVIEW.md +155 -0
  21. data/.ai-assistance/code/data_fields.md +242 -0
  22. data/.ai-assistance/code/dependencies.md +151 -0
  23. data/.ai-assistance/code/diff_as_input.md +234 -0
  24. data/.ai-assistance/code/diff_service_deep_dive.md +192 -0
  25. data/.ai-assistance/code/ecoPortal_architecture/00_overview_and_index.md +55 -0
  26. data/.ai-assistance/code/ecoPortal_architecture/01_terminology_dictionary.md +181 -0
  27. data/.ai-assistance/code/ecoPortal_architecture/02_data_model.md +192 -0
  28. data/.ai-assistance/code/ecoPortal_architecture/03_api_layers.md +147 -0
  29. data/.ai-assistance/code/ecoPortal_architecture/04_graphql_queries_mutations.md +277 -0
  30. data/.ai-assistance/code/ecoPortal_architecture/05_page_workflows.md +200 -0
  31. data/.ai-assistance/code/ecoPortal_architecture/06_search_and_filters.md +228 -0
  32. data/.ai-assistance/code/ecoPortal_architecture/07_data_fields.md +197 -0
  33. data/.ai-assistance/code/ecoPortal_architecture/08_stages_sections.md +243 -0
  34. data/.ai-assistance/code/ecoPortal_architecture/09_people_contractors_locations.md +196 -0
  35. data/.ai-assistance/code/ecoPortal_architecture/10_forces_workflow_builder.md +132 -0
  36. data/.ai-assistance/code/ecoPortal_architecture/11_integration_gems.md +187 -0
  37. data/.ai-assistance/code/ecoPortal_architecture/12_ai_documentation_sources_gaps.md +236 -0
  38. data/.ai-assistance/code/ecoPortal_architecture/13_ai_infrastructure.md +183 -0
  39. data/.ai-assistance/code/ecoportal_schema_reference.md +240 -0
  40. data/.ai-assistance/code/graphql_domain_knowledge.md +230 -0
  41. data/.ai-assistance/code/refactoring/datafield-readwrite-shape-asymmetry.md +71 -0
  42. data/.ai-assistance/code/refactoring/opportunities.md +251 -0
  43. data/.ai-assistance/code/schema_analysis.md +321 -0
  44. data/.ai-assistance/code/search_filters.md +868 -0
  45. data/.ai-assistance/code/spec_coverage.md +73 -0
  46. data/.ai-assistance/code/workflow-command-guide.md +438 -0
  47. data/.ai-assistance/code/workflow-space.md +353 -0
  48. data/.ai-assistance/conventions/CLAUDE.md +30 -0
  49. data/.ai-assistance/conventions/code-working-tree-protocol.md +199 -0
  50. data/.ai-assistance/conventions/gitignore-rules.md +42 -0
  51. data/.ai-assistance/conventions/permission-guidance.md +120 -0
  52. data/.ai-assistance/integrations/README.md +70 -0
  53. data/.ai-assistance/integrations/gitkraken-mcp.md +107 -0
  54. data/.ai-assistance/integrations/gitlab-mcp.md +123 -0
  55. data/.ai-assistance/integrations/local-git.md +60 -0
  56. data/.ai-assistance/local_paths.example.md +17 -0
  57. data/.ai-assistance/projects/TODO.md +97 -0
  58. data/.ai-assistance/projects/api-v2-to-graphql-migration/DECISIONS.md +168 -0
  59. data/.ai-assistance/projects/api-v2-to-graphql-migration/INTENT.md +60 -0
  60. data/.ai-assistance/projects/api-v2-to-graphql-migration/TODO.md +267 -0
  61. data/.ai-assistance/projects/api-v2-to-graphql-migration/UPSTREAM.md +53 -0
  62. data/.ai-assistance/projects/api-v2-to-graphql-migration/notes/csv-template-pipeline-design.md +102 -0
  63. data/.ai-assistance/projects/api-v2-to-graphql-migration/notes/cutover-usecase-gap-audit.md +139 -0
  64. data/.ai-assistance/projects/dynamic-model-generation/INTENT.md +93 -0
  65. data/.ai-assistance/projects/eco-helpers-compat/INTENT.md +244 -0
  66. data/.ai-assistance/projects/eco-helpers-compat/MIGRATION_GUIDE.md +266 -0
  67. data/.ai-assistance/projects/eco-helpers-compat/TODO.md +86 -0
  68. data/.ai-assistance/projects/ecoportal-api-v2-doublemodel-review/INTENT.md +101 -0
  69. data/.ai-assistance/projects/graphql-agent/GAP_ANALYSIS.md +177 -0
  70. data/.ai-assistance/projects/ooze-graphql-native-migration/DECISIONS.md +161 -0
  71. data/.ai-assistance/projects/ooze-graphql-native-migration/INTENT.md +125 -0
  72. data/.ai-assistance/projects/ooze-graphql-native-migration/RISKS.md +126 -0
  73. data/.ai-assistance/projects/ooze-graphql-native-migration/TODO.md +256 -0
  74. data/.ai-assistance/projects/ooze-graphql-native-migration/analysis/2026-06-30-cutover-workflow-deep-review.md +122 -0
  75. data/.ai-assistance/projects/ooze-graphql-native-migration/analysis/2026-07-01-forces-via-workflow-commands-miss-rca.md +148 -0
  76. data/.ai-assistance/projects/page-model/DECISIONS.md +245 -0
  77. data/.ai-assistance/projects/page-model/TODO.md +190 -0
  78. data/.ai-assistance/projects/search-filter-builder/INTENT.md +107 -0
  79. data/.ai-assistance/projects/search-filter-builder/TODO.md +131 -0
  80. data/.ai-assistance/projects/template-maintenance/DESIGN.md +134 -0
  81. data/.ai-assistance/projects/workflow-space/TODO.md +213 -0
  82. data/.ai-assistance/reinstall-claude-desktop-windows.md +136 -0
  83. data/.ai-assistance/scripts/CLAUDE.md +150 -0
  84. data/.ai-assistance/scripts/bridge-init.sh +86 -0
  85. data/.ai-assistance/scripts/bridge-status.sh +44 -0
  86. data/.ai-assistance/scripts/capabilities-check.ts +104 -0
  87. data/.ai-assistance/scripts/check-outbox.sh +43 -0
  88. data/.ai-assistance/scripts/dep_graph.rb +91 -0
  89. data/.ai-assistance/scripts/lock-acquire.sh +103 -0
  90. data/.ai-assistance/scripts/lock-multi.sh +124 -0
  91. data/.ai-assistance/scripts/lock-queue.sh +94 -0
  92. data/.ai-assistance/scripts/setup-mcps.test.ts +188 -0
  93. data/.ai-assistance/scripts/setup-mcps.ts +234 -0
  94. data/.ai-assistance/scripts/task-complete.ts +74 -0
  95. data/.ai-assistance/scripts/task-create.ts +75 -0
  96. data/.ai-assistance/scripts/task-read.ts +125 -0
  97. data/.ai-assistance/scripts/token-logger.js +220 -0
  98. data/.ai-assistance/scripts/token-report.ts +158 -0
  99. data/.ai-assistance/scripts/token-session-start.js +66 -0
  100. data/.ai-assistance/skills/ai-instructions/SKILL.md +48 -0
  101. data/.ai-assistance/skills/code-specs/SKILL.md +69 -0
  102. data/.ai-assistance/skills/corporate-policies/SKILL.md +201 -0
  103. data/.ai-assistance/skills/dep-graph/SKILL.md +139 -0
  104. data/.ai-assistance/skills/ep-ai-manager/SKILL.md +417 -0
  105. data/.ai-assistance/skills/gemini-assist/SKILL.md +63 -0
  106. data/.ai-assistance/skills/gemini-assist/gemini-mcp-server.js +205 -0
  107. data/.ai-assistance/skills/gemini-assist/gemini_ask.py +1 -0
  108. data/.ai-assistance/skills/gemini-assist/gemini_ask.rb +240 -0
  109. data/.ai-assistance/skills/gemini-assist/prompts/cycle_end_review.txt +25 -0
  110. data/.ai-assistance/skills/graphql-schema-analysis/SKILL.md +261 -0
  111. data/.ai-assistance/skills/project-cycle/SKILL.md +177 -0
  112. data/.ai-assistance/skills/refactor/SKILL.md +62 -0
  113. data/.ai-assistance/skills/rubocop/SKILL.md +93 -0
  114. data/.ai-assistance/skills/ruby-scripting/SKILL.md +215 -0
  115. data/.ai-assistance/skills/spec-generation/SKILL.md +72 -0
  116. data/.ai-assistance/standards-version.json +21 -0
  117. data/.ai-assistance/token-budget.json +32 -0
  118. data/.ai-assistance/version.json +39 -0
  119. data/.claude/settings.json +146 -0
  120. data/.env.example +18 -0
  121. data/.gitattributes +15 -0
  122. data/.gitignore +13 -0
  123. data/.rubocop.yml +121 -97
  124. data/CHANGELOG.md +673 -477
  125. data/CLAUDE.md +232 -0
  126. data/Gemfile +30 -6
  127. data/Rakefile +90 -38
  128. data/docs/worklog.md +574 -0
  129. data/ecoportal-api-graphql.gemspec +40 -40
  130. data/lib/ecoportal/api/common/graphql/CLAUDE.md +36 -0
  131. data/lib/ecoportal/api/common/graphql/client.rb +1 -1
  132. data/lib/ecoportal/api/common/graphql/http_client.rb +35 -3
  133. data/lib/ecoportal/api/common/graphql/model/CLAUDE.md +28 -0
  134. data/lib/ecoportal/api/common/graphql/model/as_input.rb +8 -5
  135. data/lib/ecoportal/api/common/graphql/model/diffable/classic_diff_service.rb +3 -1
  136. data/lib/ecoportal/api/common/graphql/model/diffable/diff_service.rb +31 -23
  137. data/lib/ecoportal/api/common/graphql/model/diffable/hash_diff_nesting.rb +54 -1
  138. data/lib/ecoportal/api/graphql/CLAUDE.md +37 -0
  139. data/lib/ecoportal/api/graphql/base/CLAUDE.md +50 -0
  140. data/lib/ecoportal/api/graphql/base/ai_summary_version.rb +17 -0
  141. data/lib/ecoportal/api/graphql/base/delta_result.rb +16 -0
  142. data/lib/ecoportal/api/graphql/base/force/binding.rb +19 -0
  143. data/lib/ecoportal/api/graphql/base/force/binding_collection.rb +62 -0
  144. data/lib/ecoportal/api/graphql/base/force/collection.rb +47 -0
  145. data/lib/ecoportal/api/graphql/base/force.rb +65 -0
  146. data/lib/ecoportal/api/graphql/base/kickstand/job.rb +17 -0
  147. data/lib/ecoportal/api/graphql/base/kickstand/workflow.rb +18 -0
  148. data/lib/ecoportal/api/graphql/base/kickstand.rb +13 -0
  149. data/lib/ecoportal/api/graphql/base/page/basic.rb +38 -0
  150. data/lib/ecoportal/api/graphql/base/page/data_field/actions_list.rb +9 -0
  151. data/lib/ecoportal/api/graphql/base/page/data_field/ai_summary.rb +18 -0
  152. data/lib/ecoportal/api/graphql/base/page/data_field/checklist.rb +29 -0
  153. data/lib/ecoportal/api/graphql/base/page/data_field/collection.rb +112 -0
  154. data/lib/ecoportal/api/graphql/base/page/data_field/contractor_entities.rb +28 -0
  155. data/lib/ecoportal/api/graphql/base/page/data_field/cross_reference.rb +54 -0
  156. data/lib/ecoportal/api/graphql/base/page/data_field/date_field.rb +23 -0
  157. data/lib/ecoportal/api/graphql/base/page/data_field/file_field.rb +25 -0
  158. data/lib/ecoportal/api/graphql/base/page/data_field/gauge.rb +19 -0
  159. data/lib/ecoportal/api/graphql/base/page/data_field/geo.rb +24 -0
  160. data/lib/ecoportal/api/graphql/base/page/data_field/image_gallery.rb +24 -0
  161. data/lib/ecoportal/api/graphql/base/page/data_field/law.rb +8 -0
  162. data/lib/ecoportal/api/graphql/base/page/data_field/mailbox.rb +9 -0
  163. data/lib/ecoportal/api/graphql/base/page/data_field/number.rb +20 -0
  164. data/lib/ecoportal/api/graphql/base/page/data_field/people.rb +35 -0
  165. data/lib/ecoportal/api/graphql/base/page/data_field/plain_text.rb +17 -0
  166. data/lib/ecoportal/api/graphql/base/page/data_field/rich_text.rb +26 -0
  167. data/lib/ecoportal/api/graphql/base/page/data_field/select.rb +41 -0
  168. data/lib/ecoportal/api/graphql/base/page/data_field/signature.rb +9 -0
  169. data/lib/ecoportal/api/graphql/base/page/data_field/smart_fill.rb +17 -0
  170. data/lib/ecoportal/api/graphql/base/page/data_field/table.rb +9 -0
  171. data/lib/ecoportal/api/graphql/base/page/data_field/tag_field.rb +21 -0
  172. data/lib/ecoportal/api/graphql/base/page/data_field.rb +137 -12
  173. data/lib/ecoportal/api/graphql/base/page/phased/stage.rb +68 -14
  174. data/lib/ecoportal/api/graphql/base/page/phased.rb +1 -0
  175. data/lib/ecoportal/api/graphql/base/page/section.rb +36 -0
  176. data/lib/ecoportal/api/graphql/base/page/section_collection.rb +79 -0
  177. data/lib/ecoportal/api/graphql/base/page.rb +2 -0
  178. data/lib/ecoportal/api/graphql/base/pages_workflow/action_type_selection.rb +17 -0
  179. data/lib/ecoportal/api/graphql/base/pages_workflow/callback_type.rb +28 -0
  180. data/lib/ecoportal/api/graphql/base/pages_workflow/command_change.rb +17 -0
  181. data/lib/ecoportal/api/graphql/base/pages_workflow/command_change_message.rb +15 -0
  182. data/lib/ecoportal/api/graphql/base/pages_workflow/command_es_change.rb +17 -0
  183. data/lib/ecoportal/api/graphql/base/pages_workflow/command_interface.rb +36 -0
  184. data/lib/ecoportal/api/graphql/base/pages_workflow/email_config.rb +18 -0
  185. data/lib/ecoportal/api/graphql/base/pages_workflow/escalation_level.rb +19 -0
  186. data/lib/ecoportal/api/graphql/base/pages_workflow/in_system_config.rb +16 -0
  187. data/lib/ecoportal/api/graphql/base/pages_workflow/mailbox_field_selection.rb +17 -0
  188. data/lib/ecoportal/api/graphql/base/pages_workflow/operation_interface.rb +39 -0
  189. data/lib/ecoportal/api/graphql/base/pages_workflow/operations/assign_to.rb +27 -0
  190. data/lib/ecoportal/api/graphql/base/pages_workflow/operations/create_page.rb +21 -0
  191. data/lib/ecoportal/api/graphql/base/pages_workflow/operations/send_notification.rb +30 -0
  192. data/lib/ecoportal/api/graphql/base/pages_workflow/people_field_selection.rb +17 -0
  193. data/lib/ecoportal/api/graphql/base/pages_workflow/recipient_config.rb +34 -0
  194. data/lib/ecoportal/api/graphql/base/pages_workflow/register_field.rb +17 -0
  195. data/lib/ecoportal/api/graphql/base/pages_workflow/task_config_selection.rb +17 -0
  196. data/lib/ecoportal/api/graphql/base/pages_workflow/time_delay_config.rb +16 -0
  197. data/lib/ecoportal/api/graphql/base/pages_workflow/trigger_interface.rb +26 -0
  198. data/lib/ecoportal/api/graphql/base/pages_workflow/triggers/conditional_logic.rb +17 -0
  199. data/lib/ecoportal/api/graphql/base/pages_workflow/user_selection.rb +16 -0
  200. data/lib/ecoportal/api/graphql/base/pages_workflow.rb +35 -0
  201. data/lib/ecoportal/api/graphql/base/preset_view.rb +17 -0
  202. data/lib/ecoportal/api/graphql/base/preview_page.rb +23 -0
  203. data/lib/ecoportal/api/graphql/base/register.rb +18 -0
  204. data/lib/ecoportal/api/graphql/base.rb +11 -0
  205. data/lib/ecoportal/api/graphql/builder/CLAUDE.md +65 -0
  206. data/lib/ecoportal/api/graphql/builder/kickstand.rb +73 -0
  207. data/lib/ecoportal/api/graphql/builder/page.rb +210 -41
  208. data/lib/ecoportal/api/graphql/builder/register/preset_view.rb +84 -0
  209. data/lib/ecoportal/api/graphql/builder/register.rb +27 -19
  210. data/lib/ecoportal/api/graphql/builder/template.rb +80 -0
  211. data/lib/ecoportal/api/graphql/builder.rb +2 -0
  212. data/lib/ecoportal/api/graphql/compat/filter_translator.rb +107 -0
  213. data/lib/ecoportal/api/graphql/compat/page_reference.rb +23 -0
  214. data/lib/ecoportal/api/graphql/compat/pages.rb +212 -0
  215. data/lib/ecoportal/api/graphql/compat/registers.rb +84 -0
  216. data/lib/ecoportal/api/graphql/compat/response.rb +35 -0
  217. data/lib/ecoportal/api/graphql/compat/search_results.rb +33 -0
  218. data/lib/ecoportal/api/graphql/compat/stage_collection.rb +70 -0
  219. data/lib/ecoportal/api/graphql/compat/stage_view.rb +76 -0
  220. data/lib/ecoportal/api/graphql/compat.rb +17 -0
  221. data/lib/ecoportal/api/graphql/concerns/data_field_access.rb +71 -0
  222. data/lib/ecoportal/api/graphql/concerns/deprecation.rb +20 -0
  223. data/lib/ecoportal/api/graphql/concerns/fragment_definitions.rb +21 -28
  224. data/lib/ecoportal/api/graphql/concerns/page_compat.rb +51 -0
  225. data/lib/ecoportal/api/graphql/concerns/snake_camel_access.rb +60 -0
  226. data/lib/ecoportal/api/graphql/concerns.rb +4 -0
  227. data/lib/ecoportal/api/graphql/connection/page.rb +11 -0
  228. data/lib/ecoportal/api/graphql/connection/pages_workflow_command.rb +13 -0
  229. data/lib/ecoportal/api/graphql/connection/preset_view.rb +11 -0
  230. data/lib/ecoportal/api/graphql/connection/preview_page.rb +11 -0
  231. data/lib/ecoportal/api/graphql/connection.rb +4 -0
  232. data/lib/ecoportal/api/graphql/file_upload/client.rb +181 -0
  233. data/lib/ecoportal/api/graphql/file_upload.rb +10 -0
  234. data/lib/ecoportal/api/graphql/fragment/action.rb +1 -1
  235. data/lib/ecoportal/api/graphql/fragment/action_category.rb +1 -1
  236. data/lib/ecoportal/api/graphql/fragment/contractor_entity.rb +1 -1
  237. data/lib/ecoportal/api/graphql/fragment/force.rb +30 -0
  238. data/lib/ecoportal/api/graphql/fragment/location_draft.rb +2 -2
  239. data/lib/ecoportal/api/graphql/fragment/location_node.rb +1 -1
  240. data/lib/ecoportal/api/graphql/fragment/locations_error.rb +1 -1
  241. data/lib/ecoportal/api/graphql/fragment/page.rb +85 -0
  242. data/lib/ecoportal/api/graphql/fragment/pages/common_page_union.rb +395 -0
  243. data/lib/ecoportal/api/graphql/fragment/pages.rb +15 -0
  244. data/lib/ecoportal/api/graphql/fragment/pages_workflow.rb +172 -0
  245. data/lib/ecoportal/api/graphql/fragment/pagination.rb +1 -1
  246. data/lib/ecoportal/api/graphql/fragment.rb +37 -27
  247. data/lib/ecoportal/api/graphql/input/contractor_entity/update.rb +25 -0
  248. data/lib/ecoportal/api/graphql/input/delta_input.rb +16 -0
  249. data/lib/ecoportal/api/graphql/input/page/archive.rb +14 -0
  250. data/lib/ecoportal/api/graphql/input/page/build_from_template.rb +13 -0
  251. data/lib/ecoportal/api/graphql/input/page/create_draft.rb +13 -0
  252. data/lib/ecoportal/api/graphql/input/page/create_from_template.rb +18 -0
  253. data/lib/ecoportal/api/graphql/input/page/delete_draft.rb +13 -0
  254. data/lib/ecoportal/api/graphql/input/page/publish_draft.rb +13 -0
  255. data/lib/ecoportal/api/graphql/input/page/review_task.rb +14 -0
  256. data/lib/ecoportal/api/graphql/input/page/unarchive.rb +14 -0
  257. data/lib/ecoportal/api/graphql/input/page/update.rb +140 -0
  258. data/lib/ecoportal/api/graphql/input/page.rb +26 -0
  259. data/lib/ecoportal/api/graphql/input/preset_view/create.rb +18 -0
  260. data/lib/ecoportal/api/graphql/input/preset_view/permission.rb +16 -0
  261. data/lib/ecoportal/api/graphql/input/preset_view/update.rb +16 -0
  262. data/lib/ecoportal/api/graphql/input/preset_view.rb +14 -0
  263. data/lib/ecoportal/api/graphql/input/register/create.rb +18 -0
  264. data/lib/ecoportal/api/graphql/input/register/update.rb +15 -0
  265. data/lib/ecoportal/api/graphql/input/register.rb +13 -0
  266. data/lib/ecoportal/api/graphql/input/search_conf/ai_generator.rb +234 -0
  267. data/lib/ecoportal/api/graphql/input/search_conf.rb +367 -0
  268. data/lib/ecoportal/api/graphql/input/variable_binding.rb +20 -0
  269. data/lib/ecoportal/api/graphql/input/workflow_command/add_action_tag.rb +18 -0
  270. data/lib/ecoportal/api/graphql/input/workflow_command/add_binding.rb +18 -0
  271. data/lib/ecoportal/api/graphql/input/workflow_command/add_comment_tagging_user_group.rb +18 -0
  272. data/lib/ecoportal/api/graphql/input/workflow_command/add_default_direct_strategy_user.rb +18 -0
  273. data/lib/ecoportal/api/graphql/input/workflow_command/add_default_strategy.rb +18 -0
  274. data/lib/ecoportal/api/graphql/input/workflow_command/add_direct_strategy_user.rb +18 -0
  275. data/lib/ecoportal/api/graphql/input/workflow_command/add_field.rb +18 -0
  276. data/lib/ecoportal/api/graphql/input/workflow_command/add_force.rb +18 -0
  277. data/lib/ecoportal/api/graphql/input/workflow_command/add_gauge_field_stop.rb +19 -0
  278. data/lib/ecoportal/api/graphql/input/workflow_command/add_linked_field_config.rb +23 -0
  279. data/lib/ecoportal/api/graphql/input/workflow_command/add_linked_helper.rb +18 -0
  280. data/lib/ecoportal/api/graphql/input/workflow_command/add_operation.rb +18 -0
  281. data/lib/ecoportal/api/graphql/input/workflow_command/add_operation_direct_strategy_user.rb +18 -0
  282. data/lib/ecoportal/api/graphql/input/workflow_command/add_operation_strategy.rb +18 -0
  283. data/lib/ecoportal/api/graphql/input/workflow_command/add_recipient_action_type.rb +18 -0
  284. data/lib/ecoportal/api/graphql/input/workflow_command/add_recipient_filter.rb +18 -0
  285. data/lib/ecoportal/api/graphql/input/workflow_command/add_recipient_people_field.rb +18 -0
  286. data/lib/ecoportal/api/graphql/input/workflow_command/add_recipient_task_config.rb +18 -0
  287. data/lib/ecoportal/api/graphql/input/workflow_command/add_recipient_user.rb +18 -0
  288. data/lib/ecoportal/api/graphql/input/workflow_command/add_scheduled_callback.rb +23 -0
  289. data/lib/ecoportal/api/graphql/input/workflow_command/add_scheduled_callback_action.rb +18 -0
  290. data/lib/ecoportal/api/graphql/input/workflow_command/add_section.rb +18 -0
  291. data/lib/ecoportal/api/graphql/input/workflow_command/add_select_field_option.rb +19 -0
  292. data/lib/ecoportal/api/graphql/input/workflow_command/add_stage.rb +18 -0
  293. data/lib/ecoportal/api/graphql/input/workflow_command/add_stage_section.rb +18 -0
  294. data/lib/ecoportal/api/graphql/input/workflow_command/add_stage_tag.rb +18 -0
  295. data/lib/ecoportal/api/graphql/input/workflow_command/add_strategy.rb +18 -0
  296. data/lib/ecoportal/api/graphql/input/workflow_command/add_task.rb +18 -0
  297. data/lib/ecoportal/api/graphql/input/workflow_command/add_task_assignment_user_group.rb +18 -0
  298. data/lib/ecoportal/api/graphql/input/workflow_command/add_workflow_callback.rb +18 -0
  299. data/lib/ecoportal/api/graphql/input/workflow_command/collapse_section.rb +18 -0
  300. data/lib/ecoportal/api/graphql/input/workflow_command/edit_binding.rb +18 -0
  301. data/lib/ecoportal/api/graphql/input/workflow_command/edit_creator_permissions.rb +18 -0
  302. data/lib/ecoportal/api/graphql/input/workflow_command/edit_default_strategy.rb +18 -0
  303. data/lib/ecoportal/api/graphql/input/workflow_command/edit_field_configuration.rb +21 -0
  304. data/lib/ecoportal/api/graphql/input/workflow_command/edit_force.rb +18 -0
  305. data/lib/ecoportal/api/graphql/input/workflow_command/edit_gauge_field_stop.rb +19 -0
  306. data/lib/ecoportal/api/graphql/input/workflow_command/edit_linked_field_config.rb +19 -0
  307. data/lib/ecoportal/api/graphql/input/workflow_command/edit_linked_helper.rb +18 -0
  308. data/lib/ecoportal/api/graphql/input/workflow_command/edit_operation.rb +18 -0
  309. data/lib/ecoportal/api/graphql/input/workflow_command/edit_operation_strategy.rb +18 -0
  310. data/lib/ecoportal/api/graphql/input/workflow_command/edit_page.rb +28 -0
  311. data/lib/ecoportal/api/graphql/input/workflow_command/edit_page_creator_permissions.rb +18 -0
  312. data/lib/ecoportal/api/graphql/input/workflow_command/edit_reminder.rb +18 -0
  313. data/lib/ecoportal/api/graphql/input/workflow_command/edit_required_sign_offs.rb +18 -0
  314. data/lib/ecoportal/api/graphql/input/workflow_command/edit_restrict_comment_tagging.rb +18 -0
  315. data/lib/ecoportal/api/graphql/input/workflow_command/edit_restrict_task_assignment.rb +18 -0
  316. data/lib/ecoportal/api/graphql/input/workflow_command/edit_scheduled_callback.rb +22 -0
  317. data/lib/ecoportal/api/graphql/input/workflow_command/edit_section_header.rb +18 -0
  318. data/lib/ecoportal/api/graphql/input/workflow_command/edit_select_field_option.rb +19 -0
  319. data/lib/ecoportal/api/graphql/input/workflow_command/edit_stage.rb +18 -0
  320. data/lib/ecoportal/api/graphql/input/workflow_command/edit_strategy.rb +18 -0
  321. data/lib/ecoportal/api/graphql/input/workflow_command/edit_task_due.rb +18 -0
  322. data/lib/ecoportal/api/graphql/input/workflow_command/edit_trigger.rb +18 -0
  323. data/lib/ecoportal/api/graphql/input/workflow_command/expand_section.rb +18 -0
  324. data/lib/ecoportal/api/graphql/input/workflow_command/field_config/contractor_entities.rb +24 -0
  325. data/lib/ecoportal/api/graphql/input/workflow_command/field_config/cross_reference.rb +23 -0
  326. data/lib/ecoportal/api/graphql/input/workflow_command/field_config/date.rb +20 -0
  327. data/lib/ecoportal/api/graphql/input/workflow_command/field_config/gauge.rb +20 -0
  328. data/lib/ecoportal/api/graphql/input/workflow_command/field_config/image_gallery.rb +20 -0
  329. data/lib/ecoportal/api/graphql/input/workflow_command/field_config/location_field.rb +24 -0
  330. data/lib/ecoportal/api/graphql/input/workflow_command/field_config/people.rb +24 -0
  331. data/lib/ecoportal/api/graphql/input/workflow_command/field_config/plain_text.rb +20 -0
  332. data/lib/ecoportal/api/graphql/input/workflow_command/field_config/rich_text.rb +20 -0
  333. data/lib/ecoportal/api/graphql/input/workflow_command/field_config/select.rb +20 -0
  334. data/lib/ecoportal/api/graphql/input/workflow_command/field_config/signature.rb +20 -0
  335. data/lib/ecoportal/api/graphql/input/workflow_command/field_config/table.rb +25 -0
  336. data/lib/ecoportal/api/graphql/input/workflow_command/move_field.rb +18 -0
  337. data/lib/ecoportal/api/graphql/input/workflow_command/move_stage.rb +18 -0
  338. data/lib/ecoportal/api/graphql/input/workflow_command/remove_action_tag.rb +18 -0
  339. data/lib/ecoportal/api/graphql/input/workflow_command/remove_binding.rb +18 -0
  340. data/lib/ecoportal/api/graphql/input/workflow_command/remove_callback.rb +18 -0
  341. data/lib/ecoportal/api/graphql/input/workflow_command/remove_comment_tagging_user_group.rb +18 -0
  342. data/lib/ecoportal/api/graphql/input/workflow_command/remove_default_direct_strategy_user.rb +18 -0
  343. data/lib/ecoportal/api/graphql/input/workflow_command/remove_default_strategy.rb +18 -0
  344. data/lib/ecoportal/api/graphql/input/workflow_command/remove_direct_strategy_user.rb +18 -0
  345. data/lib/ecoportal/api/graphql/input/workflow_command/remove_field.rb +18 -0
  346. data/lib/ecoportal/api/graphql/input/workflow_command/remove_force.rb +18 -0
  347. data/lib/ecoportal/api/graphql/input/workflow_command/remove_gauge_field_stop.rb +17 -0
  348. data/lib/ecoportal/api/graphql/input/workflow_command/remove_linked_field_config.rb +17 -0
  349. data/lib/ecoportal/api/graphql/input/workflow_command/remove_linked_helper.rb +18 -0
  350. data/lib/ecoportal/api/graphql/input/workflow_command/remove_operation.rb +18 -0
  351. data/lib/ecoportal/api/graphql/input/workflow_command/remove_operation_direct_strategy_user.rb +18 -0
  352. data/lib/ecoportal/api/graphql/input/workflow_command/remove_operation_strategy.rb +18 -0
  353. data/lib/ecoportal/api/graphql/input/workflow_command/remove_recipient_action_type.rb +18 -0
  354. data/lib/ecoportal/api/graphql/input/workflow_command/remove_recipient_filter.rb +18 -0
  355. data/lib/ecoportal/api/graphql/input/workflow_command/remove_recipient_people_field.rb +18 -0
  356. data/lib/ecoportal/api/graphql/input/workflow_command/remove_recipient_task_config.rb +18 -0
  357. data/lib/ecoportal/api/graphql/input/workflow_command/remove_recipient_user.rb +18 -0
  358. data/lib/ecoportal/api/graphql/input/workflow_command/remove_scheduled_callback.rb +18 -0
  359. data/lib/ecoportal/api/graphql/input/workflow_command/remove_section.rb +18 -0
  360. data/lib/ecoportal/api/graphql/input/workflow_command/remove_select_field_option.rb +17 -0
  361. data/lib/ecoportal/api/graphql/input/workflow_command/remove_stage.rb +18 -0
  362. data/lib/ecoportal/api/graphql/input/workflow_command/remove_stage_section.rb +18 -0
  363. data/lib/ecoportal/api/graphql/input/workflow_command/remove_stage_tag.rb +18 -0
  364. data/lib/ecoportal/api/graphql/input/workflow_command/remove_strategy.rb +18 -0
  365. data/lib/ecoportal/api/graphql/input/workflow_command/remove_task.rb +18 -0
  366. data/lib/ecoportal/api/graphql/input/workflow_command/remove_task_assignment_user_group.rb +18 -0
  367. data/lib/ecoportal/api/graphql/input/workflow_command/remove_task_due.rb +18 -0
  368. data/lib/ecoportal/api/graphql/input/workflow_command/remove_task_priority_level.rb +18 -0
  369. data/lib/ecoportal/api/graphql/input/workflow_command/reorder_forces.rb +18 -0
  370. data/lib/ecoportal/api/graphql/input/workflow_command/reorder_section.rb +18 -0
  371. data/lib/ecoportal/api/graphql/input/workflow_command.rb +251 -0
  372. data/lib/ecoportal/api/graphql/input.rb +8 -0
  373. data/lib/ecoportal/api/graphql/interface/base_page.rb +100 -58
  374. data/lib/ecoportal/api/graphql/interface/location_structure/nodes.rb +27 -28
  375. data/lib/ecoportal/api/graphql/logic/base_model.rb +2 -0
  376. data/lib/ecoportal/api/graphql/logic/base_query.rb +45 -2
  377. data/lib/ecoportal/api/graphql/logic/input.rb +15 -0
  378. data/lib/ecoportal/api/graphql/model/ai_summary_version.rb +10 -0
  379. data/lib/ecoportal/api/graphql/model/organization.rb +65 -55
  380. data/lib/ecoportal/api/graphql/model/page/basic.rb +14 -0
  381. data/lib/ecoportal/api/graphql/model/page/phased.rb +82 -20
  382. data/lib/ecoportal/api/graphql/model/page.rb +1 -0
  383. data/lib/ecoportal/api/graphql/model/page_union.rb +21 -0
  384. data/lib/ecoportal/api/graphql/model/pages_workflow.rb +20 -0
  385. data/lib/ecoportal/api/graphql/model/preset_view.rb +10 -0
  386. data/lib/ecoportal/api/graphql/model/preview_page.rb +10 -0
  387. data/lib/ecoportal/api/graphql/model/register.rb +10 -0
  388. data/lib/ecoportal/api/graphql/model.rb +8 -0
  389. data/lib/ecoportal/api/graphql/mutation/ai_summary/generate.rb +45 -0
  390. data/lib/ecoportal/api/graphql/mutation/ai_summary/submit_feedback.rb +40 -0
  391. data/lib/ecoportal/api/graphql/mutation/ai_summary.rb +13 -0
  392. data/lib/ecoportal/api/graphql/mutation/kickstand/bulk_update_jobs.rb +43 -0
  393. data/lib/ecoportal/api/graphql/mutation/kickstand/bulk_update_workflows.rb +43 -0
  394. data/lib/ecoportal/api/graphql/mutation/kickstand/fail_job.rb +39 -0
  395. data/lib/ecoportal/api/graphql/mutation/kickstand/fail_workflow.rb +39 -0
  396. data/lib/ecoportal/api/graphql/mutation/kickstand/start_job.rb +39 -0
  397. data/lib/ecoportal/api/graphql/mutation/kickstand/start_workflow.rb +39 -0
  398. data/lib/ecoportal/api/graphql/mutation/kickstand/stop_workflow.rb +39 -0
  399. data/lib/ecoportal/api/graphql/mutation/kickstand.rb +18 -0
  400. data/lib/ecoportal/api/graphql/mutation/location_structure/apply_commands.rb +3 -3
  401. data/lib/ecoportal/api/graphql/mutation/location_structure/draft/add_commands.rb +2 -2
  402. data/lib/ecoportal/api/graphql/mutation/location_structure/draft/create.rb +2 -2
  403. data/lib/ecoportal/api/graphql/mutation/location_structure/draft/drop_bad_commands.rb +3 -3
  404. data/lib/ecoportal/api/graphql/mutation/location_structure/draft/publish.rb +3 -3
  405. data/lib/ecoportal/api/graphql/mutation/page/approve_review_task.rb +40 -0
  406. data/lib/ecoportal/api/graphql/mutation/page/archive.rb +40 -0
  407. data/lib/ecoportal/api/graphql/mutation/page/batch_update_review_task.rb +40 -0
  408. data/lib/ecoportal/api/graphql/mutation/page/build_from_template.rb +50 -0
  409. data/lib/ecoportal/api/graphql/mutation/page/create_draft.rb +40 -0
  410. data/lib/ecoportal/api/graphql/mutation/page/create_from_template.rb +43 -0
  411. data/lib/ecoportal/api/graphql/mutation/page/delete_draft.rb +40 -0
  412. data/lib/ecoportal/api/graphql/mutation/page/execute_force_commands.rb +69 -0
  413. data/lib/ecoportal/api/graphql/mutation/page/execute_workflow_commands.rb +51 -0
  414. data/lib/ecoportal/api/graphql/mutation/page/publish_draft.rb +40 -0
  415. data/lib/ecoportal/api/graphql/mutation/page/reject_review_task.rb +40 -0
  416. data/lib/ecoportal/api/graphql/mutation/page/restart_review_task.rb +40 -0
  417. data/lib/ecoportal/api/graphql/mutation/page/unarchive.rb +40 -0
  418. data/lib/ecoportal/api/graphql/mutation/page/undo_review_task.rb +40 -0
  419. data/lib/ecoportal/api/graphql/mutation/page/update.rb +40 -0
  420. data/lib/ecoportal/api/graphql/mutation/page/update_variable_bindings.rb +44 -0
  421. data/lib/ecoportal/api/graphql/mutation/page.rb +28 -0
  422. data/lib/ecoportal/api/graphql/mutation/preset_view/create.rb +35 -0
  423. data/lib/ecoportal/api/graphql/mutation/preset_view/destroy.rb +35 -0
  424. data/lib/ecoportal/api/graphql/mutation/preset_view/permission.rb +37 -0
  425. data/lib/ecoportal/api/graphql/mutation/preset_view/update.rb +35 -0
  426. data/lib/ecoportal/api/graphql/mutation/preset_view.rb +15 -0
  427. data/lib/ecoportal/api/graphql/mutation/register/create.rb +35 -0
  428. data/lib/ecoportal/api/graphql/mutation/register/destroy.rb +35 -0
  429. data/lib/ecoportal/api/graphql/mutation/register/update.rb +35 -0
  430. data/lib/ecoportal/api/graphql/mutation/register.rb +14 -0
  431. data/lib/ecoportal/api/graphql/mutation/smart_fill/generate.rb +36 -0
  432. data/lib/ecoportal/api/graphql/mutation/smart_fill/submit_feedback.rb +40 -0
  433. data/lib/ecoportal/api/graphql/mutation/smart_fill.rb +13 -0
  434. data/lib/ecoportal/api/graphql/mutation/template/create.rb +39 -0
  435. data/lib/ecoportal/api/graphql/mutation/template/create_related_page.rb +46 -0
  436. data/lib/ecoportal/api/graphql/mutation/template/destroy_related_page.rb +43 -0
  437. data/lib/ecoportal/api/graphql/mutation/template/publish.rb +39 -0
  438. data/lib/ecoportal/api/graphql/mutation/template/unpublish.rb +39 -0
  439. data/lib/ecoportal/api/graphql/mutation/template/update.rb +43 -0
  440. data/lib/ecoportal/api/graphql/mutation/template/update_information.rb +43 -0
  441. data/lib/ecoportal/api/graphql/mutation/template.rb +18 -0
  442. data/lib/ecoportal/api/graphql/mutation.rb +8 -0
  443. data/lib/ecoportal/api/graphql/payload/ai_summary_generate.rb +12 -0
  444. data/lib/ecoportal/api/graphql/payload/execute_workflow_commands.rb +36 -0
  445. data/lib/ecoportal/api/graphql/payload/force_commands.rb +31 -0
  446. data/lib/ecoportal/api/graphql/payload/kickstand/bulk_update_jobs.rb +36 -0
  447. data/lib/ecoportal/api/graphql/payload/kickstand/bulk_update_workflows.rb +36 -0
  448. data/lib/ecoportal/api/graphql/payload/kickstand/job.rb +13 -0
  449. data/lib/ecoportal/api/graphql/payload/kickstand/workflow.rb +13 -0
  450. data/lib/ecoportal/api/graphql/payload/kickstand.rb +15 -0
  451. data/lib/ecoportal/api/graphql/payload/location_structure/draft/create.rb +33 -34
  452. data/lib/ecoportal/api/graphql/payload/ok_payload.rb +21 -0
  453. data/lib/ecoportal/api/graphql/payload/page/archive.rb +13 -0
  454. data/lib/ecoportal/api/graphql/payload/page/build_from_template.rb +13 -0
  455. data/lib/ecoportal/api/graphql/payload/page/create_from_template.rb +13 -0
  456. data/lib/ecoportal/api/graphql/payload/page/draft.rb +13 -0
  457. data/lib/ecoportal/api/graphql/payload/page/review_task.rb +13 -0
  458. data/lib/ecoportal/api/graphql/payload/page/unarchive.rb +13 -0
  459. data/lib/ecoportal/api/graphql/payload/page/update.rb +13 -0
  460. data/lib/ecoportal/api/graphql/payload/page/update_variable_bindings.rb +13 -0
  461. data/lib/ecoportal/api/graphql/payload/page.rb +19 -0
  462. data/lib/ecoportal/api/graphql/payload/preset_view.rb +11 -0
  463. data/lib/ecoportal/api/graphql/payload/register.rb +11 -0
  464. data/lib/ecoportal/api/graphql/payload/template/create.rb +13 -0
  465. data/lib/ecoportal/api/graphql/payload/template/create_related_page.rb +13 -0
  466. data/lib/ecoportal/api/graphql/payload/template/destroy_related_page.rb +13 -0
  467. data/lib/ecoportal/api/graphql/payload/template/publish.rb +13 -0
  468. data/lib/ecoportal/api/graphql/payload/template/unpublish.rb +13 -0
  469. data/lib/ecoportal/api/graphql/payload/template/update.rb +13 -0
  470. data/lib/ecoportal/api/graphql/payload/template/update_information.rb +13 -0
  471. data/lib/ecoportal/api/graphql/payload/template.rb +18 -0
  472. data/lib/ecoportal/api/graphql/payload.rb +11 -0
  473. data/lib/ecoportal/api/graphql/query/action.rb +1 -1
  474. data/lib/ecoportal/api/graphql/query/action_categories.rb +1 -1
  475. data/lib/ecoportal/api/graphql/query/actions.rb +2 -2
  476. data/lib/ecoportal/api/graphql/query/contractor_entities.rb +1 -1
  477. data/lib/ecoportal/api/graphql/query/file_upload_signature.rb +76 -0
  478. data/lib/ecoportal/api/graphql/query/location_structure/draft.rb +2 -2
  479. data/lib/ecoportal/api/graphql/query/location_structure.rb +1 -1
  480. data/lib/ecoportal/api/graphql/query/location_structures.rb +1 -1
  481. data/lib/ecoportal/api/graphql/query/page.rb +45 -0
  482. data/lib/ecoportal/api/graphql/query/page_delta.rb +47 -0
  483. data/lib/ecoportal/api/graphql/query/page_with_forces.rb +43 -0
  484. data/lib/ecoportal/api/graphql/query/pages.rb +59 -0
  485. data/lib/ecoportal/api/graphql/query/pages_workflow_commands.rb +59 -0
  486. data/lib/ecoportal/api/graphql/query/register_preset_views.rb +78 -0
  487. data/lib/ecoportal/api/graphql/query/register_preview_pages.rb +83 -0
  488. data/lib/ecoportal/api/graphql/query/templates.rb +53 -0
  489. data/lib/ecoportal/api/graphql/query.rb +11 -0
  490. data/lib/ecoportal/api/graphql.rb +60 -2
  491. data/lib/ecoportal/api/graphql_version.rb +5 -5
  492. data/scripts/auto-worker-scheduler.sh +386 -0
  493. data/tests/contractor_entity_create.rb +19 -19
  494. data/tests/contractor_entity_udpate.rb +20 -20
  495. data/tests/dump_page_model.rb +74 -0
  496. data/tests/loc_structure_get.rb +1 -2
  497. data/tests/loc_structure_update.rb +51 -51
  498. data/tests/loc_structures_get.rb +15 -15
  499. metadata +436 -5
@@ -0,0 +1,266 @@
1
+ # eco-helpers → GraphQL Migration Guide
2
+
3
+ *Migrating eco-helpers scripts from `ecoportal-api-v2` to `ecoportal-api-graphql`.*
4
+
5
+ ---
6
+
7
+ ## TL;DR
8
+
9
+ For most page scripts: **change one line** (the API initialiser). Everything else stays the same.
10
+
11
+ ```ruby
12
+ # Before (APIv2)
13
+ api = Ecoportal::API::V2.new(email: ENV['EMAIL'], pass: ENV['PASS'], org_id: ENV['ORG'])
14
+
15
+ # After (GraphQL)
16
+ api = Ecoportal::API::GraphQL.new(email: ENV['EMAIL'], pass: ENV['PASS'], org_id: ENV['ORG'])
17
+ ```
18
+
19
+ `api.pages` and `api.registers` expose the same interface — the same method names,
20
+ the same argument shapes, the same block and return-value patterns.
21
+
22
+ ---
23
+
24
+ ## What Changes
25
+
26
+ ### Initialiser
27
+
28
+ | | APIv2 | GraphQL |
29
+ |---|---|---|
30
+ | Class | `Ecoportal::API::V2` | `Ecoportal::API::GraphQL` |
31
+ | Gem | `ecoportal-api-v2` | `ecoportal-api-graphql` |
32
+ | `email:` | ✓ | ✓ |
33
+ | `pass:` | ✓ | ✓ |
34
+ | `org_id:` | ✓ | ✓ |
35
+ | `host:` | ✓ (default `live.ecoportal.com`) | ✓ (same default) |
36
+
37
+ ### Gem dependency in your script's Gemfile
38
+
39
+ ```ruby
40
+ # Remove:
41
+ gem 'ecoportal-api-v2'
42
+
43
+ # Add:
44
+ gem 'ecoportal-api-graphql'
45
+ ```
46
+
47
+ ---
48
+
49
+ ## What Stays the Same
50
+
51
+ ### `pages` interface
52
+
53
+ | Method | APIv2 signature | GraphQL compat | Notes |
54
+ |---|---|---|---|
55
+ | `get(id)` | `pages.get(id)` | ✓ identical | |
56
+ | `get(id, stage_id:)` | `pages.get(id, stage_id: sid)` | ✓ identical | Returns `StageView` |
57
+ | `get_new(template_id)` | `pages.get_new(tid)` | ✓ identical | Returns built PageUnion |
58
+ | `create(page, from:)` | `pages.create(page, from: tid)` | ✓ identical | Returns `PageReference` |
59
+ | `update(page)` | `pages.update(page)` | ✓ identical | Returns `Response` |
60
+ | `get_body(page)` | `pages.get_body(page)` | ✓ identical | Returns change hash |
61
+
62
+ ### Page model accessors
63
+
64
+ | Accessor | Works? | Notes |
65
+ |---|---|---|
66
+ | `page.id` | ✓ | |
67
+ | `page.name` | ✓ | |
68
+ | `page.external_id` | ✓ | maps to `externalId` |
69
+ | `page.template_id` | ✓ | maps to `sourceTemplateId` |
70
+ | `page.stages?` | ✓ | |
71
+ | `page.stages['Stage Name']` | ✓ | via `Compat::StageCollection` |
72
+ | `page.stages.get_by_name(n)` | ✓ | |
73
+ | `page.stages.ordered.map(&:id)` | ✓ | |
74
+ | `page.current_stage_id` | ✓ | on PhasedPage only |
75
+ | `page.components` | ✓ | returns `DataField::Collection` |
76
+ | `page.components.get_by_name(l)` | ✓ | case-insensitive |
77
+ | `page.components.get_by_type(t)` | ✓ | symbol or string |
78
+ | `page.dirty?` | ✓ | |
79
+ | `page.consolidate!` | ✓ | resets change tracking |
80
+ | `page.validate` | ✓ (always nil) | server validates on mutation |
81
+ | `stage.components` | ✓ | |
82
+ | `stage.sections` | ✓ | |
83
+ | `stage.active?` / `stage.started?` | ✓ | |
84
+
85
+ ### Page reference (after create)
86
+
87
+ ```ruby
88
+ ref = api.pages.create(draft, from: template_id)
89
+ ref.page_id # ✓
90
+ ref.active_stage_id # ✓
91
+ ref.success? # ✓
92
+ ```
93
+
94
+ ### `registers` interface
95
+
96
+ | Method | APIv2 | GraphQL compat | Notes |
97
+ |---|---|---|---|
98
+ | `search(id, opts) { \|r\| }` | ✓ | ✓ | Cursor-paginated |
99
+ | `result.id` in block | ✓ | ✓ | |
100
+ | No-block → `.total` | ✓ | ✓ | via `SearchResults` |
101
+ | `.total_before_filtering` | ✓ | ✓ | |
102
+
103
+ ---
104
+
105
+ ## What Requires Review
106
+
107
+ ### 1. Filter format in `registers.search`
108
+
109
+ Scripts that pass v2-style filter hashes are **automatically translated** by
110
+ `Compat::FilterTranslator`. You only need to review if your script passes filters
111
+ in a non-standard or custom format.
112
+
113
+ **Automatic translation (no action needed):**
114
+
115
+ ```ruby
116
+ # v2 date_filter with lbound/ubound — automatically converted to gte/lte
117
+ { 'type' => 'date_filter', 'key' => 'updated_at', 'lbound' => '2025-01-01', 'ubound' => '2025-12-31' }
118
+ # → { operation: 'date_filter', params: { key: 'updated_at', gte: '2025-01-01', lte: '2025-12-31' } }
119
+
120
+ # tag_filter — passed through unchanged (same ES backend)
121
+ { 'type' => 'tag_filter', 'tags' => [...] }
122
+
123
+ # register_filter — passed through unchanged
124
+ { 'type' => 'register_filter', 'params' => { 'ids' => [...] } }
125
+ ```
126
+
127
+ **Requires review:** if your script builds filters with keys like `extact_filter`
128
+ (typo), non-standard operation names, or custom filter shapes not listed above —
129
+ those will pass through unchanged and may return empty results silently.
130
+ See `search_filters.md` for the full list of valid operation names (all snake_case).
131
+
132
+ **Quick search to run on your script repo:**
133
+
134
+ ```bash
135
+ grep -rn "date_filter\|tag_filter\|filters.*type\|type.*filter" scripts/
136
+ ```
137
+
138
+ ### 2. `pages.update` — always fetch before update
139
+
140
+ The GraphQL path requires `patchVer` for concurrency control.
141
+ `Input::Page::Update.from_model` injects it automatically **if you fetched the page first**.
142
+
143
+ ```ruby
144
+ # Correct — always fetch first
145
+ page = api.pages.get(page_id)
146
+ page.name = 'New Name'
147
+ api.pages.update(page)
148
+
149
+ # Incorrect — updating a page you constructed manually (no patchVer)
150
+ page = MyManualPageObject.new(...)
151
+ api.pages.update(page) # ⚠ patchVer will be nil — server may reject
152
+ ```
153
+
154
+ If your script fetches pages via `get` before updating, no change needed.
155
+ If your script constructs page objects manually without fetching — review those paths.
156
+
157
+ ### 3. `get_new` — template ID must be the live template ID
158
+
159
+ `pages.get_new(template_id)` calls `buildPageFromTemplate` on the GraphQL API.
160
+ The `template_id` must be the live MongoDB ObjectId, same as in APIv2.
161
+
162
+ The return value has the same structure as in APIv2 — `page.components`,
163
+ `page.stages`, etc. Field IDs are server-assigned instance IDs, not template IDs.
164
+ You must use these IDs when creating the page (the compat layer handles this
165
+ automatically via `page.data_fields_updates`).
166
+
167
+ ---
168
+
169
+ ## Known Limitations
170
+
171
+ ### 1. Field types — read access only for some types
172
+
173
+ The following field types are **readable** but cannot be written via `as_input`:
174
+
175
+ | Type | Status | Notes |
176
+ |---|---|---|
177
+ | `Signature` | Read only | Captured via UI |
178
+ | `Mailbox` | Read only | System-managed |
179
+ | `ActionsList` | Read only | Manage via `api.action` builder |
180
+ | `Law` | Read only | Legal snippets, not editable via script |
181
+ | `AiSummary` | Read only | AI-generated |
182
+ | `Table` | Read only | Complex structure |
183
+
184
+ The following types **are writable** but require a file upload step first:
185
+
186
+ | Type | Status | Notes |
187
+ |---|---|---|
188
+ | `File` | Writable* | Requires REST upload → fileContainerIds |
189
+ | `ImageGallery` | Writable* | Same as File |
190
+
191
+ \* File upload support is on the roadmap. For now, `file_container_ids=` will work
192
+ if you already have `fileContainerIds` from a prior upload.
193
+
194
+ ### 2. `pages.search` — not implemented on `Compat::Pages`
195
+
196
+ APIv2's `pages.search(...)` is not part of the compat layer.
197
+ Use `api.registers.search(register_id, ...)` for register-scoped search,
198
+ or use `Model::Organization.pages(searchConf: conf)` for org-wide search.
199
+
200
+ ### 3. Performance — org search is ~3s/page
201
+
202
+ The GraphQL `pages.get` (and `pages.get_new`) fetches full DB-rendered page data.
203
+ This is ~3s per page for large pages, compared to ~200ms in APIv2 for the same data.
204
+
205
+ Mitigation: batch fetches, or use `api.registers.search` (ES-backed, fast) to
206
+ get page IDs first, then fetch only the pages you actually need to update.
207
+
208
+ ### 4. `simulate?` / dry-run mode — no change
209
+
210
+ The compat layer honours `get_body` / `dirty?` / `consolidate!` as before.
211
+ Dry-run logic that checks `dirty?` and skips `update` if not dirty continues to work.
212
+
213
+ ---
214
+
215
+ ## Quick Verification Checklist
216
+
217
+ Before switching a script to the GraphQL gem:
218
+
219
+ - [ ] Grep for `API::V2.new` — replace with `API::GraphQL.new`
220
+ - [ ] Grep for custom filter formats — verify they translate correctly
221
+ - [ ] Grep for manual page construction (without `pages.get`) — check patchVer supply
222
+ - [ ] Grep for `pages.search` — replace with `registers.search` or org search
223
+ - [ ] Run the script in `simulate` mode against a staging org
224
+
225
+ ---
226
+
227
+ ## Example: minimal diff for a typical update script
228
+
229
+ ```ruby
230
+ # Before
231
+ require 'ecoportal/api-v2'
232
+ api = Ecoportal::API::V2.new(email: ENV['EMAIL'], pass: ENV['PASS'], org_id: ENV['ORG'])
233
+
234
+ api.registers.search('REG_ID', filters: [date_range_filter('updated_at', from: '2025-01-01')]) do |result|
235
+ page = api.pages.get(result.id)
236
+ next unless page.dirty?
237
+ page.components.get_by_name('Status')&.select_option('Active')
238
+ api.pages.update(page)
239
+ page.consolidate!
240
+ end
241
+
242
+ # After (change highlighted)
243
+ require 'ecoportal/api-graphql' # ← changed gem
244
+ api = Ecoportal::API::GraphQL.new(email: ENV['EMAIL'], pass: ENV['PASS'], org_id: ENV['ORG']) # ← changed class
245
+
246
+ api.registers.search('REG_ID', filters: [date_range_filter('updated_at', from: '2025-01-01')]) do |result|
247
+ page = api.pages.get(result.id)
248
+ next unless page.dirty?
249
+ page.components.get_by_name('Status')&.select_option('Active')
250
+ api.pages.update(page)
251
+ page.consolidate!
252
+ end
253
+ # Everything else is identical.
254
+ ```
255
+
256
+ ---
257
+
258
+ ## Rollback
259
+
260
+ If a script needs to revert to APIv2:
261
+
262
+ 1. Change the require back to `ecoportal/api-v2`
263
+ 2. Change the initialiser class back to `Ecoportal::API::V2`
264
+ 3. No other code changes needed
265
+
266
+ The compat layer was designed so the rollback is always a one-line change.
@@ -0,0 +1,86 @@
1
+ # TODOs — eco-helpers GraphQL Compat Layer
2
+
3
+ > URGENT — APIv2 retires in ~3 weeks.
4
+ > Natural order: 1 → 2 → 3 → 4 → 5 (resolve open questions before implementing)
5
+
6
+ ---
7
+
8
+ ## Step 1 — Resolve open questions (Done 2026-06-07)
9
+
10
+ - [x] **1.1** Filter format confirmed: scripts use `tags_filter` and `date_range_filter`
11
+ helpers producing `type: "date_filter"` with `lbound`/`ubound` keys.
12
+ Translation: date_filter lbound→gte, ubound→lte. Other types pass through.
13
+
14
+ - [x] **1.2** `registers.search` block result: yields individual PreviewPage objects (.id etc).
15
+ No-block form returns an object with `.total` and `.total_before_filtering`.
16
+ Implemented: `Compat::SearchResults` wraps connection with both properties.
17
+
18
+ - [ ] **1.3** `pages.get_new` draft shape — still waiting on end-script repo access.
19
+ For now: `buildPageFromTemplate` returns PageUnion with field IDs and stagesIndex.
20
+
21
+ - [x] **1.4** `pages.create` reference: only `.page_id` and `.active_stage_id` used.
22
+ `Compat::PageReference` implements both correctly.
23
+
24
+ - [x] **1.5** Stage access: `stages[id_name]` AND `stages.get_by_name(id_name)` AND
25
+ `stages.ordered.map(&:id)`. Implemented via `Compat::StageCollection` wrapper
26
+ included via `Model::Page::Phased#stages` override.
27
+
28
+ ---
29
+
30
+ ## Step 2 — Scaffold `Compat::Pages` and `Compat::Registers` (Done 2026-06-07)
31
+
32
+ - [x] **2.1** `lib/ecoportal/api/graphql/compat/pages.rb`: `get`, `get_new`, `create`, `update`, `get_body`.
33
+ *Done 2026-06-07*
34
+
35
+ - [x] **2.2** `lib/ecoportal/api/graphql/compat/registers.rb`: `search` with cursor pagination
36
+ and v2 filter translation (date_filter lbound/ubound → gte/lte).
37
+ *Done 2026-06-07*
38
+
39
+ - [x] **2.3** Wired from top-level `Ecoportal::API::GraphQL`: `pages` → `Compat::Pages`, `registers` → `Compat::Registers`.
40
+ *Done 2026-06-07*
41
+
42
+ ---
43
+
44
+ ## Step 3 — Page model compatibility wrapper (Done 2026-06-07)
45
+
46
+ - [x] **3.1** `Concerns::PageCompat` included in `Interface::BasePage`:
47
+ `external_id`, `template_id`, `components`, `stages?`, `consolidate!`, `validate`, `dirty?`.
48
+ `current_stage_id` defined on `Model::Page::Phased` (reads in-progress stage from doc).
49
+ 19 specs: `spec/ecoportal/api/graphql/concerns/page_compat_spec.rb`.
50
+ *Done 2026-06-07*
51
+
52
+ - [x] **3.2** `Compat::StageCollection`: `stages[id_or_name]`, `get_by_name`, `ordered`.
53
+ Wrapped via `Model::Page::Phased#stages` override.
54
+ Specs: `spec/ecoportal/api/graphql/compat/stage_collection_spec.rb`.
55
+ *Done 2026-06-07*
56
+
57
+ - [x] **3.3** `Compat::PageReference`: `.page_id` and `.active_stage_id` (via `current_stage_id`).
58
+ Fixed: was using `currentStage` (undefined accessor); now uses `current_stage_id`.
59
+ Specs: `spec/ecoportal/api/graphql/compat/page_reference_spec.rb`.
60
+ *Done 2026-06-07*
61
+
62
+ ---
63
+
64
+ ## Step 4 — Search/filter translation
65
+
66
+ - [x] **4.1** `Compat::FilterTranslator.to_graphql(v2_filter)` — translates v2 filter hashes
67
+ to `SearchConf` objects. Handles `date_filter` (lbound→gte, ubound→lte), `tag_filter`,
68
+ `exact_filter`, `register_filter`; extracted from `Compat::Registers`.
69
+ *Done 2026-06-07 — 12 specs in `spec/ecoportal/api/graphql/compat/filter_translator_spec.rb`*
70
+
71
+ - [x] **4.2** `Logic::BaseQuery#normalize_variables` auto-calls `.to_h` on value objects
72
+ (e.g. `SearchConf`) before passing as GraphQL variables — callers no longer need explicit `.to_h`.
73
+ *Done 2026-06-07 (commit cc72902)*
74
+
75
+ ---
76
+
77
+ ## Step 5 — Integration test + migration guide
78
+
79
+ - [ ] **5.1** Run a real end-script against the compat layer (requires end-script repo access).
80
+ User will provide once `.claude/settings.json` rules are set.
81
+
82
+ - [x] **5.2** `.ai-assistance/projects/eco-helpers-compat/MIGRATION_GUIDE.md` written.
83
+ Covers: one-line initialiser change, API compatibility table, filter review checklist,
84
+ patchVer requirement, known limitations (read-only field types, no pages.search,
85
+ ~3s/page performance), example diff, rollback instructions.
86
+ *Done 2026-06-08*
@@ -0,0 +1,101 @@
1
+ # Project: DoubleModel Review & Stabilisation (`ecoportal-api-v2`)
2
+
3
+ **Created:** 2026-06-05
4
+ **Status:** idea — not started
5
+ **Primary repo:** `ecoportal-api-v2`
6
+ **Affects:** `ecoportal-api-graphql` (consumers of `as_update` / `as_input` cascade)
7
+ **Blocks:** `dynamic-model-generation` project
8
+
9
+ ---
10
+
11
+ ## Goal
12
+
13
+ Review and stabilise the `DoubleModel` implementation in `ecoportal-api-v2`, with particular
14
+ focus on:
15
+
16
+ 1. The `doc` / `original_doc` lookup chain through nested and Array-indexed models.
17
+ 2. The `root!` / `read_only!` memoisation flags and their interaction with the cascaded diff.
18
+ 3. Ensuring that memoised `@doc` cannot silently go out of sync with a parent's diff.
19
+
20
+ The outcome must be a `DoubleModel` contract that is reliable enough to underpin
21
+ `ecoportal-api-graphql`'s `as_update` / `as_input` pipeline and, eventually, auto-generated
22
+ model classes.
23
+
24
+ ---
25
+
26
+ ## Background
27
+
28
+ The `DoubleModel` stores the canonical document (`@doc`) only at the root object. All
29
+ nested descendant objects resolve their own `doc` by walking up the ownership chain and
30
+ extracting their slice of the root `@doc` by key path.
31
+
32
+ This design is correct for Hash-keyed paths (keys are deterministic). It breaks down for
33
+ Array-indexed paths (`CollectionModel` and similar), because Array indexes are positional —
34
+ if order changes, a nested object's key path no longer resolves to the right element.
35
+
36
+ The current workaround is to look up the element by its own key from the parent at access
37
+ time, rather than by stored index. This lookup is performed every time `doc` or
38
+ `original_doc` is called on a nested object inside an Array, making it operationally costly:
39
+
40
+ - The lookup re-scans the parent array on each call.
41
+ - Objects under a `CollectionModel` may be instantiated multiple times during a single render
42
+ as a side effect of these repeated resolutions.
43
+
44
+ To mitigate this, `root!` and `read_only!` class-level flags were introduced. They allow
45
+ a model class to memoise `@doc` locally (breaking the chain) when it is known to be stable.
46
+ These flags are used extensively in `ecoportal-api-graphql` model and payload classes.
47
+
48
+ ### Known risk
49
+
50
+ `root!` also signals to the cascaded diff (`DiffService`) that the object should be
51
+ excluded from the parent's diff. This is correct for read-only lookup objects (e.g. a
52
+ referenced Location node). But if `root!` is applied at a level where the object *is*
53
+ expected to contribute changes to the parent diff, the memoised `@doc` will silently
54
+ go out of sync — changes to that sub-model will not surface in `as_update`. This is
55
+ a subtle correctness risk that needs to be audited across all uses of `root!` and
56
+ `read_only!` in `ecoportal-api-graphql`.
57
+
58
+ ---
59
+
60
+ ## Scope
61
+
62
+ - Audit all uses of `root!` and `read_only!` in `ecoportal-api-graphql` model and payload
63
+ classes: confirm each is correctly applied (genuinely read-only / excluded from diff).
64
+ - Review the Array-indexed lookup in `CollectionModel` (and related): document the current
65
+ behaviour, identify cases where it causes multiple object instantiation.
66
+ - Propose and implement a more efficient resolution strategy for Array-indexed nested models
67
+ that does not require rescanning on every `doc` / `original_doc` call.
68
+ - Ensure `patch_ver` propagation through the chain is correct after any changes.
69
+ - Confirm that the `initial_doc` / `original_doc` / `doc` three-state contract is
70
+ preserved correctly after any refactor.
71
+
72
+ ---
73
+
74
+ ## Spec-first requirement
75
+
76
+ Specs related to any modification **must be written before the change is applied** to
77
+ `ecoportal-api-v2`, to lock in current behaviour and guard backwards compatibility.
78
+ Specs must also be maintained and extended after the change to prevent future regressions.
79
+
80
+ This applies both to the `ecoportal-api-v2` spec suite and to any `ecoportal-api-graphql`
81
+ specs that exercise the cascaded diff path.
82
+
83
+ ---
84
+
85
+ ## Open Questions
86
+
87
+ - Is the Array-indexed lookup fixable with a simple cache keyed by object identity
88
+ (`object_id`) that is invalidated on `doc=` / `reset!` calls?
89
+ - Are there cases in `ecoportal-api-graphql` where `root!` is applied incorrectly
90
+ (object should contribute to diff but doesn't)?
91
+ - What is the right `read_only!` vs `root!` semantic split? (`read_only!` = never
92
+ accept changes; `root!` = store doc locally + exclude from parent diff — are these
93
+ always the same thing, or should they be separable?)
94
+
95
+ ---
96
+
97
+ ## Notes
98
+
99
+ This project is primarily work in `ecoportal-api-v2`, but the review must happen with
100
+ `ecoportal-api-graphql` open alongside it, since the usage patterns there drive what
101
+ needs to be fixed.
@@ -0,0 +1,177 @@
1
+ # GraphQL Agent Corpus — Gap Analysis
2
+
3
+ *Analysed 2026-06-07 from staging corpus at `C:\claude\Projects\Claude AWS Platform\tmp\corpus\staging\success\graphql\`*
4
+ *18 staging documents reviewed.*
5
+
6
+ ---
7
+
8
+ ## Critical — Breaks Agent Reliability
9
+
10
+ | File | Issue | Fix |
11
+ |------|-------|-----|
12
+ | `2262499334_search-by-external-id.md` | Contains placeholders (`"graphqlwide760"`, `"jsonwide760"`) instead of actual query/variables | Replace with real contractor search examples |
13
+ | `2262892608_registers-searches-and-templates.md` | Entirely empty after header — no content | Populate register structure, preset views, search config |
14
+ | Agent instructions (absent) | No guidance that GraphQL queries are client-defined — agent will expect structural uniformity | Add "GraphQL is a Language" note (see below) |
15
+
16
+ ---
17
+
18
+ ## High — Agent Will Hallucinate Without Guidance
19
+
20
+ ### Error handling — completely missing
21
+ No error taxonomy. No error codes. No recovery patterns. The agent will invent error names
22
+ and suggest incorrect recovery steps.
23
+ - **Add:** 20–30 common error codes with cause and recovery (e.g. `patchVer` conflict,
24
+ invalid field ID, permission denied, stale cursor)
25
+
26
+ ### State machines — completely missing
27
+ No documented states for Page, Stage, Action, Task. No valid transitions. Agent will
28
+ suggest invalid state changes.
29
+ - **Add:** State diagrams or transition tables for each entity
30
+
31
+ ### Authorization — completely missing
32
+ `canXXX` fields exist on every Page, Stage, Action. What they mean is never explained.
33
+ - **Add:** `canXXX` field guide — when they return false, what the caller should do
34
+
35
+ ### Filter syntax — incomplete and inaccurate
36
+ The search filter docs show `fieldName` in examples but production queries use `key`.
37
+ Filter operation names are snake_case (silent failure if CamelCase is used — no error,
38
+ no results). `filters` should always be an Array.
39
+ - **Add:** Complete filter operation reference with snake_case requirement explicit.
40
+ See `.ai-assistance/code/search_filters.md` in `ecoportal-api-graphql`.
41
+
42
+ ### Field ID lifecycle — missing
43
+ Docs warn that field IDs change between template and instance, but give no algorithm for
44
+ resolving them (when to `buildFromTemplate` first, when to look up by type+label, etc.)
45
+ - **Add:** "Field ID Resolution" section — the two-step workflow and when each applies
46
+
47
+ ### `updateMode` on actions — undocumented
48
+ The UpdateAction mutation accepts `updateMode` but valid values are not documented.
49
+ Agent will omit or guess (single / series / future / all).
50
+ - **Add:** `updateMode` enum values with examples
51
+
52
+ ---
53
+
54
+ ## Medium — Gaps That Reduce Usefulness
55
+
56
+ ### Covered but incomplete
57
+
58
+ **Pages technical guide (`2235662347`):**
59
+ - Missing: how `showHiddenData` interacts with field visibility
60
+ - Missing: page state vs. stage state distinction
61
+ - Missing: what `templatesOnly` does (returns templates as pages, not instances)
62
+ - Missing: partial update semantics (sparse fields vs. full replacement)
63
+
64
+ **Authentication (`1959788614`):**
65
+ - `scope` shown as `[]` with no explanation
66
+ - Token expiry and refresh failure handling missing
67
+ - Security best practices for token storage missing
68
+
69
+ **Searching pages (`1933639695`):**
70
+ - Only 3 filter examples — no matrix of all filterable fields
71
+ - No field-value filters (search by a specific data field value)
72
+ - `mould_counter` appears in example with no explanation (deprecated; use `uid`)
73
+
74
+ **Load actions (`1933901853`):**
75
+ - Uses both `edges { node { ... } }` and `nodes` inconsistently
76
+ - `Search` input type not documented alongside its usage
77
+
78
+ **Create/Update page mutations:**
79
+ - No guidance on transaction semantics (is a partial dataFields update atomic?)
80
+ - Missing: what happens if one field update fails — does the mutation continue or abort?
81
+
82
+ ### Not covered at all
83
+
84
+ - Contractor entity lifecycle (create / approve / activate / archive)
85
+ - Archive and unarchive page flows (compound mutation pattern)
86
+ - File upload mechanics (separate from attach)
87
+ - Bulk/batch operations
88
+ - Visitor management integration
89
+ - Page forces / risk management
90
+ - Task workflow and status transitions
91
+ - AI Summary field operations
92
+ - Mailbox field operations
93
+ - Cross-reference field deep guidance
94
+ - People field — `cachedPeople` vs. `livePeople` distinction
95
+ - Webhook / subscription patterns
96
+ - Rate limiting and throttling
97
+ - Cursor invalidation policy (how long cursors remain valid)
98
+ - `deindex` and field visibility flags semantics
99
+
100
+ ---
101
+
102
+ ## Accuracy Concerns
103
+
104
+ | File | Issue |
105
+ |------|-------|
106
+ | `1931575325_updatepage.md` | Example variables may reference `templateId` where `id` (page ID) is expected |
107
+ | `1928855618_createaction.md` | Response structure example (`item: { ... }`) may not match actual wrapper |
108
+ | `2235662347_graphql-pages-technical-guide.md` | Refers to `pageUnionCommonFragment` but fragment definition is in a separate doc with no cross-link |
109
+ | Multiple | Date formats mixed (ISO8601 with Z vs. with +offset) — no guidance on when each is correct |
110
+ | Multiple | Broken Confluence external links (opaque IDs, unresolvable outside Confluence) |
111
+
112
+ ---
113
+
114
+ ## Structural Issues
115
+
116
+ 1. **No agent preamble.** There is no document that tells the agent the most important
117
+ invariants: GraphQL variability, silent filter failures, two-step field ID resolution,
118
+ compound mutation pattern. These must be added as explicit agent instructions, not
119
+ buried in examples.
120
+
121
+ 2. **No cross-reference index.** `CommonPageUnion` is referenced in 6+ documents but
122
+ defined in only one. An agent cannot reliably find what it needs.
123
+
124
+ 3. **No versioning or timestamps.** The agent cannot tell if a doc reflects the current
125
+ schema or an old version. Schema changes may invalidate examples silently.
126
+
127
+ 4. **Inconsistent example depth.** Some mutations show full request + response; others
128
+ only show the query. Agent will fill in gaps incorrectly.
129
+
130
+ 5. **Fragment defined but not explained.** `CommonPageUnion` shows the full GraphQL but
131
+ nowhere explains what `$content`, `$only_content`, `$fields` actually control in
132
+ human terms (with examples of before/after).
133
+
134
+ ---
135
+
136
+ ## Recommended Agent Preamble (add to system prompt or corpus index)
137
+
138
+ ```
139
+ You are assisting with the EcoPortal GraphQL API. Key invariants:
140
+
141
+ 1. GraphQL queries are client-defined. The same resource can be queried many ways.
142
+ Variability in examples is intentional. Multiple mutations in one request (executed
143
+ in order) is valid and used for stateless middleware clients.
144
+
145
+ 2. Filter operations are snake_case strings. CamelCase silently returns no results.
146
+ Always use: exact_filter, date_filter, and_filter, or_filter, register_filter.
147
+ The `filters` value should always be an Array.
148
+
149
+ 3. Page creation requires a 2-step sequence:
150
+ (a) buildFromTemplate → get field IDs from the built draft
151
+ (b) createFromTemplate → use those field IDs in dataFields.updates
152
+
153
+ 4. Page update requires:
154
+ (a) Fetch current page → get patchVer + current field IDs
155
+ (b) updatePage → include patchVer (required for concurrency control)
156
+
157
+ 5. The CommonPageUnion fragment ($fields/$content/$only_content variables) is the
158
+ standard pattern for fetching full page data. Use it for all page read operations.
159
+
160
+ 6. Register search (previewPages) is Elasticsearch — fast but no field IDs.
161
+ Org search (pages) is DB — slow (~3s/page) but complete data including field IDs.
162
+ ```
163
+
164
+ ---
165
+
166
+ ## Recommended Additions Priority
167
+
168
+ 1. Error taxonomy (codes, causes, recovery)
169
+ 2. State machines (Page, Stage, Action, Task)
170
+ 3. Field type matrix (all 20 types, validation, modifiers)
171
+ 4. Full contractor management (currently broken/empty)
172
+ 5. Authorization guide (`canXXX` meanings)
173
+ 6. Archive/unarchive patterns
174
+ 7. File upload guide
175
+ 8. Complete filter fieldName reference
176
+ 9. `updateMode` enum for actions
177
+ 10. Cursor invalidation policy