Files
a0_software_orchestrator/helpers/artifact_rules.py
T
Software Orchestrator 5769c1cd22 Initial commit: a0_software_orchestrator v1.0
- Auto-Registration-Bug behoben (register_project/get_project_id/resolve_project Trennung)
- 25 Tests gruen (Pytest)
- block_compactor-Tool refactored (Option B: Soft-Check statt Hard-Block)
- 4 Restbaustellen gefixt
- DB-Schema: plugin_settings-Tabelle hinzugefuegt
- 3 Schattenprojekte aus DB geloescht
- Plan v3 + Refactor-Plan + Worklog dokumentiert
2026-06-16 22:13:06 +00:00

132 lines
4.4 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"""Rules for required project artifacts (DB + repo hybrid)."""
import os
from typing import Dict, List
# ---------------------------------------------------------------------------
# DB-backed artifacts (5 mandatory: worklog, todo, project_state,
# current_status, next_steps) checked via db_state_store
# ---------------------------------------------------------------------------
DB_ARTIFACTS: List[str] = [
"worklog", # orch_worklog (mindestens 1 Eintrag)
"todo", # orch_todos (mindestens 1 Eintrag)
"project_state", # orch_kv mit key='project_state' ODER 'phase'
"current_status", # orch_status (gesetzt)
"next_steps", # orch_next_steps (mindestens 1 pending)
]
# ---------------------------------------------------------------------------
# Repo-backed artifacts (15 specs/docs/deploy files) checked as file paths
# unter project_root
# ---------------------------------------------------------------------------
REPO_ARTIFACTS: List[str] = [
"specs/current/requirements.md",
"specs/current/design.md",
"specs/current/tasks.md",
"docs/architecture.md",
"docs/test_report.md",
"docs/runtime_report.md",
"deploy/env.md",
"deploy/healthcheck.md",
"deploy/runbook.md",
"deploy/rollback.md",
]
# All artifacts (kept for backward compat with the original list)
CORE_ARTIFACTS = [f".a0/{a}.md" for a in DB_ARTIFACTS if a != "project_state"] + [
".a0/project_state.json"
] + REPO_ARTIFACTS
def _check_db_artifacts(project_name: str) -> Dict[str, bool]:
"""Prüft die 5 DB-backed Artefakte via db_state_store."""
from .db_state_store import (
get_project_id,
get_kv,
get_status,
list_worklog,
list_todos,
list_next_steps,
)
pid = get_project_id(project_name)
if pid is None:
return {
"worklog": False, "todo": False, "project_state": False,
"current_status": False, "next_steps": False,
}
return {
"worklog": len(list_worklog(pid, limit=1)) > 0,
"todo": len(list_todos(pid, status="open", limit=1)) > 0,
"project_state": (
get_kv(pid, "project_state") is not None
or get_kv(pid, "phase") is not None
),
"current_status": get_status(pid) is not None,
"next_steps": len(list_next_steps(pid, status="pending", limit=1)) > 0,
}
def _check_repo_artifacts(project_root: str) -> Dict[str, bool]:
"""Prüft die 15 Repo-Artefakte (specs/, docs/, deploy/) per File-Existenz."""
result: Dict[str, bool] = {}
for rel_path in REPO_ARTIFACTS:
result[rel_path] = os.path.exists(os.path.join(project_root, rel_path))
return result
def check_required_artifacts(
project_name: str = "",
project_root: str = "",
) -> dict:
"""Prüft alle Pflicht-Artefakte (DB + Repo).
Args:
project_name: Projektname (für DB-Checks). Default: aus project_root
abgeleitet (basename).
project_root: Projekt-Wurzelverzeichnis (für Repo-Checks). Default: cwd.
Returns:
{
"db": {artifact_name: bool, …},
"repo": {relative_path: bool, …},
"present": [alle existierenden], # kombiniert
"missing": [alle fehlenden], # kombiniert
"total": int,
}
"""
if not project_name:
project_name = os.path.basename(project_root or os.getcwd())
if not project_root:
project_root = os.getcwd()
db = _check_db_artifacts(project_name)
repo = _check_repo_artifacts(project_root)
present = [a for a, ok in db.items() if ok] + [a for a, ok in repo.items() if ok]
missing = [a for a, ok in db.items() if not ok] + [a for a, ok in repo.items() if not ok]
return {
"db": db,
"repo": repo,
"present": present,
"missing": missing,
"total": len(db) + len(repo),
}
# Backward-compat: altes Format (nur Repo-Files) für externe Caller
def check_legacy_artifacts(project_root: str) -> dict:
"""Alte CORE_ARTIFACTS-Liste als File-Existenz-Check (nur Repo)."""
missing = []
present = []
for artifact in CORE_ARTIFACTS:
path = os.path.join(project_root, artifact)
if os.path.exists(path):
present.append(artifact)
else:
missing.append(artifact)
return {"present": present, "missing": missing, "total": len(CORE_ARTIFACTS)}