ecoportal-api-graphql 1.3.13 → 1.3.16

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 (275) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +87 -0
  3. data/lib/ecoportal/api/common/graphql/client.rb +0 -2
  4. data/lib/ecoportal/api/common/graphql/http_client.rb +6 -0
  5. data/lib/ecoportal/api/graphql/base/ai_summary_version.rb +17 -17
  6. data/lib/ecoportal/api/graphql/base/file_container.rb +14 -14
  7. data/lib/ecoportal/api/graphql/base/location_classification_type.rb +15 -15
  8. data/lib/ecoportal/api/graphql/base/location_structure.rb +27 -27
  9. data/lib/ecoportal/api/graphql/base/organization.rb +15 -15
  10. data/lib/ecoportal/api/graphql/base/page/task.rb +24 -0
  11. data/lib/ecoportal/api/graphql/base/page.rb +17 -16
  12. data/lib/ecoportal/api/graphql/base/template.rb +35 -0
  13. data/lib/ecoportal/api/graphql/base.rb +37 -35
  14. data/lib/ecoportal/api/graphql/builder/contractor_entity.rb +41 -41
  15. data/lib/ecoportal/api/graphql/compat/response.rb +35 -35
  16. data/lib/ecoportal/api/graphql/connection/action.rb +11 -11
  17. data/lib/ecoportal/api/graphql/connection/action_category.rb +11 -11
  18. data/lib/ecoportal/api/graphql/connection/contractor_entity.rb +11 -11
  19. data/lib/ecoportal/api/graphql/connection/page.rb +11 -11
  20. data/lib/ecoportal/api/graphql/connection/person_member.rb +11 -11
  21. data/lib/ecoportal/api/graphql/connection/preview_page.rb +11 -11
  22. data/lib/ecoportal/api/graphql/connection.rb +17 -17
  23. data/lib/ecoportal/api/graphql/file_upload/client.rb +21 -10
  24. data/lib/ecoportal/api/graphql/fragment/field_configuration.rb +38 -0
  25. data/lib/ecoportal/api/graphql/fragment/force.rb +14 -10
  26. data/lib/ecoportal/api/graphql/fragment/location_node.rb +26 -26
  27. data/lib/ecoportal/api/graphql/fragment/page_task.rb +39 -0
  28. data/lib/ecoportal/api/graphql/fragment/template.rb +51 -0
  29. data/lib/ecoportal/api/graphql/fragment.rb +3 -0
  30. data/lib/ecoportal/api/graphql/input/contractor_entity.rb +14 -14
  31. data/lib/ecoportal/api/graphql/input/preset_view/update.rb +16 -16
  32. data/lib/ecoportal/api/graphql/input/workflow_command/add_stage.rb +18 -18
  33. data/lib/ecoportal/api/graphql/input/workflow_command/edit_field_configuration.rb +21 -21
  34. data/lib/ecoportal/api/graphql/input/workflow_command/edit_page.rb +28 -28
  35. data/lib/ecoportal/api/graphql/input/workflow_command/edit_page_creator_permissions.rb +18 -18
  36. data/lib/ecoportal/api/graphql/input/workflow_command/field_config/cross_reference.rb +23 -23
  37. data/lib/ecoportal/api/graphql/input/workflow_command/field_config/date.rb +20 -20
  38. data/lib/ecoportal/api/graphql/input/workflow_command/field_config/image_gallery.rb +20 -20
  39. data/lib/ecoportal/api/graphql/input/workflow_command/field_config/people.rb +24 -24
  40. data/lib/ecoportal/api/graphql/input/workflow_command/field_config/plain_text.rb +20 -20
  41. data/lib/ecoportal/api/graphql/input/workflow_command/field_config/rich_text.rb +20 -20
  42. data/lib/ecoportal/api/graphql/input/workflow_command/field_config/select.rb +20 -20
  43. data/lib/ecoportal/api/graphql/input/workflow_command/move_field.rb +18 -18
  44. data/lib/ecoportal/api/graphql/input/workflow_command/reorder_forces.rb +18 -18
  45. data/lib/ecoportal/api/graphql/input/workflow_command/reorder_section.rb +18 -18
  46. data/lib/ecoportal/api/graphql/input/workflow_command.rb +251 -251
  47. data/lib/ecoportal/api/graphql/input.rb +24 -24
  48. data/lib/ecoportal/api/graphql/logic/connection.rb +34 -34
  49. data/lib/ecoportal/api/graphql/model/page/task.rb +16 -0
  50. data/lib/ecoportal/api/graphql/model/page.rb +16 -15
  51. data/lib/ecoportal/api/graphql/model/person_member.rb +15 -15
  52. data/lib/ecoportal/api/graphql/model/template.rb +15 -0
  53. data/lib/ecoportal/api/graphql/model.rb +32 -30
  54. data/lib/ecoportal/api/graphql/mutation/ai_summary/generate.rb +45 -45
  55. data/lib/ecoportal/api/graphql/mutation/ai_summary/submit_feedback.rb +40 -40
  56. data/lib/ecoportal/api/graphql/mutation/contractor_entity.rb +14 -14
  57. data/lib/ecoportal/api/graphql/mutation/page/approve_review_task.rb +40 -40
  58. data/lib/ecoportal/api/graphql/mutation/page/batch_update_review_task.rb +38 -40
  59. data/lib/ecoportal/api/graphql/mutation/page/create_draft.rb +38 -40
  60. data/lib/ecoportal/api/graphql/mutation/page/delete_draft.rb +38 -40
  61. data/lib/ecoportal/api/graphql/mutation/page/execute_force_commands.rb +7 -7
  62. data/lib/ecoportal/api/graphql/mutation/page/execute_workflow_commands.rb +8 -7
  63. data/lib/ecoportal/api/graphql/mutation/page/publish_draft.rb +38 -40
  64. data/lib/ecoportal/api/graphql/mutation/page/reject_review_task.rb +40 -40
  65. data/lib/ecoportal/api/graphql/mutation/page/restart_review_task.rb +40 -40
  66. data/lib/ecoportal/api/graphql/mutation/page/undo_review_task.rb +40 -40
  67. data/lib/ecoportal/api/graphql/mutation/preset_view/destroy.rb +34 -35
  68. data/lib/ecoportal/api/graphql/mutation/register/destroy.rb +35 -35
  69. data/lib/ecoportal/api/graphql/mutation/smart_fill/generate.rb +36 -36
  70. data/lib/ecoportal/api/graphql/mutation/smart_fill/submit_feedback.rb +40 -40
  71. data/lib/ecoportal/api/graphql/mutation/smart_fill.rb +13 -13
  72. data/lib/ecoportal/api/graphql/mutation/template/create_related_page.rb +46 -46
  73. data/lib/ecoportal/api/graphql/mutation/template/destroy_related_page.rb +1 -1
  74. data/lib/ecoportal/api/graphql/mutation/template/update_information.rb +1 -1
  75. data/lib/ecoportal/api/graphql/mutation.rb +20 -20
  76. data/lib/ecoportal/api/graphql/payload/contractor_entity.rb +14 -14
  77. data/lib/ecoportal/api/graphql/payload/ok_payload.rb +36 -21
  78. data/lib/ecoportal/api/graphql/payload/page/draft.rb +26 -13
  79. data/lib/ecoportal/api/graphql/payload/page/review_task.rb +13 -13
  80. data/lib/ecoportal/api/graphql/payload/page/review_task_batch.rb +23 -0
  81. data/lib/ecoportal/api/graphql/payload/page.rb +20 -19
  82. data/lib/ecoportal/api/graphql/payload/preset_view.rb +15 -11
  83. data/lib/ecoportal/api/graphql/payload/register.rb +15 -11
  84. data/lib/ecoportal/api/graphql/payload/template/create_related_page.rb +1 -1
  85. data/lib/ecoportal/api/graphql/payload/template/destroy_related_page.rb +1 -1
  86. data/lib/ecoportal/api/graphql/payload/template/update_information.rb +1 -1
  87. data/lib/ecoportal/api/graphql/payload.rb +23 -23
  88. data/lib/ecoportal/api/graphql/query/location_structures.rb +57 -57
  89. data/lib/ecoportal/api/graphql/query/page.rb +45 -45
  90. data/lib/ecoportal/api/graphql/query/page_with_forces.rb +9 -3
  91. data/lib/ecoportal/api/graphql/query/pages_workflow_commands.rb +9 -3
  92. data/lib/ecoportal/api/graphql/query/register_preset_views.rb +78 -78
  93. data/lib/ecoportal/api/graphql/query.rb +27 -27
  94. data/lib/ecoportal/api/graphql.rb +9 -5
  95. data/lib/ecoportal/api/graphql_version.rb +1 -1
  96. metadata +9 -180
  97. data/.ai-assistance/bridge/CLAUDE.md +0 -338
  98. data/.ai-assistance/bridge/archive/.gitkeep +0 -0
  99. data/.ai-assistance/bridge/archive/oscar-a1b2c3d-gitlab-mcp-doc-update.inbox.md +0 -29
  100. data/.ai-assistance/bridge/archive/oscar-a1b2c3d-gitlab-mcp-doc-update.outbox.md +0 -18
  101. data/.ai-assistance/bridge/archive/oscar-c912c25-gemini-design-review.inbox.md +0 -42
  102. data/.ai-assistance/bridge/archive/oscar-c912c25-gemini-design-review.outbox.md +0 -115
  103. data/.ai-assistance/bridge/context/gemini-review-prompt.txt +0 -48
  104. data/.ai-assistance/bridge/context/gemini-review-response.md +0 -104
  105. data/.ai-assistance/bridge/context/project.md +0 -42
  106. data/.ai-assistance/bridge/inbox/.gitkeep +0 -0
  107. data/.ai-assistance/bridge/outbox/.gitkeep +0 -0
  108. data/.ai-assistance/bridge/outbox/request-for-standards-discovery.md +0 -48
  109. data/.ai-assistance/bridge/queue/.gitkeep +0 -1
  110. data/.ai-assistance/capabilities/CLAUDE.md +0 -27
  111. data/.ai-assistance/capabilities/assumptions-log.md +0 -80
  112. data/.ai-assistance/capabilities/code.md +0 -47
  113. data/.ai-assistance/capabilities/connectors.md +0 -37
  114. data/.ai-assistance/capabilities/cowork.md +0 -55
  115. data/.ai-assistance/code/OVERVIEW.md +0 -155
  116. data/.ai-assistance/code/data_fields.md +0 -242
  117. data/.ai-assistance/code/dependencies.md +0 -151
  118. data/.ai-assistance/code/diff_as_input.md +0 -234
  119. data/.ai-assistance/code/diff_pairing_engine.md +0 -243
  120. data/.ai-assistance/code/diff_service_deep_dive.md +0 -192
  121. data/.ai-assistance/code/ecoPortal_architecture/00_overview_and_index.md +0 -55
  122. data/.ai-assistance/code/ecoPortal_architecture/01_terminology_dictionary.md +0 -181
  123. data/.ai-assistance/code/ecoPortal_architecture/02_data_model.md +0 -192
  124. data/.ai-assistance/code/ecoPortal_architecture/03_api_layers.md +0 -147
  125. data/.ai-assistance/code/ecoPortal_architecture/04_graphql_queries_mutations.md +0 -277
  126. data/.ai-assistance/code/ecoPortal_architecture/05_page_workflows.md +0 -200
  127. data/.ai-assistance/code/ecoPortal_architecture/06_search_and_filters.md +0 -228
  128. data/.ai-assistance/code/ecoPortal_architecture/07_data_fields.md +0 -197
  129. data/.ai-assistance/code/ecoPortal_architecture/08_stages_sections.md +0 -243
  130. data/.ai-assistance/code/ecoPortal_architecture/09_people_contractors_locations.md +0 -196
  131. data/.ai-assistance/code/ecoPortal_architecture/10_forces_workflow_builder.md +0 -132
  132. data/.ai-assistance/code/ecoPortal_architecture/11_integration_gems.md +0 -187
  133. data/.ai-assistance/code/ecoPortal_architecture/12_ai_documentation_sources_gaps.md +0 -236
  134. data/.ai-assistance/code/ecoPortal_architecture/13_ai_infrastructure.md +0 -183
  135. data/.ai-assistance/code/ecoportal_schema_reference.md +0 -240
  136. data/.ai-assistance/code/filter_contract_matrix.md +0 -177
  137. data/.ai-assistance/code/graphql_domain_knowledge.md +0 -240
  138. data/.ai-assistance/code/refactoring/datafield-readwrite-shape-asymmetry.md +0 -71
  139. data/.ai-assistance/code/refactoring/opportunities.md +0 -251
  140. data/.ai-assistance/code/schema_analysis.md +0 -321
  141. data/.ai-assistance/code/search_filters.md +0 -868
  142. data/.ai-assistance/code/spec_coverage.md +0 -73
  143. data/.ai-assistance/code/template_diff_pairing_domain.md +0 -175
  144. data/.ai-assistance/code/workflow-command-guide.md +0 -466
  145. data/.ai-assistance/code/workflow-space.md +0 -353
  146. data/.ai-assistance/conventions/CLAUDE.md +0 -30
  147. data/.ai-assistance/conventions/code-working-tree-protocol.md +0 -199
  148. data/.ai-assistance/conventions/gitignore-rules.md +0 -42
  149. data/.ai-assistance/conventions/permission-guidance.md +0 -120
  150. data/.ai-assistance/integrations/README.md +0 -70
  151. data/.ai-assistance/integrations/gitkraken-mcp.md +0 -107
  152. data/.ai-assistance/integrations/gitlab-mcp.md +0 -123
  153. data/.ai-assistance/integrations/local-git.md +0 -60
  154. data/.ai-assistance/local_paths.example.md +0 -17
  155. data/.ai-assistance/projects/TODO.md +0 -118
  156. data/.ai-assistance/projects/api-v2-to-graphql-migration/DECISIONS.md +0 -168
  157. data/.ai-assistance/projects/api-v2-to-graphql-migration/INTENT.md +0 -60
  158. data/.ai-assistance/projects/api-v2-to-graphql-migration/TODO.md +0 -267
  159. data/.ai-assistance/projects/api-v2-to-graphql-migration/UPSTREAM.md +0 -53
  160. data/.ai-assistance/projects/api-v2-to-graphql-migration/notes/csv-template-pipeline-design.md +0 -102
  161. data/.ai-assistance/projects/api-v2-to-graphql-migration/notes/cutover-usecase-gap-audit.md +0 -139
  162. data/.ai-assistance/projects/compat-layer-audit/COMPAT_AUDIT.md +0 -244
  163. data/.ai-assistance/projects/dynamic-model-generation/INTENT.md +0 -93
  164. data/.ai-assistance/projects/eco-helpers-compat/INTENT.md +0 -244
  165. data/.ai-assistance/projects/eco-helpers-compat/MIGRATION_GUIDE.md +0 -266
  166. data/.ai-assistance/projects/eco-helpers-compat/TODO.md +0 -86
  167. data/.ai-assistance/projects/ecoportal-api-v2-doublemodel-review/INTENT.md +0 -101
  168. data/.ai-assistance/projects/graphql-agent/GAP_ANALYSIS.md +0 -177
  169. data/.ai-assistance/projects/ooze-graphql-native-migration/DECISIONS.md +0 -161
  170. data/.ai-assistance/projects/ooze-graphql-native-migration/INTENT.md +0 -125
  171. data/.ai-assistance/projects/ooze-graphql-native-migration/INVENTORY.md +0 -136
  172. data/.ai-assistance/projects/ooze-graphql-native-migration/RISKS.md +0 -126
  173. data/.ai-assistance/projects/ooze-graphql-native-migration/TODO.md +0 -261
  174. data/.ai-assistance/projects/ooze-graphql-native-migration/analysis/2026-06-30-cutover-workflow-deep-review.md +0 -122
  175. data/.ai-assistance/projects/ooze-graphql-native-migration/analysis/2026-07-01-forces-via-workflow-commands-miss-rca.md +0 -148
  176. data/.ai-assistance/projects/page-model/DECISIONS.md +0 -245
  177. data/.ai-assistance/projects/page-model/TODO.md +0 -190
  178. data/.ai-assistance/projects/qa-services-delivery/DECISIONS.md +0 -93
  179. data/.ai-assistance/projects/qa-services-delivery/INTENT.md +0 -76
  180. data/.ai-assistance/projects/qa-services-delivery/PHASE3-SCOPE.md +0 -115
  181. data/.ai-assistance/projects/qa-services-delivery/ROADMAP.md +0 -99
  182. data/.ai-assistance/projects/qa-services-delivery/TODO.md +0 -81
  183. data/.ai-assistance/projects/search-filter-builder/INTENT.md +0 -107
  184. data/.ai-assistance/projects/search-filter-builder/TODO.md +0 -131
  185. data/.ai-assistance/projects/template-automatic-build-maintenance/INTENT.md +0 -87
  186. data/.ai-assistance/projects/template-automatic-build-maintenance/TODO.md +0 -108
  187. data/.ai-assistance/projects/template-diff-deploy/INTENT.md +0 -12
  188. data/.ai-assistance/projects/template-diff-deploy/TODO.md +0 -9
  189. data/.ai-assistance/projects/template-maintenance/DESIGN.md +0 -134
  190. data/.ai-assistance/projects/template-maintenance/PHASE0-FINDINGS.md +0 -93
  191. data/.ai-assistance/projects/template-maintenance/README.md +0 -14
  192. data/.ai-assistance/projects/template-model-logic/CATEGORY_CATALOG.md +0 -236
  193. data/.ai-assistance/projects/template-model-logic/CLASSIFICATION_SPIKE.md +0 -243
  194. data/.ai-assistance/projects/template-model-logic/DESIGN_NOTE.md +0 -154
  195. data/.ai-assistance/projects/workflow-space/TODO.md +0 -213
  196. data/.ai-assistance/reinstall-claude-desktop-windows.md +0 -136
  197. data/.ai-assistance/scripts/CLAUDE.md +0 -150
  198. data/.ai-assistance/scripts/bridge-inbox-check.sh +0 -75
  199. data/.ai-assistance/scripts/bridge-init.sh +0 -86
  200. data/.ai-assistance/scripts/bridge-status.sh +0 -44
  201. data/.ai-assistance/scripts/capabilities-check.ts +0 -104
  202. data/.ai-assistance/scripts/check-outbox.sh +0 -43
  203. data/.ai-assistance/scripts/dep_graph.rb +0 -91
  204. data/.ai-assistance/scripts/lock-acquire.sh +0 -103
  205. data/.ai-assistance/scripts/lock-multi.sh +0 -124
  206. data/.ai-assistance/scripts/lock-queue.sh +0 -94
  207. data/.ai-assistance/scripts/setup-mcps.test.ts +0 -188
  208. data/.ai-assistance/scripts/setup-mcps.ts +0 -234
  209. data/.ai-assistance/scripts/task-complete.ts +0 -74
  210. data/.ai-assistance/scripts/task-create.ts +0 -75
  211. data/.ai-assistance/scripts/task-read.ts +0 -125
  212. data/.ai-assistance/scripts/token-logger.js +0 -220
  213. data/.ai-assistance/scripts/token-report.ts +0 -158
  214. data/.ai-assistance/scripts/token-session-start.js +0 -66
  215. data/.ai-assistance/skills/ai-instructions/SKILL.md +0 -48
  216. data/.ai-assistance/skills/code-specs/SKILL.md +0 -69
  217. data/.ai-assistance/skills/corporate-policies/SKILL.md +0 -201
  218. data/.ai-assistance/skills/dep-graph/SKILL.md +0 -139
  219. data/.ai-assistance/skills/ep-ai-manager/SKILL.md +0 -417
  220. data/.ai-assistance/skills/gemini-assist/SKILL.md +0 -63
  221. data/.ai-assistance/skills/gemini-assist/gemini-mcp-server.js +0 -205
  222. data/.ai-assistance/skills/gemini-assist/gemini_ask.py +0 -1
  223. data/.ai-assistance/skills/gemini-assist/gemini_ask.rb +0 -240
  224. data/.ai-assistance/skills/gemini-assist/prompts/cycle_end_review.txt +0 -25
  225. data/.ai-assistance/skills/graphql-schema-analysis/SKILL.md +0 -261
  226. data/.ai-assistance/skills/procedural-memory/SKILL.md +0 -319
  227. data/.ai-assistance/skills/project-cycle/SKILL.md +0 -177
  228. data/.ai-assistance/skills/project-self-docs/SKILL.md +0 -181
  229. data/.ai-assistance/skills/project-self-docs/scripts/self_docs_scan.py +0 -378
  230. data/.ai-assistance/skills/refactor/SKILL.md +0 -62
  231. data/.ai-assistance/skills/rubocop/SKILL.md +0 -93
  232. data/.ai-assistance/skills/ruby-scripting/SKILL.md +0 -215
  233. data/.ai-assistance/skills/spec-generation/SKILL.md +0 -72
  234. data/.ai-assistance/standards-version.json +0 -22
  235. data/.ai-assistance/token-budget.json +0 -32
  236. data/.ai-assistance/version.json +0 -39
  237. data/.claude/settings.json +0 -150
  238. data/.env.example +0 -18
  239. data/.gitattributes +0 -15
  240. data/.gitignore +0 -37
  241. data/.gitlab-ci.yml +0 -45
  242. data/.markdownlint.json +0 -4
  243. data/.rspec +0 -3
  244. data/.rubocop.yml +0 -121
  245. data/.ruby-version +0 -1
  246. data/.yardopts +0 -10
  247. data/CLAUDE.md +0 -243
  248. data/Gemfile +0 -30
  249. data/Rakefile +0 -90
  250. data/bin/console +0 -14
  251. data/bin/setup +0 -8
  252. data/bin/setup.ps1 +0 -6
  253. data/docs/self-docs/ARCHITECTURE.md +0 -88
  254. data/docs/self-docs/CHANGES.jsonl +0 -12
  255. data/docs/self-docs/COMPLIANCE.md +0 -79
  256. data/docs/self-docs/CONVENTIONS.md +0 -74
  257. data/docs/self-docs/INTEGRATIONS.md +0 -65
  258. data/docs/self-docs/OPERATIONS.md +0 -76
  259. data/docs/self-docs/OVERVIEW.md +0 -64
  260. data/docs/self-docs/STATUS.md +0 -73
  261. data/docs/self-docs/self-docs-index.json +0 -51
  262. data/docs/worklog.md +0 -977
  263. data/ecoportal-api-graphql.gemspec +0 -40
  264. data/scripts/auto-worker-scheduler.sh +0 -386
  265. data/tests/actions_get.rb +0 -7
  266. data/tests/contractor_entities_get.rb +0 -20
  267. data/tests/contractor_entity_create.rb +0 -19
  268. data/tests/contractor_entity_udpate.rb +0 -20
  269. data/tests/dump_page_model.rb +0 -74
  270. data/tests/dump_template_model.rb +0 -90
  271. data/tests/loc_structure_get.rb +0 -10
  272. data/tests/loc_structure_update.rb +0 -51
  273. data/tests/loc_structures_get.rb +0 -15
  274. data/tests/local_libs.rb +0 -20
  275. data/tests/validate_queries.rb +0 -127
