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
data/docs/worklog.md ADDED
@@ -0,0 +1,574 @@
1
+ # Worklog — ecoportal-api-graphql
2
+
3
+ A rolling record of what has been done, what is in progress, and what comes next.
4
+ Update before ending a session. Read from the bottom up to find the latest state.
5
+
6
+ For per-project tracking (intent, decisions, upstream deps), see `.ai-assistance/projects/<slug>/`.
7
+ This file tracks cross-project session state and the overall repo status.
8
+
9
+ ---
10
+
11
+ ## ▶ DEEP REVIEW (2026-06-30 late) — pre-live audit of TOOCS + CANS; 3 more fixes
12
+
13
+ Exhaustive audit (4 parallel sub-investigations) of both prod dry-runs before going live.
14
+ Full detail + every hypothesis/verdict: `.ai-assistance/projects/ooze-graphql-native-migration/
15
+ analysis/2026-06-30-cutover-workflow-deep-review.md`. Three real issues found & FIXED (gem only):
16
+ 1. **Number `""`→`0.0`** (`data_field/number.rb`) — `"".to_f` wrote a real 0.0 over the server
17
+ value for an empty CSV numeric cell. Now blank→nil. (Live-corruption footgun.)
18
+ 2. **People reader node-fallback** (`data_field/people.rb`) — read only `peopleIds`; if a read
19
+ ever returned it null while `people{id}` nodes were present, an append would WIPE. Now falls
20
+ back to the nodes (mirrors CrossReference). (Latent, hardened.)
21
+ 3. **CANS create dry-run mislabel** (`compat/pages.rb` + `interface/base_page.rb`) — a
22
+ buildFromTemplate draft carries a patchVer, so `new_draft?` (patchVer-nil) mis-previewed a
23
+ CREATE as an UPDATE. Now marked via `_compat_source_template_id` in `get_new`. (Display only.)
24
+ Verified-correct (no change): People append preserves; Select all-options shape; PlainText clear;
25
+ dirty baselines; CANS routing (no duplicate-create); the stageId guard breaks no other case.
26
+ +20 specs incl. a fixture replay (`spec/.../integration/toocs_submit_replay_spec.rb`) that
27
+ reproduces the EXACT observed TOOCS body and proves the stageId regression. New tool
28
+ `tests/dump_page_model.rb` dumps a page model before/after a submit for fixtures.
29
+
30
+ **FOLLOW-UP (2026-07-01) — …61 RESOLVED + Gauge fixed.** CANS field …61 `0.0` is a REAL zero:
31
+ `STANDARD COST=0` (unquoted) in the CSV — not an artifact. Verified `Eco::CSV` (eco-helpers
32
+ `lib/eco/csv.rb`): stdlib `::CSV`, no nil/empty override → unquoted empty→nil, quoted empty `""`→""
33
+ (so quoted-empty numeric cells WOULD hit `"".to_f→0.0`; the blank→nil fix is the right net).
34
+ **Gauge** had the identical `numeric&.to_f` footgun → fixed; Number+Gauge now share
35
+ `DataField#numeric_or_nil` (can't drift). +6 Gauge specs. Suite 470/0/2 pending, rubocop clean.
36
+ Remaining (non-blocking): created-CANS-pages-unsubmitted (parked); confirm 6a32…d7d=='Coding'.
37
+ Farmers case audited (own note): `-simulate` is a no-op for GraphQL writes (can't dry-run-validate)
38
+ + stale-patchVer risk on multi-doc suppliers — see analysis doc.
39
+
40
+ ---
41
+
42
+ ## ▶ RESOLVED (2026-06-30 late) — update+submit now carries `stageId` (full-cycle fix, gem-only)
43
+
44
+ **FIXED — gem suite 445/0/2 pending, rubocop clean. Re-run TOOCS `-simulate` to confirm the
45
+ body now shows `:stageId`, then it's safe to run live.** The fix is GEM-ONLY (eco-helpers
46
+ unchanged — `OozeRedirect#stage` already builds the StageView; the gem now does the recording).
47
+
48
+ **Root cause (confirmed end-to-end):** `OozeRedirect#stage` builds a `Compat::StageView` but the
49
+ base OozeSamples loop **enqueues/updates the FULL page** (enqueue is first-wins by id — the
50
+ StageView is never the queued object). `process_ooze` calls `target.submit!` on that full page,
51
+ whose `current_stage_id` server-state inference returned nil → the operation nil-guard dropped
52
+ `stageId`. The StageView (which knows its stage id) was discarded after the `with_stage` block.
53
+
54
+ **Fix (3 parts, gem):**
55
+ 1. `Model::Page::Phased#_compat_active_stage_id` (new accessor) — `Compat::StageView#initialize`
56
+ records the viewed stage id on its `@page` (which IS the queued page, same object), so a later
57
+ `submit!`/`sign_off!` on that page can resolve the stage the work was done on.
58
+ 2. `Compat::Pages#compat_stage_id` resolves most-explicit-first: pinned `submit!(stage_id:)` →
59
+ `_compat_active_stage_id` (StageView) → `current_stage_id` (inference, last resort).
60
+ 3. `Input::Page::Update.from_model` **raises** when `submit`/`task` present but `stage_id` nil —
61
+ the platform invariant (people-field perms are stage-scoped; submit MUST name its stage).
62
+ +11 specs (stage_view records active stage; compat_stage_id order; guard raises/permits).
63
+ Captured in `.ai-assistance/code/ecoPortal_architecture/08_stages_sections.md` (why + mechanism).
64
+
65
+ **Schema (verified):** `stageId` is a FIELD of `UpdatePageInput`, NOT a separate `updatePage(...)`
66
+ arg. (Stale/wrong: `diff_as_input.md:224` flat-arg shape — fix later.)
67
+
68
+ **Known limitation (non-blocking):** `Phased#current_stage_id` (server-state inference) can return
69
+ nil / the wrong stage on multi-stage pages; it's now only a guarded last resort — prefer a stage
70
+ view. The dry-run still prints only the input hash, not operationName + variables (Oscar steer;
71
+ follow-up, not built).
72
+
73
+ <details><summary>original blocker note (for history)</summary>
74
+
75
+ **Do NOT run the TOOCS/ooze update+submit cases live until fixed.** During `-simulate` the
76
+ act-gov TOOCS body came back **without `stageId`**:
77
+ ```
78
+ {:id=>"6a32...aa8", :patchVer=>229, :submit=>true,
79
+ :task=>{:completePageTask=>{:forcedComplete=>true}},
80
+ :dataFields=>{:updates=>[{:people=>{...}}]}} # ← no :stageId
81
+ ```
82
+
83
+ **Schema settled (verified):** `stageId` is a FIELD of `UpdatePageInput` (the single
84
+ `input: UpdatePageInput!` wrapper) — NOT a separate `updatePage(...)` argument. Sources agree:
85
+ `ecoportal_schema_reference.md:90`, `schema_analysis.md:94`, `04_graphql_queries_mutations.md:144`,
86
+ and the gem's own `mutation/page/update.rb:17`. So `from_model` is right to nest `stageId` inside
87
+ the input. (Stale/contradicting: `diff_as_input.md:224` shows an old flat-arg shape — wrong, fix later.)
88
+
89
+ **Root cause:** `Model::Page::Phased#current_stage_id` (phased.rb:25) returned **nil** for this page
90
+ → `compat_stage_id` nil → `from_model`'s nil-guard (`input[k]=v unless v.nil?`) dropped `stageId`.
91
+ `current_stage_id` matches `state=='inprogress' || active==true` in `doc['stagesIndex']||doc['stages']`;
92
+ the `CommonPageUnion` get path apparently doesn't yield a matching stage. The 2026-06-29 "stage
93
+ advanced" confirmation was the **create** path (top-level `stageId`) — the **update+submit** path
94
+ was never exercised, so this is a real, untested gap. `08_stages_sections.md:59` warns a submit
95
+ without `stageId` may not associate with the right stage → unsafe on prod.
96
+
97
+ **Fix (agreed direction, NOT yet built):**
98
+ 1. **Hard guard** — `from_model`/`compat_submit_kargs` must RAISE when `submit: true` (or a `task`)
99
+ is present but `stageId` is nil. Never send a submit without its stage. (Definitely correct.)
100
+ 2. **Resolution** — make `current_stage_id` actually resolve on the update path. Resolution
101
+ approach parked pending diagnosis (see note below). Candidates: fix the `doc['stages']` state
102
+ match, fetch `currentStage`/`PhasedPageFields` in the compat get query, or pin `stage_id` in the case.
103
+
104
+ **NOTE (Oscar steer):** the dry-run feedback currently `pp`s only the `input` hash. To diagnose
105
+ this (and make the preview faithful) it should print the **full GraphQL request** — `operationName`
106
+ + the **variables** actually sent — not just the input sub-tree. Noted as a follow-up; not built yet.
107
+
108
+ </details>
109
+
110
+ ---
111
+
112
+ ## ▶ START HERE TOMORROW (2026-07-01 — LAST cutover day)
113
+
114
+ Branch `fix/ooze-redirect-faithful-dryrun` (gem + eco-helpers), all UNCOMMITTED.
115
+
116
+ **Confirmed working on live act-gov (2026-06-30 end):** TOOCS dry-run now prints the faithful
117
+ body and is CLEAN — `dataFields.updates` = ONLY the People field (`Coding completed by`):
118
+ ```
119
+ :dataFields=>{:updates=>[{:people=>{:id=>"6a3225522b97b00073c22cea",
120
+ :peopleIds=>["65d6d3dcacb0b3000773f547"]}}]}}
121
+ ```
122
+ No phantom empty `crossReference` clears (CrossReference set-based `dirty?` fix works);
123
+ Breakdown Agency correctly omitted (already coded on the page = code 8422). People write-path
124
+ good. `submit: true` + `forcedComplete` ride along as expected.
125
+
126
+ **Do, in order:**
127
+ 1. **Re-confirm CANS** `-simulate` (jamestrong) — expect the create body (templateId +
128
+ PlainText/Number/Select updates) still clean. (Last seen good before the CrossReference fix;
129
+ re-run to be sure nothing regressed.)
130
+ 2. **Commit** the branch in both repos (only after the above looks right). Changes:
131
+ - gem: `compat/pages.rb` (faithful dry-run body), `base/page/data_field/cross_reference.rb`
132
+ (set-based dirty vs `original_doc`), specs (`compat/pages_spec`, `model/page/phased_spec`,
133
+ `base/page/data_field_spec`), `.ai-assistance/projects/ooze-graphql-native-migration/`,
134
+ this worklog + `.ai-assistance/code/refactoring/datafield-readwrite-shape-asymmetry.md`.
135
+ - eco-helpers: `ooze_samples/ooze_base_case.rb` (affirmative `[dry-run] would create/update`
136
+ line) + the earlier shim slimming (`ooze_redirect.rb`, `register_update_case.rb`).
137
+ - implementation: `toocs_coding_case.rb` already reverted clean (diagnostic removed) — no commit needed there.
138
+ - Full gem suite green: 434 examples, 0 failures, 2 pending. Rubocop clean on touched files.
139
+ 3. **Parity runs** — the real 1-Jul validation: wire the CANS/TOOCS A/B harness
140
+ (see [[project-parity-test-plan]]) and run the 3 prod use cases on GraphQL.
141
+
142
+ **Optional / non-blocking:**
143
+ - Tidy: `page.sourceTemplateId` → `page.source_template_id` at BOTH call sites in
144
+ `compat/pages.rb` (`create` + `create_body`) if house style prefers snake (not a rubocop
145
+ offense — calls aren't flagged; SnakeCamelAccess is snake→camel one-way).
146
+ - The OPEN REVIEW below (DataField shape asymmetry: File/Image/Contractor) — separate, not a blocker.
147
+
148
+ ---
149
+
150
+ ## ▶ OPEN REVIEW (2026-06-30) — DataField read/write shape asymmetry (flagged for thorough review)
151
+
152
+ A real bug found+fixed on `CrossReference` (it was READ from `references.nodes` but WRITTEN to
153
+ `pages`; a custom `dirty?` I'd hand-rolled wrongly baselined on `doc` instead of `original_doc`).
154
+ Audit shows the SAME read≠write asymmetry on **FileField, ImageGallery, ContractorEntities**
155
+ (broken readers + phantom-dirty; pre-existing) and mildly on TagField. NOT a 1-Jul blocker
156
+ (cutover cases don't hit them), but needs a dedicated pass. Full audit + fix direction + a retro
157
+ on why it slipped: `.ai-assistance/code/refactoring/datafield-readwrite-shape-asymmetry.md`.
158
+ Key guardrail: never compute a dirty baseline from `doc` — use `original_doc`/`DiffService`; add
159
+ `consolidate!`-cycle specs to every staged-write field.
160
+
161
+ ---
162
+
163
+ ## ▶ HANDOFF (2026-06-29) — lint clean; stage-advance reframed; SCIM + new projects
164
+
165
+ ### Done this session
166
+ - **Gem RuboCop clean** — 0 offenses / 526 files (commit `b3c6139` on `pages`). Safe
167
+ autocorrect + targeted code fixes + scoped `.rubocop.yml` relaxations for intentional
168
+ public-interface patterns (`id`/`ids`/`clientMutationId` AllowedNames; OneClassPerFile/
169
+ FileName/ToEnumArguments excludes). Adding `id`/`ids` centrally let RuboCop strip 17
170
+ now-redundant inline disables. (To run rubocop here: `bundle config set --local
171
+ local.graphql-client <path>` + `local.graphlient <path>` — rubygems.org index fetch fails
172
+ under the SSL inspection, so local git overrides are required. Stored in gitignored `.bundle/config`.)
173
+ - **Training repo branch move** — `C:/ruby_scripts/implementation/training` had 21 unpushed
174
+ commits + uncommitted changes on `master`. Moved to new branch **`api-deprecation`**
175
+ (HEAD `ab312a4`); `master` reset to `origin/master` (`c4984db`). Uncommitted changes
176
+ (token-budget.json, settings.json, CLAUDE.md, untracked scripts/) carried to api-deprecation,
177
+ left uncommitted (machine-local — dev to commit). Recovery: `git branch -f master ab312a4`.
178
+
179
+ ### Stage-advance — RESOLVED ✅ (gem submit was correct; old call shape was wrong)
180
+ **Live-confirmed 2026-06-29** (new test `compat_v2/page/submit_signoff_on_create`: 5/5 PASS,
181
+ incl. "stage advanced after submit + sign-off"). Root cause: the stage has a **review-task
182
+ config**, so `completePageTask` alone (the old `stage_submit` call, no `submit:`, no inline
183
+ sign-off) just enters "reviewing" and never advances. The single call that advances:
184
+ `updatePage(submit: true, task: { completePageTask: { signOff: true } })`. Backend logic
185
+ (persisted `.graphql` ops + `app/services/new_ep/tasks/workflow.rb`) verified the inline
186
+ sign-off auto-approves the review in the same call. NOT a missing-field issue (validation
187
+ would surface as `success? == false`; the gem selects `errors` and `Logic::Payload#success?`
188
+ honours it). See memory `page-stage-submission` for the authoritative logic.
189
+ - **Gem change (commit pending, `pages`):** `Input::Page::Update.from_model`'s
190
+ `complete_page_task:` now accepts a Hash → `{ completePageTask: { signOff:, forcedComplete:,
191
+ notes: } }`. The throwaway page id is per-run (printed `page=<id>` at the assertion).
192
+
193
+ ### Next steps
194
+ 1. **Stage-advance — DONE** (see above). Optional follow-up: switch the old `stage_submit`
195
+ test to the confirmed `submit: true, complete_page_task: { sign_off: true }` call so it also
196
+ goes green (currently left as the no-submit diagnostic). Dev's call.
197
+ 2. **Backend persisted-query investigation — DONE** (Explore agent, 2026-06-29). Authoritative
198
+ submit/sign-off logic captured in memory `page-stage-submission`; SCIM Users endpoint in
199
+ `project-scim-users-apiv0-adapter`.
200
+ 3. **NEW test — DONE & PASSING live:** `compat_v2/page/submit_signoff_on_create` (create →
201
+ fill required + location → `submit: true` + inline `completePageTask { signOff: true }` →
202
+ stage advances). Shared helpers extracted to `mini/automated-tests/lib/page_stage_helpers.rb`.
203
+ 4. **NEW project — SCIM Users → APIv0 adapter (URGENT):** APIv0 (People) decommissioned 1 Jul
204
+ 2026 (ext. to ~31 Jul). Need: list SCIM Users + adapter mapping SCIM model → legacy APIv0
205
+ People model for 2-3 maintained customer integrations + some Pages use cases. See memory
206
+ `project-scim-users-apiv0-adapter`.
207
+ 5. **NEW project — Azure Gallery App:** Entra/Azure AD gallery app to shorten customer SCIM
208
+ setup; possibly VS/.NET; reuse Oscar's old abandoned repos. Not started. See memory
209
+ `project-azure-gallery-app`.
210
+ 6. Carried-over: gem RSpec regression specs (8.6) for the 12 cutover fixes (offline); push
211
+ `pages` + `api-deprecation`; snake/camel access revisit + specs (memory `project-snake-camel-access`).
212
+
213
+ ---
214
+
215
+ ## ▶ HANDOFF (2026-06-28, late) — cutover write/submit path; ONE open item: stage advance
216
+
217
+ The mini `automated-tests` harness now covers read + ALL field-type writes + structure +
218
+ stage-write + page-location, **27/28 green**. **12 gem bugs** found & fixed against live
219
+ (see the 2026-06-28 entry below + commits). Tests are now **fresh/isolated** (each run uses
220
+ ~2 throwaway pages via `AutomatedTest.shared_page_id` + stage_submit's own). Cutover
221
+ gem/integration surface is essentially done.
222
+
223
+ ### THE ONE OPEN ITEM — stage submit doesn't advance the stage
224
+ `compat_v2/page/stage_submit`: location persists ✓, required fields filled ✓, `updatePage`
225
+ returns OK ✓, but the stage does **not** transition (before==after). Investigation so far:
226
+ - Schema (`.ai-assistance/tmp/20260605T101224_live_ep_graphql_schema.graphql.json`): there is
227
+ **no dedicated submit mutation**. Stage submit goes via `updatePage` `TaskInput` →
228
+ `completePageTask` (`CompletePageInput { forcedComplete, signOff, notes }`) or `reviewPageTask`.
229
+ - `submit: true` + `completePageTask` together → OK but no advance (submit seems to just save
230
+ + shadow the task). Latest attempt (commit `ab312a4`): **`completePageTask` ALONE** (no
231
+ submit:true). **Needs a live re-run to confirm.**
232
+ - If still no advance, next levers: `task: { completePageTask: { forcedComplete: true } }`;
233
+ or **get the exact submit call from Insomnia / browser network tab** (dev has it) — that's
234
+ the authoritative answer. The stage may also need its **activeTask id**, or stage 1's task
235
+ may be a review task (reviewPageTask). The test logs `page=<id>` on the failing assertion
236
+ for UI inspection.
237
+
238
+ ### State / branches (all UNPUSHED)
239
+ - gem `pages` ~40 ahead; multi_org_api `api-deprecation` (farmers OozeRedirect); eco-helpers
240
+ `master` (`988bf1be` process_ooze stage_id + the pre-existing field_patches.rb change).
241
+ - Cutover scorecard (memory `project-apiv2-cutover-usecases`): P0.1 farmers ✓, P0.3 phased
242
+ write-path ✓ (live), P1.4 get_by_name(type:) ✓, P1.5 filters ✓, P1.7 submit (plumbing ✓,
243
+ stage-advance OPEN). Remaining non-gem: P0.2 release/pin `pages` (dev), P1.6 cans membranes
244
+ dedup (customer script).
245
+
246
+ ### Next session
247
+ 1. Re-run `-mini -automated-tests`; if stage_submit still fails, resolve the submit-advance
248
+ (forcedComplete, or the real call from Insomnia) — last cutover thread.
249
+ 2. `bundle exec rspec` (offline regression specs); push the three branches.
250
+ 3. Optional: retire the now-optional `-automated-tests-setup` seeder; update
251
+ `mini/automated-tests/CLAUDE.md` for the fresh-per-test convention. Then CSV-300 (Group 9.3).
252
+
253
+ ---
254
+
255
+ ## 2026-06-28 — page-read/create path validated against live; 8 bugs fixed; dispatch suite GREEN
256
+
257
+ The mini `automated-tests` harness was run end-to-end against the live Mini org for the
258
+ first time and flushed out **8 sequential bugs in the page create/read path** — which had
259
+ clearly never been exercised against the API on the `pages` branch. All fixed; the
260
+ `compat_v2/fields/dispatch` proof (OozeRedirect v2 `===` on real field instances for
261
+ PlainText/Number/Select/People/CrossReference + Select read methods) now passes.
262
+ **Final: 13 passed, 0 failed, 0 skipped.**
263
+
264
+ ### Bugs fixed (all on `pages`)
265
+ 1. `376b08d` — `CommonPageUnion` fragment **name casing** (registered `:CommonPageUnion`,
266
+ defined `commonPageUnion`) → server rejected every page read.
267
+ 2. `856454d` — bare **`DateTime` selections** (`createdAt/updatedAt/archivedAt`) needed
268
+ `{ dateTime }` (PageFields confirmed live; location_draft + pages_workflow same pattern).
269
+ 3. `3f0c2d5` — `CommonPageUnion` **directive vars undeclared**; restored per-op defaults
270
+ (`$content/$only_content/$fields`) via graphlient string-type defaults; Query::Page +
271
+ BuildFromTemplate default block → CommonPageUnion.
272
+ 4. `974cd31` — **`PageUnion` module→class** (v2 `resolve_class` matches `when Class`; a
273
+ Module fell through to "Unknown class").
274
+ 5. `264e47c` — compat **`create` omitted required `dataFields`** (non-null input).
275
+ 6. `f4acf67` — `Query::Page`/`Query::Pages` missing **`base_path 'currentOrganization'`**
276
+ (response nests under currentOrganization; direct instantiation by Compat::Pages dug
277
+ `data.page` → "Complete failure on request. Path: [\"page\"]").
278
+ 7. `f4acf67` — `corePageData` missing page-level **`__typename`** → PageUnion couldn't
279
+ dispatch Phased/Basic, fell back to Interface::BasePage.
280
+ 8. `4e1e673` — **phased read-compat flatten**: `Model::Page::Phased` overrides
281
+ `raw_data_fields`/`raw_sections` to flatten stages→sections→fields (dedup by id), so
282
+ `page.components`/`page.sections` work v2-style. field_collection stays the single
283
+ source (write path reuses it; mutations forward via shared doc refs).
284
+
285
+ Each fix was diagnosed against code/JSON and, where possible, verified offline (module-vs-
286
+ class resolution, graphlient variable-default emission, flatten dedup against the real
287
+ response shape) before the live re-run — to cut the one-bug-per-round-trip loop.
288
+
289
+ ### Known follow-ups (compat layer — not blocking the dispatch proof)
290
+ - **Section identity:** `sectionUnion` fragment fetches no section `id` → `page.sections`
291
+ can't dedup (only `heading`). Small fix: add `id` to the fragment.
292
+ - **Write/collection review:** single-element mutations forward via shared refs; collection
293
+ ops (add/remove/reorder, multi-section identity) need review.
294
+ - **Orphaned elements — clarified by dev 2026-06-28 (corrects an earlier overstatement):**
295
+ distinguish the *backend data model* from the *GraphQL-exposed model*. The GraphQL Page
296
+ **render** (stages→sections→fields) doesn't expose orphaned fields (no section) or sections
297
+ (no stage) — a property of the render, not proof orphaned data can't exist server-side. The
298
+ GraphQL Page type *may* later add flat `dataFields`/`sections`/`stages` accessors as core
299
+ (we suggested it); not done. Orphaned exposure is doubtful and, if added, would use this same
300
+ aliasing. ⇒ our flatten-from-stages covers everything the render exposes today; no
301
+ orphaned-fetch work is actionable (the render doesn't return them). (`CommonPageUnion` also
302
+ lacks `... on BasicPage { sections }`; revisit when basic-page reads are exercised.)
303
+
304
+ ### Harness (training repo) commits this run
305
+ `974cd31`-era fixes to the seeder: Compat::Pages 2-step `get_new`+`create` (not Builder),
306
+ `_seed` template/register ids in `fixtures.json`, layered committed-base + gitignored
307
+ `fixtures.local.json`, graphlient fork path-mount in training Gemfile, connectivity test
308
+ issues a real `templates` query (not proxy-class attrs).
309
+
310
+ ### Update (same day) — WRITE path validated; +1 bug; harness extended
311
+ - **WRITE/update path GREEN.** Field value round-trip (`compat_v2/fields/values`, TODO 8.1)
312
+ passes live: get → set value → `pages.update` → re-read → persisted, for **PlainText,
313
+ Number, and Select**. First successful `updatePage` through the compat layer.
314
+ - **Bug #9 (`652cbc9`):** `CommonPageUnion` didn't fetch `patchVer`; compat-read pages had
315
+ `patchVer=nil` → couldn't update. Added it to `corePageData`. (Tally now **9 bugs**.)
316
+ - Also done: section `id` in `sectionUnion` + `raw_sections` dedup (`7237374`) + a
317
+ `compat_v2/page/structure` sections test (green); probe retired (training `edca4bf`);
318
+ Group 8 next-steps logged (`3faa0a3`); `origin/pages` duplicate handoff commit merged
319
+ clean (`0477f80`). Suite: **20 checks, all green** (after a test-only Number Float-compare fix).
320
+ - values test extended with **People (`people_ids=`) + CrossReference (`page_ids=`)**
321
+ round-trips, fixture-gated (SKIP until `person_id` / `crossref_target_page_id` set in
322
+ `fixtures.local.json`) — these exercise the array-field write path + the known-missing
323
+ compat DSL when enabled.
324
+
325
+ ### Next
326
+ - **8.1 finish:** supply a `person_id` + `crossref_target_page_id` fixture to validate the
327
+ People/CrossReference writes (may expose dirty-tracking gaps on the array setters).
328
+ - **8.2** `submit!` / stage completion (note: advances the seeded page's stage — use a
329
+ throwaway page or be deliberate). **8.3** search filters. **8.6** gem RSpec regression
330
+ specs for the 9 fixes (pure offline). See migration TODO Group 8.
331
+
332
+ ---
333
+
334
+ ## 2026-06-27 — graphql-client revival branch built, pushed, wired into this gem
335
+
336
+ Migration TODO **7.1** closed. See `.ai-assistance/projects/api-v2-to-graphql-migration/`
337
+ (TODO.md 7.1, UPSTREAM.md graphql-client section).
338
+
339
+ ### Done
340
+ - **`integration/revival` branch on `rellampec/graphql-client`** — combines all four open
341
+ upstream PRs into one buildable ref. Built off `master` by cherry-picking the *unique
342
+ content* of each PR in clean order (#79 hygiene → #80 docs → #81 char-tests → #82 parse
343
+ fix) plus a single `ci: pin i18n` commit (each PR branch carried an identical copy).
344
+ Applying #79 before #80 avoided the known 1-line CHANGELOG conflict. **Pushed.**
345
+ Suite **green**: 176 runs, 0 failures, 0 errors, 4 skips; rubocop clean (61 files).
346
+ - **Gemfile override (commit `8827b2f`)** — graphql-client forced to the fork branch in
347
+ `ecoportal-api-graphql`'s Gemfile, mirroring the existing graphlient override. Rationale:
348
+ gemspecs can't carry git sources, and graphlient (which pulls graphql-client transitively)
349
+ is a public gem we can't fork-point — so the override lives in the highest Gemfile we
350
+ control. Reversible; remove once the parse fix ships upstream.
351
+ - Migration **TODO Group 7** added earlier today (commit `c8d36bc`): 7.1 (this) + 7.2
352
+ (portable `mini/automated-tests/` harness in the training repo — not yet started).
353
+
354
+ ### Blocked — needs the developer (agent sandbox network)
355
+ - **`bundle install` could not complete here** — rubygems.org TLS interception (same block as
356
+ `live.ecoportal.com`); the git source itself fetched fine. Run in your shell:
357
+ ```
358
+ bundle install # regenerates Gemfile.lock with the fork branch
359
+ bundle exec rspec # confirm resolution + green
360
+ ```
361
+
362
+ ### Also done — TODO 7.2: portable `mini/automated-tests/` harness (training repo)
363
+ - Built a self-contained, env-portable regression suite in the **training repo** at
364
+ `mini/automated-tests/`: assertion harness (`lib/asserter.rb`, `lib/test.rb` w/ auto-registry,
365
+ `lib/fixtures.rb`), a runner CLI `-automated-tests` (`automated_tests_case.rb`; `-list`/`-only`/
366
+ `-page-id`/`-fixtures`), and two seed tests (`org_read_test.rb`, `field_dispatch_test.rb` — the
367
+ assertion-based evolution of `gql_read_probe_case.rb`). Wired via one line in
368
+ `mini/config/session.rb`. Portability: org-specifics live only in `fixtures.json` (org_id
369
+ pinned by `-mini`); copy folder → edit fixtures → add the session.rb line to target another org.
370
+ - **Verified offline** (harness wiring green via mock-graphql driver; all files `ruby -c` clean).
371
+ Live run is yours: `ruby main.rb -mini -automated-tests -page-id <all-21-fields template page id>`.
372
+ Folder doc: `mini/automated-tests/CLAUDE.md`.
373
+ - **Refined per dev feedback + committed** (training `master`):
374
+ - **Area structure** (RSpec-style; folder mirrors namespace mirrors label):
375
+ `tests/connectivity/org_read`, `tests/compat_v2/fields/dispatch`, `tests/pages/` reserved.
376
+ `-only` is prefix-aware (`-only compat_v2` runs the subtree); recursive loader.
377
+ Commit `e7949ac`.
378
+ - **Readiness + seed tooling** (`-automated-tests-setup`): read-only readiness check
379
+ (verifies `fixtures.json` resolves) + opt-in idempotent seeder (`-seed`, dry-run unless
380
+ `-commit`). `ensure_page` via `create_from_template` (gem-verified input shape);
381
+ `ensure_register` best-effort. **Template creation stays manual** — gem wraps it
382
+ (`Builder::Template#create(commands:)`) but authoring the WorkflowCommandInput array is
383
+ the unsolved part (`project-template-update-architecture`). Commit `2fcacdb`.
384
+ Live `-commit` write path UNVERIFIED from sandbox (TLS) — dev confirms payload shapes.
385
+ - Confirmed: `gql_read_probe_case.rb` is superseded (dispatch → `compat_v2/fields/dispatch`,
386
+ auth → `connectivity/org_read`); retire it once the suite is green live.
387
+
388
+ ---
389
+
390
+ ## 2026-06-26 — OozeRedirect validation + training-repo proof-test docs
391
+
392
+ Resuming the **APIv2-cutover** front (top priority, deadline **1 Jul 2026**). Full detail
393
+ in memory `project-apiv2-cutover-usecases` (updated today). Pick up here.
394
+
395
+ ### Done today
396
+ - **OozeRedirect smoke-tested offline** (no live API) against the `pages`-branch gem (1.3.8)
397
+ via the training-repo bundle. Result: compat layer is **structurally sound** — all
398
+ constants resolve, `FieldPatches.apply!` clean, all compat methods land, and the v2 `===`
399
+ patch correctly matches GraphQL instances for all 5 mapped types. Two defects found:
400
+ - 🔴 **BLOCKER:** released `ecoportal-api-graphql 1.3.4` (what eco-helpers loads in its OWN
401
+ bundle) has **no `base/page/` layer at all** — Pages/DataField is unreleased (`pages`
402
+ branch only). Against 1.3.4 every patch **silently no-ops** (`safe_const` swallows
403
+ NameError) → use cases die with NoMethodError at runtime. **Releasing / pinning the
404
+ `pages` branch is a hard prerequisite for the cutover.**
405
+ - 🟢 **FIXED (uncommitted):** `OozeRedirect::FieldPatches Select#deselect` called
406
+ `mark_dirty!` (exists nowhere) → NoMethodError. Removed it; verified the in-place
407
+ `doc['options']` mutation is already caught by `DataField#dirty?` (LeafDiffService).
408
+ Change is in **eco-helpers** `lib/eco/api/usecases/graphql/compat/ooze_redirect/field_patches.rb`.
409
+ - **Read-only proof case built** in the training repo: `mini/config/graphql_cases/gql_read_probe_case.rb`
410
+ (CLI `-gql-read-probe`, optional `-page-id`). Reads currentOrganization → `pages.get(id)`
411
+ → `FieldPatches.apply!` → asserts v2 `===` dispatch on REAL fields. **Zero writes.**
412
+ Verified it boots end-to-end (loads, registers command, builds GraphQL client onto the
413
+ live mini endpoint, reaches auth).
414
+ - **Docs (per user):** training `CLAUDE.md` reframed as the proving ground (proof tests =
415
+ committed, not gitignored); new `mini/CLAUDE.md` (Mini Testing Site = test org on the
416
+ PROD platform `live.ecoportal.com`, org_id `59263deaed164b0019b1613d`); new
417
+ `graphql_cases/CLAUDE.md` (proof-test convention + the probe documented).
418
+
419
+ ### Blocked — needs the developer
420
+ - **Live `mini` read run can't run from the agent sandbox** — TLS to `live.ecoportal.com`
421
+ fails `certificate verify failed` even with sandbox disabled + good CA bundle (network-layer
422
+ interception in the agent env, NOT a CA problem on this machine). **Run it in your own
423
+ shell** (`!` prefix so output lands here):
424
+ ```
425
+ cd C:/ruby_scripts/implementation/training; $env:ENVIRO_CONTEXT='local'; $env:LOCAL_REPOS='C:/ruby_scripts/git'
426
+ ruby main.rb -mini -gql-read-probe # auth smoke
427
+ ruby main.rb -mini -gql-read-probe -page-id <ID> # full dispatch test (need a page-id from the all-21-fields template)
428
+ ```
429
+ (If `already activated rake 13.4.2 … requires 13.3.1` appears, use `bundle exec ruby …`.)
430
+
431
+ ### Uncommitted working-tree state (nothing committed today — awaiting your call)
432
+ - **eco-helpers:** `field_patches.rb` (the `mark_dirty!` fix).
433
+ - **training:** `CLAUDE.md` (M), `mini/CLAUDE.md` (new), `graphql_cases/CLAUDE.md` (new),
434
+ `gql_read_probe_case.rb` (new). All parse clean.
435
+ - **ecoportal-api-graphql (this repo):** only this worklog edit.
436
+
437
+ ### Next (resume order)
438
+ 1. You run the probe in your shell + paste output (with a page-id) → closes OozeRedirect
439
+ validation on real data.
440
+ 2. Commit: eco-helpers fix; training docs+probe (ask before committing).
441
+ 3. Decide the **`pages` branch release/pin** (the blocker) — without it the cutover can't run.
442
+ 4. Then the still-open cutover items: **cans dedup** rework, **farmers/supplier_documents**
443
+ (Custom::UseCase) treatment. See `project-apiv2-cutover-usecases`.
444
+
445
+ ---
446
+
447
+ ## ▶ CRITICAL — HOLIDAY HANDOFF (2026-06-16, dev away from 2026-06-17)
448
+
449
+ Detailed state in memory `session-handoff-graphql-client-revival`, `page-stage-submission`,
450
+ `graphlient-error-masking`, `project-template-update-architecture`. Three fronts:
451
+
452
+ ### ✅ Code is PUSHED — remaining actions are light
453
+ - **graphlient** `C:\ruby_scripts\git\graphlient`, PR **#116** branch `feature/directives-dsl-support` is PUSHED (origin = `b621655`): unify inline fragments under `spread(on:)` (`spread :Name` / `spread on: :Type {}` / `spread on: :Type`; standalone `on` removed) + ostruct/mutex_m test-load fix + rubocop. **rspec + rubocop CLEAN.** REMAINING: post the @dblock reply (drafted in memory `session-handoff-graphql-client-revival`: "ready for re-review", explains the unify-under-`spread` decision + co-maintainer thanks) → await re-review.
454
+ - **ecoportal-api-graphql** branch `pages` is PUSHED through `7c45b0f` (origin/pages): `bafbf80` B3 (require all 12 field_config byType modules), `837901e` docs, `7c45b0f` stage submit/close-out via updatePage `task` input (see memory `page-stage-submission`). Only this worklog commit is local-ahead → push when convenient (docs only).
455
+
456
+ ### 🟠 graphql-client PRs — OPEN, awaiting maintainer
457
+ - **#79** hygiene → **#80** docs (stacked on #79) + **#81** characterization tests + **#82** parse-robustness fix (anchored regex; rspec+rubocop clean). All blocked only on a `github-community-projects` maintainer approving the CI workflow run (first-time-contributor gate).
458
+ - **After #79 merges:** rebase #80 onto `upstream/master` + force-push (esp. if #79 is squash-merged) so #80 collapses to just its docs diff (resolve the 1-line CHANGELOG conflict).
459
+ - #76 issue: developer already updated it. Keep OPEN until #82 ships.
460
+
461
+ ### 🟡 PARKED (non-critical, logged for later)
462
+ - graphlient **error-masking** fix — `ClientError` drops `inner_exception` (`client.rb:19/41`); fix = `ClientError.new(e.message, e)`. Own PR. See `graphlient-error-masking` (user recalls patching BOTH gems).
463
+ - ecoportal **`updateRelatedPage`** mutation gap (only genuine structural template omission; additive — see refactoring log).
464
+ - Refresh **stale docs** `diff_as_input.md` + `diff_service_deep_dive.md` (describe pre-v1.3.8 behaviour).
465
+ - **eco-helpers template-edit UX** — ship Sketch B (`graphql.template.edit` typed DSL); A (mutating read-model) later. See `project-template-update-architecture`.
466
+ - **Template meta-language** decision: declarative diffable text vs imperative command bus — either needs a diff→`WorkflowCommandInput` compiler (the real work). Record in a DECISIONS log if pursued.
467
+
468
+ ---
469
+
470
+ ## 2026-06-13 — fork revival kickoff (graphlient #115 confirmed; upstream ai-assistance deployed)
471
+
472
+ ### Done
473
+
474
+ - **Migration TODO 1.2 closed** — graphlient DSL-only mode (`to_query_string` + `spread`) is
475
+ **already merged** into `ashkan18/graphlient` master as **PR #115** (verified via
476
+ `git ls-remote upstream`). NOT yet released → still ours to change (we authored it).
477
+ - **Upstream-clone AI context deployed (local-only, verified non-leaking):**
478
+ - `graphlient/CLAUDE.md` rewritten (was truncated) with role + hard guardrails; already
479
+ gitignored upstream.
480
+ - `graphql-client/CLAUDE.md` created; excluded via `.git/info/exclude` (NOT tracked
481
+ `.gitignore`).
482
+ - `.ai-assistance/README.md` pointer added to each clone, excluded via `.git/info/exclude`.
483
+ - `git status` clean in both clones — confirmed none of it is visible to git.
484
+ - **Deprecation research (background agent, primary sources):** gems are healthier than assumed.
485
+ graphql-client actively released (0.26.0, 2025-05-29), community-stewarded not abandoned;
486
+ graphlient low-velocity but active master. No evidence of major-org migration off them.
487
+ ecoPortal's CI/CD removal was internal, not an industry trend. → revival is realistic.
488
+
489
+ ### Blocked
490
+
491
+ - **Global permission allowlist for the upstream clones** — the auto-mode safety classifier
492
+ **denied** writing `permissions.allow` to `~/.claude/settings.json` (won't let the agent
493
+ self-authorize permission rules). Developer must paste the block manually (provided in chat).
494
+ Until then, running specs/git in the sibling clones will still prompt.
495
+
496
+ ### graphql-client revival — progress (local, unpushed)
497
+
498
+ - **(1) Hygiene PR — DONE locally.** Branch `chore/add-changelog-contributing` off `upstream/master`
499
+ (1 commit): `CHANGELOG.md` (reconstructed from merged PRs/tags back to 0.23.0; #60 correctly
500
+ placed under Unreleased, not 0.26.0) + `CONTRIBUTING.md` (Minitest flow).
501
+ - **(2) Characterization specs — DONE locally, green.** Branch `test/parse-fragment-characterization`
502
+ off `upstream/master` (1 commit): `test/test_parse_fragment_characterization.rb` — 3 tests /
503
+ 18 assertions pinning inline-named-fragment resolution, transitive local fragments, and
504
+ `source_document` vs sliced `document`. Built from a background-agent analysis that confirmed
505
+ the fix hinges on the `str.match(/fragment\s*#{const_name}/)` heuristic at `client.rb:161`.
506
+ - **(3) Parse-level inline-fragment fix — NOT STARTED** (behavior-changing; design in
507
+ `project-graphql-client-redesign`). Must preserve the 6 characterized behaviors + fix the
508
+ prefix-collision edge by anchoring to `fragment\s+Name\s+on\b`.
509
+
510
+ ### Env blocker
511
+
512
+ - **`bundle install` fails in-sandbox** (SSL cert verification to rubygems.org → `erubi ~> 1.6`
513
+ unresolved). Worked around by running the new test via system `graphql` gem directly
514
+ (`ruby -Ilib -Itest`). Full bundler-locked suite + RuboCop must run in CI (needs push) or with
515
+ sandbox disabled for `bundle install`.
516
+
517
+ ### Open Questions
518
+
519
+ - None.
520
+
521
+ ---
522
+
523
+ ## 2026-06-10 — ep-ai-standards deployments (token logging, lock protocol, policies)
524
+
525
+ ### Done
526
+
527
+ - **Token budget logging** deployed: `token-logger.js` (Stop hook), `token-session-start.js`
528
+ (SessionStart hook), `token-report.ts` (cross-project weekly report). `.ai-assistance/token-budget.json`
529
+ set to priority=medium. `.claude/settings.json` hooks wired. `.ai-assistance/local/` gitignored.
530
+
531
+ - **Cross-repo locking** deployed: `lock-multi.sh` (atomic multi-repo lock with estimated_release
532
+ + stale cleanup), `lock-queue.sh` (priority turn-request queue in `bridge/queue/`),
533
+ `.ai-assistance/version.json` (feature detection).
534
+
535
+ - **`corporate-policies` skill** v1.0 deployed — 13 directives with ecoPortal Confluence
536
+ policy citations (AI Usage Policy, Privacy, GDPR, Secure Engineering, etc.).
537
+
538
+ - **`ruby-scripting` skill** deployed — auth patterns, patchVer read-before-write, cross-platform
539
+ file handling, error handling template for scripts using the ecoportal gem stack.
540
+
541
+ - **LEARNING markers** seeded in worklog for Phase 0 EPAI pipeline.
542
+
543
+ - **`.gitattributes`** — LF enforcement.
544
+
545
+ ### No blockers
546
+
547
+ ---
548
+
549
+ ## 2026-06-08 — ep-ai-standards v1.0.0 alignment
550
+
551
+ ### Done
552
+
553
+ - **ep-ai-standards retrofit applied** — `eP_AI_Manager` skill installed at
554
+ `.ai-assistance/skills/eP_AI_Manager/SKILL.md`. Standards version pinned to v1.0.0
555
+ in `.ai-assistance/standards-version.json`.
556
+ - **`docs/worklog.md` created** — this file; satisfies `workflows/session-handoff` standard.
557
+ - **CLAUDE.md updated** — "Read these first" section added with worklog pointer; skill index
558
+ updated to include `eP_AI_Manager`.
559
+
560
+ ### Blocked / Pending
561
+
562
+ - Active project work (see `.ai-assistance/projects/` for current project state)
563
+
564
+ ### Open Questions
565
+
566
+ - None at this time.
567
+
568
+ ---
569
+
570
+ ## How to use this file
571
+
572
+ - **Starting a session:** read from the bottom up.
573
+ - **Ending a session:** add a dated section at the top with Done / Blocked / Open Questions.
574
+ - **Per-project detail:** see `.ai-assistance/projects/<slug>/` (INTENT.md, TODO.md, DECISIONS.md).