ui-design-workbench-cli 0.6.6__tar.gz → 0.6.7__tar.gz
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.
- {ui_design_workbench_cli-0.6.6 → ui_design_workbench_cli-0.6.7}/PKG-INFO +2 -2
- {ui_design_workbench_cli-0.6.6 → ui_design_workbench_cli-0.6.7}/README.md +1 -1
- {ui_design_workbench_cli-0.6.6 → ui_design_workbench_cli-0.6.7}/pyproject.toml +1 -1
- {ui_design_workbench_cli-0.6.6 → ui_design_workbench_cli-0.6.7}/scripts/fidelity_platform_adapters.py +27 -3
- {ui_design_workbench_cli-0.6.6 → ui_design_workbench_cli-0.6.7}/scripts/render_preview.py +9 -5
- {ui_design_workbench_cli-0.6.6 → ui_design_workbench_cli-0.6.7}/scripts/scan_ui.py +71 -1
- {ui_design_workbench_cli-0.6.6 → ui_design_workbench_cli-0.6.7}/scripts/ui_design_workbench_cli.egg-info/PKG-INFO +2 -2
- {ui_design_workbench_cli-0.6.6 → ui_design_workbench_cli-0.6.7}/scripts/uidw.py +21 -1
- {ui_design_workbench_cli-0.6.6 → ui_design_workbench_cli-0.6.7}/SKILL.md +0 -0
- {ui_design_workbench_cli-0.6.6 → ui_design_workbench_cli-0.6.7}/references/adapter-api.md +0 -0
- {ui_design_workbench_cli-0.6.6 → ui_design_workbench_cli-0.6.7}/references/agent-integrations.md +0 -0
- {ui_design_workbench_cli-0.6.6 → ui_design_workbench_cli-0.6.7}/references/cache-protocol.md +0 -0
- {ui_design_workbench_cli-0.6.6 → ui_design_workbench_cli-0.6.7}/references/component-catalog.json +0 -0
- {ui_design_workbench_cli-0.6.6 → ui_design_workbench_cli-0.6.7}/references/component-catalog.md +0 -0
- {ui_design_workbench_cli-0.6.6 → ui_design_workbench_cli-0.6.7}/references/component-inventory.json +0 -0
- {ui_design_workbench_cli-0.6.6 → ui_design_workbench_cli-0.6.7}/references/design-modes.md +0 -0
- {ui_design_workbench_cli-0.6.6 → ui_design_workbench_cli-0.6.7}/references/fidelity.md +0 -0
- {ui_design_workbench_cli-0.6.6 → ui_design_workbench_cli-0.6.7}/references/ir-schema.md +0 -0
- {ui_design_workbench_cli-0.6.6 → ui_design_workbench_cli-0.6.7}/references/native-rendering.md +0 -0
- {ui_design_workbench_cli-0.6.6 → ui_design_workbench_cli-0.6.7}/references/platform-profiles.json +0 -0
- {ui_design_workbench_cli-0.6.6 → ui_design_workbench_cli-0.6.7}/references/platform-standards.md +0 -0
- {ui_design_workbench_cli-0.6.6 → ui_design_workbench_cli-0.6.7}/references/platforms.md +0 -0
- {ui_design_workbench_cli-0.6.6 → ui_design_workbench_cli-0.6.7}/references/quality-automation.md +0 -0
- {ui_design_workbench_cli-0.6.6 → ui_design_workbench_cli-0.6.7}/references/review-workflow.md +0 -0
- {ui_design_workbench_cli-0.6.6 → ui_design_workbench_cli-0.6.7}/references/ui-guidance-mode.md +0 -0
- {ui_design_workbench_cli-0.6.6 → ui_design_workbench_cli-0.6.7}/references/ui-policy-schema.md +0 -0
- {ui_design_workbench_cli-0.6.6 → ui_design_workbench_cli-0.6.7}/references/ui-reviewer.md +0 -0
- {ui_design_workbench_cli-0.6.6 → ui_design_workbench_cli-0.6.7}/references/validation.md +0 -0
- {ui_design_workbench_cli-0.6.6 → ui_design_workbench_cli-0.6.7}/references/workbench-ui.md +0 -0
- {ui_design_workbench_cli-0.6.6 → ui_design_workbench_cli-0.6.7}/schemas/native-render-state.schema.json +0 -0
- {ui_design_workbench_cli-0.6.6 → ui_design_workbench_cli-0.6.7}/schemas/ui-agent-job.schema.json +0 -0
- {ui_design_workbench_cli-0.6.6 → ui_design_workbench_cli-0.6.7}/schemas/ui-graph.schema.json +0 -0
- {ui_design_workbench_cli-0.6.6 → ui_design_workbench_cli-0.6.7}/schemas/ui-ir.patch.schema.json +0 -0
- {ui_design_workbench_cli-0.6.6 → ui_design_workbench_cli-0.6.7}/schemas/ui-ir.schema.json +0 -0
- {ui_design_workbench_cli-0.6.6 → ui_design_workbench_cli-0.6.7}/schemas/uidw-config.schema.json +0 -0
- {ui_design_workbench_cli-0.6.6 → ui_design_workbench_cli-0.6.7}/scripts/android_resource_resolver.py +0 -0
- {ui_design_workbench_cli-0.6.6 → ui_design_workbench_cli-0.6.7}/scripts/android_xml_support.py +0 -0
- {ui_design_workbench_cli-0.6.6 → ui_design_workbench_cli-0.6.7}/scripts/apple_resource_resolver.py +0 -0
- {ui_design_workbench_cli-0.6.6 → ui_design_workbench_cli-0.6.7}/scripts/coverage_report.py +0 -0
- {ui_design_workbench_cli-0.6.6 → ui_design_workbench_cli-0.6.7}/scripts/fidelity_adapter_api.py +0 -0
- {ui_design_workbench_cli-0.6.6 → ui_design_workbench_cli-0.6.7}/scripts/fidelity_adapters.py +0 -0
- {ui_design_workbench_cli-0.6.6 → ui_design_workbench_cli-0.6.7}/scripts/fidelity_core.py +0 -0
- {ui_design_workbench_cli-0.6.6 → ui_design_workbench_cli-0.6.7}/scripts/generate_interaction_matrix.py +0 -0
- {ui_design_workbench_cli-0.6.6 → ui_design_workbench_cli-0.6.7}/scripts/ir_contracts.py +0 -0
- {ui_design_workbench_cli-0.6.6 → ui_design_workbench_cli-0.6.7}/scripts/layout_model.py +0 -0
- {ui_design_workbench_cli-0.6.6 → ui_design_workbench_cli-0.6.7}/scripts/merge_review_state.py +0 -0
- {ui_design_workbench_cli-0.6.6 → ui_design_workbench_cli-0.6.7}/scripts/native_render_android.py +0 -0
- {ui_design_workbench_cli-0.6.6 → ui_design_workbench_cli-0.6.7}/scripts/native_render_apple.py +0 -0
- {ui_design_workbench_cli-0.6.6 → ui_design_workbench_cli-0.6.7}/scripts/native_render_contracts.py +0 -0
- {ui_design_workbench_cli-0.6.6 → ui_design_workbench_cli-0.6.7}/scripts/native_render_registry.py +0 -0
- {ui_design_workbench_cli-0.6.6 → ui_design_workbench_cli-0.6.7}/scripts/platform_component_catalog.py +0 -0
- {ui_design_workbench_cli-0.6.6 → ui_design_workbench_cli-0.6.7}/scripts/quality_common.py +0 -0
- {ui_design_workbench_cli-0.6.6 → ui_design_workbench_cli-0.6.7}/scripts/scoped_context.py +0 -0
- {ui_design_workbench_cli-0.6.6 → ui_design_workbench_cli-0.6.7}/scripts/smoke_preview.js +0 -0
- {ui_design_workbench_cli-0.6.6 → ui_design_workbench_cli-0.6.7}/scripts/ui_design_workbench_cli.egg-info/SOURCES.txt +0 -0
- {ui_design_workbench_cli-0.6.6 → ui_design_workbench_cli-0.6.7}/scripts/ui_design_workbench_cli.egg-info/dependency_links.txt +0 -0
- {ui_design_workbench_cli-0.6.6 → ui_design_workbench_cli-0.6.7}/scripts/ui_design_workbench_cli.egg-info/entry_points.txt +0 -0
- {ui_design_workbench_cli-0.6.6 → ui_design_workbench_cli-0.6.7}/scripts/ui_design_workbench_cli.egg-info/requires.txt +0 -0
- {ui_design_workbench_cli-0.6.6 → ui_design_workbench_cli-0.6.7}/scripts/ui_design_workbench_cli.egg-info/top_level.txt +0 -0
- {ui_design_workbench_cli-0.6.6 → ui_design_workbench_cli-0.6.7}/scripts/uidw_mcp.py +0 -0
- {ui_design_workbench_cli-0.6.6 → ui_design_workbench_cli-0.6.7}/scripts/validate_platform_profiles.py +0 -0
- {ui_design_workbench_cli-0.6.6 → ui_design_workbench_cli-0.6.7}/scripts/visual_regression.py +0 -0
- {ui_design_workbench_cli-0.6.6 → ui_design_workbench_cli-0.6.7}/setup.cfg +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: ui-design-workbench-cli
|
|
3
|
-
Version: 0.6.
|
|
3
|
+
Version: 0.6.7
|
|
4
4
|
Summary: Repository UI indexing, graph, preview, and deterministic review CLI
|
|
5
5
|
Author: Elgreed
|
|
6
6
|
Project-URL: Homepage, https://github.com/Elgreed/ui-design-workbench
|
|
@@ -131,4 +131,4 @@ A Windows `.exe` is not published yet. PyPI + `pipx` is the primary cross-platfo
|
|
|
131
131
|
- [IR schema](references/ir-schema.md)
|
|
132
132
|
- [Review workflow](references/review-workflow.md)
|
|
133
133
|
|
|
134
|
-
Current CLI version: `0.6.
|
|
134
|
+
Current CLI version: `0.6.7`.
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "ui-design-workbench-cli"
|
|
7
|
-
version = "0.6.
|
|
7
|
+
version = "0.6.7"
|
|
8
8
|
description = "Repository UI indexing, graph, preview, and deterministic review CLI"
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
requires-python = ">=3.10"
|
|
@@ -272,7 +272,15 @@ class AndroidXmlAdapter:
|
|
|
272
272
|
for attr, (path, group) in mapping.items():
|
|
273
273
|
if attr in attrs:
|
|
274
274
|
resolved = catalog.resolve(attrs[attr], group, normalized_style)
|
|
275
|
-
value = resolved.value
|
|
275
|
+
value = _normalize_ref(str(resolved.value), "colors" if group == "color" else group) if resolved.resolved else attrs[attr]
|
|
276
|
+
if not resolved.resolved and str(attrs[attr]).startswith(("@", "?")):
|
|
277
|
+
result.unsupported.append({
|
|
278
|
+
"adapter": self.id,
|
|
279
|
+
"file": active_context.source,
|
|
280
|
+
"line": line,
|
|
281
|
+
"expression": f'{attr}="{attrs[attr]}"',
|
|
282
|
+
"reason": "unresolved-android-resource",
|
|
283
|
+
})
|
|
276
284
|
source = resolved.source or (style_entry.source if attr not in explicit_attrs and style_entry else active_context.source)
|
|
277
285
|
source_line = resolved.line if resolved.source else style_entry.line if attr not in explicit_attrs and style_entry else line
|
|
278
286
|
group_name, key = path.split(".", 1)
|
|
@@ -319,7 +327,9 @@ class AndroidXmlAdapter:
|
|
|
319
327
|
result.unsupported.append({"adapter": self.id, "file": active_context.source, "line": line, "expression": ", ".join(sorted(unsupported_constraints)), "reason": "unsupported-constraint-equation"})
|
|
320
328
|
if attrs.get("text"):
|
|
321
329
|
resolved = catalog.resolve(attrs["text"], "string", normalized_style)
|
|
322
|
-
node["text"] = resolved.value if resolved.resolved else
|
|
330
|
+
node["text"] = resolved.value if resolved.resolved else attrs["text"]
|
|
331
|
+
if not resolved.resolved and str(attrs["text"]).startswith(("@", "?")):
|
|
332
|
+
result.unsupported.append({"adapter": self.id, "file": active_context.source, "line": line, "expression": f'text="{attrs["text"]}"', "reason": "unresolved-android-resource"})
|
|
323
333
|
node["provenance"]["text"] = property_evidence(resolved.source or active_context.source, resolved.line if resolved.source else line, f'text="{attrs["text"]}"', self.id, resolved.confidence if resolved.source else "exact")
|
|
324
334
|
if attrs.get("hint"):
|
|
325
335
|
resolved = catalog.resolve(attrs["hint"], "string", normalized_style)
|
|
@@ -347,6 +357,14 @@ class AndroidXmlAdapter:
|
|
|
347
357
|
node["asset"] = drawable.asset or asset
|
|
348
358
|
node["style"].update(drawable.style)
|
|
349
359
|
node["provenance"]["asset"] = property_evidence(drawable.source or active_context.source, drawable.line if drawable.source else line, str(asset), self.id, drawable.confidence)
|
|
360
|
+
for key in drawable.style:
|
|
361
|
+
node["provenance"][f"style.{key}"] = property_evidence(
|
|
362
|
+
drawable.source or active_context.source,
|
|
363
|
+
drawable.line if drawable.source else line,
|
|
364
|
+
str(asset),
|
|
365
|
+
self.id,
|
|
366
|
+
drawable.confidence,
|
|
367
|
+
)
|
|
350
368
|
if not drawable.asset:
|
|
351
369
|
result.unsupported.append({"adapter": self.id, "file": active_context.source, "line": line, "expression": asset, "reason": "unsupported-android-drawable"})
|
|
352
370
|
scale_types = {"centerCrop": "cover", "fitCenter": "contain", "centerInside": "contain", "fitXY": "fill", "center": "none"}
|
|
@@ -361,7 +379,13 @@ class AndroidXmlAdapter:
|
|
|
361
379
|
"type": "icon", "component": "ImageButton.drawable", "asset": node["asset"], "alt": node.get("alt", ""),
|
|
362
380
|
"layout": {"width": "fill", "height": "fill"}, "style": {"objectFit": node.get("style", {}).get("objectFit", "contain")}, "children": [],
|
|
363
381
|
"source": {"file": active_context.source, "line": line}, "confidence": node.get("confidence", "high"), "standardRef": node.get("standardRef"),
|
|
364
|
-
"provenance": {
|
|
382
|
+
"provenance": {
|
|
383
|
+
"component": property_evidence(active_context.source, line, "ImageButton drawable", self.id, "high"),
|
|
384
|
+
"asset": node["provenance"].get("asset", property_evidence(active_context.source, line, str(node["asset"]), self.id, "exact")),
|
|
385
|
+
"layout.width": property_evidence(active_context.source, line, "ImageButton drawable bounds", self.id, "high"),
|
|
386
|
+
"layout.height": property_evidence(active_context.source, line, "ImageButton drawable bounds", self.id, "high"),
|
|
387
|
+
"style.objectFit": node["provenance"].get("style.objectFit", property_evidence(active_context.source, line, "ImageButton drawable scale", self.id, "high")),
|
|
388
|
+
},
|
|
365
389
|
}
|
|
366
390
|
node["children"].insert(0, icon_id)
|
|
367
391
|
if node.get("layout", {}).get("direction") == "overlay":
|
|
@@ -676,11 +676,15 @@ def fidelity_audit(ir: dict[str, Any]) -> dict[str, Any]:
|
|
|
676
676
|
excluded_routes, invalid_route_exclusions = exclusion_keys(fidelity.get("excludedRoutes", []), "route")
|
|
677
677
|
discovered_screens = ir.get("discoveredScreens", [])
|
|
678
678
|
discovered_routes = ir.get("discoveredRoutes", [])
|
|
679
|
-
translated_screen_keys =
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
679
|
+
translated_screen_keys: set[str] = set()
|
|
680
|
+
for screen in screens:
|
|
681
|
+
if screen.get("translationStatus") == "inventory":
|
|
682
|
+
continue
|
|
683
|
+
translated_screen_keys.add(str(
|
|
684
|
+
screen.get("discoveredKey")
|
|
685
|
+
or f'{screen.get("source", {}).get("file", "")}#{screen.get("source", {}).get("symbol", screen.get("name", ""))}'
|
|
686
|
+
))
|
|
687
|
+
translated_screen_keys.update(str(key) for key in screen.get("discoveredKeys", []) if key)
|
|
684
688
|
expected_screen_keys = {f'{screen.get("file", "")}#{screen.get("name", "")}' for screen in discovered_screens}
|
|
685
689
|
missing_screen_keys = sorted(expected_screen_keys - translated_screen_keys - excluded_screens)
|
|
686
690
|
translated_routes = {
|
|
@@ -1022,6 +1022,26 @@ def evidence_for_screen(screen: dict[str, Any], discovered: list[dict[str, Any]]
|
|
|
1022
1022
|
source_file = str(screen.get("source", {}).get("file") or "")
|
|
1023
1023
|
fragment = str(screen.get("fragment") or "")
|
|
1024
1024
|
symbol = str(screen.get("source", {}).get("symbol") or screen.get("name") or "")
|
|
1025
|
+
discovered_key = str(screen.get("discoveredKey") or "")
|
|
1026
|
+
navigation_file = str(screen.get("navigationSource", {}).get("file") or "")
|
|
1027
|
+
if discovered_key:
|
|
1028
|
+
matched = next((
|
|
1029
|
+
candidate for candidate in discovered
|
|
1030
|
+
if f'{candidate.get("file", "")}#{candidate.get("name", "")}' == discovered_key
|
|
1031
|
+
), None)
|
|
1032
|
+
if matched:
|
|
1033
|
+
return matched
|
|
1034
|
+
if fragment:
|
|
1035
|
+
fragment_matches = [
|
|
1036
|
+
candidate for candidate in discovered
|
|
1037
|
+
if str(candidate.get("fragment") or "") == fragment
|
|
1038
|
+
]
|
|
1039
|
+
if navigation_file:
|
|
1040
|
+
matched = next((candidate for candidate in fragment_matches if str(candidate.get("file") or "") == navigation_file), None)
|
|
1041
|
+
if matched:
|
|
1042
|
+
return matched
|
|
1043
|
+
if len(fragment_matches) == 1:
|
|
1044
|
+
return fragment_matches[0]
|
|
1025
1045
|
return next((
|
|
1026
1046
|
candidate for candidate in discovered
|
|
1027
1047
|
if str(candidate.get("file") or candidate.get("source", {}).get("file") or "") == source_file
|
|
@@ -1032,6 +1052,39 @@ def evidence_for_screen(screen: dict[str, Any], discovered: list[dict[str, Any]]
|
|
|
1032
1052
|
), {})
|
|
1033
1053
|
|
|
1034
1054
|
|
|
1055
|
+
def consolidate_translated_android_variants(translated_screens: list[dict[str, Any]]) -> None:
|
|
1056
|
+
"""Keep one canonical screen per Android layout while retaining qualifier evidence."""
|
|
1057
|
+
grouped: dict[str, list[dict[str, Any]]] = {}
|
|
1058
|
+
for screen in translated_screens:
|
|
1059
|
+
if screen.get("platform") != "android" or not screen.get("androidLayout"):
|
|
1060
|
+
continue
|
|
1061
|
+
key = str(screen.get("id") or screen.get("androidLayout"))
|
|
1062
|
+
grouped.setdefault(key, []).append(screen)
|
|
1063
|
+
|
|
1064
|
+
consolidated: list[dict[str, Any]] = []
|
|
1065
|
+
emitted: set[str] = set()
|
|
1066
|
+
for screen in translated_screens:
|
|
1067
|
+
if screen.get("platform") != "android" or not screen.get("androidLayout"):
|
|
1068
|
+
consolidated.append(screen)
|
|
1069
|
+
continue
|
|
1070
|
+
key = str(screen.get("id") or screen.get("androidLayout"))
|
|
1071
|
+
if key in emitted:
|
|
1072
|
+
continue
|
|
1073
|
+
emitted.add(key)
|
|
1074
|
+
variants = grouped[key]
|
|
1075
|
+
canonical = next((item for item in variants if not item.get("resourceQualifier")), variants[-1])
|
|
1076
|
+
if len(variants) > 1:
|
|
1077
|
+
canonical["resourceVariants"] = [
|
|
1078
|
+
{
|
|
1079
|
+
"qualifier": str(item.get("resourceQualifier") or "default"),
|
|
1080
|
+
"source": dict(item.get("source", {})),
|
|
1081
|
+
}
|
|
1082
|
+
for item in variants
|
|
1083
|
+
]
|
|
1084
|
+
consolidated.append(canonical)
|
|
1085
|
+
translated_screens[:] = consolidated
|
|
1086
|
+
|
|
1087
|
+
|
|
1035
1088
|
def reconcile_translated_android_screens(
|
|
1036
1089
|
translated_screens: list[dict[str, Any]],
|
|
1037
1090
|
discovered: list[dict[str, Any]],
|
|
@@ -1313,6 +1366,7 @@ def starter_ir(scan_result: dict[str, Any]) -> dict[str, Any]:
|
|
|
1313
1366
|
for context in adapter_contexts
|
|
1314
1367
|
]
|
|
1315
1368
|
translated = translate_sources(adapter_contexts)
|
|
1369
|
+
consolidate_translated_android_variants(translated.screens)
|
|
1316
1370
|
resolve_translated_android_includes(translated)
|
|
1317
1371
|
token_resolver = TokenResolver(translated.tokens)
|
|
1318
1372
|
for node in translated.nodes.values():
|
|
@@ -1325,6 +1379,16 @@ def starter_ir(scan_result: dict[str, Any]) -> dict[str, Any]:
|
|
|
1325
1379
|
raw_scan_screens = scan_result.get("screens", [])
|
|
1326
1380
|
reconcile_translated_android_screens(translated.screens, raw_scan_screens)
|
|
1327
1381
|
reconcile_translated_screens(translated.screens, raw_scan_screens)
|
|
1382
|
+
for screen in translated.screens:
|
|
1383
|
+
variant_keys = []
|
|
1384
|
+
for variant in screen.get("resourceVariants", []):
|
|
1385
|
+
variant_file = str(variant.get("source", {}).get("file") or "")
|
|
1386
|
+
candidate = next((item for item in raw_scan_screens if str(item.get("file") or "") == variant_file), None)
|
|
1387
|
+
if candidate:
|
|
1388
|
+
variant_keys.append(f'{candidate.get("file", "")}#{candidate.get("name", "")}')
|
|
1389
|
+
keys = [str(screen.get("discoveredKey") or ""), *variant_keys]
|
|
1390
|
+
if any(keys):
|
|
1391
|
+
screen["discoveredKeys"] = list(dict.fromkeys(key for key in keys if key))
|
|
1328
1392
|
if scan_result.get("primaryPlatforms") == ["flutter"]:
|
|
1329
1393
|
discovered_flutter = {str(item.get("name") or "") for item in raw_scan_screens}
|
|
1330
1394
|
translated.screens[:] = [
|
|
@@ -1447,9 +1511,15 @@ def starter_ir(scan_result: dict[str, Any]) -> dict[str, Any]:
|
|
|
1447
1511
|
for item in screens
|
|
1448
1512
|
}
|
|
1449
1513
|
represented_discovered = {str(item.get("discoveredKey") or "") for item in screens if item.get("discoveredKey")}
|
|
1514
|
+
represented_variant_files = {
|
|
1515
|
+
str(variant.get("source", {}).get("file") or "")
|
|
1516
|
+
for item in screens
|
|
1517
|
+
for variant in item.get("resourceVariants", [])
|
|
1518
|
+
if isinstance(variant, dict)
|
|
1519
|
+
}
|
|
1450
1520
|
for inventory in inventory_screens:
|
|
1451
1521
|
key = (str(inventory.get("source", {}).get("file") or ""), str(inventory.get("fragment") or ""))
|
|
1452
|
-
if key in represented or str(inventory.get("discoveredKey") or "") in represented_discovered:
|
|
1522
|
+
if key[0] in represented_variant_files or key in represented or str(inventory.get("discoveredKey") or "") in represented_discovered:
|
|
1453
1523
|
continue
|
|
1454
1524
|
screens.append(inventory)
|
|
1455
1525
|
stack = [str(inventory.get("root") or "")]
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: ui-design-workbench-cli
|
|
3
|
-
Version: 0.6.
|
|
3
|
+
Version: 0.6.7
|
|
4
4
|
Summary: Repository UI indexing, graph, preview, and deterministic review CLI
|
|
5
5
|
Author: Elgreed
|
|
6
6
|
Project-URL: Homepage, https://github.com/Elgreed/ui-design-workbench
|
|
@@ -131,4 +131,4 @@ A Windows `.exe` is not published yet. PyPI + `pipx` is the primary cross-platfo
|
|
|
131
131
|
- [IR schema](references/ir-schema.md)
|
|
132
132
|
- [Review workflow](references/review-workflow.md)
|
|
133
133
|
|
|
134
|
-
Current CLI version: `0.6.
|
|
134
|
+
Current CLI version: `0.6.7`.
|
|
@@ -53,7 +53,7 @@ from scan_ui import (
|
|
|
53
53
|
|
|
54
54
|
|
|
55
55
|
CACHE_VERSION = 8
|
|
56
|
-
CLI_VERSION = "0.6.
|
|
56
|
+
CLI_VERSION = "0.6.7"
|
|
57
57
|
CONFIG_VERSION = 5
|
|
58
58
|
STATE_DIR_NAME = ".ui-design-workbench"
|
|
59
59
|
CONFIG_NAME = "config.json"
|
|
@@ -1036,6 +1036,24 @@ def prune_missing_token_refs(value: Any, tokens: dict[str, Any]) -> Any:
|
|
|
1036
1036
|
return copy.deepcopy(value)
|
|
1037
1037
|
|
|
1038
1038
|
|
|
1039
|
+
def prune_orphan_provenance(node: dict[str, Any]) -> dict[str, Any]:
|
|
1040
|
+
"""Remove evidence entries for authored properties pruned during cache migration."""
|
|
1041
|
+
provenance = node.get("provenance")
|
|
1042
|
+
if not isinstance(provenance, dict):
|
|
1043
|
+
return node
|
|
1044
|
+
|
|
1045
|
+
def path_exists(path: str) -> bool:
|
|
1046
|
+
current: Any = node
|
|
1047
|
+
for part in path.split("."):
|
|
1048
|
+
if not isinstance(current, dict) or part not in current:
|
|
1049
|
+
return False
|
|
1050
|
+
current = current[part]
|
|
1051
|
+
return True
|
|
1052
|
+
|
|
1053
|
+
node["provenance"] = {path: evidence for path, evidence in provenance.items() if path_exists(str(path))}
|
|
1054
|
+
return node
|
|
1055
|
+
|
|
1056
|
+
|
|
1039
1057
|
def merge_authored_state(
|
|
1040
1058
|
generated: dict[str, Any],
|
|
1041
1059
|
design_model: dict[str, Any],
|
|
@@ -1074,6 +1092,7 @@ def merge_authored_state(
|
|
|
1074
1092
|
cleaned_authored = prune_missing_token_refs(authored, merged_tokens)
|
|
1075
1093
|
if not isinstance(cleaned_authored, dict):
|
|
1076
1094
|
continue
|
|
1095
|
+
prune_orphan_provenance(cleaned_authored)
|
|
1077
1096
|
existing = result.setdefault("nodes", {}).get(node_id, {})
|
|
1078
1097
|
merged = copy.deepcopy(existing)
|
|
1079
1098
|
for key, value in cleaned_authored.items():
|
|
@@ -1085,6 +1104,7 @@ def merge_authored_state(
|
|
|
1085
1104
|
merged["sourceState"] = "stale"
|
|
1086
1105
|
else:
|
|
1087
1106
|
merged.pop("sourceState", None)
|
|
1107
|
+
prune_orphan_provenance(merged)
|
|
1088
1108
|
result["nodes"][node_id] = merged
|
|
1089
1109
|
|
|
1090
1110
|
fixtures = design_model.get("scenarioFixtures", {})
|
|
File without changes
|
|
File without changes
|
{ui_design_workbench_cli-0.6.6 → ui_design_workbench_cli-0.6.7}/references/agent-integrations.md
RENAMED
|
File without changes
|
{ui_design_workbench_cli-0.6.6 → ui_design_workbench_cli-0.6.7}/references/cache-protocol.md
RENAMED
|
File without changes
|
{ui_design_workbench_cli-0.6.6 → ui_design_workbench_cli-0.6.7}/references/component-catalog.json
RENAMED
|
File without changes
|
{ui_design_workbench_cli-0.6.6 → ui_design_workbench_cli-0.6.7}/references/component-catalog.md
RENAMED
|
File without changes
|
{ui_design_workbench_cli-0.6.6 → ui_design_workbench_cli-0.6.7}/references/component-inventory.json
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{ui_design_workbench_cli-0.6.6 → ui_design_workbench_cli-0.6.7}/references/native-rendering.md
RENAMED
|
File without changes
|
{ui_design_workbench_cli-0.6.6 → ui_design_workbench_cli-0.6.7}/references/platform-profiles.json
RENAMED
|
File without changes
|
{ui_design_workbench_cli-0.6.6 → ui_design_workbench_cli-0.6.7}/references/platform-standards.md
RENAMED
|
File without changes
|
|
File without changes
|
{ui_design_workbench_cli-0.6.6 → ui_design_workbench_cli-0.6.7}/references/quality-automation.md
RENAMED
|
File without changes
|
{ui_design_workbench_cli-0.6.6 → ui_design_workbench_cli-0.6.7}/references/review-workflow.md
RENAMED
|
File without changes
|
{ui_design_workbench_cli-0.6.6 → ui_design_workbench_cli-0.6.7}/references/ui-guidance-mode.md
RENAMED
|
File without changes
|
{ui_design_workbench_cli-0.6.6 → ui_design_workbench_cli-0.6.7}/references/ui-policy-schema.md
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{ui_design_workbench_cli-0.6.6 → ui_design_workbench_cli-0.6.7}/schemas/ui-agent-job.schema.json
RENAMED
|
File without changes
|
{ui_design_workbench_cli-0.6.6 → ui_design_workbench_cli-0.6.7}/schemas/ui-graph.schema.json
RENAMED
|
File without changes
|
{ui_design_workbench_cli-0.6.6 → ui_design_workbench_cli-0.6.7}/schemas/ui-ir.patch.schema.json
RENAMED
|
File without changes
|
|
File without changes
|
{ui_design_workbench_cli-0.6.6 → ui_design_workbench_cli-0.6.7}/schemas/uidw-config.schema.json
RENAMED
|
File without changes
|
{ui_design_workbench_cli-0.6.6 → ui_design_workbench_cli-0.6.7}/scripts/android_resource_resolver.py
RENAMED
|
File without changes
|
{ui_design_workbench_cli-0.6.6 → ui_design_workbench_cli-0.6.7}/scripts/android_xml_support.py
RENAMED
|
File without changes
|
{ui_design_workbench_cli-0.6.6 → ui_design_workbench_cli-0.6.7}/scripts/apple_resource_resolver.py
RENAMED
|
File without changes
|
|
File without changes
|
{ui_design_workbench_cli-0.6.6 → ui_design_workbench_cli-0.6.7}/scripts/fidelity_adapter_api.py
RENAMED
|
File without changes
|
{ui_design_workbench_cli-0.6.6 → ui_design_workbench_cli-0.6.7}/scripts/fidelity_adapters.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{ui_design_workbench_cli-0.6.6 → ui_design_workbench_cli-0.6.7}/scripts/merge_review_state.py
RENAMED
|
File without changes
|
{ui_design_workbench_cli-0.6.6 → ui_design_workbench_cli-0.6.7}/scripts/native_render_android.py
RENAMED
|
File without changes
|
{ui_design_workbench_cli-0.6.6 → ui_design_workbench_cli-0.6.7}/scripts/native_render_apple.py
RENAMED
|
File without changes
|
{ui_design_workbench_cli-0.6.6 → ui_design_workbench_cli-0.6.7}/scripts/native_render_contracts.py
RENAMED
|
File without changes
|
{ui_design_workbench_cli-0.6.6 → ui_design_workbench_cli-0.6.7}/scripts/native_render_registry.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{ui_design_workbench_cli-0.6.6 → ui_design_workbench_cli-0.6.7}/scripts/visual_regression.py
RENAMED
|
File without changes
|
|
File without changes
|