from __future__ import annotations from .shared import * class TaskBriefSeedHistoryMixin: @staticmethod def _extract_markdown_section_lines(content: str, *, heading: str) -> list[str]: target = f"## {heading}".lower() lines = content.splitlines() in_section = False collected: list[str] = [] for raw in lines: line = raw.strip() if line.lower().startswith("## "): if line.lower() == target: in_section = True continue if in_section: break if in_section and line: collected.append(line) return collected @staticmethod def _extract_markdown_meta_value(content: str, *, key: str) -> str | None: prefix = f"- {key}:" for raw in content.splitlines(): line = raw.strip() if line.startswith(prefix): return line.split(":", 1)[1].strip() or None return None @classmethod def _normalize_generated_at(cls, raw_generated: str | None, fallback: datetime) -> str: if not raw_generated: return fallback.isoformat() for fmt in ("%Y-%m-%d %H:%M:%S %z",): try: return datetime.strptime(raw_generated, fmt).isoformat() except Exception: pass try: return datetime.fromisoformat(raw_generated).isoformat() except Exception: return raw_generated @classmethod def _load_seed_history(cls) -> tuple[list[dict[str, Any]], list[dict[str, Any]]]: docs_dir = cls._project_root() / "docs/task_briefs" if not docs_dir.exists(): return [], [] briefs: list[dict[str, Any]] = [] runs: list[dict[str, Any]] = [] for file_path in sorted(docs_dir.glob("task_brief_*.md")): try: content = file_path.read_text(encoding="utf-8") except Exception: continue if not content.strip(): continue stem = "".join(ch for ch in file_path.stem if ch.isalnum() or ch in {"_", "-"}) brief_id = f"brief_seed_{stem}"[:64] run_id = f"run_seed_{stem}"[:64] fallback_time = datetime.fromtimestamp(file_path.stat().st_mtime) generated_at = cls._normalize_generated_at( cls._extract_markdown_meta_value(content, key="Generated At"), fallback=fallback_time, ) title = "导入任务包" for line in content.splitlines(): if line.strip().startswith("# "): title = line.strip()[2:].strip() or title break changed_section = cls._extract_markdown_section_lines(content, heading="Changed Files") changed_files = [line[2:].strip() for line in changed_section if line.startswith("- ") and line[2:].strip()] scope_section = cls._extract_markdown_section_lines(content, heading="Scope") scope_items = [line[2:].strip() if line.startswith("- ") else line for line in scope_section] scope_summary = ";".join([item for item in scope_items if item][:2]).strip() if not scope_summary: scope_summary = "从 docs/task_briefs 自动导入" run = { "id": run_id, "brief_id": brief_id, "title": title, "template_id": DEFAULT_TEMPLATE_ID, "template_name": DEFAULT_TEMPLATE_NAME, "generated_at": generated_at, "generated_by": 0, "status": "imported", "changed_files": changed_files, "scope_summary": scope_summary, } brief = { "id": brief_id, "title": title, "status": "ready", "created_at": generated_at, "updated_at": generated_at, "latest_run_id": run_id, "template_id": DEFAULT_TEMPLATE_ID, "template_name": DEFAULT_TEMPLATE_NAME, "summary": scope_summary, "content": content.strip(), "changed_files": changed_files, } runs.append(run) briefs.append(brief) return briefs, runs