ecoportal-api-graphql 1.3.10 → 1.3.11
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.
- checksums.yaml +4 -4
- data/.ai-assistance/code/diff_pairing_engine.md +243 -0
- data/.ai-assistance/code/graphql_domain_knowledge.md +20 -10
- data/.ai-assistance/code/template_diff_pairing_domain.md +175 -0
- data/.ai-assistance/code/workflow-command-guide.md +28 -0
- data/.ai-assistance/projects/ooze-graphql-native-migration/INVENTORY.md +136 -0
- data/.ai-assistance/projects/ooze-graphql-native-migration/TODO.md +6 -1
- data/.ai-assistance/projects/qa-services-delivery/DECISIONS.md +93 -0
- data/.ai-assistance/projects/qa-services-delivery/INTENT.md +76 -0
- data/.ai-assistance/projects/qa-services-delivery/PHASE3-SCOPE.md +115 -0
- data/.ai-assistance/projects/qa-services-delivery/ROADMAP.md +99 -0
- data/.ai-assistance/projects/qa-services-delivery/TODO.md +81 -0
- data/.ai-assistance/projects/template-automatic-build-maintenance/INTENT.md +77 -0
- data/.ai-assistance/projects/template-automatic-build-maintenance/TODO.md +97 -0
- data/.ai-assistance/projects/template-diff-deploy/INTENT.md +12 -0
- data/.ai-assistance/projects/template-diff-deploy/TODO.md +9 -0
- data/.ai-assistance/projects/template-maintenance/PHASE0-FINDINGS.md +93 -0
- data/.ai-assistance/projects/template-maintenance/README.md +14 -0
- data/CHANGELOG.md +87 -0
- data/docs/worklog.md +279 -0
- data/ecoportal-api-graphql.gemspec +1 -1
- data/lib/ecoportal/api/graphql/base/page/data_field.rb +1 -1
- data/lib/ecoportal/api/graphql/builder/template_builder.rb +174 -0
- data/lib/ecoportal/api/graphql/builder.rb +17 -16
- data/lib/ecoportal/api/graphql/diff/change.rb +59 -0
- data/lib/ecoportal/api/graphql/diff/command_synthesizer.rb +329 -0
- data/lib/ecoportal/api/graphql/diff/cross_object_diff.rb +165 -0
- data/lib/ecoportal/api/graphql/diff/deploy.rb +121 -0
- data/lib/ecoportal/api/graphql/diff/id_resolver.rb +64 -0
- data/lib/ecoportal/api/graphql/diff/pairing/candidate.rb +32 -0
- data/lib/ecoportal/api/graphql/diff/pairing/engine.rb +173 -0
- data/lib/ecoportal/api/graphql/diff/pairing/ledger.rb +119 -0
- data/lib/ecoportal/api/graphql/diff/pairing/signals.rb +104 -0
- data/lib/ecoportal/api/graphql/diff/strategy.rb +113 -0
- data/lib/ecoportal/api/graphql/diff/version_diff.rb +332 -0
- data/lib/ecoportal/api/graphql/diff.rb +34 -0
- data/lib/ecoportal/api/graphql/fragment/pages/common_page_union.rb +1 -0
- data/lib/ecoportal/api/graphql/input/workflow_command/add_field.rb +27 -18
- data/lib/ecoportal/api/graphql/mutation/action/archive.rb +1 -1
- data/lib/ecoportal/api/graphql/mutation/action/create.rb +1 -1
- data/lib/ecoportal/api/graphql/mutation/action/update.rb +1 -1
- data/lib/ecoportal/api/graphql/mutation/contractor_entity/create.rb +1 -1
- data/lib/ecoportal/api/graphql/mutation/contractor_entity/destroy.rb +1 -1
- data/lib/ecoportal/api/graphql/mutation/contractor_entity/update.rb +1 -1
- data/lib/ecoportal/api/graphql/mutation/kickstand/fail_workflow.rb +1 -1
- data/lib/ecoportal/api/graphql/mutation/kickstand/start_workflow.rb +1 -1
- data/lib/ecoportal/api/graphql/mutation/kickstand/stop_workflow.rb +1 -1
- data/lib/ecoportal/api/graphql.rb +1 -0
- data/lib/ecoportal/api/graphql_version.rb +1 -1
- data/tests/dump_template_model.rb +90 -0
- data/tests/validate_queries.rb +31 -9
- metadata +31 -3
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
require_relative 'local_libs'
|
|
2
|
+
require 'json'
|
|
3
|
+
require 'fileutils'
|
|
4
|
+
|
|
5
|
+
# Dump a TEMPLATE's GraphQL model to JSON, so a real template can be captured as the golden
|
|
6
|
+
# fixture for the template-editing pipeline (build-from-scratch + diff-and-update).
|
|
7
|
+
#
|
|
8
|
+
# A template IS a page in this API (Query::Templates returns PageUnion nodes), so its structural
|
|
9
|
+
# skeleton — stages -> sections -> components(fields) — comes from the ordinary page model, exactly
|
|
10
|
+
# like tests/dump_page_model.rb. On top of that, this tool also captures the page's *workflow
|
|
11
|
+
# command log* (Query::PagesWorkflowCommands) — the applied command history that drives the
|
|
12
|
+
# workflow builder (callbacks / operations / strategies / recipients config).
|
|
13
|
+
#
|
|
14
|
+
# Two artefacts are written per template:
|
|
15
|
+
# spec/fixtures/templates/<id>[_<label>].json -> structural page doc (golden master)
|
|
16
|
+
# spec/fixtures/templates/<id>[_<label>].commands.json -> workflow command log (if readable)
|
|
17
|
+
#
|
|
18
|
+
# Usage (run where the GraphQL connection is configured, like the other tests/):
|
|
19
|
+
# ruby tests/dump_template_model.rb <TEMPLATE_ID> [--out PATH] [--label before|after]
|
|
20
|
+
#
|
|
21
|
+
# Reference target (see .ai-assistance/projects/template-maintenance/DESIGN.md):
|
|
22
|
+
# ruby tests/dump_template_model.rb 6a3fa5b8f89e07c758df622b --label golden
|
|
23
|
+
#
|
|
24
|
+
# Run --label before / --label after around an executeWorkflowCommands batch to diff exactly
|
|
25
|
+
# what a command sequence changed — the same before/after workflow dump_page_model.rb enables.
|
|
26
|
+
|
|
27
|
+
def parse_args(argv)
|
|
28
|
+
opts = { template_id: nil, out: nil, label: nil }
|
|
29
|
+
rest = argv.dup
|
|
30
|
+
opts[:template_id] = rest.shift
|
|
31
|
+
until rest.empty?
|
|
32
|
+
flag = rest.shift
|
|
33
|
+
case flag
|
|
34
|
+
when '--out' then opts[:out] = rest.shift
|
|
35
|
+
when '--label' then opts[:label] = rest.shift
|
|
36
|
+
else
|
|
37
|
+
warn "Unknown argument: #{flag}"
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
opts
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
opts = parse_args(ARGV)
|
|
44
|
+
|
|
45
|
+
unless opts[:template_id]
|
|
46
|
+
warn 'Usage: ruby tests/dump_template_model.rb <TEMPLATE_ID> [--out PATH] [--label before|after]'
|
|
47
|
+
exit 1
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
default_dir = File.expand_path('../spec/fixtures/templates', __dir__)
|
|
51
|
+
default_name = [opts[:template_id], opts[:label]].compact.join('_')
|
|
52
|
+
struct_path = opts[:out] || File.join(default_dir, "#{default_name}.json")
|
|
53
|
+
commands_path = File.join(File.dirname(struct_path), "#{File.basename(struct_path, '.json')}.commands.json")
|
|
54
|
+
|
|
55
|
+
api = Ecoportal::API::GraphQL.new
|
|
56
|
+
|
|
57
|
+
# 1) Structural skeleton — a template is a page, so fetch it via the page model.
|
|
58
|
+
page = api.pages.get(opts[:template_id])
|
|
59
|
+
|
|
60
|
+
if page.nil?
|
|
61
|
+
warn "Could not fetch template '#{opts[:template_id]}' as a page"
|
|
62
|
+
exit 2
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
doc = page.respond_to?(:doc) ? page.doc : page.instance_variable_get(:@page)&.doc
|
|
66
|
+
|
|
67
|
+
FileUtils.mkdir_p(File.dirname(struct_path))
|
|
68
|
+
File.write(struct_path, JSON.pretty_generate(doc))
|
|
69
|
+
|
|
70
|
+
puts "Dumped template structure '#{opts[:template_id]}' -> #{struct_path}"
|
|
71
|
+
puts " name: #{page.respond_to?(:name) ? page.name : '(n/a)'}"
|
|
72
|
+
puts " patchVer: #{page.respond_to?(:patchVer) ? page.patchVer : '(n/a)'}"
|
|
73
|
+
|
|
74
|
+
# 2) Workflow command log — the applied-command history behind the workflow builder.
|
|
75
|
+
# Wrapped in a rescue: the PagesWorkflow read model is still partial (stages is a bare
|
|
76
|
+
# passarray as of SCHEMA_VERSION 20260605), so treat this as best-effort.
|
|
77
|
+
begin
|
|
78
|
+
query = Ecoportal::API::GraphQL::Query::PagesWorkflowCommands.new(api.client)
|
|
79
|
+
commands = []
|
|
80
|
+
query.each(id: opts[:template_id], first: 100) do |cmd|
|
|
81
|
+
commands << (cmd.respond_to?(:doc) ? cmd.doc : cmd)
|
|
82
|
+
end
|
|
83
|
+
File.write(commands_path, JSON.pretty_generate(commands))
|
|
84
|
+
puts "Dumped #{commands.size} workflow command(s) -> #{commands_path}"
|
|
85
|
+
rescue StandardError => e
|
|
86
|
+
warn "Workflow command log not captured (#{e.class}: #{e.message})"
|
|
87
|
+
warn ' -> structural fixture is still valid; the command log read may be WIP for this org.'
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
puts 'Tip: capture --label before and --label after an executeWorkflowCommands batch, then diff the JSON.'
|
data/tests/validate_queries.rb
CHANGED
|
@@ -41,8 +41,12 @@ client = Ecoportal::API::Common::GraphQL::Client.new(
|
|
|
41
41
|
)
|
|
42
42
|
schema = GraphQL::Schema.from_introspection(JSON.parse(File.read(schema_path)))
|
|
43
43
|
|
|
44
|
-
# Collect every concrete query class (recursively, incl. nested like
|
|
45
|
-
|
|
44
|
+
# Collect every concrete query AND mutation class (recursively, incl. nested like
|
|
45
|
+
# LocationStructure::Draft). Mutations are included because a dead fragment reference (e.g. the
|
|
46
|
+
# removed `___Const__Fragment` convention) only surfaces when the operation is RENDERED — and
|
|
47
|
+
# mutations were previously unscanned, which is exactly how the Action/ContractorEntity mutation
|
|
48
|
+
# fragment breakage reached production undetected.
|
|
49
|
+
op_classes = []
|
|
46
50
|
collect = lambda do |mod|
|
|
47
51
|
mod.constants.each do |const|
|
|
48
52
|
obj = begin
|
|
@@ -52,20 +56,31 @@ collect = lambda do |mod|
|
|
|
52
56
|
end
|
|
53
57
|
next unless obj.is_a?(Module)
|
|
54
58
|
|
|
55
|
-
|
|
59
|
+
op_classes << obj if obj.is_a?(Class) && obj.private_method_defined?(:basic_block)
|
|
56
60
|
collect.call(obj)
|
|
57
61
|
end
|
|
58
62
|
end
|
|
59
63
|
collect.call(Ecoportal::API::GraphQL::Query)
|
|
60
|
-
|
|
64
|
+
collect.call(Ecoportal::API::GraphQL::Mutation)
|
|
65
|
+
op_classes.uniq!
|
|
61
66
|
|
|
62
67
|
structural_bugs = {}
|
|
63
68
|
other_errors = {}
|
|
69
|
+
render_failures = {}
|
|
64
70
|
render_skips = []
|
|
65
71
|
|
|
66
|
-
|
|
72
|
+
op_classes.sort_by(&:name).each do |klass|
|
|
67
73
|
inst = klass.new(client)
|
|
68
|
-
|
|
74
|
+
begin
|
|
75
|
+
query_str = client.to_query_string(&inst.send(:basic_block))
|
|
76
|
+
rescue NameError => e
|
|
77
|
+
# The operation cannot even RENDER — an unresolved constant / dead fragment reference
|
|
78
|
+
# (e.g. the removed `___Const__Fragment` convention pointing at a Fragment:: constant that
|
|
79
|
+
# no longer exists now that fragments are a registry). Same bug class that crashed the live
|
|
80
|
+
# LocationDraft / Action / ContractorEntity paths. HARD FAIL.
|
|
81
|
+
render_failures[klass.name] = ["#{e.class}: #{e.message}"]
|
|
82
|
+
next
|
|
83
|
+
end
|
|
69
84
|
fragments = begin
|
|
70
85
|
inst.send(:assemble_fragments, query_str)
|
|
71
86
|
rescue StandardError
|
|
@@ -81,9 +96,16 @@ rescue StandardError => e
|
|
|
81
96
|
render_skips << "#{klass.name} — #{e.class}: #{e.message}"
|
|
82
97
|
end
|
|
83
98
|
|
|
84
|
-
puts "Validated #{
|
|
99
|
+
puts "Validated #{op_classes.size} query + mutation classes against #{File.basename(schema_path)}\n\n"
|
|
100
|
+
|
|
101
|
+
puts '## FRAGMENT / RENDER FAILURES (fail the build — operation could not render, e.g. dead fragment ref):'
|
|
102
|
+
if render_failures.empty?
|
|
103
|
+
puts ' none ✅'
|
|
104
|
+
else
|
|
105
|
+
render_failures.each { |name, msgs| puts " #{name}\n - #{msgs.join("\n - ")}" }
|
|
106
|
+
end
|
|
85
107
|
|
|
86
|
-
puts
|
|
108
|
+
puts "\n## STRUCTURAL BUGS (fail the build — bare object / over-selected scalar):"
|
|
87
109
|
if structural_bugs.empty?
|
|
88
110
|
puts ' none ✅'
|
|
89
111
|
else
|
|
@@ -102,4 +124,4 @@ unless render_skips.empty?
|
|
|
102
124
|
render_skips.each { |s| puts " #{s}" }
|
|
103
125
|
end
|
|
104
126
|
|
|
105
|
-
exit(structural_bugs.empty? ? 0 : 1)
|
|
127
|
+
exit(structural_bugs.empty? && render_failures.empty? ? 0 : 1)
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: ecoportal-api-graphql
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 1.3.
|
|
4
|
+
version: 1.3.11
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Oscar Segura
|
|
@@ -160,7 +160,7 @@ dependencies:
|
|
|
160
160
|
version: '3.3'
|
|
161
161
|
- - ">="
|
|
162
162
|
- !ruby/object:Gem::Version
|
|
163
|
-
version: 3.3.
|
|
163
|
+
version: 3.3.3
|
|
164
164
|
type: :runtime
|
|
165
165
|
prerelease: false
|
|
166
166
|
version_requirements: !ruby/object:Gem::Requirement
|
|
@@ -170,7 +170,7 @@ dependencies:
|
|
|
170
170
|
version: '3.3'
|
|
171
171
|
- - ">="
|
|
172
172
|
- !ruby/object:Gem::Version
|
|
173
|
-
version: 3.3.
|
|
173
|
+
version: 3.3.3
|
|
174
174
|
- !ruby/object:Gem::Dependency
|
|
175
175
|
name: graphlient
|
|
176
176
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -219,6 +219,7 @@ files:
|
|
|
219
219
|
- ".ai-assistance/code/data_fields.md"
|
|
220
220
|
- ".ai-assistance/code/dependencies.md"
|
|
221
221
|
- ".ai-assistance/code/diff_as_input.md"
|
|
222
|
+
- ".ai-assistance/code/diff_pairing_engine.md"
|
|
222
223
|
- ".ai-assistance/code/diff_service_deep_dive.md"
|
|
223
224
|
- ".ai-assistance/code/ecoPortal_architecture/00_overview_and_index.md"
|
|
224
225
|
- ".ai-assistance/code/ecoPortal_architecture/01_terminology_dictionary.md"
|
|
@@ -241,6 +242,7 @@ files:
|
|
|
241
242
|
- ".ai-assistance/code/schema_analysis.md"
|
|
242
243
|
- ".ai-assistance/code/search_filters.md"
|
|
243
244
|
- ".ai-assistance/code/spec_coverage.md"
|
|
245
|
+
- ".ai-assistance/code/template_diff_pairing_domain.md"
|
|
244
246
|
- ".ai-assistance/code/workflow-command-guide.md"
|
|
245
247
|
- ".ai-assistance/code/workflow-space.md"
|
|
246
248
|
- ".ai-assistance/conventions/CLAUDE.md"
|
|
@@ -267,15 +269,27 @@ files:
|
|
|
267
269
|
- ".ai-assistance/projects/graphql-agent/GAP_ANALYSIS.md"
|
|
268
270
|
- ".ai-assistance/projects/ooze-graphql-native-migration/DECISIONS.md"
|
|
269
271
|
- ".ai-assistance/projects/ooze-graphql-native-migration/INTENT.md"
|
|
272
|
+
- ".ai-assistance/projects/ooze-graphql-native-migration/INVENTORY.md"
|
|
270
273
|
- ".ai-assistance/projects/ooze-graphql-native-migration/RISKS.md"
|
|
271
274
|
- ".ai-assistance/projects/ooze-graphql-native-migration/TODO.md"
|
|
272
275
|
- ".ai-assistance/projects/ooze-graphql-native-migration/analysis/2026-06-30-cutover-workflow-deep-review.md"
|
|
273
276
|
- ".ai-assistance/projects/ooze-graphql-native-migration/analysis/2026-07-01-forces-via-workflow-commands-miss-rca.md"
|
|
274
277
|
- ".ai-assistance/projects/page-model/DECISIONS.md"
|
|
275
278
|
- ".ai-assistance/projects/page-model/TODO.md"
|
|
279
|
+
- ".ai-assistance/projects/qa-services-delivery/DECISIONS.md"
|
|
280
|
+
- ".ai-assistance/projects/qa-services-delivery/INTENT.md"
|
|
281
|
+
- ".ai-assistance/projects/qa-services-delivery/PHASE3-SCOPE.md"
|
|
282
|
+
- ".ai-assistance/projects/qa-services-delivery/ROADMAP.md"
|
|
283
|
+
- ".ai-assistance/projects/qa-services-delivery/TODO.md"
|
|
276
284
|
- ".ai-assistance/projects/search-filter-builder/INTENT.md"
|
|
277
285
|
- ".ai-assistance/projects/search-filter-builder/TODO.md"
|
|
286
|
+
- ".ai-assistance/projects/template-automatic-build-maintenance/INTENT.md"
|
|
287
|
+
- ".ai-assistance/projects/template-automatic-build-maintenance/TODO.md"
|
|
288
|
+
- ".ai-assistance/projects/template-diff-deploy/INTENT.md"
|
|
289
|
+
- ".ai-assistance/projects/template-diff-deploy/TODO.md"
|
|
278
290
|
- ".ai-assistance/projects/template-maintenance/DESIGN.md"
|
|
291
|
+
- ".ai-assistance/projects/template-maintenance/PHASE0-FINDINGS.md"
|
|
292
|
+
- ".ai-assistance/projects/template-maintenance/README.md"
|
|
279
293
|
- ".ai-assistance/projects/workflow-space/TODO.md"
|
|
280
294
|
- ".ai-assistance/reinstall-claude-desktop-windows.md"
|
|
281
295
|
- ".ai-assistance/scripts/CLAUDE.md"
|
|
@@ -449,6 +463,7 @@ files:
|
|
|
449
463
|
- lib/ecoportal/api/graphql/builder/register.rb
|
|
450
464
|
- lib/ecoportal/api/graphql/builder/register/preset_view.rb
|
|
451
465
|
- lib/ecoportal/api/graphql/builder/template.rb
|
|
466
|
+
- lib/ecoportal/api/graphql/builder/template_builder.rb
|
|
452
467
|
- lib/ecoportal/api/graphql/compat.rb
|
|
453
468
|
- lib/ecoportal/api/graphql/compat/filter_translator.rb
|
|
454
469
|
- lib/ecoportal/api/graphql/compat/page_reference.rb
|
|
@@ -473,6 +488,18 @@ files:
|
|
|
473
488
|
- lib/ecoportal/api/graphql/connection/person_member.rb
|
|
474
489
|
- lib/ecoportal/api/graphql/connection/preset_view.rb
|
|
475
490
|
- lib/ecoportal/api/graphql/connection/preview_page.rb
|
|
491
|
+
- lib/ecoportal/api/graphql/diff.rb
|
|
492
|
+
- lib/ecoportal/api/graphql/diff/change.rb
|
|
493
|
+
- lib/ecoportal/api/graphql/diff/command_synthesizer.rb
|
|
494
|
+
- lib/ecoportal/api/graphql/diff/cross_object_diff.rb
|
|
495
|
+
- lib/ecoportal/api/graphql/diff/deploy.rb
|
|
496
|
+
- lib/ecoportal/api/graphql/diff/id_resolver.rb
|
|
497
|
+
- lib/ecoportal/api/graphql/diff/pairing/candidate.rb
|
|
498
|
+
- lib/ecoportal/api/graphql/diff/pairing/engine.rb
|
|
499
|
+
- lib/ecoportal/api/graphql/diff/pairing/ledger.rb
|
|
500
|
+
- lib/ecoportal/api/graphql/diff/pairing/signals.rb
|
|
501
|
+
- lib/ecoportal/api/graphql/diff/strategy.rb
|
|
502
|
+
- lib/ecoportal/api/graphql/diff/version_diff.rb
|
|
476
503
|
- lib/ecoportal/api/graphql/error.rb
|
|
477
504
|
- lib/ecoportal/api/graphql/error/locations_error.rb
|
|
478
505
|
- lib/ecoportal/api/graphql/error/locations_error/fetch_nested.rb
|
|
@@ -826,6 +853,7 @@ files:
|
|
|
826
853
|
- tests/contractor_entity_create.rb
|
|
827
854
|
- tests/contractor_entity_udpate.rb
|
|
828
855
|
- tests/dump_page_model.rb
|
|
856
|
+
- tests/dump_template_model.rb
|
|
829
857
|
- tests/loc_structure_get.rb
|
|
830
858
|
- tests/loc_structure_update.rb
|
|
831
859
|
- tests/loc_structures_get.rb
|