Audit route documentation coverage

This commit is contained in:
2026-06-27 12:32:27 +02:00
parent c67be207ab
commit 9a2e5db041
3 changed files with 63 additions and 4 deletions
+3 -2
View File
@@ -501,8 +501,9 @@ Keep here:
Improve later: Improve later:
- keep `tools/prompt_map_audit.py` passing; it now checks referenced - keep `tools/prompt_map_audit.py` passing; it now checks referenced
expression/composition/scene pools, item-template axes, and object-template expression/composition/scene pools, item-template axes, object-template
metadata values for both string and object templates. metadata values for both string and object templates, and critical route
documentation plus expected smoke coverage.
### Node / UI Path ### Node / UI Path
+4 -2
View File
@@ -813,11 +813,13 @@ The script does not import ComfyUI. It parses the repo and prints:
- JSON reference validation for every `scene_pools`, `expression_pools`, and - JSON reference validation for every `scene_pools`, `expression_pools`, and
`composition_pools` reference; `composition_pools` reference;
- item template validation so `{placeholder}` names resolve to `item_axes`. - item template validation so `{placeholder}` names resolve to `item_axes`.
- route documentation validation so critical route modules are listed in this
map and the architecture plan, and covered by their expected smoke cases.
Use its output to spot doc drift after adding a new node or pool. If a new node Use its output to spot doc drift after adding a new node or pool. If a new node
or pool appears there but not in this map, update the relevant route table. The or pool appears there but not in this map, update the relevant route table. The
script exits nonzero when JSON pool references or item template axes do not script exits nonzero when JSON pool references, item template axes, critical
resolve. route docs, or critical route smoke coverage do not resolve.
## Behavioral Smoke Helper ## Behavioral Smoke Helper
+56
View File
@@ -32,6 +32,30 @@ POOL_REFERENCE_KEYS = {
} }
TEMPLATE_TOKEN_RE = re.compile(r"{([a-zA-Z_][a-zA-Z0-9_]*)}") TEMPLATE_TOKEN_RE = re.compile(r"{([a-zA-Z_][a-zA-Z0-9_]*)}")
CRITICAL_ROUTE_MODULES: tuple[tuple[str, str], ...] = (
("builder_prompt_route.py", "builder_prompt_route_policy"),
("builder_config_route.py", "builder_config_route_policy"),
("krea_format_route.py", "krea_format_route_policy"),
("sdxl_format_route.py", "sdxl_format_route_policy"),
("caption_format_route.py", "caption_format_route_policy"),
("pair_builder.py", "pair_builder_policy"),
("row_assembly.py", "row_assembly_policy"),
("row_category_route.py", "row_category_route_policy"),
("row_prompt_axes.py", "row_prompt_axes_policy"),
("row_route_metadata.py", "row_route_metadata_policy"),
("row_subject_route.py", "row_subject_route_policy"),
("caption_metadata_routes.py", "caption_metadata_routes"),
("sdxl_tag_routes.py", "sdxl_tag_routes"),
)
ENTRY_ROUTE_SNIPPETS: tuple[str, ...] = (
"`build_prompt` -> `builder_prompt_route.py`",
"`build_prompt_from_configs` -> `builder_config_route.py`",
"`format_krea2_prompt` -> `krea_format_route.py`",
"`format_sdxl_prompt` -> `sdxl_format_route.py`",
"`naturalize_caption` -> `caption_format_route.py`",
)
def _literal_or_none(node: ast.AST) -> Any: def _literal_or_none(node: ast.AST) -> Any:
try: try:
@@ -287,6 +311,31 @@ def _json_reference_errors(paths: list[Path]) -> list[tuple[str, str, str]]:
return errors return errors
def _routing_doc_errors() -> list[tuple[str, str, str]]:
docs = {
"docs/prompt-pool-routing-map.md": ROOT / "docs" / "prompt-pool-routing-map.md",
"docs/prompt-architecture-improvement-plan.md": ROOT / "docs" / "prompt-architecture-improvement-plan.md",
}
smoke_path = ROOT / "tools" / "prompt_smoke.py"
smoke_text = smoke_path.read_text(encoding="utf-8") if smoke_path.exists() else ""
errors: list[tuple[str, str, str]] = []
for module_name, smoke_case in CRITICAL_ROUTE_MODULES:
if not (ROOT / module_name).exists():
errors.append((module_name, "module", "critical route module is missing"))
for doc_name, doc_path in docs.items():
doc_text = doc_path.read_text(encoding="utf-8") if doc_path.exists() else ""
if module_name not in doc_text:
errors.append((module_name, doc_name, "critical route module is not documented"))
if smoke_case and smoke_case not in smoke_text:
errors.append((module_name, "tools/prompt_smoke.py", f"missing smoke case: {smoke_case}"))
route_map_text = docs["docs/prompt-pool-routing-map.md"].read_text(encoding="utf-8")
for snippet in ENTRY_ROUTE_SNIPPETS:
if snippet not in route_map_text:
errors.append(("(entry route)", "docs/prompt-pool-routing-map.md", f"missing entry snippet: {snippet}"))
return errors
def print_table(headers: tuple[str, ...], rows: list[tuple[Any, ...]]) -> None: def print_table(headers: tuple[str, ...], rows: list[tuple[Any, ...]]) -> None:
widths = [len(header) for header in headers] widths = [len(header) for header in headers]
for row in rows: for row in rows:
@@ -359,6 +408,13 @@ def main() -> int:
print_table(("File", "Path", "Issue"), reference_errors) print_table(("File", "Path", "Issue"), reference_errors)
return 1 return 1
print("OK: all JSON pool references and item template axes resolve.") print("OK: all JSON pool references and item template axes resolve.")
print("\n# Routing Documentation Validation")
routing_doc_errors = _routing_doc_errors()
if routing_doc_errors:
print_table(("Module", "Location", "Issue"), routing_doc_errors)
return 1
print("OK: critical route modules are documented and covered by smoke cases.")
return 0 return 0