pyegeria HTTP-endpoint audit: SDK fixes, Dr.Egeria features, overview metrics, test coverage - #274
Open
dwolfson wants to merge 47 commits into
Open
pyegeria HTTP-endpoint audit: SDK fixes, Dr.Egeria features, overview metrics, test coverage#274dwolfson wants to merge 47 commits into
dwolfson wants to merge 47 commits into
Conversation
Cross-checked pyegeria's OMVS client methods against two Egeria-team
audits of the Egeria-api-*.http example collections (endpoint-coverage
audit + error-only audit) and against the real 6.1 distribution's
http-client-collections as ground truth.
Fixed URL/body bugs:
- action_author: remove_first_action_process_step missing GUID segment
- asset_maker: _async_unassign_action reassign/unassign copy-paste bug;
catalog-target methods pointed at automated-curation instead of
asset-maker
- runtime_manager: publish_open_lineage_event hit the wrong endpoint;
cohort connect/disconnect/unregister used a stale omag-servers/...
URL shape instead of cohort-members/... (disconnect was also DELETE
instead of POST)
- collection_manager: detach_agreement_actor took two element GUIDs
against a URL that doesn't exist server-side; real endpoint takes the
relationship GUID directly (signature change, live caller in
md_processing/v2/collection_manager_processor.py updated to resolve
the relationship GUID via ClassificationExplorer.get_relationships
instead of tracking a GUID that link_agreement_actor never returns)
- classification_explorer: unlink_elements_as_peer_duplicates had a
related-elements/ vs elements/ path bug and called the classification
delete helper instead of the relationship delete helper
- governance_officer: addGovernanceDefinitionToElement-style methods
already correct; removed the license/certification update/decertify
methods that collided by name with classification_explorer's
equivalent (functionally identical) implementations under EgeriaTech's
generic attribute delegation - classification_explorer's now wins
unambiguously instead of relying on dict insertion order
- reference_data: fixed ValidValuesImplementationProperties naming,
dropped a fabricated ConsistentValidValuesProperties class (that
relationship has no properties in the real API)
- project_manager: set_project_dependency/set_project_hierarchy sent a
fabricated properties class the server doesn't recognize
- server_operations: integration-daemon and engine-host calls used a
legacy /users/{userId}/... path shape (and integration_daemon
underscore instead of hyphen) that 404s against a real server
- full_omag_server_config: removed set_server_user_password, which
called a server-user-password endpoint that has never existed
(confirmed against ConfigPropertiesResource.java; no callers)
New methods added (endpoint existed server-side, pyegeria had no
client method): connection_maker get_connector_types_by_connector_
provider_class_name; asset_maker detach_catalog_target; lineage_linker
update_lineage/detach_lineage; metadata_expert detach_related_elements_
in_store; project_manager get_project_hierarchy; collection_manager
set/clear_editing/scoping/staging_collection; governance_officer
license_element/certify_element; classification_explorer get_resource_
list/get_supported_by_resource; reference_data valid-value-
implementation/associated/consistent/mapped relationship pairs.
Added pyegeria/http_client_notes.md to record the intentional
divergences above (license/cert routing, removed dead method) outside
the pyegeria/http clients/ directory, since that directory gets
periodically replaced wholesale from an Egeria distribution copy.
Signed-off-by: Dan Wolfson <dan.wolfson@pdr-associates.com>
…aHub rename, and Reference Data family
Wires up the new Egeria PR (DataHub -> DataSharingHub rename + Liskov
connector rename; ExternalStandard, WorkingSet, AccountingCodes types) plus
the ValidValuesAssignment/ReferenceValueAssignment/SpecificationProperty
Assignment relationships, through the full Dr.Egeria compact-spec ->
processor -> report-spec pipeline.
New/changed Dr.Egeria commands:
- Create Working Set (Collections) - and 5 more real Egeria Collection
subtypes with no prior command: Event Set, Context Event Collection,
IT Subsystem, Naming Standard Rule Set, Software Archive
- Create External Standard (External Reference)
- Classify/Reclassify/Declassify Accounting Codes (Curation)
- DataHub -> DataSharingHub: clean rename (delete + recreate, matching
Egeria's own no-backward-compat-shim choice), COLLECTION_SUBTYPES updated
- New "Reference Data" family (commands_reference_data_compact.json):
- Link/Detach Element to Valid Values (generic ValidValuesAssignment)
- Link/Detach Reference Value Assignment
- Link/Detach Specification Property Assignment
- Setup/Clear Valid Metadata Value, Map Name, Map Value
- Set Consistent Metadata Values
plus two contextual ValidValuesAssignment variants in their natural
families: Link/Detach Question to Valid Values (Glossary), Link/Detach
Data Field to Valid Values (Data Designer) - all three share one new
OM_TYPE-dispatched processor, ReferenceDataLinkProcessor.
pyegeria SDK additions backing the above:
- classification_explorer.py: set/clear_accounting_codes_classification
- valid_metadata.py: link/detach_specification_property (plus a missing
`logger` import in that module)
- external_links.py: EXTERNAL_REFERENCE_PROPS/TYPES were missing
ExternalSourceCode entirely (pre-existing gap, fixed alongside adding
ExternalStandard)
Processing-code verification (per the compact-spec-sync lifecycle - a new
custom_attribute isn't proven wired just because it validates and
templates): caught and fixed a real gap where Working Set's new
`Disposition` attribute wasn't read anywhere in
set_collection_manager_body(), and caught a bug in my own first pass at the
DataHub rename (COLLECTION_SUBTYPES needs the display name for the
`Create {X}` dispatch lookup to resolve, not the bare type name).
Regenerated via refresh_specs --merge-reports; validate_compact_specs: 0
errors; pytest tests/ -m unit and test_gen_report_specs.py both pass; a
--validate smoke test against hand-written markdown confirmed
Create Working Set / Create External Standard resolve end-to-end with
correct qualified names.
Also fixes 4 stale sample-data/egeria-inbox/dr-egeria-help-*.md files that
were accidentally deleted then restored during this session's cleanup.
Signed-off-by: Dan Wolfson <dan.wolfson@pdr-associates.com>
…e Valid Metadata Value lookup Egeria changed GovernanceDomain from a Java enum to a domainIdentifier Valid Metadata Value set, so deployments can extend the list of governance domains without rebuilding Egeria. Dr.Egeria's Domain Identifier attribute was still typed as a hardcoded "Enum" (GovernanceDomains) tied to the old fixed set of 9 values. - md_processing/v2/parsing.py: new `legacy_enum_type` hint for "Valid Value"-style attributes. Old ALL_CAPS enum names (and new-style display names for the original 9 - the normalization already treats underscores and spaces the same) resolve locally via the existing GovernanceDomains enum with no server call; anything the old enum doesn't recognize (a new display name like "All Domains", or a deployment-added custom domain) falls through to the existing live valid_metadata_values lookup/cache mechanism (already implemented, just not wired to this attribute before). - Domain Identifier (Governance Officer - shared via bundle inheritance by all 28 governance-definition subtype commands, e.g. Create Governance Policy/Risk/Threat, plus Action Author's 3 governance-process commands which reference the same globally-shared attribute name) and Role Domain Identifier (Solution Architect's Create Solution Role) migrated from style "Enum" to "Valid Value", property_name "domainIdentifier", legacy_enum_type "GovernanceDomains". - Verified live against the real domainIdentifier valid value set: the original 9 domains kept their exact ordinals (Data=1, Privacy=2, ..., Other=99) except ALL is now officially labelled "All Domains"; confirmed old-style, new-style, and two already-deployed custom domains (Drug Development=20, Sustainability=9) all resolve to the correct int via direct unit-level calls against _process_attribute_value. Processing-code verification caught a real, pre-existing bug unrelated to the style migration itself: set_solution_architect_body() never read Role Domain Identifier into the outgoing body at all (old style or new) - fixed alongside the migration. Regenerated via refresh_specs --merge-reports; validate_compact_specs: 0 errors; pytest tests/ -m unit and test_gen_report_specs.py both pass. Signed-off-by: Dan Wolfson <dan.wolfson@pdr-associates.com>
…RIA_ISSUES.md triage
Two real bugs found and fixed while investigating why a bulk dr_egeria
--process run against the live server was crashing/timing out, plus a
pass through the whole open-issues tracker.
- md_processing/v2/processors.py: AsyncBaseCommandProcessor.fetch_element()
now retries the same ClassificationExplorer call (up to 2 attempts) on a
PyegeriaTimeoutException instead of immediately falling through to the
MetadataExpert fallback. A timeout means either the request was
transient (retrying the same call is exactly as likely to succeed as
switching endpoints) or the server is under sustained load (a different
endpoint is no more likely to help, and its response shape isn't
guaranteed compatible with what downstream code expects -- switching on
a timeout was trading a clean failure for a KeyError crash).
MetadataExpert stays the fallback for genuine non-timeout failures, and
as a last resort after retries are exhausted. (ISSUE-51)
- pyegeria/core/_server_client.py: validate_open_metadata_delete_request
now builds a default {"class": "OpenMetadataDeleteRequestBody"} when no
body is given, instead of returning None straight into a .model_dump()
call three lines later in every caller of the shared
_async_open_metadata_delete_body_request helper. Was an unconditional
AttributeError crash for the common "just delete it" case (e.g.
MetadataExpert.delete_metadata_element(guid) with no body). (ISSUE-31)
- PYEGERIA_ISSUES.md: fixed a numbering bug in the tracker itself (three
ISSUE-# values were each independently reused for two unrelated
entries -- renumbered the later duplicates 45/46/47 -> 53/54/55, noted
in the file header). Triaged all 21 open entries; closed the two above
plus ISSUE-19 (found already fixed in code, never marked closed).
Updated ISSUE-52 (Egeria-server integration-connector write load) with
a post-restart observation.
Verified: pytest tests/ -m unit passes throughout. Re-ran the same
100+-command dr-egeria help file that originally crashed on its first
command (ISSUE-51) and separately timed out repeatedly (ISSUE-52) --
against a freshly-restarted server it now completes cleanly end-to-end,
every command SUCCESS, 0 errors, ~6 minutes total (vs. 70+ minutes and
repeated timeouts before).
Signed-off-by: Dan Wolfson <dan.wolfson@pdr-associates.com>
…body validator in reference_data.py
- pyegeria/omvs/metadata_expert.py: process_related_element_list()'s
relationship_list=True branch looked for the relationship list under
"elementList" instead of the real key, "relationships", nested inside
the server's OpenMetadataRelationshipListResponse envelope
({"relationshipList": {"relationships": [...]}}). Also, two call sites
(get_metadata_element_relationships, get_all_metadata_element_
relationships) weren't passing relationship_list=True at all, so they
looked for the wrong top-level key too. Both bugs fixed; confirmed live
with a real ResultsSet/SavedQuery/SmartQuery relationship that all three
affected methods (those two plus find_relationships_between_elements,
which already had relationship_list=True set and so was only hit by the
inner-key bug) now return the relationship instead of "No elements
found". (ISSUE-39, ISSUE-49)
- pyegeria/omvs/reference_data.py: 7 relationship-link methods
(link_valid_value_member, link_valid_values_assignment,
link_reference_value_assignment, link_valid_value_implementation,
link_associated_valid_values, link_consistent_valid_values,
link_mapped_valid_values) called _async_create_element_body_request,
which validates the body against NewElementRequestBody's Pydantic model
(class: Literal["NewElementRequestBody"]) -- but every one of these
methods' own docstring documents a NewRelationshipRequestBody sample
body, which always fails that Literal check. Swapped to the matching
helper, _async_new_relationship_request (validates against
NewRelationshipRequestBody, identical call signature, no other code
changes needed). Verified live: linked a real ValidValueMember to a
ValidValueSet using exactly the documented sample body -- previously
failed on every call, now succeeds. (ISSUE-56, reported by another
session working on resource-explorer)
Verified: pytest tests/ -m unit passes throughout both fixes.
Signed-off-by: Dan Wolfson <dan.wolfson@pdr-associates.com>
…names, no depth override pyegeria/omvs/asset_catalog.py: _async_get_asset_lineage_graph_by_guid hardcoded "queryGraphDepth": 5 with no way to override it. Checked the real AssetLineageGraphRequestBody Java class (-> QueryOptions -> GetOptions): that field name doesn't exist on the body at all -- the real field is "graphQueryDepth", inherited from GetOptions (which also defines "maxMermaidNodeCount" and "includeOnlyRelationships"). So the hardcoded 5 was always silently dropped server-side; the server's own default (coincidentally also 5) was what actually applied the whole time. Found the same problem on "relationshipTypes", which isn't real either -- the actual field is "includeOnlyRelationships", so the caller-supplied relationship-type filter has never worked either. Fixed both field names, and added graph_query_depth/max_mermaid_node_count parameters (the real maxMermaidNodeCount field was never sent before) to all three call layers: _async_get_asset_lineage_graph_by_guid, get_asset_lineage_graph_by_guid, get_asset_lineage_mermaid_graph. Verified live: created a throwaway asset, spied on the outgoing request body, confirmed graph_query_depth=7/max_mermaid_node_count=42 arrive as graphQueryDepth/maxMermaidNodeCount in the POST body and the server accepts the call. pytest tests/ -m unit passes. (ISSUE-24) Signed-off-by: Dan Wolfson <dan.wolfson@pdr-associates.com>
…ve ToDos tests/functional-tests/test_my_profile.py::test_create_my_todo created a real ToDo against the live server on every run and never deleted it, silently accumulating orphaned ToDo entities across repeated test runs. Added a finally block that deletes the created GUID via a MetadataExpert client, matching the delete pattern used elsewhere in this file's own verification steps. Verified live: ran the test, confirmed the ToDo was created, then confirmed the same GUID is soft-deleted immediately after the run. pytest tests/ -m unit passes. (ISSUE-45) Signed-off-by: Dan Wolfson <dan.wolfson@pdr-associates.com>
…apping (ISSUE-22) Two stacked bugs in the Impact/Confidence/Confidentiality/Criticality/ Retention classification path: 1. commands_curation_compact.json: the 'Governance Status' attribute had been migrated to style 'Valid Value' but with no explicit property_name, so it auto-derived to the nonexistent 'governanceStatus' property, silently falling through to a stale ALL-CAPS fallback list. Fixed via the Spec Editor API: property_name is now 'statusIdentifier', and valid_values matches the real GovernanceClassificationStatus set (Discovered/Proposed/Imported/Validated/Deprecated/Obsolete/Other). 2. md_processing/v2/curation.py: _GOVERNANCE_SHARED_FIELDS mapped 'Governance Status' to the outgoing JSON key 'status', but the real field on ImpactProperties/ConfidenceProperties/ConfidentialityProperties/ CriticalityProperties/RetentionClassificationProperties is statusIdentifier -- 'status' is silently ignored by the server. Fixed the mapping to 'statusIdentifier'. Ownership was not affected (its ClassificationSpec uses its own explicit field map, not _GOVERNANCE_SHARED_FIELDS); Retention was affected and is fixed by the same change. Verified end-to-end via a live Classify Impact run through the actual Dr.Egeria pipeline: Governance Status: Validated -> statusIdentifier: 3 persisted correctly. Test element cleaned up afterward. Templates regenerated via refresh_specs --merge-reports. Signed-off-by: Dan Wolfson <dan.wolfson@pdr-associates.com>
…arams on solution blueprint retrieval (ISSUE-23) Raised the remaining max_mermaid_node_count=5 defaults to 10 across _server_client.py's shared find/get helpers (_async_get_name_request, _async_get_guid_request, _async_get_request_body_request, _async_activity_status_search_request, content-status/deployment-status search variants) and asset_catalog.py's lineage-graph methods, matching _async_find_request's already-raised default. Also fixed get_solution_blueprint_by_guid/_async_get_solution_blueprint_by_guid (solution_architect.py) -- when body was None, no body was ever sent, so graph_query_depth/max_mermaid_node_count were dead parameters regardless of the default. Same 'dead parameter' shape ISSUE-26 already fixed for get_info_supply_chain_by_guid/get_solution_role_by_guid; fixed the same way by building an AnyTimeRequestBody when body is None, and added max_mermaid_node_count as an explicit parameter (previously not accepted at all). get_solution_component_by_guid was checked and found NOT to share this bug -- it already routes through _async_get_guid_request and forwards both parameters correctly. Verified live via request-body spies for all three: the shared-default raise, the blueprint fix, and the component non-fix. pytest tests/ -m unit passes. Signed-off-by: Dan Wolfson <dan.wolfson@pdr-associates.com>
…SSUE-27 audit Scripted audit of ~350 self._async_*(...) delegation call sites across pyegeria/omvs/*.py (all multi-line all-positional calls, plus single-line calls with 3+ bare-identifier positional args), each cross-checked against its target async method's actual (last-defined, matching Python's real name resolution) parameter order. Found and fixed 4 real bugs, all in governance_officer.py/solution_architect.py; everything else was either an exact match or a same-value/different-local-name false positive. 1. solution_architect.py: delete_solution_role's sync wrapper transposed cascade_delete and body when calling _async_delete_solution_role -- sent the bool into the body slot and the body dict into the cascade slot. Fixed the call order. 2. governance_officer.py: add_regulator_to_regulation called the wrong async method entirely (_async_link_governance_results, a copy-paste leftover hitting a completely different relationship/URL) instead of _async_add_regulator_to_regulation. Fixed the call target. 3. governance_officer.py: _async_add_regulator_to_regulation/ _async_detach_regulator_from_regulation both built the wrong URL (self.url_marker is already governance-officer, so the hardcoded literal governance-officer/ after it duplicated the segment) and the attach method used the wrong properties class (GovernanceResultsProperties instead of RegulatorProperties). Fixed both against Egeria-api-governance-officer.http's ground truth. 4. governance_officer.py: detach_governance_results passed data_asset_guid twice, pushing the real body argument out of the target's 3-parameter signature entirely. Fixed by removing the duplicate. Verified live against qs-view-server: delete_solution_role via a request-body spy; add_regulator_to_regulation/detach_regulator_from_regulation end-to-end with throwaway Regulation+Organization elements, cleaned up afterward; detach_governance_results via a request-body spy. Also logged ISSUE-57 (Egeria server, not pyegeria-fixable): live-verifying the untouched, unrelated _async_link_governance_results surfaced a genuine server-side relationship end1/end2 ordering bug, out of scope here. pytest tests/ -m unit passes. Signed-off-by: Dan Wolfson <dan.wolfson@pdr-associates.com>
…ver (Egeria server, not pyegeria) Re-ran the updateNote 404 repro end-to-end via pyegeria (create DataStructure + NoteLog + Note all succeed, update 404s) against the current qs-view-server post the environment restart noted in ISSUE-52, to rule out this being a stale finding from the original redeploy. Still reproduces identically. Nothing to fix client-side -- no code change, tracker note only. Signed-off-by: Dan Wolfson <dan.wolfson@pdr-associates.com>
…lates endpoint (ISSUE-43)
_async_get_server_templates_by_dep_impl_type built a URL with
?startFrom={..}&pageSize={..}&getTemplates=true appended, but
Egeria-api-runtime-manager.http's getServerTemplatesByDeployedImplementationType
worked example shows a plain POST with no query string at all -- pagination
and the Template filter both belong in the FilterRequestBody. The sibling
non-templates method in the same file already builds the URL correctly with
no query string. Removed the spurious suffix; the shared
_async_get_name_request helper already builds startFrom/pageSize into the
body correctly regardless (confirmed via a before/after request-body spy).
Verified live against qs-view-server: the call now succeeds cleanly. A real
2+-page pagination comparison still isn't possible with this demo dataset
(no Template-classified software servers of any tested deployed
implementation type exist), same limitation the issue already noted --
resolved via ground-truth comparison instead, per the issue's own suggested
next step.
pytest tests/ -m unit passes.
Signed-off-by: Dan Wolfson <dan.wolfson@pdr-associates.com>
…side count discrepancy Numbers have shifted since 2026-07-24 (demo data changed): count is now 58, get_relationships now 57, not 276/55. Cross-checked against a second, independent pyegeria list-based method (MetadataExpert.find_relationships_between_elements, a different OMVS client/endpoint) with the same filter -- also returns 57, identical GUID set to get_relationships. Two independent pyegeria code paths agree exactly with each other; only the server's native COUNT(*) endpoint disagrees, by 1. Re-confirmed the 'not the type filter' and 'not status/effectivity' findings still hold with current data. Nothing to fix client-side -- genuinely server-side, narrower but still real. No code change, tracker note only. Signed-off-by: Dan Wolfson <dan.wolfson@pdr-associates.com>
…pyegeria since 2026-08-03 Re-checked live and found _async_update_comment (_server_client.py) already auto-fetches qualifiedName via _async_get_comment_by_guid when the caller's body doesn't supply one -- the exact workaround this entry described as living in 'application code', actually shipped directly in pyegeria itself since 92cde6a (2026-08-03), just never reflected in the tracker. Verified live: created a throwaway DataStructure + comment, called update_comment with no qualifiedName in the body -- succeeds cleanly. No pyegeria code change needed, tracker correction only. Also includes a concurrent edit from another session correcting ISSUE-58 (renumbered from a same-day ISSUE-57 collision) -- self-diagnosed as a caller error, not a resolver bug, landed on this shared tracker file while this session was working. Signed-off-by: Dan Wolfson <dan.wolfson@pdr-associates.com>
…ecification-properties/by-type (ISSUE-17) Original diagnosis (server-side enum-binding drift, unfixable) was wrong. Egeria-api-valid-metadata.http's getSpecificationPropertyByType worked example uses specificationPropertyType=PRODUCED_GUARD -- SCREAMING_SNAKE_CASE -- which succeeds immediately when tried directly. The real problem: get_specification_property_types() returns its stringMap verbatim from a different server endpoint (specification-properties/type-names) that uses PascalCase keys (e.g. ProducedGuard) for the same enum -- a genuine cross-endpoint casing inconsistency on the server, but one pyegeria can paper over: _async_get_specification_property_by_type did zero conversion, so feeding it the single most natural, discoverable input (a key from get_specification_property_types()) always 400'd. Fixed by auto-converting PascalCase/camelCase input to SCREAMING_SNAKE_CASE via a plain regex (no hardcoded type list); an already-correct SCREAMING_SNAKE_CASE value passes through untouched. Verified live: all 12 real specification property types, fed straight from get_specification_property_types() into get_specification_property_by_type() unmodified, now resolve successfully (10 return results, 2 correctly return 'No elements found' -- no data of that type). Already-correct form (PRODUCED_GUARD) still works. pytest tests/ -m unit passes. Signed-off-by: Dan Wolfson <dan.wolfson@pdr-associates.com>
…finition REST endpoint User's decision: no pyegeria wrapper or Dr.Egeria command work until the server-side endpoint actually exists. No code change. Signed-off-by: Dan Wolfson <dan.wolfson@pdr-associates.com>
…ing cold-start crawl quickstart-egeria-main had been restarted again (uptime ~1h vs. sibling containers' 8h+), giving a fresh post-restart observation window rather than a stale one. OpenAPICataloguer's creation rate is clearly decelerating (134->86->48->26->8->6 across shrinking trailing windows), not a steady continuous rate -- better characterized as a one-time cold-start crawl that converges than unbounded re-crawling. JacquardDigitalProductLoom logged zero activity in this window (too early to rule out recurrence). Server responsiveness confirmed fast right now (0.02-0.19s/call, no timeouts). Net: acute symptom not currently reproducing; still genuinely Egeria-server/deployment-config territory, lower urgency than originally assessed. No pyegeria code change -- infra investigation only. Signed-off-by: Dan Wolfson <dan.wolfson@pdr-associates.com>
…ver (Egeria server, not pyegeria) Re-ran with a raw body passed straight through MetadataExpert.find_metadata_elements (bypassing pyegeria body-construction, equivalent to the original raw-curl repro) against the current, restarted qs-view-server -- metadataElementSubtypeNames still has zero effect (byte-identical type mix with/without it). Nothing to fix client-side. No code change, tracker note only. Signed-off-by: Dan Wolfson <dan.wolfson@pdr-associates.com>
…e-GUID artifact in the broad scan Re-ran both independent cross-checks (direct exhaustive GlossaryTerm scan vs. type-mix within an exhaustive Referenceable scan; SemanticAssignment relationship participants vs. Referenceable scan membership) against the current, restarted qs-view-server. Magnitude improved (61%/73% coverage this time vs. the original ~54%/5.6%) but the core defect clearly persists -- still a real, substantial undercount, not a rounding gap. New this pass: the exhaustive Referenceable scan itself returned 39 duplicate GUIDs across different pages (19166 total vs 19127 distinct) -- not previously noted, suggests unstable server-side result ordering for this specific broad-type scan as a plausible (unconfirmed) mechanism behind the omissions too. Nothing to fix client-side. No code change, tracker note only. Signed-off-by: Dan Wolfson <dan.wolfson@pdr-associates.com>
…onfirm ISSUE-55 still accurate ISSUE-55's original entry had a second, unrelated issue (glossary-term sort-scope/pagination) merged in underneath it with no --- divider and an orphaned second Status: line, from the original egeria-workspaces-fs consolidation. Split it out as its own numbered entry (ISSUE-60), no content changed. Re-checked ISSUE-55 itself against the current server/pydantic models -- FindRequestBody still has no exclude-type/negation field anywhere (checked both Egeria-api-metadata-expert.http and the live FindRequestBody model). Per user's decision, left as a documented, blocked enhancement -- nothing actionable in pyegeria until Egeria adds real server-side negation support. No code change. Signed-off-by: Dan Wolfson <dan.wolfson@pdr-associates.com>
…plicate risk (ISSUE-59) Two-part fix for Create <X> upsert commands silently duplicating an element when the caller changes ### Qualified Name to something the as-is lookup has never seen before: 1. fetch_as_is() now tries an explicit ### GUID attribute directly via fetch_element() before any qualified-name-derivation or name-based lookup. Previously this attribute was accepted and parsed but never consulted for the as-is lookup at all -- the one case where a caller most needs the check to target a specific element (renaming its QN) was exactly the case it was silently ignored. 2. The existing 'same Display Name, different QN' guard (added since this issue was filed) now calls self._add_warning() instead of only logger.info() -- the risk was already detected server-side, it just never reached the caller in --process/--validate output. The warning names the existing element's GUID and how to target it directly. Verified live with the exact original repro: Create Perspective with a new Qualified Name and no GUID now creates a second element AND prints an explicit warning (previously fully silent); a follow-up re-run with the same QN plus the original GUID correctly rewrites to Update, returns the same GUID, and the fetched element shows the QN actually changed with version incremented 1->2 -- no duplicate. Test elements cleaned up. pytest tests/ -m unit passes. Signed-off-by: Dan Wolfson <dan.wolfson@pdr-associates.com>
…irmed unreliable, not a design ambiguity Checked pyegeria's request shape against Egeria-api-glossary-manager.http's findGlossaryTerms worked example -- byte-identical, not a client-side body-construction bug. Tested live: sequencing_property=displayName/ qualifiedName both still return server-internal order, not alphabetical. Went further than the original repro -- compared None/ASCENDING/DESCENDING/ CREATION_DATE_RECENT: None/DESCENDING/CREATION_DATE_RECENT return identical first-page sets while ASCENDING differs, so the parameter isn't fully inert (influences scan strategy) but never produces an actual sorted order. Confirms fetch-all-then-sort client-side is necessary, not just cautious. Product-strategy questions (fetch-all vs paged UI, maxPageSize, shared helper) remain genuine team decisions, not attempted here -- nothing client-side to fix regardless. No code change, tracker note only. Signed-off-by: Dan Wolfson <dan.wolfson@pdr-associates.com>
Spot-checked the exact original repro plus the three previously-crashing scramble sites and ClassificationExplorer.find_root_elements's field-scramble fix, live against qs-view-server -- all still correct, no regression. pytest tests/ -m unit passes. No code change, tracker note only. Signed-off-by: Dan Wolfson <dan.wolfson@pdr-associates.com>
…ence Re-confirmed live: bogus GUID raises PyegeriaNotFoundException (not NameError), and a real find-then-fetch-by-guid round trip succeeds with the correct identifier. Also fixed a stale 'currently broken outright' note in the Quick-reference table that hadn't been updated when this was fixed 2026-08-05. No code change. Signed-off-by: Dan Wolfson <dan.wolfson@pdr-associates.com>
Re-ran test_create_my_todo directly against the live server -- passes, confirms its own cleanup, and a direct get_metadata_element_by_guid immediately after correctly raises PyegeriaNotFoundException. No code change, tracker note only. Signed-off-by: Dan Wolfson <dan.wolfson@pdr-associates.com>
Recreated the exact repro fresh (new ResultsSet + SavedQuery pair, real SmartQuery link) -- get_metadata_element_relationships correctly returns the relationship instead of 'No elements found'. Test elements cleaned up. pytest tests/ -m unit passes. No code change, tracker note only. Signed-off-by: Dan Wolfson <dan.wolfson@pdr-associates.com>
Created a fresh ValidValueDefinition pair, linked via _async_link_valid_value_member() -- succeeds. Test elements cleaned up. No code change, tracker note only. Signed-off-by: Dan Wolfson <dan.wolfson@pdr-associates.com>
…ia first, pyegeria second, closed last Split the flat 'Open Issues' section (previously several loosely-related ## subsections mixing pyegeria bugs, Egeria server bugs, design discussions, and docs gaps) into two clearly-scoped sections ordered by what's actionable: 1. 'Open Egeria Server issues (not fixable in pyegeria)' -- ISSUE-30, 57, 52, 53, 54, 38, 41, 60. Pure Egeria-side defects; nothing here can be fixed by editing this repo. 2. 'Open pyegeria items (including follow-ons blocked on an Egeria fix)' -- ISSUE-48, 55. Both are pyegeria/Dr.Egeria SDK gaps that are currently blocked on an Egeria Server capability that doesn't exist yet; each entry already documents what pyegeria needs to build once that capability ships, so the follow-on work isn't lost. Everything else (all entries whose current Status is fixed/n/a/not-a-bug) moved to the existing Appendix, unchanged in content -- this consolidates several since-reclassified entries (ISSUE-14, 17, 39, 43 were fixed pyegeria-side but still sitting under the old 'Egeria Server' heading; ISSUE-19 was fixed but sitting under 'Docs' gaps) into the Fixed appendix where they now belong. No issue content was altered -- verified every '### ISSUE-N' title line is byte-identical to HEAD before/after (diff on sorted title lists is empty). Reordering only. Also fixed a real extraction bug caught before writing the file: an initial mechanical pass mistook '#'-prefixed Python comment lines inside fenced code examples for markdown headers, which would have silently truncated ~18 entries (ISSUE-34 lost 724 words, ISSUE-60 lost 352, several others 100-250 words each) -- redone fence-aware, verified word-for-word against the original before replacing the file. Signed-off-by: Dan Wolfson <dan.wolfson@pdr-associates.com>
…biguity warning (ISSUE-59) The 'Automatic Command Rewriting (Upsert)' section only described matching by Qualified Name -- stale since ISSUE-59's fix: an explicit ### GUID now takes priority for the as-is lookup, and re-running Create <X> with a new Qualified Name under the same Display Name now surfaces an explicit warning instead of silently duplicating. Added a paragraph documenting both, including the exact warning text and how to correctly rename an element's Qualified Name via ### GUID. Signed-off-by: Dan Wolfson <dan.wolfson@pdr-associates.com>
…just CPU load Recurred while retrying the help-Glossary --process step. docker stats showed Postgres at up to 650% CPU; connecting directly found the real mechanism -- 38 connections stuck 'idle in transaction' against the egeria DB, all holding the same entity-table query shape open. CPU eased over 15 minutes without by-name-search latency improving at all, showing this is a connection-holding problem, not simple compute starvation. No code change, diagnostic note only. Signed-off-by: Dan Wolfson <dan.wolfson@pdr-associates.com>
Three new command surfaces in Dr.Egeria v2, added via the Spec Editor
REST API (compact-spec edits) plus bespoke processors where the
generic family walkers don't apply:
Action Author family:
- Create Embedded Process (EmbeddedProcess -> Action -> Process ->
Asset; upsert-by-qualified-name via AssetMaker's generic asset
endpoints, same pattern as report.py's ReportProcessor since no
dedicated OMVS wrapper exists for this type).
- Initiate Engine Action (ad-hoc runtime request against a governance
engine, distinct from the family's existing design-time Governance
Action Process/Type/Step definitions). Fixed a real pyegeria bug
along the way: AutomatedCuration._async_initiate_engine_action's URL
was missing the required {governanceEngineName} path segment
entirely (confirmed against AutomatedCurationResource.java's actual
@PostMapping route) -- the method was unusable before this. Verified
live: the fixed URL now reaches Egeria's real business logic
(governance-engine-name resolution, request-type validation), not
the malformed-URL client error it hit before.
- Cancel Engine Action. New "Cancel"/"Initiate" verbs added to
STANDARD_VERBS (extraction.py) since neither existed -- both
intentional new verbs, not overloading Delete/Remove/Create (Cancel
doesn't erase the audit record; Initiate is never an idempotent
upsert the way every other Create command is).
Lineage Linker family (new):
- One generic Link/Update/Unlink command triple covering all seven
Lineage Linker OMVS relationship types (DataFlow, ControlFlow,
ProcessCall, LineageMapping, DataMapping, UltimateSource,
UltimateDestination) via a Relationship Type selector attribute --
mirrors the OMVS client's own generic link_lineage() design rather
than 14 thin per-type command wrappers. Link and Unlink share one
processor class (LineageLinkProcessor) because compact-spec tooling
treats every LINK_VERBS member as synonyms for variant-registration
purposes, so two different classes would silently clobber each
other's dispatcher slot -- same constraint CurationLinkProcessor
already resolves the same way.
- Found and fixed a second pyegeria/Egeria-platform bug along the way:
deleteRelationshipInStore rejects its own server-side default
deleteMethod (LookForLineage) for relationship deletes
(OMAG-COMMON-400-032) -- confirmed live against a real DataFlow
relationship, and confirmed independently reproducing in unrelated
integration connectors (JacquardDigitalProductLoom,
OMAGServerPlatformCataloguer) in the live server's own logs, so this
isn't specific to the new command. Added the missing delete_method
field to DeleteRelationshipRequestBody (models.py) so callers can
override it; LineageLinker.detach_lineage now passes SOFT_DELETE
explicitly.
Verified against a live server (quickstart, qs-view-server): created
and inspected a real EmbeddedProcess element directly, created and
inspected a real DataFlow relationship directly (all properties
landed correctly), unlinked it and confirmed the relationship was
actually gone, confirmed Initiate Engine Action's fixed URL reaches
real Egeria business logic. compact-spec validation (0 errors),
pytest -m unit, and test_gen_report_specs.py all pass.
Also fixes a same-name attribute-pooling hazard the new Lineage Linker
family's original attribute defs accidentally tripped: attributes with
the same NAME across different family JSON files get treated as one
shared pool by generate_md_cmd_templates, so a same-named-but-
different-definition "Relationship Type"/"Guard"/"Label"/"Description"
briefly clobbered unrelated commands' rendered template output in
Glossary/Curation/Action Author (caught via git diff on the synced
egeria-workspaces-fs templates, fixed by renaming the Lineage-Linker-
specific one and aligning the rest to the existing canonical text).
Signed-off-by: Dan Wolfson <dan.wolfson@pdr-associates.com>
Signed-off-by: Dan Wolfson <dan.wolfson@pdr-associates.com>
New count_elements_by_property(mgr, type_name, property_name, property_value, as_of) — counts ACTIVE elements of a given type whose named string property equals a value, e.g. counting DigitalProduct elements by deploymentStatus for the Egeria Overview dashboard's Data Products tile (egeria-workspaces-fs OVERVIEW_NEXT_STEPS.md "Remaining app wiring"). Same native-count-with-fallback seam as the existing count_elements (one cheap native count_metadata_elements call, falls back to len(find_metadata_elements(...)) on older servers), just with a searchProperties EQ condition instead of a bare type filter. Verified live against quickstart's Egeria server (via a live-patched copy in the quickstart-pyegeria-web container's site-packages, since that container runs the published pyegeria package, not this dev checkout): correctly counted 2 ACTIVE of 6 total DigitalProduct elements. pytest -m unit passes. Signed-off-by: Dan Wolfson <dan.wolfson@pdr-associates.com>
…bump deps - test_automated_curation.py: point at the actual local server names (good_server_1 -> qs-metadata-store, good_view_server_2 for the UC server-element test) instead of stale names from an older environment; update the UC-from-template test's target (laz3/port 8080 -> uc-unity-coco/port 8087, matching the actual running container); add test_initiate_file_directory_create_and_survey exercising initiate_gov_action_process against FileDirectory:CreateAndSurveyGovernanceActionProcess. - uv.lock: routine dependency version bumps. Signed-off-by: Dan Wolfson <dan.wolfson@pdr-associates.com>
Confirmed live 2026-08-17 (after the quickstart Egeria redeploy): ClassificationExplorer.get_relationships(page_size=5000) now fails with OMAG-COMMON-400-010 "The number of records to return, 5000... is greater than the allowable maximum of 1000" on findRelationshipsBetweenMetadataElements. count_relationships() catches this as a total failure and returns None, so every caller silently degraded instead of erroring -- context_readiness_funnel's `lineage` stage, ai_ready_assets' composite (which also depends on DataFlow relationships), and any AttachedRating/Comment/Like/Tag/ NoteLog count via feedback_summary() were all quietly returning None/0-that-looked-intentional rather than their real values. Caught while re-verifying the Overview dashboard's Data Products tile (this session's prior commit) after the redeploy -- its dataProductsRatings=None looked like "confirmed zero ratings" but was actually this same silent failure; the true value (also 0, re-verified after this fix) happened to match by coincidence, not because the earlier check was actually sound. Replaced the three hardcoded page_size=5000 call sites with the existing DEFAULT_CAP constant (500, already the established cap used throughout this file, safely under the new 1000 server limit) -- count_relationships (line 304), and the two DataFlow relationship fetches inside ai_ready_assets (lines 727, 848). Verified live: funnel.lineage 372→null became 9 (real count); funnel.aiReady 0→null-masked became 4; Data Products' dataProductsRatings now computes a real (still coincidentally 0) result instead of silently failing. pytest -m unit passes. Note for whoever picks this up: `grep -rn "page_size=5000"` also hits egeria-workspaces-fs's insights_handler.py (one call site) and this repo's test_overview_asof.py -- not fixed here, out of scope for the Overview dashboard work this was found during, but likely the same live bug wherever it's hit. Signed-off-by: Dan Wolfson <dan.wolfson@pdr-associates.com>
Previously a bare hardcoded module constant in pyegeria/core/_globals.py, completely disconnected from the .env/config.json settings system every other pyegeria default already goes through. Follow-up to c631f0c (the page_size=5000 fix): that fixed the three call sites that had drifted to their own oversized literal, but max_paging_size itself was still not something a deployment could tune without a code change if Egeria's server-side page-size limit changes again. New settings field egeria_max_page_size (EGERIA_MAX_PAGE_SIZE env var / "Egeria Max Page Size" in config.json), same Field(default=..., alias=...) pattern as egeria_width, merged in load_app_config() the same way. _globals.py now reads it from settings at import time (wrapped in try/except, falling back to the bare 500 default if settings can't load yet -- e.g. mid-bootstrap, no .env present -- so this can't break the import chain). overview_metrics.py's DEFAULT_CAP now derives from max_paging_size instead of an independent hardcoded 500 -- one source of truth instead of two constants that happened to match today by coincidence. Verified live: EGERIA_MAX_PAGE_SIZE=750 override confirmed working both standalone and inside the quickstart-pyegeria-web container (docker exec -e EGERIA_MAX_PAGE_SIZE=750 ... -> max_paging_size == 750). Default (no override) still correctly resolves to 500, safely under Egeria's 1000 max. pytest -m unit passes. Signed-off-by: Dan Wolfson <dan.wolfson@pdr-associates.com>
OVERVIEW_NEXT_STEPS.md's "Usage % contextualised" looked blocked on a
genuine per-asset participation traversal (no native "count of
elements reachable from a relationship" API exists in Egeria/pyegeria
today). It isn't, once routed through the right relationship instead
of trying to walk every asset: `ImplementedBy` (model 0737, Solution
Implementation) links a SolutionComponent to its concrete
implementation -- end1 is always SolutionComponent, end2 is whatever
actually implements it.
Confirmed live 2026-08-17: on this dataset end2 is a real mix (109
GovernanceActionType, 31 genuine Asset-subtype elements --
IntegrationConnector/SoftwareServer/Topic/SoftwareServerPlatform), so
filtering end2 to Asset-subtype elements and counting distinct GUIDs
is a single bounded relationship fetch, not a traversal. Also checked
the sibling relationship ImplementationResource -- connects only to
GovernanceActionType in this dataset, not useful here, not included.
New contextualised_coverage(mgr, ce, as_of) returns
{contextualisedCount, assetTotal, contextualisedPct}. Documented as a
proxy in its own docstring, not the literal metric: confirms an asset
was given *some* solution-design context via ImplementedBy, not that
its specific SolutionComponent is itself wired into an
InformationSupplyChain/SolutionBlueprint (would need a second
composition-relationship hop) -- same single-hop tradeoff every other
proxy metric in this module already makes (e.g. `lineage` counting
DataFlow relationships without confirming strict-sense lineage
semantics per edge).
Verified live: contextualisedCount=31, assetTotal=384,
contextualisedPct=8.1. pytest -m unit passes.
Signed-off-by: Dan Wolfson <dan.wolfson@pdr-associates.com>
…0b1f) Four gaps identified by comparing recent production changes against existing test coverage, all closeable without a live server: - test_automated_curation_engine_action.py: regression test for AutomatedCuration._async_initiate_engine_action's URL shape. b17f71e's commit message documents this method was unusable before that commit -- the URL was missing the required {governanceEngineName} path segment -- and nothing protected against it regressing. Mocks _async_make_request, asserts the URL, body shape, and sync-wrapper delegation. - test_action_author_processor_coverage.py: dispatcher-registration coverage for the "Action Author" family, mirroring test_governance_processor_coverage .py's existing check for "Governance Officer". register_governance_processors is family-name-gated (CLAUDE.md's documented gotcha) and "Action Author" was added as a second gated family in b17f71e with no equivalent test -- this walks the real compact specs and asserts every Action Author command variant reaches a processor, the OM_TYPE-routed Link commands reach their dedicated processors, and Create Embedded Process / Initiate Engine Action / Cancel Engine Action reach their bespoke override registrations. - test_overview_metrics.py: unit tests for contextualised_coverage (8010b1f) and count_elements_by_property (d2143e7), the two newest overview_metrics functions -- both were only "verified live," not added to the suite that covers every sibling metric. - test_globals_max_paging_size.py: unit tests for the env-configurable max_paging_size added in 18486a9 -- default value, EGERIA_MAX_PAGE_SIZE override, and the fallback-to-500 path when settings can't load yet, plus confirming overview_metrics.DEFAULT_CAP tracks it as one source of truth. pytest tests/micro-tests/ passes (including the full suite together, to rule out cross-test pollution from the reload-based max_paging_size tests). Signed-off-by: Dan Wolfson <dan.wolfson@pdr-associates.com>
Initiate Engine Action has a real side effect (kicks off whatever the target governance engine is configured to run), unlike every other Dr.Egeria command's metadata-only create/update/delete -- flagged during today's test-coverage audit before adding any live functional/scenario test for it. Current coverage stays at the mocked/unit level (dispatcher-registration + client URL-shape tests added this session); live coverage needs a decision on an isolated test target first. Signed-off-by: Dan Wolfson <dan.wolfson@pdr-associates.com>
karma_leaderboard: top-N people by karma. One bounded find over ContributionRecord elements (karmaPoints is a scalar property on the record itself, not derived from counting related things), filtered to Person-anchored records via the standard Anchors classification each element already carries, sorted desc. engagement_series: weekly-bucketed feedback trend. Reuses the same 5 feedback-relationship-type queries feedback_summary() already makes, keeping each relationship's createTime instead of only the count, bucketed into ISO weeks and zero-filled across the trailing window. Both feed the Overview dashboard's People panel leaderboard/ engagementSeries fields, previously left None as "deferred". Signed-off-by: Dan Wolfson <dan.wolfson@pdr-associates.com>
Extends governed_coverage() to bucket the same hits list it already fetches for byClassification/topZones into fullyGoverned (carries >=1 substantive governance classification: Confidentiality/Criticality/ Impact/Retention) and partialZoneOnly (carries ZoneMembership and nothing else from the governance set) -- no extra query, just additional aggregation over data already in hand. Feeds the Overview dashboard's "Fully/Partial/Ungoverned breakdown", previously a hardcoded sample split with a comment noting the shape governed_coverage returned couldn't support it. Signed-off-by: Dan Wolfson <dan.wolfson@pdr-associates.com>
load_compact_specs_from_dir() pools attribute_definitions from every compact_commands/*.json file by name alone -- b17f71e's commit message documents this silently corrupting Glossary/Curation/Action Author's rendered templates when the new Lineage Linker family's original attribute defs reused "Relationship Type"/"Guard"/"Label"/"Description" with different definitions. It was only caught by a human diffing synced templates afterward, not by a test. test_compact_attribute_name_collisions.py reads every real compact JSON file directly and compares only the fields generate_md_cmd_templates.py's _write_attr_block() actually renders (input_required, data_type/style, description, attr_labels, valid_values, default_value) -- ignoring bookkeeping-only fields like "Journal Entry" that don't affect template output. A blanket zero-collisions assertion turned out too strict: several common attribute names (Identifier, Element Id, Effective Time, ...) are already, legitimately duplicated with family-specific wording across many files, predating this test. So the test instead baselines today's known collisions and fails only on a NEW colliding name -- verified the detection logic actually works by injecting a synthetic collision into a temp directory and confirming it fails before adding the baseline exemption mechanism. Also corrects a stale pointer in c631f0c's commit message (claimed test_overview_asof.py needed the same page_size=5000 fix; that file doesn't exist in this repo and the grep now returns nothing) -- noted in BACKLOG.md rather than rewriting already-pushed history. pytest tests/micro-tests/ passes in full. Signed-off-by: Dan Wolfson <dan.wolfson@pdr-associates.com>
…ng it PR odpi#252 (docs/backlog-template-scan-findings, 2026-07-06) documented two findings. Its Create Project Parent ID/Parent Relationship Type Name item is superseded -- already fixed and documented in more depth directly on main (2026-08-02, "Parent ID/Parent Relationship Type Name silently dropped on Update (fixed)"). Its cross-family Link/Attach template-defect scan (missing reference fields on Link_Term-Term_Relationship/Attach_Comment, copy-pasted field text on a few Governance Officer/Data Designer commands) is NOT captured anywhere else, so closing odpi#252 outright would have silently lost it. Ported here with the fix path updated from Tinderbox (retired 2026-08-05) to the Dr.Egeria Spec Editor. Signed-off-by: Dan Wolfson <dan.wolfson@pdr-associates.com>
orphan_glossary_terms: approved-but-unassigned glossary terms. One bounded SemanticAssignment relationship fetch, filtered to the GlossaryTerm-typed end, distinct-GUID count is the "referenced" set; orphan = term total - referenced. Same single-bounded-fetch shape as contextualised_coverage's ImplementedBy proxy. stale_assets: assets with no update in N days (default 180). One bounded Asset element fetch, each element's own version metadata (_update_time, already used elsewhere in this module) compared against a cutoff -- no relationship traversal. as_of anchors both the query and the cutoff clock, matching certifications_summary's own as_of handling. Both feed the Overview dashboard's Attention Queue panel, previously two of five rows with no backend computation at all. Signed-off-by: Dan Wolfson <dan.wolfson@pdr-associates.com>
…ions
analytic_registry.py: adds count_elements_by_property,
contextualised_coverage, karma_leaderboard, engagement_series,
orphan_glossary_terms, stale_assets to _BUILTINS -- the registry's own
docstring claimed to cover "every analytic function that already
exists," which had gone stale relative to overview_metrics.py's real
content. 23/23 parity restored against analytic_demo_specs.py, which
gets one matching demo FormatSet per new function.
Verified live: /api/analytics returns all 23 functions, /api/report-specs
returns 348 specs including all 6 new demos, and executing "Analytic
Demo - Orphan Glossary Terms" returns real data
({"termTotal": 407, "referencedCount": 9, "orphanCount": 398}).
Also logs PYEGERIA_ISSUES.md ISSUE-61: no Dr.Egeria command exists to
attach a GovernanceMetric to its implementation via the GovernanceResults
relationship, even though the OMVS wrapper
(GovernanceOfficer.link_governance_results) already exists -- found
while piloting GovernanceMetric->Report as the "describe a dashboard
metric in Egeria itself" design (see egeria-workspaces-fs's
OVERVIEW_NEXT_STEPS.md for the full pilot writeup). Purely a missing
compact-spec command + processor wiring, not an SDK gap.
Signed-off-by: Dan Wolfson <dan.wolfson@pdr-associates.com>
No Dr.Egeria command existed for GovernanceResults (linking a GovernanceMetric to the data asset where its measurements are kept), even though the OMVS wrapper (GovernanceOfficer.link_governance_results/ _async_link_governance_results, plus detach_governance_results/ _async_detach_governance_results) already existed -- purely missing compact-spec + processor wiring, not an SDK gap. Added via the Dr.Egeria Spec Editor's REST API (compact-spec edits): - Two new attributes, "Governance Metric" (existing_element: GovernanceMetric) and "Data Asset" (existing_element: Asset), both Reference Name style, matching the sibling "Governance Definition"/ "Referenceable" pair on "Link Governed By". - New command "Link Governance Results" (OM_TYPE GovernanceResults, bundle "Link Command Base" -- same bundle every other simple Governance Officer Link command uses). GovernanceLinkProcessor (md_processing/v2/governance.py) already handles both Link and its Detach/Unlink/Remove variants from one spec entry via build_command_variants -- no separate registration needed. Added a "Governance Results" entry to its endpoint_map and one apply_changes branch per direction, calling _async_link_governance_results/ _async_detach_governance_results with a body built via the existing generic set_rel_prop_body() (produces class "GovernanceResultsProperties" from the object_type name, matching the real properties class exactly -- no bespoke body builder needed, same as Notification Subscriber/Zone Hierarchy/ Monitored Resource). Verified: validate_compact_specs reports 0 errors (same pre-existing 26 warnings as baseline, none new); refresh_specs regenerated basic+advanced markdown templates correctly; test_governance_processor_coverage.py confirms the new command variants reach GovernanceLinkProcessor via the existing generic family walk with no dispatcher changes required. Added 3 new unit tests to test_governance_link_processor.py (link, unlink, missing-reference-guid) following the file's existing per-object-type pattern -- all pass, along with the full pytest tests/micro-tests/ suite. Signed-off-by: Dan Wolfson <dan.wolfson@pdr-associates.com>
Dan added the "Link Governance Results" Dr.Egeria command (commit 80526c3) and cut pyegeria 6.0.18.2 with it plus this session's other Overview dashboard work. Verified live against the pilot GovernanceMetric/ Report pair: validate/process both succeed, the relationship resolves correctly via mgr.get_all_related_elements() after re-linking through the new command. Moved the entry from "Open pyegeria items" to the Appendix's "Fixed / Resolved" section per this file's own convention, keeping its ISSUE-61 number. Also verified 6.0.18.2 itself: installed into quickstart-pyegeria-web, all 23 analytic_registry.py functions and 348 report specs present, "Link Governance Results" resolves and executes correctly end to end. Signed-off-by: Dan Wolfson <dan.wolfson@pdr-associates.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Accumulated fixes and features from an extended
pyegeriaHTTP-endpoint audit and Dr.Egeria work, spanning 42 commits. Grouped by theme below (see individual commit messages for full detail — most document live verification against a real Egeria server).pyegeria SDK bug fixes (found via systematic HTTP-endpoint/ISSUE audit)
2603117), including a genuinely brokenAutomatedCuration.initiate_engine_actionmissing its{governanceEngineName}path segment (b17f71e)fetch_elementtimeout retry + a delete-body crash (a6fdbd4)reference_data.py(ISSUE-56) (880cc44)AssetCataloglineage graph used two nonexistent field names, no depth override (9277b23)property_name/wire-key mapping (ISSUE-22) (58c23ee)max_mermaid_node_countdefault raised, dead params on solution blueprint retrieval fixed (ISSUE-23) (dd33b95)fe2357b)server-templatesendpoint (ISSUE-43) (7114e24)specification-properties/by-type(ISSUE-17) (afa5285)fetch_as_isnow honors an explicit GUID, warns on silent-duplicate risk (ISSUE-59) (3ea695c)overview_metricspage_size=5000exceeded Egeria's new 1000-record max (c631f0c)Dr.Egeria features
f1c5ed1)2afa6d3)b17f71e)4aff48e)Link/Unlink Governance Resultscommand (Governance Officer family) — the OMVS wrapper (GovernanceOfficer.link_governance_results/detach_governance_results) already existed but had no compact-spec/dispatcher wiring; now routes through the existingGovernanceLinkProcessor(80526c3)Overview dashboard metrics
count_elements_by_propertyhelper (d2143e7)max_paging_sizemade env-configurable (EGERIA_MAX_PAGE_SIZE), replacing a hardcoded module constant (18486a9)contextualised_coverage(Usage % contextualised) (8010b1f)karma_leaderboardandengagement_series(57a345c)governed_coveragenow returns a Fully/Partial governance split (4c86092)Test coverage
test_create_my_todoteardown fix — was leaking live ToDos (097558c)FileDirectory:CreateAndSurveygovernance-action-process test, live-verified (be89676)overview_metricsunit tests,max_paging_sizeconfig tests (51be451)29eebc1)Dependencies
uv.lockrefreshed to close all 90 open Dependabot alerts (1 critical, ~24 high, ~30 medium, ~9 low) — all resolved within existingpyproject.tomlconstraints, no manual pins needed (be89676)Docs / issue tracking
PYEGERIA_ISSUES.mdmaintenance: re-verification passes confirming prior fixes still hold, status restructuring by who-can-fix-it (Egeria vs. pyegeria vs. closed), and new/updated issue write-ups (ISSUE-52, -59, -60, and re-checks of -14, -25, -28, -30, -38, -48, -53, -54, -55, -56)BACKLOG.mdentries flagging the live-test risk forInitiate Engine Actionand a stale pointer correction in an earlier commit messageTesting
pytest tests/micro-testspasses in full. Most individual fixes/features are documented as live-verified against a real Egeria server in their own commit messages. TheFileDirectory:CreateAndSurveytest inbe89676was run against a liveqs-view-serverthis session and confirmed passing.🤖 Generated with Claude Code