ecoportal-api-graphql 1.3.10 → 1.3.12

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 (86) hide show
  1. checksums.yaml +4 -4
  2. data/.ai-assistance/code/diff_pairing_engine.md +243 -0
  3. data/.ai-assistance/code/filter_contract_matrix.md +177 -0
  4. data/.ai-assistance/code/graphql_domain_knowledge.md +20 -10
  5. data/.ai-assistance/code/template_diff_pairing_domain.md +175 -0
  6. data/.ai-assistance/code/workflow-command-guide.md +28 -0
  7. data/.ai-assistance/projects/ooze-graphql-native-migration/INVENTORY.md +136 -0
  8. data/.ai-assistance/projects/ooze-graphql-native-migration/TODO.md +6 -1
  9. data/.ai-assistance/projects/qa-services-delivery/DECISIONS.md +93 -0
  10. data/.ai-assistance/projects/qa-services-delivery/INTENT.md +76 -0
  11. data/.ai-assistance/projects/qa-services-delivery/PHASE3-SCOPE.md +115 -0
  12. data/.ai-assistance/projects/qa-services-delivery/ROADMAP.md +99 -0
  13. data/.ai-assistance/projects/qa-services-delivery/TODO.md +81 -0
  14. data/.ai-assistance/projects/template-automatic-build-maintenance/INTENT.md +87 -0
  15. data/.ai-assistance/projects/template-automatic-build-maintenance/TODO.md +108 -0
  16. data/.ai-assistance/projects/template-diff-deploy/INTENT.md +12 -0
  17. data/.ai-assistance/projects/template-diff-deploy/TODO.md +9 -0
  18. data/.ai-assistance/projects/template-maintenance/PHASE0-FINDINGS.md +93 -0
  19. data/.ai-assistance/projects/template-maintenance/README.md +14 -0
  20. data/.ai-assistance/skills/procedural-memory/SKILL.md +319 -0
  21. data/.ai-assistance/standards-version.json +21 -20
  22. data/CHANGELOG.md +119 -0
  23. data/CLAUDE.md +10 -0
  24. data/docs/self-docs/ARCHITECTURE.md +88 -0
  25. data/docs/self-docs/CHANGES.jsonl +7 -0
  26. data/docs/self-docs/CONVENTIONS.md +74 -0
  27. data/docs/self-docs/INTEGRATIONS.md +63 -0
  28. data/docs/self-docs/OVERVIEW.md +51 -0
  29. data/docs/self-docs/STATUS.md +69 -0
  30. data/docs/self-docs/self-docs-index.json +39 -0
  31. data/docs/worklog.md +256 -0
  32. data/ecoportal-api-graphql.gemspec +1 -1
  33. data/lib/ecoportal/api/common/graphql/model/diffable.rb +54 -54
  34. data/lib/ecoportal/api/graphql/base/action.rb +43 -43
  35. data/lib/ecoportal/api/graphql/base/contractor_entity/member_changes.rb +67 -67
  36. data/lib/ecoportal/api/graphql/base/page/data_field/collection.rb +7 -0
  37. data/lib/ecoportal/api/graphql/base/page/data_field/contractor_entities.rb +28 -28
  38. data/lib/ecoportal/api/graphql/base/page/data_field/file_field.rb +25 -25
  39. data/lib/ecoportal/api/graphql/base/page/data_field/image_gallery.rb +24 -24
  40. data/lib/ecoportal/api/graphql/base/page/data_field.rb +1 -1
  41. data/lib/ecoportal/api/graphql/base/page/section_collection.rb +85 -79
  42. data/lib/ecoportal/api/graphql/base/preset_view.rb +17 -17
  43. data/lib/ecoportal/api/graphql/base/register.rb +18 -18
  44. data/lib/ecoportal/api/graphql/builder/template_builder.rb +174 -0
  45. data/lib/ecoportal/api/graphql/builder.rb +17 -16
  46. data/lib/ecoportal/api/graphql/compat/filter_translator.rb +63 -28
  47. data/lib/ecoportal/api/graphql/concerns/page_compat.rb +51 -51
  48. data/lib/ecoportal/api/graphql/concerns.rb +14 -14
  49. data/lib/ecoportal/api/graphql/diff/change.rb +59 -0
  50. data/lib/ecoportal/api/graphql/diff/command_synthesizer.rb +329 -0
  51. data/lib/ecoportal/api/graphql/diff/cross_object_diff.rb +165 -0
  52. data/lib/ecoportal/api/graphql/diff/deploy.rb +121 -0
  53. data/lib/ecoportal/api/graphql/diff/id_resolver.rb +64 -0
  54. data/lib/ecoportal/api/graphql/diff/pairing/candidate.rb +32 -0
  55. data/lib/ecoportal/api/graphql/diff/pairing/engine.rb +173 -0
  56. data/lib/ecoportal/api/graphql/diff/pairing/ledger.rb +119 -0
  57. data/lib/ecoportal/api/graphql/diff/pairing/signals.rb +104 -0
  58. data/lib/ecoportal/api/graphql/diff/strategy.rb +113 -0
  59. data/lib/ecoportal/api/graphql/diff/version_diff.rb +332 -0
  60. data/lib/ecoportal/api/graphql/diff.rb +34 -0
  61. data/lib/ecoportal/api/graphql/file_upload/client.rb +181 -181
  62. data/lib/ecoportal/api/graphql/fragment/page.rb +85 -85
  63. data/lib/ecoportal/api/graphql/fragment/pages/common_page_union.rb +1 -0
  64. data/lib/ecoportal/api/graphql/input/action/update.rb +14 -14
  65. data/lib/ecoportal/api/graphql/input/contractor_entity/update.rb +41 -41
  66. data/lib/ecoportal/api/graphql/input/location_structure/apply_commands.rb +47 -47
  67. data/lib/ecoportal/api/graphql/input/location_structure/draft/add_commands.rb +49 -49
  68. data/lib/ecoportal/api/graphql/input/location_structure/update_command.rb +27 -27
  69. data/lib/ecoportal/api/graphql/input/search_conf.rb +436 -367
  70. data/lib/ecoportal/api/graphql/input/workflow_command/add_field.rb +27 -18
  71. data/lib/ecoportal/api/graphql/interface/location_structure/command.rb +30 -30
  72. data/lib/ecoportal/api/graphql/logic/input.rb +26 -26
  73. data/lib/ecoportal/api/graphql/mutation/action/archive.rb +1 -1
  74. data/lib/ecoportal/api/graphql/mutation/action/create.rb +1 -1
  75. data/lib/ecoportal/api/graphql/mutation/action/update.rb +1 -1
  76. data/lib/ecoportal/api/graphql/mutation/contractor_entity/create.rb +1 -1
  77. data/lib/ecoportal/api/graphql/mutation/contractor_entity/destroy.rb +1 -1
  78. data/lib/ecoportal/api/graphql/mutation/contractor_entity/update.rb +1 -1
  79. data/lib/ecoportal/api/graphql/mutation/kickstand/fail_workflow.rb +1 -1
  80. data/lib/ecoportal/api/graphql/mutation/kickstand/start_workflow.rb +1 -1
  81. data/lib/ecoportal/api/graphql/mutation/kickstand/stop_workflow.rb +1 -1
  82. data/lib/ecoportal/api/graphql.rb +1 -0
  83. data/lib/ecoportal/api/graphql_version.rb +1 -1
  84. data/tests/dump_template_model.rb +90 -0
  85. data/tests/validate_queries.rb +31 -9
  86. metadata +40 -3
