chore(repo): initialize team collaboration repository
This commit is contained in:
@@ -0,0 +1,5 @@
|
||||
"""Evidence Bundle 生成。"""
|
||||
|
||||
from .bundle import build_evidence_bundle
|
||||
|
||||
__all__ = ["build_evidence_bundle"]
|
||||
@@ -0,0 +1,69 @@
|
||||
"""把一次 Run 的可重放事件打成最小证据包。"""
|
||||
from __future__ import annotations
|
||||
|
||||
import json
|
||||
from pathlib import Path
|
||||
|
||||
from sqlalchemy import select
|
||||
from sqlalchemy.ext.asyncio import AsyncSession
|
||||
|
||||
from ..config import get_settings
|
||||
from ..models import EvidenceBundle, Run, RunEvent, iso_z
|
||||
|
||||
|
||||
async def build_evidence_bundle(session: AsyncSession, run: Run) -> EvidenceBundle:
|
||||
events = (
|
||||
await session.scalars(
|
||||
select(RunEvent).where(RunEvent.run_id == run.id).order_by(RunEvent.seq)
|
||||
)
|
||||
).all()
|
||||
root = get_settings().object_store_path / "runs" / run.id
|
||||
root.mkdir(parents=True, exist_ok=True)
|
||||
timeline_path = root / "events.ndjson"
|
||||
timeline = "\n".join(
|
||||
json.dumps(
|
||||
{
|
||||
"seq": event.seq,
|
||||
"ts": iso_z(event.ts),
|
||||
"source": event.source,
|
||||
"kind": event.kind,
|
||||
"severity": event.severity,
|
||||
"message": event.message,
|
||||
"payload": event.payload,
|
||||
},
|
||||
ensure_ascii=False,
|
||||
sort_keys=True,
|
||||
)
|
||||
for event in events
|
||||
)
|
||||
timeline_path.write_text(timeline + ("\n" if timeline else ""), encoding="utf-8")
|
||||
manifest = {
|
||||
"schema_version": 1,
|
||||
"run_id": run.id,
|
||||
"workflow": {
|
||||
"key": run.workflow_key,
|
||||
"version": run.workflow_version,
|
||||
"spec_hash": run.spec_hash,
|
||||
},
|
||||
"environment_fingerprint": run.env_fingerprint,
|
||||
"checkpoint": run.checkpoint,
|
||||
"event_count": len(events),
|
||||
"files": [{"path": "events.ndjson", "bytes": timeline_path.stat().st_size}],
|
||||
}
|
||||
manifest_path = root / "manifest.json"
|
||||
manifest_path.write_text(
|
||||
json.dumps(manifest, ensure_ascii=False, indent=2, sort_keys=True),
|
||||
encoding="utf-8",
|
||||
)
|
||||
size = manifest_path.stat().st_size + timeline_path.stat().st_size
|
||||
bundle = EvidenceBundle(
|
||||
run_id=run.id,
|
||||
uri=str(root),
|
||||
manifest=manifest,
|
||||
size_bytes=size,
|
||||
completeness=1.0,
|
||||
missing_fields=[],
|
||||
)
|
||||
session.add(bundle)
|
||||
await session.flush()
|
||||
return bundle
|
||||
Reference in New Issue
Block a user