@@ -1,131 +0,0 @@
1
- # TODOs — Search Filter Builder
2
-
3
- > Natural order: 1 → 2 → 3 → 4 → 5. Step 1 unblocks everything else.
4
-
5
- ---
6
-
7
- ## Step 1 — Ground truth: gather filter fieldNames and operator examples
8
-
9
- - [x] **1.1** Insomnia v5 export reviewed — all search patterns documented in
10
- `.ai-assistance/code/search_filters.md`. Confirmed operations: exact_filter,
11
- date_filter, register_filter, and_filter, or_filter (all snake_case).
12
- *Done 2026-06-07*
13
-
14
- - [x] **1.2** Backend filter classes read — `app/services/new_ep/es/filters/`.
15
- Key findings: 29 global filter operations via dynamic class routing (operation →
16
- `"#{op.camelize}Filter"` class name); no central whitelist — filters auto-discovered.
17
- Page-specific fieldNames: external_id, state, name, creator_id, created_at, updated_at,
18
- template_id, id, location_id, all_location_ids, other_tags, archived, draft, mould_counter.
19
- Full human date mode list extracted from `HumanDateFilterable` concern.
20
- *Done 2026-06-08*
21
-
22
- - [x] **1.3** Frontend `.graphql` + `createFilter.ts` swept — 159 unique operations found.
23
- New operations confirmed beyond prior Insomnia list: `one_of_filter`, `none_of_filter`,
24
- `has_any_filter`, `match_filter`, `exists_filter`, `doesnt_exist_filter`, `boolean_filter`,
25
- `numeric_range_filter`, `isnt_exact_filter`, `not_register_filter`.
26
- Confirmed `in_filter`/`range_filter`/`ne_filter` are NOT real operations.
27
- *Done 2026-06-08*
28
-
29
- - [x] **1.4** `search_filters.md` extended with:
30
- - Full fieldName reference table for Pages (core metadata, location, tag, boolean fields)
31
- - Extended operation reference (15 confirmed operations including new ones)
32
- - Human date mode table (30+ modes from HumanDateFilterable)
33
- - Parametrization patterns section (SearchConf#with — 3 examples)
34
- - Updated Filter Builder constants with confirmed/denied status
35
- *Done 2026-06-08*
36
-
37
- ---
38
-
39
- ## Step 2+3 — Design + Implement (Done 2026-06-07)
40
-
41
- - [x] **2.1+3.1** Implemented `Input::SearchConf` with nested filter classes:
42
- `SearchConf::Exact`, `SearchConf::DateRange`, `SearchConf::Register`,
43
- `SearchConf::And`, `SearchConf::Or`. Plain Ruby value objects, no Logic::Input.
44
- Chainable builder, `to_h` serialises to the expected Hash structure.
45
- `as_json` support for transparent JSON serialisation.
46
- *`lib/ecoportal/api/graphql/input/search_conf.rb`*
47
-
48
- - [x] **2.2+3.3** Parametrization via `#with(**substitutions)` — returns a cloned
49
- `SearchConf` with substituted values propagated into nested filters.
50
- *Confirmed immutable (original not mutated)*
51
-
52
- - [x] **4.1** 23 RSpec specs covering all filter types, builder methods, sorter
53
- single/array convention, parametrization, nested Or propagation, as_json.
54
- *`spec/ecoportal/api/graphql/input/search_conf_spec.rb`*
55
-
56
- ## Remaining
57
-
58
- - [x] **3.4** Wire `SearchConf` acceptance into queries — implemented via
59
- `Logic::BaseQuery#normalize_variables`: auto-calls `.to_h` on any value responding to `to_h`
60
- before passing as GraphQL variables. All queries accept `SearchConf` directly.
61
- *Done 2026-06-07 (commit cc72902)*
62
-
63
- - [ ] **5.1 — Fluent DSL (future):** Replace the explicit constructor API with a fluent
64
- operator-based DSL using Ruby's `&` (AND) and `|` (OR) operators — similar to how
65
- Arel/Sequel work. Proposed syntax:
66
-
67
- ```ruby
68
- # Simple field predicate
69
- Search[:external_id].eq('ABC')
70
- Search[:updated_at].since('2025-01-01')
71
- Search[:state].is(:active)
72
-
73
- # Compound (& = AND, | = OR — operator precedence is natural)
74
- Search[:external_id].eq('ABC') & Search.in_register('REG_ID')
75
-
76
- Search[:state].is(:active) | Search[:state].is(:draft)
77
-
78
- # Complex: register + date AND (state active OR draft)
79
- Search.in_register('REG_ID') &
80
- Search[:updated_at].since('2025-01-01') &
81
- (Search[:state].is(:active) | Search[:state].is(:draft))
82
-
83
- # Parametrize via .with
84
- base = Search[:external_id].eq('X') & Search.in_register('REG')
85
- copy = base.with(external_id: 'Y')
86
- ```
87
-
88
- Implementation: `Search[]` returns a `FieldRef` object; `.eq`, `.is`, `.since`,
89
- `.contains` return filter value objects; `&` and `|` return `And`/`Or` composites.
90
- Everything still serialises via `to_h`. The current explicit API (`SearchConf::Exact.new`)
91
- remains as the foundation — the DSL is a layer on top.
92
-
93
- **Why operator-based over method-chain (`filter.or.attr.label.contains(...)`):**
94
- - `&`/`|` have natural Ruby precedence — parentheses control grouping as expected
95
- - No ambiguity between "start a new filter" vs "modify current filter"
96
- - Composable: any sub-expression can be stored in a variable and reused
97
- - Familiar to developers who know Arel, Sequel, or Mongoid
98
-
99
- **AI-generation hook:** The structured DSL makes AI output easy to validate —
100
- the AI emits `Search[:field].op(value)` expressions that can be parsed/verified
101
- before execution.
102
-
103
- ## ~~Steps 2–4~~ — Done (superseded by implementation)
104
-
105
- Steps 2–4 were planning artefacts written before implementation. All are complete:
106
- - `SearchConf`, `SearchConf::Exact/DateRange/Register/And/Or/RawFilter` — implemented
107
- - `#to_h`, `#with`, `normalize_variables` auto-`to_h` — implemented
108
- - 23 RSpec specs covering all types — implemented
109
- - `search_filters.md` code-spec — implemented
110
- - Fluent DSL (`SearchConf[:field].eq(v)`, `&`, `|`) — implemented 2026-06-08
111
-
112
- ---
113
-
114
- ## Step 5 — AI filter generation
115
-
116
- - [x] **5.1** Prompt template designed — system prompt in `SearchConf::AIGenerator::SYSTEM_PROMPT`:
117
- all 13 operations with params, 11 page fieldNames with types/values, snake_case rule,
118
- instruction to use `date_filter mode:` for relative dates.
119
- *Done 2026-06-09*
120
-
121
- - [x] **5.2** `SearchConf.from_description(text, api_key:, model:, register_id:, context:, validate:)`.
122
- Claude tool use (structured output via `build_search_conf` JSON schema).
123
- `SearchConf::AIGenerator` in `input/search_conf/ai_generator.rb`.
124
- Lazy require — `anthropic` gem not a hard dependency; helpful LoadError if missing.
125
- `.env` loaded automatically in `spec_helper.rb` via dotenv.
126
- Live tests tagged `:live`: `bundle exec rspec ...ai_generator_spec.rb --tag live`
127
- *Done 2026-06-09*
128
-
129
- - [ ] **5.3** Evaluate: compare AI-generated filters against hand-crafted equivalents
130
- using the Insomnia sample set as ground truth. Run live tests, collect outputs,
131
- compare to manually built `SearchConf` instances.
@@ -1,87 +0,0 @@
1
- # Project: Template Automatic Build & Maintenance ★ #1 PRIORITY
2
-
3
- **Status:** ACTIVE — the #1-priority project. **Created:** 2026-07-04 (merges the former
4
- `template-diff-deploy` + `template-maintenance` projects into one plan).
5
- **Domain reference (read first):** `.ai-assistance/code/template_diff_pairing_domain.md`
6
- **Code spec:** `.ai-assistance/code/diff_pairing_engine.md`
7
- **Governing security standard (read before wiring live creds):** `security/ai-service-account-scope`
8
- in ep-ai-standards. This automation MUST authenticate as a dedicated per-org SERVICE ACCOUNT whose
9
- grant covers templates/org-config only -- page records (customer data + PII) are structurally out of
10
- scope, enforced by the credential grant, not by instruction. This is the practitioner discovery point
11
- for that standard (the template automation is its concrete consumer). The "sandbox creds" in success
12
- criterion #4 below must be provisioned to that scope. Platform dependency RESOLVED: templates ARE pages
13
- (`PageUnion`), but `stage.tags` (wrongly deprecated ~21 months ago) has been restored via ecoPortal MR
14
- !6649, so a rule scoped to template stages can structurally exclude record stages. Defining and
15
- provisioning the concrete grant is now OUR work (this gem + agent), not a platform blocker -- see the
16
- service-account grant task in `TODO.md`.
17
- **Superseded folders (pointers only now):** `template-diff-deploy/`, `template-maintenance/`.
18
- **Sibling projects:** `qa-services-delivery` (verify), `ooze-graphql-native-migration`,
19
- `template-csv-pipeline` (memory).
20
-
21
- ---
22
-
23
- ## Why this is one project
24
-
25
- Both former projects are two halves of the SAME lifecycle and share ONE emission layer (an ordered
26
- `WorkflowCommand` batch with `placeholderId` threading applied to `executeWorkflowCommands`):
27
-
28
- - **BUILD** (was `template-maintenance`) — build/maintain 300+ templates programmatically
29
- (CSV→templates pipeline, deadline ~Sept 2026): declare a desired template → emit an ordered command
30
- sequence → apply → read back to verify.
31
- - **MAINTAIN / DIFF-DEPLOY** (was `template-diff-deploy`) — make UAT→PROD change replication smooth:
32
- detect (diff) → review → deploy (delta commands) → verify → monitor, eliminating the two manual
33
- regressions (lost PROD-only changes; premature release of unapproved UAT changes).
34
-
35
- BUILD is "add everything"; DIFF-DEPLOY is "add/remove/edit only the delta". Same command vocabulary,
36
- same id-threading, same apply path. Keeping them as one project keeps the emission layer unified.
37
-
38
- ## The core hard problem (unchanged)
39
-
40
- No stable identity across independent Mongo objects (template vs child page, UAT vs PROD). Self-version
41
- diff (same ids) is trivial and done; cross-object diff is an **equivalence-matching** problem — pair
42
- fields on multiple weak signals (genome + type + label + options), human-assisted for the ambiguous
43
- ones, with a persisted **learning ledger**. See the domain reference for the full failure-mode map.
44
-
45
- ## Approach (confirmed)
46
-
47
- - **Self-version diff first** (done) — the portable "commit".
48
- - **Pairing = equivalence matching**, not identity — multi-signal, confidence-scored, human-in-loop,
49
- ledger-backed (`Diff::Pairing::Engine` + `Ledger`; also feeds Product's Field-ID / template-entity-id).
50
- - **Diff MODALITIES** — a composable family, NOT one diff: `Diff::Strategy` over four axes
51
- (pairing `:id|:genome|:type_label|:assisted` × scope `:structural|:config_only|:data_migration` ×
52
- move-sensitivity × intent `:changelog|:deploy|:sync_readiness`). `VersionDiff` is the `:id`
53
- front-end; `CrossObjectDiff` is the cross-object front-end (pairs fields, emits the SAME `Change`
54
- output against the pairing map, consumed by the existing synthesizer/deploy unchanged).
55
- - **Unified BUILD emitter in the gem** — `Builder::TemplateBuilder` turns a declarative spec into the
56
- ordered `WorkflowCommand` batch (stages→sections→fields→options→config→gauge-stops), threading
57
- `placeholderId`s exactly as `Diff::CommandSynthesizer` does. BUILD and DIFF-DEPLOY share one layer.
58
- - **Layering** — mechanics (read model, command vocab, build emitter, diff, apply, pairing engine +
59
- ledger) live in the gem so admin/troubleshooting/integration/QA all reuse them; orchestration
60
- (interactive assisted-resolution UX, session flows, `TypedFieldsPairing` as an extra signal) is in
61
- eco-helpers.
62
-
63
- ## The pipeline
64
-
65
- ```
66
- BUILD: desired spec ─► TemplateBuilder ─► ordered WorkflowCommands ─► Builder::Template#create/update ─► verify
67
- MAINTAIN: pair (id|genome|type_label|assisted+ledger) ─► diff (modality) ─► delta WorkflowCommands
68
- ─► Deploy#execute! (gated on `unsupported`) ─► verify (ecoportal-qa) ─► monitor (sync-ready)
69
- ```
70
-
71
- ## Scope
72
-
73
- - In: self-version diff (done); genomeSignature exposure (done); pairing engine + ledger (done); diff
74
- modalities/Strategy (done); cross-object diff path (done); Change→WorkflowCommands synthesis (done);
75
- gem-level BUILD emitter (done); UAT→PROD replay; sync-readiness monitoring; CSV→templates pipeline
76
- (later); tighten `ecoportal-qa` to consume the gem's page-model.
77
- - Out: waiting on Product's template-entity-id (we bridge + feed it); auto-applying without human
78
- review of unresolved pairings; workflow-config-per-stage diff until `PagesWorkflow.stages` read model
79
- is completed (see `template-maintenance/PHASE0-FINDINGS.md` §2).
80
-
81
- ## Success criteria
82
-
83
- 1. A ticket's UAT changes are captured exactly and rendered as a review checklist (self-version). ✅
84
- 2. Two templates diff correctly with pairing; unresolved pairings are escalated to a human + remembered. ✅ engine + cross-object path ready; interactive UX pending (eco-helpers).
85
- 3. A reviewed delta deploys to PROD as WorkflowCommands, then is verified (ecoportal-qa) — no regressions.
86
- 4. A template can be BUILT from a declarative spec via one ordered command batch. ✅ emitter ready; live characterization pending (sandbox creds).
87
- 5. Monitoring shows which registers/subsets are sync-ready to their active template.
@@ -1,108 +0,0 @@
1
- # TODOs — Template Automatic Build & Maintenance ★ #1 PRIORITY
2
-
3
- Legend: `[ ]` todo · `[~]` in progress · `[x]` done · `[!]` blocked
4
- Domain reference: `.ai-assistance/code/template_diff_pairing_domain.md`
5
- Code spec: `.ai-assistance/code/diff_pairing_engine.md`
6
-
7
- This merges the former `template-diff-deploy/TODO.md` (MAINTAIN track) and
8
- `template-maintenance/DESIGN.md`+`PHASE0-FINDINGS.md` (BUILD track). BUILD and DIFF-DEPLOY share ONE
9
- emission layer: an ordered `WorkflowCommand` batch with `placeholderId` threading.
10
-
11
- ---
12
-
13
- ## MAINTAIN track (diff → deploy → verify → monitor)
14
-
15
- ### Phase 1 — Self-version diff (same object, exact) ✅ DONE
16
- - [x] `Diff::VersionDiff` — two same-id snapshots → structured changelog (stages/sections/fields/options).
17
- - [x] `Diff::Change` — command-ready (op/kind/id/before/after) + human `#description`.
18
-
19
- ### Phase 2 — Expose genome + Change→commands ✅ DONE
20
- - [x] `genomeSignature` on the data-field fragment + `Base::Page::DataField` (`passthrough`).
21
- - [x] `Diff::CommandSynthesizer` — `[Change]` → ordered built `WorkflowCommand` batch; edit-mode moves
22
- gated on `Diff::IdResolver`; type change / resolver-less move → UNSUPPORTED (never guessed).
23
- - [x] `Diff::Deploy` — `from_versions(before, after, target_doc:)`; `#execute!` gates on `unsupported`.
24
-
25
- ### Phase 3 — Pairing engine (equivalence) ✅ DONE
26
- - [x] `Diff::Pairing::Engine` + `Signals` (genome 0.5 / type 0.2 / label 0.2 / options 0.1), greedy 1:1,
27
- auto-accept ≥0.85 unless near-tie, ambiguous 0.5–0.85, unmatched <0.5; genome fallible (0 not veto).
28
- - [x] `Diff::Pairing::Ledger` — persisted confirmed pairs (consulted first; supersede-on-correct).
29
- - [x] `Engine#confirm!(candidate, matched_by: :human)` assisted-resolution hook.
30
- - [ ] TODO (eco-helpers): interactive assisted-resolution UX; `TypedFieldsPairing` as an extra signal;
31
- live A/B parity harness.
32
-
33
- ### Phase 3b — Gauge-stop + typed byType config emission + placeholderId threading ✅ DONE
34
- - [x] `VersionDiff` emits `:gauge_stop` + `:field_config` (byType, data-driven `BYTYPE_CONFIG`,
35
- conservative — only confirmed read↔byType-key matches; unmappable props NOT fabricated).
36
- - [x] `CommandSynthesizer` maps them; `thread_placeholders:` id-threading primitive (Deploy → on).
37
-
38
- ### Phase 4 — Diff modalities (composable strategies) ✅ DONE 2026-07-04 (branch `feature/template-phase4-modalities-builder-docs`)
39
- - [x] `Diff::Strategy` value object over the four axes: pairing `:id|:genome|:type_label|:assisted` ×
40
- scope `:structural|:config_only|:data_migration` × move-sensitivity × intent
41
- `:changelog|:deploy|:sync_readiness`. Validates axes; `#filter(changes)` applies scope +
42
- move-sensitivity; `.default` reproduces the pre-Phase-4 self-version behaviour EXACTLY (BC).
43
- - [x] `VersionDiff.new(before, after, strategy:)` — the `:id` front-end now filters its computed
44
- change-set through the strategy (default = unchanged; specs prove BC + config_only + move-insensitive).
45
- - [x] `Diff::CrossObjectDiff` — the CROSS-OBJECT front-end: pairs FIELDS via `Pairing::Engine` (+ optional
46
- `Ledger`), builds the id-correspondence map from the ACCEPTED pairs, then emits the SAME `Change`
47
- output (relabel/retype on paired fields; target-only → :added; confidently-unpaired source → :removed).
48
- Ambiguous/unmatched (incl. same-genome relabels + near-ties) are held in `#unresolved` for a human —
49
- NEVER auto-paired, auto-added, or auto-removed. Feeds `CommandSynthesizer`/`Deploy` unchanged.
50
- - [x] `Deploy.from_cross_object(source, target, engine:, strategy:)` + `Deploy#pairing` (exposes
51
- accepted/ambiguous/unmatched for adjudication before apply).
52
- - [x] Specs: `strategy_spec` (16), `cross_object_diff_spec`, `version_diff_modalities_spec`. Full diff
53
- suite 120 examples (was 93; +27). Rubocop clean.
54
-
55
- ### Phase 5 — Deploy + verify + monitor (NEXT)
56
- - [ ] UAT→PROD replay end-to-end: pair → diff → delta commands → apply → verify via `ecoportal-qa`.
57
- - [ ] Pre/post self-version diff on PROD to confirm the recreation matches the intended delta.
58
- - [ ] Sync-readiness monitoring: which registers/subsets can sync to their active template.
59
-
60
- ---
61
-
62
- ## BUILD track (build-from-scratch → verify)
63
-
64
- ### Phase B0 — Study & capture ✅ DONE (see `template-maintenance/PHASE0-FINDINGS.md`)
65
- - [x] `Builder::Template#create/update(commands:)` + `Input::WorkflowCommand` are the apply facade.
66
- - [x] `placeholderId` is the id-threading primitive (client-chosen, resolved intra-batch).
67
- - [x] `tests/dump_template_model.rb` captures a template's structural page doc; reference target
68
- `6a3fa5b8f89e07c758df622b` (needs sandbox creds to run live).
69
-
70
- ### Phase B1 — Gem-level BUILD emitter (unified with diff) ✅ DONE 2026-07-04 (branch `feature/template-phase4-modalities-builder-docs`)
71
- - [x] `Builder::TemplateBuilder` — declarative spec (stages→sections→fields→options→config→gauge-stops)
72
- → ordered `WorkflowCommand` batch, `placeholderId`-threaded. Order: addStage → addSection →
73
- addStageSection → editSectionHeader → addField → addSelectFieldOption / addGaugeFieldStop /
74
- editFieldConfiguration(byType:). Verified against `Builder::Template#create/update(commands:)` + the
75
- real input classes' VALID_KEYS (only valid keys emitted; nothing fabricated — config passed through
76
- under its byType sub-hash exactly as supplied). Shares the SAME `placeholderId` threading concept as
77
- `Diff::CommandSynthesizer`. 13 specs. Rubocop clean.
78
- - [ ] UNSUPPORTED/deferred here (honest): forces/strategies/callbacks/tasks/recipients in a build spec
79
- (the command inputs exist but the build spec shape for them was not confirmed — add per confirmed
80
- shape); `field_type` enum values not validated against the schema (passed through as given).
81
-
82
- ### Phase B2 — Live characterization (NEXT, needs sandbox)
83
- - [ ] Replay `TemplateBuilder` output to reconstruct sample `6a3fa5b8…622b`; assert structure-equivalence
84
- vs the pinned `dump_template_model.rb` fixture. `executeWorkflowCommands` mutates → sandbox, not CI.
85
-
86
- ### Phase B3 — CSV→templates pipeline (later, deadline ~Sept 2026)
87
- - [ ] CSV extract → `TemplateBuilder` spec → build batch, for the 300+ template delivery. Section/field
88
- identity via hidden-field + description (see memory: project-template-csv-pipeline).
89
-
90
- ---
91
-
92
- ## Cross-cutting
93
- - [ ] **Service-account grant (gates live use; governed by ep-ai-standards `security/ai-service-account-scope`).**
94
- This automation must run as a dedicated per-org SERVICE ACCOUNT scoped to templates/org-config only --
95
- page records out of scope, enforced by the grant (structural PII/compliance boundary, not instruction).
96
- Platform enabler is in place: `stage.tags` (wrongly deprecated ~21 months ago) restored via ecoPortal
97
- MR !6649, so a rule scoped to template stages can exclude record stages. OUR remaining work:
98
- (a) enumerate in-scope object types (templates; and which of registers / stages / tag defs / workflow +
99
- automation config / custom-field defs -- explicit in/out per type, each a potential path back to records);
100
- (b) write the concrete `stage.tags` rule and confirm no record stage shares those tags;
101
- (c) fix the read/write surface per type (edit templates? read-only org-config?);
102
- (d) provision the per-org account and confirm its `canXXX` set carries NO page-record capability.
103
- Feeds the "sandbox creds" needed by Phase B2 / Phase 5. Reference: INTENT header + the standard.
104
- - [ ] Tighten `ecoportal-qa` to consume the gem's page-model instead of its own `TemplateModel`.
105
- - [ ] Emit `stageId`/`sectionId` back-refs on diff-side `addField`/`addSection` (BUILD already does;
106
- the diff synthesizer's structural adds still emit only label/placeholder — then threading covers them).
107
- - [ ] Extend `BYTYPE_CONFIG` per field type as read↔byType-key shapes are confirmed; gauge-stop reorder.
108
- - [ ] Complete the `PagesWorkflow.stages` read model to unblock workflow-config-per-stage diff.
@@ -1,12 +0,0 @@
1
- # MOVED → `template-automatic-build-maintenance` ★ #1 PRIORITY
2
-
3
- This project has been **merged** into the unified **Template Automatic Build & Maintenance** project.
4
-
5
- - Single INTENT: `../template-automatic-build-maintenance/INTENT.md`
6
- - Single TODO: `../template-automatic-build-maintenance/TODO.md`
7
-
8
- The MAINTAIN track (diff → deploy → verify → monitor) that lived here is now the "MAINTAIN track"
9
- section of the merged TODO. Nothing here is authoritative any more — do not update this folder.
10
-
11
- Domain reference (unchanged): `.ai-assistance/code/template_diff_pairing_domain.md`.
12
- Code spec (unchanged): `.ai-assistance/code/diff_pairing_engine.md`.
@@ -1,9 +0,0 @@
1
- # MOVED → `template-automatic-build-maintenance/TODO.md`
2
-
3
- The diff/deploy TODOs (Phases 1–5) are now the **MAINTAIN track** of the merged
4
- **Template Automatic Build & Maintenance** project (★ #1 priority):
5
-
6
- → `../template-automatic-build-maintenance/TODO.md`
7
-
8
- Phases 1–3b + Phase 4 (diff modalities: `Diff::Strategy` + `CrossObjectDiff`) are DONE there.
9
- Do not add TODOs here.
@@ -1,134 +0,0 @@
1
- # Template-Maintenance Tooling — Design & Scoping
2
-
3
- **Status:** DESIGN ONLY — not started. Implementation deferred until after the backwards-compat
4
- cutover release. This doc scopes the work so the AI agent (integrations agent) can pick it up.
5
- **Owner:** Oscar. **Drafted:** 2026-07-02.
6
-
7
- ---
8
-
9
- ## Why
10
-
11
- A customer delivery needs **300+ templates** built/maintained programmatically (deadline ~Sept
12
- 2026 for the CSV→templates pipeline). We need a GraphQL-native way to **build and update templates
13
- (workflows)** — create stages/sections/fields/forces/strategies/etc., and later diff a desired
14
- template against a live one and apply only the delta.
15
-
16
- This is a **new, additive** capability. It has **no end-script dependencies** and does **not** touch
17
- the maintained cutover integrations (toocs-coding, cans-upsert, supplier-documents, and Travis's
18
- upcoming mitre10). **OozeRedirect stays for the APIv2-shaped cases.** Template editing needs **no
19
- backwards compatibility** — we rewrite it cleanly, reusing the *ideas* (not the code) proven for
20
- APIv2, and add specs (preventative — see "Testing philosophy").
21
-
22
- Can ship in the **same release** as the cutover fixes as long as it **loads** and **passes the tests
23
- we can gather** (no runtime coupling to existing scripts).
24
-
25
- ---
26
-
27
- ## What already exists (survey, 2026-07-01/02) — this is "extend a pattern", not "build new"
28
-
29
- ### Gem (`ecoportal-api-graphql`) — the mutation surface is largely built
30
- - **91** `input/workflow_command/*.rb` command inputs (stages, sections, fields, forces, bindings,
31
- tasks, strategies, operations, recipients, callbacks, gauge stops, linked fields, select options…).
32
- - `input/workflow_command.rb` — `WorkflowCommand::COMMAND_MAP` registry (`SCHEMA_VERSION`).
33
- - `mutation/page/execute_workflow_commands.rb` — applies a command batch (`executeWorkflowCommands`).
34
- - `query/pages_workflow_commands.rb` + `base/pages_workflow*` — the workflow READ model.
35
- - `base/force.rb` — queues `editForce`/`addBinding` commands (forces ARE mutable via the command-bus;
36
- see `.ai-assistance/code/ecoPortal_architecture/10_forces_workflow_builder.md`).
37
-
38
- ### eco-helpers — the samples space + the diff→commands PRECEDENT
39
- - `lib/eco/api/usecases/graphql/samples/pages/{page,org_page}/{base,dsl}.rb` + `pages/CLAUDE.md` —
40
- the **established sample convention**: each sample is a `base.rb` + `dsl.rb` pair. A template
41
- sample slots in as `samples/pages/template/{base,dsl}.rb`.
42
- - `lib/eco/api/usecases/graphql/samples/location/command/{dsl,service,service/tree_update,results,
43
- track_changed_ids}.rb` + `samples/location/service/tree_diff/convertible/*` — a **working
44
- diff→apply-commands engine** for LOCATION STRUCTURE (which uses `location_structure/apply_commands`
45
- in the gem). This is the architectural precedent to mirror for templates.
46
- - **`track_changed_ids` is the hard part already solved:** newly created nodes get server-assigned
47
- ids that *subsequent* commands must reference (a new stage's id feeds the addSection targeting it).
48
- Template build has the identical id-threading problem — reuse this pattern, don't reinvent it.
49
-
50
- ---
51
-
52
- ## Design: template editing = the location diff→commands engine, retargeted to workflow commands
53
-
54
- Mirror `samples/location/command` + `tree_diff`, but:
55
- - **Target model:** template/workflow (stages → sections → fields → forces/strategies/…) instead of
56
- the location tree.
57
- - **Command vocabulary:** the 91 `WorkflowCommand` inputs instead of location `apply_commands`.
58
- - **Apply mutation:** `executeWorkflowCommands` instead of `applyCommands`.
59
- - **DSL home:** `samples/pages/template/{base,dsl}.rb`, following the existing `page`/`org_page` shape.
60
-
61
- Two capabilities, in order of need:
62
- 1. **Build from scratch** — declare a desired template via the DSL → emit an ordered command sequence
63
- (addStage → addSection → addField → …) → `executeWorkflowCommands`, threading server-assigned ids
64
- between commands (`track_changed_ids` pattern) → read back to verify.
65
- 2. **Diff & update** — read the live template's workflow structure, diff against the desired DSL,
66
- emit only the delta commands (the eventual UAT→PROD `template-diff-deploy` need). Build (1) first;
67
- (2) reuses the same command emitter + the tree_diff approach.
68
-
69
- ---
70
-
71
- ## Reference target (the test/characterization anchor)
72
-
73
- Reconstruct **template sample `6a3fa5b8f89e07c758df622b`** step by step. Capture it once as a pinned
74
- fixture (a `dump_template` tool — extend `tests/dump_page_model.rb`'s approach to fetch the workflow
75
- structure via the `pages_workflow_commands`/`PagesWorkflow` read). Each construction step reproduces
76
- one piece of that sample; the fixture is the golden master to diff against.
77
-
78
- ---
79
-
80
- ## Testing philosophy (aligned with how our devs actually work)
81
-
82
- NOT specs-first-as-design. Specs here are **preventative** (guard against future breakage), matching
83
- the team's practice. Two layers:
84
- 1. **Offline serialization specs (CI-pure, fast):** each `WorkflowCommand` input → correct GraphQL
85
- payload; the command emitter produces the right ordered sequence + id-threading for a given DSL.
86
- Added incrementally as each command type is wired — regression net, not design driver.
87
- 2. **Live characterization harness (sandbox org, NOT CI):** replay the command sequence to reconstruct
88
- sample `6a3fa5b8…622b`, fetch the result, assert structure-equivalence vs the pinned fixture.
89
- `executeWorkflowCommands` mutates server state, so this runs against a sandbox/dev org by hand,
90
- not in CI. Doubles as the regression net for the 300+ template delivery.
91
-
92
- Specs go in **eco-helpers** (for the samples/pages layer) and in the gem (for command serialization).
93
-
94
- ---
95
-
96
- ## Phases
97
-
98
- - **Phase 0 — Study & capture (read-only; no prod writes):** read the two precedents
99
- (`samples/pages/{page,org_page}/{base,dsl}.rb` + `pages/CLAUDE.md`; `samples/location/command` +
100
- `tree_diff`, esp. `track_changed_ids`); build `dump_template` + pin sample `6a3fa5b8…622b`; map which
101
- of the 91 commands the sample needs.
102
- - **Phase 1 — Gem read-back + ergonomic execute facade:** confirm the `PagesWorkflow` read returns a
103
- diff-able structure; ensure `executeWorkflowCommands` has a clean builder facade. Offline command
104
- specs (incremental).
105
- - **Phase 2 — `samples/pages/template/{base,dsl}.rb` (build-from-scratch):** DSL → ordered command
106
- emitter + id-threading → execute → read-back verify.
107
- - **Phase 3 — Characterization suite:** the sandbox replay-the-sample suite (one assertion group per
108
- construction step) vs the Phase 0 fixture.
109
- - **Phase 4 — Diff & update:** read live template, diff vs desired, emit delta commands (reuses the
110
- tree_diff approach). Feeds `template-diff-deploy` (UAT→PROD via changelog).
111
- - **Phase 5 — Ship:** rides the same release; gated only on "loads + passes gathered tests"; no
112
- end-script deps; OozeRedirect untouched.
113
-
114
- ---
115
-
116
- ## Constraints / guardrails
117
- - No runtime coupling to the maintained integrations; OozeRedirect is for APIv2 cases only.
118
- - `WorkflowCommandInput` API is **volatile** — design for change (thin, data-driven command mapping;
119
- keep `SCHEMA_VERSION` in view).
120
- - Prefer capturing verified platform facts in the **shared** knowledge base (not machine-local memory)
121
- — the forces-RCA lesson.
122
-
123
- ## Open questions (for the implementing agent / Oscar)
124
- 1. Sandbox org for the live characterization harness — which org/creds?
125
- 2. Is the `PagesWorkflow` read complete enough to diff a full template, or are there gaps (like the
126
- forces READ query `Query::PageWithForces`, which is WIP)?
127
- 3. Command ordering/dependency rules — is there a canonical order the backend expects, or does
128
- `executeWorkflowCommands` resolve intra-batch references? (drives the id-threading design)
129
- 4. Does `6a3fa5b8…622b` exercise forces? If so, coordinate with the `force_support?` read/write split.
130
-
131
- ## Related
132
- - `.ai-assistance/code/ecoPortal_architecture/10_forces_workflow_builder.md` (command-bus + forces)
133
- - Memory: post-cutover-priorities, project-template-csv-pipeline, project-template-diff-deploy,
134
- project-template-update-architecture, project-workflow-space.
@@ -1,93 +0,0 @@
1
- # Template-Maintenance — Phase 0 Findings (2026-07-02)
2
-
3
- Ground-truth survey of the gem + eco-helpers surface, verified against actual code (not the
4
- DESIGN.md second-hand survey). Corrections to DESIGN.md assumptions are flagged **⚠**.
5
-
6
- ---
7
-
8
- ## 1. The gem mutation surface is MORE complete than DESIGN.md implied
9
-
10
- - **⚠ `Builder::Template` already exists and is wired** (`lib/ecoportal/api/graphql/builder/template.rb`,
11
- exposed as `GraphQL#template`, `graphql.rb:98`). It offers:
12
- `create(commands:)`, `update(model, commands:, patch_ver:)`, `publish(id:)`, `unpublish(id:)`,
13
- `update_information(id:, ...)`, `create_related_page(...)`, `destroy_related_page(...)`.
14
- → The template create/update **apply** step is done. We do **not** need to build a new facade
15
- for `executeWorkflowCommands` on the template side — `Builder::Template#create/update` already
16
- wrap `Mutation::Template::{Create,Update}` with a `commands:` array.
17
- - `Builder::Page#execute_workflow_commands` also exists (per `builder/CLAUDE.md`) for the
18
- page-level workflow command path.
19
- - `Input::WorkflowCommand` (`input/workflow_command.rb`) is the command registry:
20
- **108 commands** in `COMMAND_MAP`, `SCHEMA_VERSION = '20260605'`, with:
21
- - `.build(command_key, **kwargs)` → `{ key => sliced_kwargs }` (validates key, slices to VALID_KEYS, compacts nils, keeps false)
22
- - `.build_commands(specs)` → maps an ordered array of single-key specs into the batch
23
- - `.valid_key?(key)`
24
-
25
- ## 2. A template IS a page (read path)
26
-
27
- - **⚠ DESIGN.md Open Question #2 ("is PagesWorkflow read complete enough to diff a template?")
28
- is partly moot for STRUCTURE.** `Query::Templates` returns `PageUnion` nodes with `PageFields`
29
- — a template is read as an ordinary page. So the structural skeleton
30
- (**stages → sections → components(fields)**) comes from the page model, exactly like a live page.
31
- `dump_template_model.rb` therefore reuses `api.pages.get(id)` for structure.
32
- - The `PagesWorkflow` read model (`base/pages_workflow.rb`) is the **workflow-command config**
33
- layer (callbacks, operations, triggers, strategies, recipients). **⚠ It is partial:** `stages`
34
- is a bare `passarray` (no per-stage strategy/section tree). So:
35
- - **Build-from-scratch (Phase 2): UNBLOCKED.** Emit commands, execute, read the page back to verify.
36
- - **Structural diff (Phase 4): mostly UNBLOCKED** via the page model (stages/sections/fields).
37
- - **Workflow-config diff (callbacks/strategies per stage): BLOCKED** on completing the
38
- `PagesWorkflow.stages` read model. Track as a Phase-4 dependency, not a Phase-2 blocker.
39
- - Forces read is on the page model but `Query::PageWithForces` is WIP (see forces notes) — a
40
- forces-aware diff is a later dependency.
41
-
42
- ## 3. `placeholderId` is the id-threading primitive (the key design fact)
43
-
44
- The location-structure engine threads server-assigned ids **post-hoc** (zip input↔result, extract
45
- `newId`, remap table). **The workflow command bus does NOT need that** — it uses **client-chosen
46
- `placeholderId`s resolved intra-batch**:
47
-
48
- | Command | Placeholder it defines | References (by placeholder or real id) |
49
- |---|---|---|
50
- | `addStage` | `placeholderId` | — |
51
- | `addSection` | `placeholderId` | — |
52
- | `addStageSection` | — | `stageId`, `sectionId` |
53
- | `addField` | `placeholderId` | `stageId`, `sectionId`, `column` |
54
- | `addSelectFieldOption` | `placeholderId` | `dataFieldId` |
55
- | `addForce` | `placeholderId` | — |
56
- | `addBinding` | `placeholderId` | `forceId` |
57
-
58
- → The emitter assigns a stable `placeholderId` to every new node and references it downstream in
59
- the **same batch**. This is simpler than the location `track_changed_ids` remap. **⚠ Correction to
60
- DESIGN.md:** we mirror the location engine's *shape* (DSL → ordered commands → apply → read-back),
61
- but the id-threading is placeholder-based, not `newId`-remap-based.
62
-
63
- **Open question to confirm live:** does `executeWorkflowCommands` resolve placeholderIds across the
64
- *whole* batch, or only within ordering constraints (e.g. must addStage precede addStageSection)?
65
- The emitter already emits in dependency order (stage → section → stageSection → field → option),
66
- so this is safe either way; confirm during the Phase-3 sandbox replay.
67
-
68
- ## 4. What Phase 0 delivered (this commit)
69
-
70
- - `tests/dump_template_model.rb` — captures a template's structural page doc
71
- (`spec/fixtures/templates/<id>.json`) + best-effort workflow command log
72
- (`<id>.commands.json`). Mirrors `dump_page_model.rb`; run `--label before/after` around a batch
73
- to diff. **Reference target:** sample `6a3fa5b8f89e07c758df622b` (needs a live/sandbox org to run).
74
- - `spec/.../input/workflow_command_serialization_spec.rb` — offline serialization contract for the
75
- structural command families + the `build_commands` ordered-emitter shape + placeholderId threading.
76
- 10 examples, green. This is the net the eco-helpers emitter is written against.
77
-
78
- ## 5. Revised phase view
79
-
80
- - **Phase 1 (gem):** DONE-ENOUGH. `Builder::Template` + `Input::WorkflowCommand` are the facade;
81
- offline command specs exist and grow as new command types are exercised.
82
- - **Phase 2 (eco-helpers):** `samples/pages/template/{base,dsl}.rb` + a command-emitter service
83
- (DSL → ordered commands w/ placeholderId threading → `Builder::Template#create/update` → read-back).
84
- Offline emitter specs are fully achievable without live calls.
85
- - **Phase 3 (sandbox):** replay to reconstruct `6a3fa5b8…622b`; assert structure-equivalence vs the
86
- `dump_template_model.rb` fixture. Needs a sandbox org (Open Question #1 — creds TBD).
87
- - **Phase 4 (diff):** structural diff via page model now; workflow-config diff waits on the
88
- `PagesWorkflow.stages` read model.
89
-
90
- ## Open questions still owned by Oscar
91
- 1. Sandbox org + creds for the Phase-3 live characterization harness.
92
- 2. Priority of completing the `PagesWorkflow.stages` read model (gates workflow-config diff).
93
- 3. Does `6a3fa5b8…622b` exercise forces? (gates the forces read/write split for its replay)
@@ -1,14 +0,0 @@
1
- # MOVED → `template-automatic-build-maintenance` ★ #1 PRIORITY
2
-
3
- This project has been **merged** into the unified **Template Automatic Build & Maintenance** project.
4
-
5
- - Single INTENT: `../template-automatic-build-maintenance/INTENT.md`
6
- - Single TODO: `../template-automatic-build-maintenance/TODO.md`
7
-
8
- The BUILD track (build-from-scratch → verify → CSV pipeline) that lived here is now the "BUILD track"
9
- section of the merged TODO. The gem-level BUILD emitter is DONE
10
- (`Builder::TemplateBuilder`, shares the diff's `placeholderId` emission layer).
11
-
12
- `DESIGN.md` and `PHASE0-FINDINGS.md` are RETAINED here as background — the merged INTENT/TODO reference
13
- them for the survey + the `placeholderId` id-threading facts. They are historical context, not the
14
- active task list. Do not add new TODOs here — use the merged TODO.