@@ -1,18 +1,27 @@
1
- module Ecoportal
2
- module API
3
- class GraphQL
4
- module Input
5
- class WorkflowCommand
6
- module AddField
7
- SCHEMA_VERSION = '20260605'.freeze
8
- VALID_KEYS = %i[placeholderId fieldType label stageId sectionId column].freeze
9
-
10
- def self.build(**kwargs)
11
- kwargs.slice(*VALID_KEYS).compact
12
- end
13
- end
14
- end
15
- end
16
- end
17
- end
18
- end
1
+ module Ecoportal
2
+ module API
3
+ class GraphQL
4
+ module Input
5
+ class WorkflowCommand
6
+ module AddField
7
+ SCHEMA_VERSION = '20260605'.freeze
8
+ # VERIFIED against the live schema dump (WorkflowAddFieldInput, 20260605): the create
9
+ # command accepts ONLY these keys. There is NO `description` and NO `required` field on
10
+ # WorkflowAddFieldInput. `description` is instead a top-level key of
11
+ # WorkflowEditFieldConfigurationInput, so a field's description is persisted via a
12
+ # follow-up editFieldConfiguration command (see Builder::TemplateBuilder /
13
+ # Diff::CommandSynthesizer). `required` has NO input key anywhere in the schema (not on
14
+ # AddField, not on editFieldConfiguration top-level or any byType sub-input) and so
15
+ # cannot be persisted through the workflow command bus at all — callers must treat it as
16
+ # a read-only/unsupported attribute. Do NOT add these keys here (the server rejects them).
17
+ VALID_KEYS = %i[placeholderId fieldType label stageId sectionId column].freeze
18
+
19
+ def self.build(**kwargs)
20
+ kwargs.slice(*VALID_KEYS).compact
21
+ end
22
+ end
23
+ end
24
+ end
25
+ end
26
+ end
27
+ end
@@ -1,30 +1,30 @@
1
- module Ecoportal
2
- module API
3
- class GraphQL
4
- module Interface
5
- module LocationStructure
6
- class Command < Logic::BaseModel
7
- passkey :id
8
- passthrough :state
9
-
10
- def target_ids
11
- (doc || {}).values_at(:nodeId, :newId, :id)
12
- end
13
-
14
- def keys
15
- (doc || {}).keys
16
- end
17
-
18
- def set_values(**kargs)
19
- kargs.each do |key, value|
20
- send(key, value) if respond_to?(key, true)
21
- end
22
-
23
- self
24
- end
25
- end
26
- end
27
- end
28
- end
29
- end
30
- end
1
+ module Ecoportal
2
+ module API
3
+ class GraphQL
4
+ module Interface
5
+ module LocationStructure
6
+ class Command < Logic::BaseModel
7
+ passkey :id
8
+ passthrough :state
9
+
10
+ def target_ids
11
+ (doc || {}).values_at(:nodeId, :newId, :id)
12
+ end
13
+
14
+ def keys
15
+ (doc || {}).keys
16
+ end
17
+
18
+ def set_values(**kargs)
19
+ kargs.each do |key, value|
20
+ send(key, value) if respond_to?(key, true)
21
+ end
22
+
23
+ self
24
+ end
25
+ end
26
+ end
27
+ end
28
+ end
29
+ end
30
+ end
@@ -1,26 +1,26 @@
1
- module Ecoportal
2
- module API
3
- class GraphQL
4
- module Logic
5
- class Input < Logic::BaseModel
6
- passthrough :clientMutationId
7
-
8
- class << self
9
- # Builds a mutation input hash from a model's diff.
10
- # Subclasses override this to reshape fields (e.g. array → IdDiffInput).
11
- # @param model [Common::GraphQL::Model] the subject model.
12
- # @return [Hash, nil] the mutation input hash, or nil when there are no changes.
13
- def from_model(model, client_mutation_id: '')
14
- diff = model.as_update
15
- return nil if diff.nil?
16
-
17
- diff[:patchVer] = model.patchVer if model.respond_to?(:patchVer) && !model.patchVer.nil?
18
- diff[:clientMutationId] = client_mutation_id unless client_mutation_id.to_s.empty?
19
- diff
20
- end
21
- end
22
- end
23
- end
24
- end
25
- end
26
- end
1
+ module Ecoportal
2
+ module API
3
+ class GraphQL
4
+ module Logic
5
+ class Input < Logic::BaseModel
6
+ passthrough :clientMutationId
7
+
8
+ class << self
9
+ # Builds a mutation input hash from a model's diff.
10
+ # Subclasses override this to reshape fields (e.g. array → IdDiffInput).
11
+ # @param model [Common::GraphQL::Model] the subject model.
12
+ # @return [Hash, nil] the mutation input hash, or nil when there are no changes.
13
+ def from_model(model, client_mutation_id: '')
14
+ diff = model.as_update
15
+ return nil if diff.nil?
16
+
17
+ diff[:patchVer] = model.patchVer if model.respond_to?(:patchVer) && !model.patchVer.nil?
18
+ diff[:clientMutationId] = client_mutation_id unless client_mutation_id.to_s.empty?
19
+ diff
20
+ end
21
+ end
22
+ end
23
+ end
24
+ end
25
+ end
26
+ end
@@ -29,7 +29,7 @@ module Ecoportal
29
29
  fullMessages
