ecoportal-api-graphql 1.3.5 → 1.3.10

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