__init__.py 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596
  1. #!/usr/bin/env python3
  2. # -*- coding: utf-8 -*-
  3. from __future__ import annotations
  4. import json
  5. from pathlib import Path
  6. from typing import Any
  7. SCHEMA_VERSION = "webnovel-write-gate/v1"
  8. STAGES = ("prewrite", "precommit", "postcommit")
  9. def issue(
  10. code: str,
  11. *,
  12. message: str,
  13. severity: str = "blocker",
  14. path: str = "",
  15. impact: str = "",
  16. repair: str = "",
  17. details: Any = None,
  18. ) -> dict[str, Any]:
  19. return {
  20. "code": code,
  21. "severity": severity,
  22. "message": message,
  23. "path": path,
  24. "impact": impact,
  25. "repair": repair,
  26. "details": details,
  27. }
  28. def gate_report(
  29. *,
  30. stage: str,
  31. project_root: str | Path,
  32. chapter: int,
  33. phase: str,
  34. errors: list[dict[str, Any]] | None = None,
  35. warnings: list[dict[str, Any]] | None = None,
  36. details: dict[str, Any] | None = None,
  37. ) -> dict[str, Any]:
  38. errors = errors or []
  39. warnings = warnings or []
  40. return {
  41. "schema_version": SCHEMA_VERSION,
  42. "stage": stage,
  43. "project_root": str(project_root),
  44. "chapter": chapter,
  45. "phase": phase,
  46. "ok": not any(item.get("severity") == "blocker" for item in errors),
  47. "errors": errors,
  48. "warnings": warnings,
  49. "details": details or {},
  50. }
  51. def format_gate_report(report: dict[str, Any], output_format: str = "json") -> str:
  52. if output_format == "json":
  53. return json.dumps(report, ensure_ascii=False, indent=2)
  54. status = "OK" if report.get("ok") else "ERROR"
  55. lines = [
  56. f"{status} write-gate {report.get('stage')}",
  57. f"project_root: {report.get('project_root')}",
  58. f"chapter: {report.get('chapter')}",
  59. f"phase: {report.get('phase')}",
  60. ]
  61. for item in report.get("errors") or []:
  62. lines.append(f"ERROR {item.get('code')}: {item.get('message')}")
  63. if item.get("path"):
  64. lines.append(f" path: {item.get('path')}")
  65. if item.get("impact"):
  66. lines.append(f" impact: {item.get('impact')}")
  67. if item.get("repair"):
  68. lines.append(f" repair: {item.get('repair')}")
  69. for item in report.get("warnings") or []:
  70. lines.append(f"WARNING {item.get('code')}: {item.get('message')}")
  71. return "\n".join(lines)
  72. def run_write_gate(project_root: str | Path, *, chapter: int, stage: str) -> dict[str, Any]:
  73. if stage == "prewrite":
  74. from .prewrite import run_prewrite_gate
  75. return run_prewrite_gate(Path(project_root), chapter)
  76. if stage == "precommit":
  77. from .precommit import run_precommit_gate
  78. return run_precommit_gate(Path(project_root), chapter)
  79. if stage == "postcommit":
  80. from .postcommit import run_postcommit_gate
  81. return run_postcommit_gate(Path(project_root), chapter)
  82. raise ValueError(f"unknown write-gate stage: {stage}")