30
30
  }
31
31
  item {
32
- ___Fragment__Action
32
+ spread :Action
33
33
  }
34
34
  }
35
35
  end
@@ -28,7 +28,7 @@ module Ecoportal
28
28
  fullMessages
29
29
  }
30
30
  item {
31
- ___Fragment__Action
31
+ spread :Action
32
32
  }
33
33
  }
34
34
  end
@@ -28,7 +28,7 @@ module Ecoportal
28
28
  fullMessages
29
29
  }
30
30
  item {
31
- ___Fragment__Action
31
+ spread :Action
32
32
  }
33
33
  }
34
34
  end
@@ -28,7 +28,7 @@ module Ecoportal
28
28
  fullMessages
29
29
  }
30
30
  item {
31
- ___Fragment__ContractorEntity
31
+ spread :ContractorEntity
32
32
  }
33
33
  }
34
34
  end
@@ -28,7 +28,7 @@ module Ecoportal
28
28
  fullMessages
29
29
  }
30
30
  item {
31
- ___Fragment__ContractorEntity
31
+ spread :ContractorEntity
32
32
  }
33
33
  }
34
34
  end
@@ -28,7 +28,7 @@ module Ecoportal
28
28
  fullMessages
29
29
  }
30
30
  item {
31
- ___Fragment__ContractorEntity
31
+ spread :ContractorEntity
32
32
  }
