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,97 @@
|
|
|
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
|
+
- [ ] Tighten `ecoportal-qa` to consume the gem's page-model instead of its own `TemplateModel`.
|
|
94
|
+
- [ ] Emit `stageId`/`sectionId` back-refs on diff-side `addField`/`addSection` (BUILD already does;
|
|
95
|
+
the diff synthesizer's structural adds still emit only label/placeholder — then threading covers them).
|
|
96
|
+
- [ ] Extend `BYTYPE_CONFIG` per field type as read↔byType-key shapes are confirmed; gauge-stop reorder.
|
|
97
|
+
- [ ] Complete the `PagesWorkflow.stages` read model to unblock workflow-config-per-stage diff.
|
|
@@ -0,0 +1,12 @@
|
|
|
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`.
|
|
@@ -0,0 +1,9 @@
|
|
|
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.
|
|
@@ -0,0 +1,93 @@
|
|
|
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)
|
|
@@ -0,0 +1,14 @@
|
|
|
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.
|
data/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,93 @@
|
|
|
2
2
|
|
|
3
3
|
All notable changes to this project will be documented in this file.
|
|
4
4
|
|
|
5
|
+
## [1.3.11] - 2026-07-04
|
|
6
|
+
|
|
7
|
+
Template automatic **build & maintenance** engine (backwards-compatible — a self-contained new
|
|
8
|
+
`Diff` module + a build emitter; nothing existing changed). Validated **offline** (specs + fixtures +
|
|
9
|
+
shapes checked against the live schema dump); the live UAT→PROD round trip is pending a sandbox org.
|
|
10
|
+
|
|
11
|
+
### Added
|
|
12
|
+
|
|
13
|
+
- **`genomeSignature`** fetched on every data-field type (added once to the `dataFieldInterface`
|
|
14
|
+
fragment, `@skip(if: $only_content)`) + `passthrough :genomeSignature` on `Base::Page::DataField` —
|
|
15
|
+
a strong-but-fallible field-pairing signal.
|
|
16
|
+
- **`Diff::VersionDiff`** — two same-object (retained-id) template snapshots → an exact structural
|
|
17
|
+
changelog: added/removed/changed/moved for stages, sections, fields (label/type/section-move),
|
|
18
|
+
select options (label/weight), **gauge stops** (add/remove/threshold/color, matched by stop id), and
|
|
19
|
+
typed **`byType` field config** (conservative, only confirmed read↔input-key matches: Gauge `max`;
|
|
20
|
+
Select `dataType/multiple/flat/other/otherDesc`; Date `showTime/pastOnly/todayButton`).
|
|
21
|
+
- **`Diff::Change`** — command-ready change (`op`/`kind`/`id`/`label`/`path`/`attribute`/`before`/
|
|
22
|
+
`after`/`parent_id`/`by_type`) with a human `#description`; `#to_h` is the stable interchange shape.
|
|
23
|
+
- **`Diff::CommandSynthesizer`** — a `Change` set → an ordered `WorkflowCommand` batch (the replayable
|
|
24
|
+
"commit"): moves/renames/config, options, gauge stops, `editFieldConfiguration(byType:)`, with
|
|
25
|
+
**`placeholderId` threading** so dependent intra-batch creates reference not-yet-created nodes.
|
|
26
|
+
Genuinely ambiguous cases (field type change, moves without a target id) are left **UNSUPPORTED** —
|
|
27
|
+
never guessed.
|
|
28
|
+
- **`Diff::Deploy`** — `from_versions(before, after, target_doc:)` / `from_cross_object(...)` produce
|
|
29
|
+
the ordered batch ready for `executeWorkflowCommands`; `#execute!` refuses to run while the honest
|
|
30
|
+
`unsupported` list is non-empty unless `allow_partial: true`; inert until an executor is passed.
|
|
31
|
+
- **`Diff::IdResolver`** — indexes a target doc's stage names + section headings → ids for move
|
|
32
|
+
resolution; duplicate keys resolve to `nil` (never guesses).
|
|
33
|
+
- **`Diff::Pairing::{Engine,Signals,Candidate,Ledger}`** — multi-signal equivalence matching for
|
|
34
|
+
cross-object templates (genome 0.5 + type 0.2 + label 0.2 + options-by-value 0.1, averaged over
|
|
35
|
+
applicable signals; greedy 1:1; auto-accept ≥0.85, ambiguous 0.5–0.85, unmatched <0.5; genome
|
|
36
|
+
mismatch scores 0 but does **not** veto). `Ledger` persists confirmed pairs (consulted first;
|
|
37
|
+
human corrections supersede).
|
|
38
|
+
- **`Diff::Strategy`** — composable diff modalities: pairing (`:id`/`:genome`/`:type_label`/
|
|
39
|
+
`:assisted`) × scope (`:structural`/`:config_only`/`:data_migration`) × move-sensitivity × intent
|
|
40
|
+
(`:changelog`/`:deploy`/`:sync_readiness`). `.default` reproduces exact pre-existing behaviour.
|
|
41
|
+
- **`Diff::CrossObjectDiff`** — diffs two templates with **no shared ids** by building the
|
|
42
|
+
id-correspondence map via `Pairing::Engine` (+ optional `Ledger`), then emitting the same `Change`
|
|
43
|
+
output that feeds `CommandSynthesizer`/`Deploy`. Ambiguous/unmatched held in `#unresolved` for a
|
|
44
|
+
human — never auto-paired.
|
|
45
|
+
- **`Builder::TemplateBuilder`** — a declarative template spec (stages→sections→fields→options→
|
|
46
|
+
config→gauge-stops) → an ordered `WorkflowCommand` batch for `Builder::Template#create/update`,
|
|
47
|
+
using the **same `placeholderId` threading** as the diff synthesizer so build-from-scratch and
|
|
48
|
+
diff-deploy emit through one layer. Emits only verified input `VALID_KEYS`. A field's `description`
|
|
49
|
+
(e.g. a CSV/hidden-field identity token) is emitted as a follow-up `editFieldConfiguration(
|
|
50
|
+
dataFieldId:, description:)` — the correct schema seam, since `WorkflowAddFieldInput` has no
|
|
51
|
+
`description` key.
|
|
52
|
+
- **Stage/section back-refs on added nodes** (`Diff::CommandSynthesizer`) — an added field's `addField`
|
|
53
|
+
now carries `sectionId` (`Change#parent_id`) + `stageId` (new `Change#owner_id`); an added section
|
|
54
|
+
emits a follow-up `addStageSection(stageId:, sectionId:)`. All threaded via `ref()` (parent
|
|
55
|
+
placeholder when created same-batch, else real id; omitted when unknown → historical behaviour
|
|
56
|
+
unchanged). `VersionDiff` records `parent_id`/`owner_id` on added field/section changes.
|
|
57
|
+
|
|
58
|
+
### Fixed
|
|
59
|
+
|
|
60
|
+
- **Fragment references migrated to the `spread :Name` registry convention.** The Action and
|
|
61
|
+
ContractorEntity **mutations** (`create`/`update`/`destroy`, `create`/`update`/`archive`) still used
|
|
62
|
+
the dead `___Const__Fragment` convention, which resolves a Ruby constant `Fragment::<Name>` that no
|
|
63
|
+
longer exists (fragments are a registry now) → `uninitialized constant … Fragment::… (NameError)` at
|
|
64
|
+
render time. Now `spread :Action` / `spread :ContractorEntity`, matching the already-migrated queries.
|
|
65
|
+
(The sibling breakage in eco-helpers' location-command optimizations is fixed in eco-helpers 3.2.17;
|
|
66
|
+
it crashed the live act-gov locations sync.)
|
|
67
|
+
- **Kickstand workflow mutations — bare `DateTime` selection.** `Kickstand::{Start,Stop,Fail}Workflow`
|
|
68
|
+
selected `startedAt`/`stoppedAt`/`failedAt` bare → "Field must have selections". Now
|
|
69
|
+
`{ dateTime timeZone }` (same class as the 1.3.10 LocationStructure fix).
|
|
70
|
+
- **`tests/validate_queries.rb` now renders MUTATIONS too** (was queries only) and **hard-fails on a
|
|
71
|
+
render error** (dead fragment / unresolved constant), not just a soft skip — the offline guard for
|
|
72
|
+
both classes above. It caught the 3 Kickstand bugs immediately.
|
|
73
|
+
|
|
74
|
+
### Schema realities (verified against the live introspection dump)
|
|
75
|
+
|
|
76
|
+
- **`required` cannot be set via the workflow command bus** — there is NO `required` input key anywhere
|
|
77
|
+
in the schema (not on `WorkflowAddFieldInput`, not on `WorkflowEditFieldConfigurationInput` or any of
|
|
78
|
+
its 12 byType sub-inputs). Callers must treat field-`required` as **read-only / out-of-band**
|
|
79
|
+
(ecoportal-qa `:skip`s `required`-readiness by design).
|
|
80
|
+
|
|
81
|
+
### Dependencies
|
|
82
|
+
|
|
83
|
+
- **Requires `ecoportal-api-v2 >= 3.3.3`** (was `>= 3.3.2`). 3.3.2 has a Ruby-3.x `TypeError` in the
|
|
84
|
+
`DoubleModel` cascade (`_cascaded_attributes_trace`) that crashes `as_update`/`DiffService` on any
|
|
85
|
+
model with nested attributes — fixed in v2 3.3.3. Raising the floor stops the broken v2 from
|
|
86
|
+
resolving on consumers.
|
|
87
|
+
|
|
88
|
+
### Known gaps (tracked, not in this release)
|
|
89
|
+
|
|
90
|
+
- Live characterization (UAT→PROD replay + verify) is pending a sandbox org + credentials.
|
|
91
|
+
|
|
5
92
|
## [1.3.10] - 2026-07-03
|
|
6
93
|
|
|
7
94
|
Hotfix (backwards-compatible). Resolves a live failure on the Turners & Growers users sync.
|
data/docs/worklog.md
CHANGED
|
@@ -8,6 +8,285 @@ This file tracks cross-project session state and the overall repo status.
|
|
|
8
8
|
|
|
9
9
|
---
|
|
10
10
|
|
|
11
|
+
## ▶ SESSION 2026-07-06 — RELEASED the fixed stack; act-gov tagtree + toocs live-green
|
|
12
|
+
|
|
13
|
+
The 2026-07-05 crash-fixing arc shipped. **All three live-verified green** on act-gov (direct
|
|
14
|
+
`-no-email` runs): **tagtree-update** (created draft → 8 insert / 3 archive → published, no customer
|
|
15
|
+
email) and **toocs-coding** (Oscar confirmed). Released, in dependency order:
|
|
16
|
+
- **ecoportal-api-v2 `v3.3.3`** — Ruby-3.x cascade block-param fix + regression spec.
|
|
17
|
+
- **ecoportal-api-graphql `v1.3.11`** — Diff build+maintenance engine; fragment-convention + Kickstand
|
|
18
|
+
DateTime fixes; requires v2 >= 3.3.3; validate_queries now covers mutations + hard-fails on render.
|
|
19
|
+
- **eco-helpers `v3.2.17`** — native template build+maintenance + ooze-native; location fragment
|
|
20
|
+
(`spread :LocationDraft`) + `worfklow` no-email typo fixes; requires gem >= 1.3.11 + v2 >= 3.3.3.
|
|
21
|
+
- **multi_org_api** (`master` + `api-deprecation`) — `-no-email` now forwarded through the rake
|
|
22
|
+
wrapper + `worfklow` typo fixed (stops customer emails during rake/scheduled tests).
|
|
23
|
+
|
|
24
|
+
Oscar git-pushed all repos + gem-published; **deploying via server `bundle update ecoportal-api-v2
|
|
25
|
+
ecoportal-api-graphql eco-helpers`** (production Gemfile floors gem>=1.3.9/eco-helpers>=3.2.16, but the
|
|
26
|
+
gemspec floors force v2>=3.3.3 + gem>=1.3.11 transitively). Systemic guard against the recurring
|
|
27
|
+
stale-release drift: raised gemspec dependency FLOORS everywhere + extended `validate_queries.rb`.
|
|
28
|
+
|
|
29
|
+
**STILL OPEN (non-blocking):** rake `notify_exception` emails the customer on task error regardless of
|
|
30
|
+
`-no-email` — decision pending (suppress / route-to-dev / keep). See [[no-email-leak-paths]].
|
|
31
|
+
|
|
32
|
+
---
|
|
33
|
+
|
|
34
|
+
## ▶ SESSION 2026-07-05 — 3 live act-gov crashes = ONE root cause (stale released gems); fixed-stack floors
|
|
35
|
+
|
|
36
|
+
Three live crashes on act-gov (`-toocs-coding` + org-structure sync), all the **same class**: the
|
|
37
|
+
server runs **stale RELEASED gems** while the fixes already exist in local/tagged code.
|
|
38
|
+
1. **v2 cascade `TypeError`** (`_cascaded_attributes_trace … is not a symbol nor a string`) via
|
|
39
|
+
`as_update`/`DiffService` on a `Phased` page — server `ecoportal-api-v2 3.3.2`; fix (Ruby-3.x
|
|
40
|
+
block-param swap) is commit `6a2b1b5`, released now as **v3.3.3**. See [[v2-cascade-blockparam-332-bug]].
|
|
41
|
+
2. **`updatedAt` "must have selections"** + 3. **`createdAt` "selections can't be made on scalars"** —
|
|
42
|
+
LocationStructure queries; server gem **1.3.9**; fixed in gem **1.3.10** (already tagged).
|
|
43
|
+
|
|
44
|
+
**Resolution (release-prepped; publish + server `bundle update` are Oscar's):**
|
|
45
|
+
- v2 **`v3.3.3`** tagged (`03561ed`): CHANGELOG + **cascade regression spec** (double_model_spec, 6 ex green).
|
|
46
|
+
- gem **`1.3.11`** re-tagged (`ad4f788`): gemspec now requires **`ecoportal-api-v2 >= 3.3.3`**.
|
|
47
|
+
- eco-helpers (`ecd5f03f`): gemspec requires **`ecoportal-api-graphql >= 1.3.11` + `ecoportal-api-v2 >= 3.3.3`**.
|
|
48
|
+
- **Systemic guard = raised dependency FLOORS** so `bundle` cannot resolve a broken version again;
|
|
49
|
+
plus the existing `tests/validate_queries.rb` (query class) + the new cascade regression spec.
|
|
50
|
+
- **LOCAL runs already bind the fixed clones** — `multi_org_api` (branch `api-deprecation`) Gemfile
|
|
51
|
+
`:local` group path-mounts gem `main` (1.3.11) + v2 `master` (3.3.3).
|
|
52
|
+
|
|
53
|
+
**Then Oscar ran `-tagtree-update` locally → the version-drift crashes were GONE** (loaded 14126 nodes,
|
|
54
|
+
created the draft), exposing the NEXT layer: **a dead-fragment-convention class.**
|
|
55
|
+
- `uninitialized constant …Fragment::LocationDraft (NameError)` at render — eco-helpers
|
|
56
|
+
`Helpers::Location::Command::EndPoints::Optimizations` still used the legacy `___Const__Fragment`
|
|
57
|
+
convention, which evals a `Fragment::<Name>` CONSTANT that no longer exists (fragments are a registry
|
|
58
|
+
now; `spread :Name`). Fixed → `spread :LocationDraft`/`:LocationsError` (eco-helpers `352a9657`).
|
|
59
|
+
- **Swept the whole class:** the gem's **Action + ContractorEntity MUTATIONS** had the same dead refs
|
|
60
|
+
(queries were migrated, mutations missed) → `spread :Action`/`:ContractorEntity` (gem `44a4288`).
|
|
61
|
+
- **Systemic guard:** `tests/validate_queries.rb` now renders **mutations** (was queries only) and
|
|
62
|
+
**hard-fails on render error** (dead fragment / unresolved constant). It immediately caught **3
|
|
63
|
+
`Kickstand::{Start,Stop,Fail}Workflow` bare-`DateTime`** bugs → fixed `{ dateTime timeZone }`.
|
|
64
|
+
Validator now **EXIT 0** (fragment + structural buckets clean); suite **635/0/2**, rubocop clean.
|
|
65
|
+
See [[fragment-spread-convention]]. Remaining validator "OTHER" findings (union/schema-dump-staleness)
|
|
66
|
+
are pre-existing → separate follow-up with a fresh schema dump.
|
|
67
|
+
- Gem `v1.3.11` re-tagged (`44a4288`); eco-helpers `3.2.17` (`352a9657`); both unpublished.
|
|
68
|
+
**NEXT: Oscar re-runs `-tagtree-update` + `-toocs-coding` locally to confirm, then publishes + deploys.**
|
|
69
|
+
|
|
70
|
+
---
|
|
71
|
+
|
|
72
|
+
## ▶ SESSION 2026-07-04 (cont.) — v1.3.11 tag, addField schema-verified, learnings captured, live-script drafted
|
|
73
|
+
|
|
74
|
+
Post-round-4 follow-through on the #1 template project. **Gem `v1.3.11` tagged locally** (`fc45db7`,
|
|
75
|
+
unpublished — Oscar pushes/`gem push`); **eco-helpers bumped 3.2.17** (`243822b9`, unpublished).
|
|
76
|
+
- **addField (`5754d7f`, folded into v1.3.11):** schema-verified — `WorkflowAddFieldInput` has NO
|
|
77
|
+
`description`/`required`; `required` exists NOWHERE in the schema (read-only). `description` now via
|
|
78
|
+
follow-up `editFieldConfiguration`; added-field/section `stageId`/`sectionId` back-refs emitted. See
|
|
79
|
+
[[workflow-command-schema-realities]].
|
|
80
|
+
- **Learnings recorded (answering Oscar's "are these learnings?"):** cross-session memory
|
|
81
|
+
([[workflow-command-schema-realities]], [[register-membership-via-tags]]) + AI-readable code-spec
|
|
82
|
+
(`workflow-command-guide.md` "Schema realities" section, `2098415`) + CHANGELOG + this worklog. Prime
|
|
83
|
+
material for the [[project-graphql-agent-aws]] corpus (GAP_ANALYSIS flagged this exact gap class).
|
|
84
|
+
- **qa tag-superset SyncReadiness (merged, qa `c058782`):** `base_tags ⊆ compiled_tags` register-
|
|
85
|
+
membership check. **Surfaced a gem read-path gap:** gem has NO `compiledTags`; `baseTags` has an
|
|
86
|
+
accessor but the `corePageData` fragment fetches only `otherTags`. So live tag-membership `:skip`s
|
|
87
|
+
until (a) `baseTags` is added to the read fragment (genomeSignature-style one-liner) AND (b) Oscar
|
|
88
|
+
confirms "compiled tags" semantics (baseTags? base+other? backend-computed incl. inherited/forces?).
|
|
89
|
+
- **Live characterization script drafted (training `feature/template-live-characterization` `ab147f0`,
|
|
90
|
+
UNMERGED):** `-template-maintenance` case, dry-run default, `-commit` gates the only live write.
|
|
91
|
+
Offline smoke PASSED against local clones (6 well-formed commands, 0 unsupported, Applier dry-run,
|
|
92
|
+
DriftReport match?==true). Commands for Oscar in its README. 4 assumptions to confirm (template read
|
|
93
|
+
path; register-search signature; tag-superset membership; `graphql.page` executor accepts a template
|
|
94
|
+
workflow batch). Runs only in `ENVIRO_CONTEXT=local` (path-mounted clones) until v1.3.11 is published.
|
|
95
|
+
|
|
96
|
+
**OPEN for Oscar:** (1) publish gem v1.3.11 + repoint eco-helpers; (2) confirm "compiled tags" semantics
|
|
97
|
+
→ then the `baseTags` fragment fix; (3) set up the Mini test register + before/after template, then run
|
|
98
|
+
the live characterization (dry-run → commit); (4) decide whether the training case sits on `master` or
|
|
99
|
+
`api-deprecation`.
|
|
100
|
+
|
|
101
|
+
---
|
|
102
|
+
|
|
103
|
+
## ▶ SESSION 2026-07-04 (cont.) — Template build+maintenance made #1; increments #4 merged; gem v1.3.11 prepped
|
|
104
|
+
|
|
105
|
+
Oscar set **template automatic build & maintenance as #1 priority**. Ran the usual 3 parallel threads
|
|
106
|
+
(one per repo), all merged to mains, developer-only authorship. Suites **gem 627 (2 pending live-AI) /
|
|
107
|
+
eco-helpers 274 / qa 104 — 0 failures.** Mains: gem `a07f708`→release `70fd252`, eco-helpers `8dc89c45`,
|
|
108
|
+
qa `ac8077c`.
|
|
109
|
+
|
|
110
|
+
- **Gem (thread A):** `Diff::Strategy` (composable modalities: pairing × scope × move-sensitivity ×
|
|
111
|
+
intent; `.default` = prior behaviour) + `Diff::CrossObjectDiff` (two templates with NO shared ids →
|
|
112
|
+
`Pairing::Engine` builds the id map → same `Change` output → `CommandSynthesizer`/`Deploy`;
|
|
113
|
+
ambiguous held in `#unresolved`) + `Builder::TemplateBuilder` (declarative spec → build command
|
|
114
|
+
batch, shares the diff's placeholderId threading). Reconciled the two project-doc folders into
|
|
115
|
+
`.ai-assistance/projects/template-automatic-build-maintenance/` (★#1). +27 diff / +13 builder / +16
|
|
116
|
+
strategy specs.
|
|
117
|
+
- **eco-helpers (thread B):** native deploy→verify→monitor loop under `samples/pages/template/deploy/`
|
|
118
|
+
(`Applier` dry-run default / `commit:` + injected executor / refuses on `unsupported` unless
|
|
119
|
+
`allow_partial:`; `DriftReport` pre/post self-version diff vs intended on an id-free signature;
|
|
120
|
+
pluggable `Verifier`, `QaVerifier` soft-wires ecoportal-qa only if on load path, else `NullVerifier`;
|
|
121
|
+
`SyncReadiness` per-entry) + CSV→template build (`FormatMap`→`Parser`→`Builder` →
|
|
122
|
+
`Builder::Template#create`; format isolated in `FormatMap`). +31 specs.
|
|
123
|
+
- **qa (thread C):** deploy-verification + sync-readiness as new check-sets in the existing framework
|
|
124
|
+
(two `Runner` entrypoints → canonical `Result`); consumes the gem page-model. Intended-change
|
|
125
|
+
contract = `{meta, changes:[Change#to_h]}` (accepts wrapper or bare list, sym/str keys); needs a
|
|
126
|
+
`baseline_doc:` for no-unintended-change; richer gem `Diff::VersionDiff` injectable via
|
|
127
|
+
`Compiler.new(diff_class:)`. +30 specs.
|
|
128
|
+
|
|
129
|
+
**★ TWO INDEPENDENTLY-CONFIRMED SEAMS (B and C reached the same conclusions):**
|
|
130
|
+
1. The gem `Diff` module was **unreleased** (1.3.10 was the location hotfix). B/C bind to it via
|
|
131
|
+
injected/lazy seams so they run offline against released 1.3.9/1.3.10. **→ Prepped gem `v1.3.11`**
|
|
132
|
+
(`chore(release)` `70fd252`: version bump + full CHANGELOG for the Diff module + `TemplateBuilder`).
|
|
133
|
+
NOT yet tagged/published — Oscar to tag `v1.3.11` + publish, then repoint eco-helpers to it so the
|
|
134
|
+
deploy loop binds to the real `Diff` classes.
|
|
135
|
+
2. Gem **`addField` input drops `description`/`required`** → CSV/hidden-field identity token + `required`
|
|
136
|
+
readiness can't persist through `addField` (C `:skip`s `required`; B keeps only the hidden anchor).
|
|
137
|
+
Also diff-side `addField`/`addSection` lack `stageId`/`sectionId` back-refs.
|
|
138
|
+
**✅ RESOLVED (schema-verified, folded into v1.3.11 — merge `d42c528`, retag at `fc45db7`):**
|
|
139
|
+
introspection shows `WorkflowAddFieldInput` = `{placeholderId,fieldType,label,stageId,sectionId,
|
|
140
|
+
column}` — **no `description`**, and **`required` exists NOWHERE in the schema** (not on AddField,
|
|
141
|
+
not on any of the 12 byType edit sub-inputs). So: `description` now persists via a follow-up
|
|
142
|
+
`editFieldConfiguration(dataFieldId:, description:)` (TemplateBuilder + synthesizer); added-field
|
|
143
|
+
`addField` carries `sectionId`(parent_id)+`stageId`(new `Change#owner_id`), added-section emits
|
|
144
|
+
`addStageSection`, all `ref()`-threaded. **`required` is permanently read-only/out-of-band** (qa
|
|
145
|
+
`:skip` is correct-by-design, not a gap). Suite 635/0/2, rubocop clean.
|
|
146
|
+
|
|
147
|
+
**STATE OF #1 PROJECT:** full build+maintain engine exists **end-to-end offline** — build (CSV or
|
|
148
|
+
declarative → commands), diff (self-version + cross-object via pairing), deploy (apply + drift-check),
|
|
149
|
+
verify (qa), monitor (sync-readiness). Gap to "trusted" = **(a) publish v1.3.11** (tagged locally at
|
|
150
|
+
`fc45db7`, incl. the addField resolution; push + `gem push` are Oscar's) **+ repoint eco-helpers**
|
|
151
|
+
(bumped to 3.2.17, unpublished), and **(b) the sandbox live pass** (Mini site; a dedicated test
|
|
152
|
+
register + a template whose compiled tags ⊇ the register `base_tags` + a before/after version — see
|
|
153
|
+
[[register-membership-via-tags]]; script to be prepped; sandbox can't reach live.ecoportal.com so
|
|
154
|
+
Oscar runs it). Sync-readiness should also gain the **tag-superset** dimension (register membership =
|
|
155
|
+
`base_tags` ⊆ compiled tags), not just field presence.
|
|
156
|
+
|
|
157
|
+
---
|
|
158
|
+
|
|
159
|
+
## ▶ SESSION 2026-07-04 (cont.) — 3 parallel-thread increments #3 merged + strategic briefing captured
|
|
160
|
+
|
|
161
|
+
**Increments #3 (all merged to mains, green, developer-only authorship):** gem `main` `c607be9`,
|
|
162
|
+
eco-helpers `master` `5adb4a21`, qa `master` `41cb2e6`. Suites **gem 587 (2 pending live-AI) /
|
|
163
|
+
eco-helpers 243 / qa 74 — 0 failures.**
|
|
164
|
+
- **Templates (gem):** `VersionDiff` now **emits** gauge-stop (`add/remove/editGaugeFieldStop`, matched
|
|
165
|
+
by retained stop id) + typed `byType` field-config changes (`editFieldConfiguration(byType:)`,
|
|
166
|
+
conservative — only confirmed read-prop↔input-key 1:1: Gauge `max`; Select `dataType/multiple/flat/
|
|
167
|
+
other/otherDesc`; Date `showTime/pastOnly/todayButton`; shapes verified vs the live schema dump).
|
|
168
|
+
`CommandSynthesizer` maps them + **placeholderId threading** (Deploy default on): deterministic
|
|
169
|
+
client placeholders on added nodes, later same-batch refs rewritten via `ref()`. +26 specs.
|
|
170
|
+
UNSUPPORTED (honest): unconfirmed byType props (PlainText `multiline`/`required`, RichText/People/
|
|
171
|
+
Table/CrossReference bodies), gauge-stop reorder (no ordering field), structural back-refs in adds.
|
|
172
|
+
- **samples/pages (eco-helpers):** native `TypedFieldsPairing` (groups by GraphQL type string, 2-pass
|
|
173
|
+
label match, `EXCLUDED_TYPES` TagField/Chart/FrequencyRateChart) + `Copying#copy_field_content` +
|
|
174
|
+
`Register::MigrationCase < Register::Base`. Ports live FLAT at `graphql/helpers/pages/*` (not the
|
|
175
|
+
TODO's `.../migration/*`) for round-2 consistency. Deferred: v2 mapped-field hooks
|
|
176
|
+
(`copy_hooked_fields`/`field_maps`), live A/B parity run (creds). +27 specs.
|
|
177
|
+
- **QA (ecoportal-qa):** sub-phase **3c CLI wiring** (`--jira KEY` → DryRunClient default, offline
|
|
178
|
+
CI-preview; `--audit-log PATH` JSONL; report-only default) + **3b `RestClient` skeleton**
|
|
179
|
+
(config-parameterized transition-names/verdict-field, injected HTTP transport, stub-driven specs,
|
|
180
|
+
no real HTTP). No McpClient. +22 specs. Note: `PHASE3-SCOPE.md`/`ROADMAP.md` live on the gem branch
|
|
181
|
+
`feature/qa-services-delivery-project` under `.ai-assistance/projects/qa-services-delivery/`, NOT in
|
|
182
|
+
the qa repo — worklog wording earlier was ambiguous.
|
|
183
|
+
|
|
184
|
+
**★ STRATEGIC BRIEFING from Oscar (captured to memory — see the index).** The next arc is
|
|
185
|
+
**customer-facing agents/apps**, all governed by a management **no-support-dependency mandate**
|
|
186
|
+
([[principle-customer-facing-automation]]): self-documenting config, auto gap-detection, guide the
|
|
187
|
+
technician, CI/CD that blocks breaking changes + auto-generates self-tested migrations, pricing
|
|
188
|
+
transparency, extensive Confluence docs the AI can pull from. Four threads:
|
|
189
|
+
1. **GraphQL / "Integrations" agent → Claude-on-AWS (Client Services workspace)** — corpus already
|
|
190
|
+
staged externally (`C:\claude\Projects\Claude AWS Platform\tmp\corpus\staging\success\graphql\`,
|
|
191
|
+
18 docs), push deliberately held until repo learnings could enrich it. **NOW the moment.** Ships a
|
|
192
|
+
generic Postman/Insomnia collection + a new Confluence self-serve subsection ("Do it yourself"/
|
|
193
|
+
Training/Learning/Examples). `.ai-assistance/projects/graphql-agent/GAP_ANALYSIS.md` is the (stale,
|
|
194
|
+
2026-06-07) gap map — many gaps now filled by code-specs written since. See [[project-graphql-agent-aws]].
|
|
195
|
+
2. **SCIM agent = Entra ID gallery app** — driver: **APIv0 retires END-JUL 2026, FIRM.** Kill the
|
|
196
|
+
high-touch Entra SCIM enrollment (free Travis). Design gated on a **rich structured Travis
|
|
197
|
+
interview** + an **Oscar walkthrough of the Entra caveats** (both Oscar-requested, pending). Open:
|
|
198
|
+
Microsoft Partner vs unlisted-app, gallery upgrade/migration mechanism. See
|
|
199
|
+
[[project-azure-gallery-app]] + [[project-scim-users-apiv0-adapter]].
|
|
200
|
+
3. **Webhooks** — about to officially release; page payload sends only internal `page_id`. Oscar's
|
|
201
|
+
private (un-raised) view: should also send `externalId`. See [[project-webhooks-subscriptions]].
|
|
202
|
+
4. **Platform-agnostic integrations (Zapier as referent, not dependency)** — reusable, auto-detects
|
|
203
|
+
template-drift breakage; UAT-vs-PROD ideal; generic requirements interview with Oscar pending. See
|
|
204
|
+
[[project-integrations-platform-agnostic]].
|
|
205
|
+
|
|
206
|
+
**NEXT:** decide with Oscar whether to start the GraphQL-agent corpus enrichment now (in-repo work I
|
|
207
|
+
can do; the actual AWS push needs his creds/workspace). The 3 gem/helpers/qa threads can also continue
|
|
208
|
+
(#4 increments) in parallel as before.
|
|
209
|
+
|
|
210
|
+
---
|
|
211
|
+
|
|
212
|
+
## ▶ SESSION 2026-07-04 — 3 parallel-thread increments #2 (all merged to mains, green)
|
|
213
|
+
|
|
214
|
+
Same shape as the prior session: one background agent per repo, separate working trees, each on a
|
|
215
|
+
feature branch, then **all consolidated to their mains + branches deleted** (Oscar's call),
|
|
216
|
+
developer-only authorship. Suites: **gem 561 (2 pending live-AI, pre-existing) / eco-helpers 216 /
|
|
217
|
+
qa 52 — 0 failures.** Mains: gem `b16b5e5`, eco-helpers `c37847d5`, qa `ec4a507`.
|
|
218
|
+
|
|
219
|
+
- **Templates (gem) — `template-diff-deploy`:** edit-mode synthesis + deploy orchestration + pairing.
|
|
220
|
+
`Diff::Deploy.from_versions(before, after, target_doc:)` turns a diff into an ordered replayable
|
|
221
|
+
`WorkflowCommand` batch for `executeWorkflowCommands`; `execute!` refuses to run while `unsupported`
|
|
222
|
+
is non-empty unless `allow_partial:`; inert until an explicit executor is passed. Edit-mode moves
|
|
223
|
+
(`moveField`, section stage-reassign via `removeStageSection`+`addStageSection`) are gated on a new
|
|
224
|
+
`Diff::IdResolver` (`from_doc` indexes stage names + section headings → ids; duplicate keys → nil,
|
|
225
|
+
**never guesses**). `Diff::Pairing::{Engine,Ledger,Signals,Candidate}`: weighted fallible signals
|
|
226
|
+
(genome 0.5 + type 0.2 + label 0.2 + select-options 0.1, averaged over applicable), greedy 1:1,
|
|
227
|
+
auto-accept ≥0.85 / ambiguous 0.5–0.85 / unmatched <0.5; **genome mismatch scores 0 but does not
|
|
228
|
+
veto** → contradicting-genome/same-label fields are escalated, never auto-paired. `Ledger` is a
|
|
229
|
+
first-class JSON artifact of confirmed equivalences, consulted first. Code-spec:
|
|
230
|
+
`.ai-assistance/code/diff_pairing_engine.md`. +44 diff specs.
|
|
231
|
+
- **samples/pages (eco-helpers):** native `Helpers::Pages::OozeHandlers#merge_values` (dispatches on
|
|
232
|
+
GraphQL DataField **type string** via `TYPE_MAP`, not V2 Component classes), included into
|
|
233
|
+
`Register::Base` with `#merge_field_values`. `Compat::Parity::{RunResult,Comparison,Harness}` A/B
|
|
234
|
+
harness (canonical-KPI + normalised payload snapshot, `equivalent?` verdict) — **pure/offline;
|
|
235
|
+
running legacy-vs-native live needs a test org + creds.** Native `Register::TargetOozesUpdateCase`
|
|
236
|
+
(CSV target ids, id-batching, dup-detection preview, fetch-per-id, dedup, KPIs; org-scan `each_page`
|
|
237
|
+
disabled). Native-only: no case flipped, no shim change, no public-API rename. +38 specs.
|
|
238
|
+
- **QA repo — sub-phase 3a:** `Jira::{Client,DryRunClient,Publisher}`. Jira is *just another Result
|
|
239
|
+
consumer* (no runner/DSL/compiler/Result changes). DryRunClient writes nothing + records intended
|
|
240
|
+
posts; Publisher redacts-before-post (ON by default, reuses `Redactor`), per-ticket idempotency
|
|
241
|
+
marker, **report-only default (never transitions unless a human names one)**, audit trail per
|
|
242
|
+
action. No RestClient/McpClient (that's blocked 3b/3c). +21 specs.
|
|
243
|
+
|
|
244
|
+
**NEXT increments (parallel threads continue):**
|
|
245
|
+
- **Templates:** extend `VersionDiff` to *emit* gauge-stop + typed `byType` field-config changes — the
|
|
246
|
+
one part of edit-mode genuinely blocked upstream in the diff (synthesizer is ready to map them once
|
|
247
|
+
emitted). Then `placeholderId` threading for dependent intra-batch creates; interactive
|
|
248
|
+
assisted-resolution UX + `TypedFieldsPairing` as an extra pairing signal (eco-helpers layer).
|
|
249
|
+
- **samples/pages:** live A/B parity run (needs test org + creds); Phase-5 `TypedFieldsPairing` /
|
|
250
|
+
migration-case porting; later phases flip `OozeSamples::*` to native + shim removal (parity-gated).
|
|
251
|
+
- **QA:** 3b/3c **decision-blocked** on 4 open Qs for Oscar — (1) Jira project + exact transition
|
|
252
|
+
names, (2) REST service-account token vs MCP-only, (3) verdict field id vs comment-only, (4) where
|
|
253
|
+
check-sets live long-term. 3a is done and unblocks the offline/CI-preview path today.
|
|
254
|
+
- Standing: 1.3.11 union fixes + CI query-validation TODO (due **2026-07-17**); live capture of
|
|
255
|
+
template `6a3fa5b8…622b` (blocked on sandbox creds); FARMERS/Travis F1/F2 (`api-deprecation`).
|
|
256
|
+
|
|
257
|
+
---
|
|
258
|
+
|
|
259
|
+
## ▶ SESSION 2026-07-03 (cont.) — Consolidation + 3 parallel-thread increments (all merged, green)
|
|
260
|
+
|
|
261
|
+
**Consolidated** all green foundation branches to their mains (Oscar's call), then built the next
|
|
262
|
+
increment of each of the 3 threads in parallel (one background agent per repo, separate working
|
|
263
|
+
trees). All merged to mains, branches deleted, developer-only authorship. Suites: **gem 515 (~live) /
|
|
264
|
+
eco-helpers 178 / qa 31 — 0 failures.**
|
|
265
|
+
|
|
266
|
+
- **Templates (gem):** `genomeSignature` now fetched on ALL data-field types (added once to the
|
|
267
|
+
`dataFieldInterface` fragment, `@skip(if: $only_content)`) + `passthrough :genomeSignature` on
|
|
268
|
+
`Base::Page::DataField` — unblocks field pairing for cross-template diffs. New
|
|
269
|
+
`Diff::CommandSynthesizer` turns a `VersionDiff` change-set into an ordered `WorkflowCommand` batch
|
|
270
|
+
(the replayable "commit"); correctly leaves UNSUPPORTED (never guesses) field type-change and
|
|
271
|
+
field/section moves (need a pairing map / target id). `Change` gained `parent_id` (stamped on option
|
|
272
|
+
changes).
|
|
273
|
+
- **samples/pages (eco-helpers):** native `Samples::Pages::Register::Base < Page::Base` reproducing
|
|
274
|
+
`RegisterUpdateCase` semantics (register-scoped batched cursor search, dedup-by-id, KPIs, dry-run,
|
|
275
|
+
process_page/process_ooze override) + native `Helpers::Pages::Creatable`. **Shim + OozeSamples names
|
|
276
|
+
untouched** (native-only). Deferred (TODO): `merge_values` typed-field pairing; v2 batch_queue dropped
|
|
277
|
+
(GraphQL is per-page). +17 specs.
|
|
278
|
+
- **QA repo:** dropped the hand-rolled `TemplateModel` (−62 net lines); `Source::{Fixture,Graphql}`
|
|
279
|
+
now yield the gem's page model (`Model::PageUnion.new(doc)`, parses offline); Compiler navigates gem
|
|
280
|
+
accessors with small adapters preserving skip-honest options/required/forces. Same toocs verdict (7/2/3).
|
|
281
|
+
|
|
282
|
+
**NEXT increments (parallel threads continue):** Templates — extend the emitter to *edit* mode +
|
|
283
|
+
wire diff→commands into a deploy flow; pairing engine (uses genomeSignature + type+label) + ledger.
|
|
284
|
+
samples/pages — native `merge_values`/typed-field pairing + A/B parity harness; native
|
|
285
|
+
`TargetOozesUpdateCase`. QA — Phase 3 Jira adapter (decision-blocked). Plus the standing 1.3.11 union
|
|
286
|
+
fixes + CI query-validation TODO (due 2026-07-17).
|
|
287
|
+
|
|
288
|
+
---
|
|
289
|
+
|
|
11
290
|
## ▶ SESSION 2026-07-03 (cont.) — Template self-version diff + genome finding + domain capture
|
|
12
291
|
|
|
13
292
|
**Built `Ecoportal::API::GraphQL::Diff::VersionDiff`** (gem branch `feature/template-version-diff`,
|
|
@@ -33,7 +33,7 @@ Gem::Specification.new do |spec|
|
|
|
33
33
|
spec.add_development_dependency 'yard', '>= 0.9.34', '< 1'
|
|
34
34
|
|
|
35
35
|
spec.add_dependency 'ecoportal-api', '~> 0.10', '>= 0.10.16'
|
|
36
|
-
spec.add_dependency 'ecoportal-api-v2', '~> 3.3', '>= 3.3.
|
|
36
|
+
spec.add_dependency 'ecoportal-api-v2', '~> 3.3', '>= 3.3.3'
|
|
37
37
|
spec.add_dependency 'graphlient', '>= 0.8.0', '< 0.9'
|
|
38
38
|
end
|
|
39
39
|
|