Initial SQL-only 1C adapter baseline
This commit is contained in:
@@ -0,0 +1,126 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Render one-shot 1C saved-state watch manifest as Markdown."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import argparse
|
||||
import json
|
||||
from pathlib import Path
|
||||
from typing import Any
|
||||
|
||||
|
||||
def load_json(path: Path) -> dict[str, Any]:
|
||||
return json.loads(path.read_text(encoding="utf-8-sig"))
|
||||
|
||||
|
||||
def line(text: str = "") -> str:
|
||||
return text.rstrip() + "\n"
|
||||
|
||||
|
||||
def bullet(text: str) -> str:
|
||||
return f"- {text}\n"
|
||||
|
||||
|
||||
def code(value: Any) -> str:
|
||||
if value is None:
|
||||
return "`null`"
|
||||
return f"`{value}`"
|
||||
|
||||
|
||||
def linked_path(manifest_path: Path, value: Any) -> Path | None:
|
||||
if not value:
|
||||
return None
|
||||
path = Path(str(value))
|
||||
if path.is_absolute():
|
||||
return path
|
||||
return (manifest_path.parent / path).resolve()
|
||||
|
||||
|
||||
def render_delta_summary(manifest_path: Path, manifest: dict[str, Any]) -> str:
|
||||
delta_path = linked_path(manifest_path, manifest.get("delta"))
|
||||
if not delta_path or not delta_path.exists():
|
||||
return ""
|
||||
delta = load_json(delta_path)
|
||||
objects = delta.get("objects") or {}
|
||||
changed = objects.get("changed") or []
|
||||
added = objects.get("added") or []
|
||||
removed = objects.get("removed") or []
|
||||
if not changed and not added and not removed:
|
||||
return ""
|
||||
out = line()
|
||||
out += line("## Delta Objects")
|
||||
for item in added:
|
||||
out += bullet(f"Added {code(item.get('full_name'))}")
|
||||
for item in removed:
|
||||
out += bullet(f"Removed {code(item.get('full_name'))}")
|
||||
for item in changed:
|
||||
out += bullet(f"Changed {code(item.get('full_name'))}")
|
||||
term_delta = item.get("term_delta") or {}
|
||||
added_terms = ((term_delta.get("added_terms") or {}).get("added") or [])
|
||||
removed_terms = ((term_delta.get("removed_terms") or {}).get("added") or [])
|
||||
if added_terms:
|
||||
out += f" New added terms: {', '.join(code(value) for value in added_terms)}\n"
|
||||
if removed_terms:
|
||||
out += f" New removed terms: {', '.join(code(value) for value in removed_terms)}\n"
|
||||
for part in (item.get("part_delta") or {}).get("changed") or []:
|
||||
before = part.get("before") or {}
|
||||
after = part.get("after") or {}
|
||||
out += (
|
||||
f" Part changed: {code(part.get('file_name'))}, "
|
||||
f"role={code(after.get('payload_role'))}, "
|
||||
f"delta_chars {code(before.get('delta_chars'))}->{code(after.get('delta_chars'))}\n"
|
||||
)
|
||||
return out
|
||||
|
||||
|
||||
def render(manifest_path: Path, manifest: dict[str, Any]) -> str:
|
||||
counts = manifest.get("counts") or {}
|
||||
safety = manifest.get("safety") or {}
|
||||
out = ""
|
||||
out += line("# 1C Saved State Watch Run")
|
||||
out += line()
|
||||
out += line(f"Database: `{manifest.get('database')}`")
|
||||
out += line(f"Run dir: `{manifest.get('run_dir')}`")
|
||||
out += line(f"Previous report: `{manifest.get('previous_report')}`")
|
||||
out += line()
|
||||
out += line("## Artifacts")
|
||||
for key in ("report", "markdown", "check", "manifest_check", "delta", "delta_markdown", "delta_check"):
|
||||
if manifest.get(key):
|
||||
out += bullet(f"{key}: `{manifest.get(key)}`")
|
||||
out += line()
|
||||
out += line("## Counts")
|
||||
for key in (
|
||||
"object_changes",
|
||||
"system_changes",
|
||||
"delta_objects_added",
|
||||
"delta_objects_removed",
|
||||
"delta_objects_changed",
|
||||
"delta_objects_unchanged",
|
||||
):
|
||||
out += bullet(f"{key}: `{counts.get(key)}`")
|
||||
out += render_delta_summary(manifest_path, manifest)
|
||||
out += line()
|
||||
out += line("## Safety")
|
||||
for key in ("read_only", "sql_write_performed", "secrets_in_report"):
|
||||
out += bullet(f"{key}: `{safety.get(key)}`")
|
||||
return out
|
||||
|
||||
|
||||
def main() -> int:
|
||||
parser = argparse.ArgumentParser(description="Render one-shot 1C saved-state watch Markdown.")
|
||||
parser.add_argument("--manifest", type=Path, required=True)
|
||||
parser.add_argument("--output", type=Path)
|
||||
args = parser.parse_args()
|
||||
|
||||
markdown = render(args.manifest, load_json(args.manifest))
|
||||
if args.output:
|
||||
args.output.parent.mkdir(parents=True, exist_ok=True)
|
||||
args.output.write_text(markdown, encoding="utf-8")
|
||||
print(json.dumps({"output": str(args.output)}, ensure_ascii=False))
|
||||
else:
|
||||
print(markdown)
|
||||
return 0
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
raise SystemExit(main())
|
||||
Reference in New Issue
Block a user