33
33
  }
34
34
  end
@@ -27,7 +27,7 @@ module Ecoportal
27
27
 
28
28
  def default_payload_block
29
29
  proc {
30
- item { id name status failedAt }
30
+ item { id name status failedAt { dateTime timeZone } }
31
31
  errors { details fullMessages }
32
32
  }
33
33
  end
@@ -27,7 +27,7 @@ module Ecoportal
27
27
 
28
28
  def default_payload_block
29
29
  proc {
30
- item { id name status startedAt }
30
+ item { id name status startedAt { dateTime timeZone } }
31
31
  errors { details fullMessages }
32
32
  }
33
33
  end
@@ -27,7 +27,7 @@ module Ecoportal
27
27
 
28
28
  def default_payload_block
29
29
  proc {
30
- item { id name status stoppedAt }
30
+ item { id name status stoppedAt { dateTime timeZone } }
31
31
  errors { details fullMessages }
32
32
  }
33
33
  end
@@ -136,3 +136,4 @@ require_relative 'graphql/mutation'
136
136
  require_relative 'graphql/builder'
137
137
  require_relative 'graphql/compat'
138
138
  require_relative 'graphql/file_upload'
139
+ require_relative 'graphql/diff'
@@ -1,5 +1,5 @@
1
1
  module Ecoportal
2
2
  module API
3
- GRAPQL_VERSION = '1.3.10'.freeze
3
+ GRAPQL_VERSION = '1.3.12'.freeze
4
4
  end
5
5
  end
@@ -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.'
@@ -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 LocationStructure::Draft).
45
- query_classes = []
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
- query_classes << obj if obj.is_a?(Class) && obj.private_method_defined?(:basic_block)
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
- query_classes.uniq!
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
- query_classes.sort_by(&:name).each do |klass|
72
+ op_classes.sort_by(&:name).each do |klass|
67
73
  inst = klass.new(client)
