Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
File renamed without changes.
26 changes: 19 additions & 7 deletions rescore.py
Original file line number Diff line number Diff line change
Expand Up @@ -232,25 +232,37 @@ def rescore(
report_path = generate_report(campaign_id, DB_PATH, baseline, result, stats)
logger.info("Report written: %s", report_path)

# Regenerate the evidence-first report (report_v2.md) so it always
# reflects the current DB state. Without this, report_v2.md retains
# conclusions (winner, eliminated, Pareto) from the prior scoring pass
# while report.md and the scores table are already updated — the two
# files would then contradict each other with no warning.
# Regenerate run-reports.md so it always reflects the current DB state.
# Without this, run-reports.md retains conclusions (winner, eliminated, Pareto)
# from the prior scoring pass while campaign-summary.md and the scores table
# are already updated — the two files would then contradict each other.
v2_ok = True
try:
v2_path = generate_campaign_report(
campaign_id, DB_PATH, baseline,
scores_result=result, stats=stats,
)
logger.info("Evidence-first report (v2) written: %s", v2_path)
logger.info("run-reports.md written: %s", v2_path)
except Exception as _v2_exc:
v2_ok = False
logger.warning(
"Evidence-first report (report_v2.md) regeneration failed (non-fatal): %s",
"run-reports.md regeneration failed (non-fatal): %s",
_v2_exc,
)

# Generate metadata.json (4th formal artifact).
try:
from src.export import generate_metadata_json # noqa: PLC0415
meta_path = generate_metadata_json(
campaign_id,
DB_PATH,
scores_result=result,
stats=stats,
)
logger.info("metadata.json written: %s", meta_path)
except Exception as _meta_exc:
logger.warning("metadata.json generation failed (non-fatal): %s", _meta_exc)

with get_connection(DB_PATH) as conn:
from src.trust_identity import summarize_report_artifact_status # noqa: PLC0415

Expand Down
103 changes: 98 additions & 5 deletions src/artifact_paths.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,48 @@
_NON_SLUG_CHARS_RE = re.compile(r"[^a-z0-9._-]+")


# =============================================================================
# CANONICAL 4-ARTIFACT CONTRACT
# =============================================================================
# These are the single authoritative definitions for artifact type strings,
# filenames, and roles. All writers, readers, DB registrations, and indexes
# MUST use these constants — never inline string literals.
#
# Artifact type strings (used in the `artifacts` DB table artifact_type column)
ARTIFACT_CAMPAIGN_SUMMARY = "campaign_summary_md"
ARTIFACT_RUN_REPORTS = "run_reports_md"
ARTIFACT_RAW_TELEMETRY = "raw_telemetry_jsonl"
ARTIFACT_METADATA = "metadata_json"
ARTIFACT_LEGACY_REPORT = "report_md"

# Canonical output filenames
FILENAME_CAMPAIGN_SUMMARY = "campaign-summary.md"
FILENAME_RUN_REPORTS = "run-reports.md"
FILENAME_RAW_TELEMETRY = "raw-telemetry.jsonl"
FILENAME_METADATA = "metadata.json"

# Human-readable roles (for display and index tables)
ARTIFACT_ROLES: dict[str, str] = {
ARTIFACT_CAMPAIGN_SUMMARY: "user-facing summary",
ARTIFACT_RUN_REPORTS: "informational detail report",
ARTIFACT_RAW_TELEMETRY: "raw machine measurement stream",
ARTIFACT_METADATA: "structured provenance and scoring record",
}

# Deprecated artifact type strings still present in the DB for historical
# campaigns. These are NOT written for new campaigns (Phase 6 complete).
# They are retained in listing/reading code for backwards compatibility with
# pre-Phase-6 campaigns only.
ARTIFACT_TYPES_DEPRECATED: frozenset[str] = frozenset({
ARTIFACT_LEGACY_REPORT,
"report_v2_md",
"scores_csv",
"raw_jsonl",
"telemetry_jsonl",
"config_yaml",
})


def artifact_root(lab_root: Path) -> Path:
"""Return the canonical artifact root for a lab root."""
return lab_root / "artifacts"
Expand Down Expand Up @@ -100,13 +142,64 @@ def report_paths(
*,
create: bool = True,
) -> dict[str, Path]:
"""Return canonical report-family paths for one campaign."""
"""Return canonical report-family paths for one campaign.

Approved artifact contract (4 formal outputs per campaign):
campaign_summary_md → campaign-summary.md (primary human-facing summary)
run_reports_md → run-reports.md (detailed human-readable evidence)
metadata_json → metadata.json (structured provenance + scores + index)

Measurements family (in artifacts/measurements/...):
raw_telemetry_jsonl → raw-telemetry.jsonl (merged request + telemetry stream)

Deprecated aliases (kept for backwards compatibility during migration):
report_md → alias for campaign_summary_md path
report_v2_md → alias for run_reports_md path
scores_csv → no longer a formal artifact; path retained for migration only
"""
reports_dir = artifact_dir(lab_root, "reports", model_identity, campaign_id, create=create)
campaign_summary = reports_dir / FILENAME_CAMPAIGN_SUMMARY
run_reports = reports_dir / FILENAME_RUN_REPORTS
metadata = reports_dir / FILENAME_METADATA
return {
"dir": reports_dir,
# ── Approved 4-artifact contract ──────────────────────────────────
"campaign_summary_md": campaign_summary,
"run_reports_md": run_reports,
"metadata_json": metadata,
# ── Deprecated aliases: read-compat only, not written for new campaigns ─
"report_md": campaign_summary, # DEPRECATED: alias for campaign_summary_md
"report_v2_md": run_reports, # DEPRECATED: alias for run_reports_md
"scores_csv": reports_dir / "scores.csv", # DEPRECATED: folded into metadata.json
Comment thread
Mad-Labs42 marked this conversation as resolved.
}


def measurement_paths(
lab_root: Path,
model_identity: str,
campaign_id: str,
*,
create: bool = True,
) -> dict[str, Path]:
"""Return canonical measurement-family paths for one campaign.

Approved artifact contract (measurements sub-family):
raw_telemetry_jsonl → raw-telemetry.jsonl (merged request + telemetry stream)

Deprecated (kept during migration):
raw_jsonl → raw.jsonl (DEPRECATED: use raw_telemetry_jsonl)
telemetry_jsonl → telemetry.jsonl (DEPRECATED: merged into raw_telemetry_jsonl)
"""
meas_dir = artifact_dir(
lab_root, "measurements", model_identity, campaign_id, create=create
)
return {
"dir": reports_dir,
"report_md": reports_dir / "report.md",
"report_v2_md": reports_dir / "report_v2.md",
"scores_csv": reports_dir / "scores.csv",
"dir": meas_dir,
# ── Approved ──────────────────────────────────────────────────────
"raw_telemetry_jsonl": meas_dir / FILENAME_RAW_TELEMETRY,
# ── Deprecated aliases: read-compat only, not written for new campaigns ─
"raw_jsonl": meas_dir / "raw.jsonl", # DEPRECATED: merged into raw_telemetry_jsonl
"telemetry_jsonl": meas_dir / "telemetry.jsonl", # DEPRECATED: merged into raw_telemetry_jsonl
}


Expand Down
69 changes: 57 additions & 12 deletions src/db.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,11 +23,13 @@
import json
import logging
import sqlite3
import threading
from datetime import datetime, timezone
from pathlib import Path
from typing import Callable
from typing import Any, Callable

logger = logging.getLogger(__name__)
_JSONL_WRITE_LOCK = threading.Lock()

# ---------------------------------------------------------------------------
# DDL — Table definitions
Expand Down Expand Up @@ -324,7 +326,10 @@
id INTEGER PRIMARY KEY AUTOINCREMENT,
campaign_id TEXT NOT NULL,
artifact_type TEXT NOT NULL,
-- report_md | scores_csv | raw_jsonl | telemetry_jsonl | config_yaml
-- Canonical types (4-artifact contract):
-- campaign_summary_md | run_reports_md | raw_telemetry_jsonl | metadata_json
-- Legacy types (pre-Phase-6 campaigns, read-compat only, not written for new runs):
-- report_md | report_v2_md | scores_csv | raw_jsonl | telemetry_jsonl
path TEXT NOT NULL,
sha256 TEXT,
created_at TEXT NOT NULL,
Expand Down Expand Up @@ -809,22 +814,62 @@ def write_request(conn: sqlite3.Connection, cycle_id: int, result_dict: dict) ->
conn.execute(f"INSERT INTO requests ({col_str}) VALUES ({placeholders})", values)


def write_raw_jsonl(jsonl_path: Path, record: dict) -> None:
"""Append a request record to raw.jsonl (immutable, append-only)."""
jsonl_path.parent.mkdir(parents=True, exist_ok=True)
import json
with open(jsonl_path, "a", encoding="utf-8") as f:
f.write(json.dumps(record) + "\n")


def write_jsonl_marker(jsonl_path: Path, marker_type: str, details: dict[str, Any]) -> None:
def write_raw_jsonl(
jsonl_path: Path,
record: dict,
*,
stream: str | None = None,
merged_path: Path | None = None,
) -> None:
"""Append a record to a JSONL file (immutable, append-only).

Phase 6 callers should pass the canonical ``raw-telemetry.jsonl`` path as
``jsonl_path`` directly. The ``merged_path`` argument is retained for any
code still adapting to the new contract; it is a no-op when both paths are
the same object.

Args:
jsonl_path: Primary output path (typically raw-telemetry.jsonl).
The record is written here exactly as supplied, with
``_stream`` injected only when ``stream`` is provided.
record: Dict to serialize as a JSONL line.
stream: If provided, injected as ``_stream`` into the record
before writing. Approved values: ``"requests"``
(request measurement records), ``"telemetry"`` (hardware
sample records), ``"marker"`` (metadata sentinels), or
``"separator"`` (run-start boundary records).
merged_path: Deprecated — kept for transition compatibility.
If provided and different from ``jsonl_path``, the record
(annotated with ``_stream``) is ALSO written to this path.
"""
import json as _json
primary_record = {**record}
if stream is not None and "_stream" not in primary_record:
primary_record["_stream"] = stream
line = _json.dumps(primary_record) + "\n"
with _JSONL_WRITE_LOCK:
jsonl_path.parent.mkdir(parents=True, exist_ok=True)
with open(jsonl_path, "a", encoding="utf-8") as f:
f.write(line)

# merged_path: kept for transition compatibility only.
# Written only when it refers to a different file than jsonl_path.
if merged_path is not None and merged_path != jsonl_path:
merged_path.parent.mkdir(parents=True, exist_ok=True)
with open(merged_path, "a", encoding="utf-8") as f:
f.write(line)


def write_jsonl_marker(jsonl_path: Path, marker_type: str, details: dict[str, Any], *, merged_path: Path | None = None) -> None:
Comment thread
coderabbitai[bot] marked this conversation as resolved.
"""
Append a metadata marker to a JSONL file.
Preserves forensic history by avoiding rewrites while providing clear boundaries.
If merged_path is provided, the marker is also written there with ``_stream="marker"``.
"""
marker = {
"meta": marker_type,
"timestamp": datetime.now(timezone.utc).isoformat(),
**details,
}
write_raw_jsonl(jsonl_path, marker)
write_raw_jsonl(jsonl_path, marker, stream="marker", merged_path=merged_path)

Loading
Loading