Add: windows mvp - transparent bugs not fixed

This commit is contained in:
DaZuo0122
2026-02-12 22:58:33 +08:00
commit 61825f647d
147 changed files with 28498 additions and 0 deletions

127
scripts/qa_validate.py Normal file
View File

@@ -0,0 +1,127 @@
#!/usr/bin/env python3
"""Validate issue QA workflow artifacts."""
from __future__ import annotations
import re
import sys
from pathlib import Path
ROOT = Path(__file__).resolve().parents[1]
ISSUES_DIR = ROOT / "issues"
REQUIRED_SECTIONS = (
"Title",
"Severity",
"Environment",
"Summary",
"Reproduction Steps",
"Expected Result",
"Actual Result",
"Root Cause Analysis",
"Fix Plan",
"Implementation Notes",
"Verification",
"Status History",
"Closure",
)
CLOSED_STATES = {"Verification Passed", "Closed"}
def issue_files() -> list[Path]:
return sorted(ISSUES_DIR.glob("issue[0-9]*.md"))
def has_section(content: str, name: str) -> bool:
pattern = rf"(?m)^##\s+{re.escape(name)}\s*$"
return bool(re.search(pattern, content))
def current_status(content: str) -> str | None:
match = re.search(r"(?m)^- Current Status:\s*`?([^`\n]+)`?\s*$", content)
return match.group(1).strip() if match else None
def screenshot_refs(content: str) -> list[str]:
pattern = r"issues/screenshots/[A-Za-z0-9._-]+\.png"
return sorted(set(re.findall(pattern, content)))
def has_before_ref(refs: list[str], issue_num: str) -> bool:
legacy = f"issues/screenshots/issue{issue_num}.png"
return any("-before-" in ref for ref in refs) or legacy in refs
def has_after_ref(refs: list[str]) -> bool:
return any("-after-" in ref for ref in refs)
def command_check_present(content: str) -> bool:
required = (
"`cargo check --workspace`",
"`cargo test --workspace`",
"`just qa-validate`",
)
return all(token in content for token in required)
def verify_issue(path: Path) -> list[str]:
errors: list[str] = []
content = path.read_text(encoding="utf-8")
issue_num_match = re.search(r"issue([0-9]+)\.md$", path.name)
issue_num = issue_num_match.group(1) if issue_num_match else "?"
for section in REQUIRED_SECTIONS:
if not has_section(content, section):
errors.append(f"{path}: missing section '## {section}'")
refs = screenshot_refs(content)
for ref in refs:
if not (ROOT / ref).exists():
errors.append(f"{path}: missing screenshot file: {ref}")
if not has_before_ref(refs, issue_num):
errors.append(
f"{path}: missing before screenshot reference "
"(use issueN-before-...png or legacy issueN.png)"
)
status = current_status(content)
if status in CLOSED_STATES and not has_after_ref(refs):
errors.append(
f"{path}: status '{status}' requires at least one after screenshot reference"
)
if status in CLOSED_STATES and not command_check_present(content):
errors.append(
f"{path}: status '{status}' requires command checklist entries for "
"cargo check, cargo test, and just qa-validate"
)
return errors
def main() -> int:
files = issue_files()
if not files:
print("error: no issue files found under issues/", file=sys.stderr)
return 1
failures: list[str] = []
for path in files:
failures.extend(verify_issue(path))
if failures:
for failure in failures:
print(f"error: {failure}", file=sys.stderr)
return 1
print(f"qa validation passed ({len(files)} issue file(s) checked)")
return 0
if __name__ == "__main__":
raise SystemExit(main())