68
- query_str = client.to_query_string(&inst.send(:basic_block))
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 #{query_classes.size} query classes against #{File.basename(schema_path)}\n\n"
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 '## STRUCTURAL BUGS (fail the build — bare object / over-selected scalar):'
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.10
4
+ version: 1.3.12
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.2
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.2
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"
@@ -235,12 +236,14 @@ files:
235
236
  - ".ai-assistance/code/ecoPortal_architecture/12_ai_documentation_sources_gaps.md"
236
237
  - ".ai-assistance/code/ecoPortal_architecture/13_ai_infrastructure.md"
237
238
  - ".ai-assistance/code/ecoportal_schema_reference.md"
239
+ - ".ai-assistance/code/filter_contract_matrix.md"
238
240
  - ".ai-assistance/code/graphql_domain_knowledge.md"
239
241
  - ".ai-assistance/code/refactoring/datafield-readwrite-shape-asymmetry.md"
240
242
  - ".ai-assistance/code/refactoring/opportunities.md"
241
243
  - ".ai-assistance/code/schema_analysis.md"
242
244
  - ".ai-assistance/code/search_filters.md"
243
245
  - ".ai-assistance/code/spec_coverage.md"
246
+ - ".ai-assistance/code/template_diff_pairing_domain.md"
244
247
  - ".ai-assistance/code/workflow-command-guide.md"
245
248
  - ".ai-assistance/code/workflow-space.md"
246
249
  - ".ai-assistance/conventions/CLAUDE.md"
@@ -267,15 +270,27 @@ files:
267
270
  - ".ai-assistance/projects/graphql-agent/GAP_ANALYSIS.md"
268
271
  - ".ai-assistance/projects/ooze-graphql-native-migration/DECISIONS.md"
269
272
  - ".ai-assistance/projects/ooze-graphql-native-migration/INTENT.md"
273
+ - ".ai-assistance/projects/ooze-graphql-native-migration/INVENTORY.md"
270
274
  - ".ai-assistance/projects/ooze-graphql-native-migration/RISKS.md"
271
275
  - ".ai-assistance/projects/ooze-graphql-native-migration/TODO.md"
272
276
  - ".ai-assistance/projects/ooze-graphql-native-migration/analysis/2026-06-30-cutover-workflow-deep-review.md"
273
277
  - ".ai-assistance/projects/ooze-graphql-native-migration/analysis/2026-07-01-forces-via-workflow-commands-miss-rca.md"
274
278
  - ".ai-assistance/projects/page-model/DECISIONS.md"
275
279
  - ".ai-assistance/projects/page-model/TODO.md"
280
+ - ".ai-assistance/projects/qa-services-delivery/DECISIONS.md"
281
+ - ".ai-assistance/projects/qa-services-delivery/INTENT.md"
282
+ - ".ai-assistance/projects/qa-services-delivery/PHASE3-SCOPE.md"
283
+ - ".ai-assistance/projects/qa-services-delivery/ROADMAP.md"
284
+ - ".ai-assistance/projects/qa-services-delivery/TODO.md"
276
285
  - ".ai-assistance/projects/search-filter-builder/INTENT.md"
277
286
  - ".ai-assistance/projects/search-filter-builder/TODO.md"
287
+ - ".ai-assistance/projects/template-automatic-build-maintenance/INTENT.md"
288
+ - ".ai-assistance/projects/template-automatic-build-maintenance/TODO.md"
289
+ - ".ai-assistance/projects/template-diff-deploy/INTENT.md"
290
+ - ".ai-assistance/projects/template-diff-deploy/TODO.md"
278
291
  - ".ai-assistance/projects/template-maintenance/DESIGN.md"
292
+ - ".ai-assistance/projects/template-maintenance/PHASE0-FINDINGS.md"
293
+ - ".ai-assistance/projects/template-maintenance/README.md"
279
294
  - ".ai-assistance/projects/workflow-space/TODO.md"
280
295
  - ".ai-assistance/reinstall-claude-desktop-windows.md"
281
296
  - ".ai-assistance/scripts/CLAUDE.md"
@@ -306,6 +321,7 @@ files:
306
321
  - ".ai-assistance/skills/gemini-assist/gemini_ask.rb"
307
322
  - ".ai-assistance/skills/gemini-assist/prompts/cycle_end_review.txt"
308
323
  - ".ai-assistance/skills/graphql-schema-analysis/SKILL.md"
324
+ - ".ai-assistance/skills/procedural-memory/SKILL.md"
309
325
  - ".ai-assistance/skills/project-cycle/SKILL.md"
310
326
  - ".ai-assistance/skills/refactor/SKILL.md"
311
327
  - ".ai-assistance/skills/rubocop/SKILL.md"
@@ -332,6 +348,13 @@ files:
332
348
  - bin/console
333
349
  - bin/setup
334
350
  - bin/setup.ps1
351
+ - docs/self-docs/ARCHITECTURE.md
352
+ - docs/self-docs/CHANGES.jsonl
353
+ - docs/self-docs/CONVENTIONS.md
354
+ - docs/self-docs/INTEGRATIONS.md
355
+ - docs/self-docs/OVERVIEW.md
356
+ - docs/self-docs/STATUS.md
357
+ - docs/self-docs/self-docs-index.json
335
358
  - docs/worklog.md
336
359
  - ecoportal-api-graphql.gemspec
337
360
  - lib/ecoportal/api-graphql.rb
@@ -449,6 +472,7 @@ files:
449
472
  - lib/ecoportal/api/graphql/builder/register.rb
450
473
  - lib/ecoportal/api/graphql/builder/register/preset_view.rb
451
474
  - lib/ecoportal/api/graphql/builder/template.rb
475
+ - lib/ecoportal/api/graphql/builder/template_builder.rb
452
476
  - lib/ecoportal/api/graphql/compat.rb
453
477
  - lib/ecoportal/api/graphql/compat/filter_translator.rb
454
478
  - lib/ecoportal/api/graphql/compat/page_reference.rb
@@ -473,6 +497,18 @@ files:
473
497
  - lib/ecoportal/api/graphql/connection/person_member.rb
474
498
  - lib/ecoportal/api/graphql/connection/preset_view.rb
475
499
  - lib/ecoportal/api/graphql/connection/preview_page.rb
500
+ - lib/ecoportal/api/graphql/diff.rb
501
+ - lib/ecoportal/api/graphql/diff/change.rb
502
+ - lib/ecoportal/api/graphql/diff/command_synthesizer.rb
503
+ - lib/ecoportal/api/graphql/diff/cross_object_diff.rb
504
+ - lib/ecoportal/api/graphql/diff/deploy.rb
505
+ - lib/ecoportal/api/graphql/diff/id_resolver.rb
506
+ - lib/ecoportal/api/graphql/diff/pairing/candidate.rb
507
+ - lib/ecoportal/api/graphql/diff/pairing/engine.rb
508
+ - lib/ecoportal/api/graphql/diff/pairing/ledger.rb
509
+ - lib/ecoportal/api/graphql/diff/pairing/signals.rb
510
+ - lib/ecoportal/api/graphql/diff/strategy.rb
511
+ - lib/ecoportal/api/graphql/diff/version_diff.rb
476
512
  - lib/ecoportal/api/graphql/error.rb
477
513
  - lib/ecoportal/api/graphql/error/locations_error.rb
478
514
  - lib/ecoportal/api/graphql/error/locations_error/fetch_nested.rb
@@ -826,6 +862,7 @@ files:
826
862
  - tests/contractor_entity_create.rb
827
863
  - tests/contractor_entity_udpate.rb
828
864
  - tests/dump_page_model.rb
865
+ - tests/dump_template_model.rb
829
866
  - tests/loc_structure_get.rb
830
867
  - tests/loc_structure_update.rb
831
868
  - tests/loc_structures_get.rb