- board.html: a card whose parent_id resolves to an existing card is rendered nested inside that parent instead of as a detached top-level column card, and stays fully draggable there (docs/intent/board-nested-child-intents.md). - metrics.py (new) + hooks in worker.py/completion_watcher.py: opt-in run_history logging gated by BOARD_METRICS_SLUGS, exposed as a compact per-card summary via trigger.py/board.html. - metrics_baseline.py (new) + worker.run_baseline(): manual CLI to send an intent straight to a model with no board pipeline, no repo access, as the comparison point for the run-metrics pilot (docs/intent/board-intent-run-metrics-baseline.md). - 16 new tests, 148/148 total passing. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01UeyiEf4XmoPgxkarAXamGe
103 lines
3.6 KiB
Python
103 lines
3.6 KiB
Python
#!/usr/bin/env python3
|
|
"""Manual pilot tool for docs/intent/board-intent-run-metrics-baseline.md:
|
|
send an existing card's intent markdown directly to a model -- no board
|
|
pipeline, no Builder/Reviewer/Researcher role prompt, no repository
|
|
access -- and log the attempt next to that card's normal run_history for
|
|
later comparison against its Board-driven runs.
|
|
|
|
Deliberately not wired into board-agent.nix as a service: this is an
|
|
explicit, occasional action an operator runs by hand against the exact
|
|
same environment (BOARD_* variables) the board-agent systemd units
|
|
already use, e.g.
|
|
|
|
sudo systemctl show board-agent-worker.service --property=Environment
|
|
|
|
Only ever writes to docs/metrics/<slug>-baseline-<timestamp>.md (created
|
|
if missing) and to the run's own state.json entry (only if the slug is
|
|
in BOARD_METRICS_SLUGS -- see metrics.record_run()); it never touches an
|
|
intent document, a review, or any other board state.
|
|
"""
|
|
|
|
import argparse
|
|
import os
|
|
import subprocess
|
|
import sys
|
|
import time
|
|
from pathlib import Path
|
|
|
|
import metrics
|
|
import trigger
|
|
import worker
|
|
|
|
|
|
def load_intent_text(slug):
|
|
if slug in trigger.list_intent_cards():
|
|
return trigger.read_intent(slug)["content"]
|
|
if slug in trigger.list_research_cards():
|
|
return trigger.read_research_intent(slug)["content"]
|
|
raise LookupError(f"unbekannte Karte: {slug}")
|
|
|
|
|
|
def write_baseline_report(repo_dir, slug, response):
|
|
metrics_dir = repo_dir / "docs" / "metrics"
|
|
metrics_dir.mkdir(parents=True, exist_ok=True)
|
|
report_path = metrics_dir / f"{slug}-baseline-{int(time.time())}.md"
|
|
report_path.write_text(response.rstrip() + "\n", encoding="utf-8")
|
|
return str(report_path.relative_to(repo_dir))
|
|
|
|
|
|
def main():
|
|
parser = argparse.ArgumentParser(description=__doc__)
|
|
parser.add_argument("slug", help="bestehender Intent- oder Research-Intent-Slug")
|
|
parser.add_argument("--runtime", choices=("codex", "claude"), required=True)
|
|
parser.add_argument("--model", required=True, help="explizites Modell -- kein stiller Default")
|
|
parser.add_argument("--reasoning-effort", default=None)
|
|
args = parser.parse_args()
|
|
|
|
if not metrics.enabled(args.slug):
|
|
print(
|
|
f"Warnung: '{args.slug}' ist nicht in BOARD_METRICS_SLUGS -- "
|
|
"das Ergebnis wird ausgegeben, aber nicht in run_history gespeichert.",
|
|
file=sys.stderr,
|
|
)
|
|
|
|
try:
|
|
intent_text = load_intent_text(args.slug)
|
|
except LookupError as error:
|
|
print(str(error), file=sys.stderr)
|
|
return 1
|
|
|
|
started_at = metrics.now_iso()
|
|
try:
|
|
response = worker.run_baseline(intent_text, args.runtime, args.model, args.reasoning_effort)
|
|
except (OSError, ValueError, RuntimeError, subprocess.TimeoutExpired) as error:
|
|
metrics.record_run(
|
|
args.slug,
|
|
"baseline_single_prompt",
|
|
status="failed",
|
|
runtime=args.runtime,
|
|
model=args.model,
|
|
reasoning_effort=args.reasoning_effort,
|
|
duration_seconds=metrics.duration_since(started_at),
|
|
)
|
|
print(f"Baseline-Lauf fehlgeschlagen: {error}", file=sys.stderr)
|
|
return 1
|
|
|
|
repo_dir = Path(os.environ["BOARD_REPO_DIR"])
|
|
report_path = write_baseline_report(repo_dir, args.slug, response)
|
|
metrics.record_run(
|
|
args.slug,
|
|
"baseline_single_prompt",
|
|
status="done",
|
|
runtime=args.runtime,
|
|
model=args.model,
|
|
reasoning_effort=args.reasoning_effort,
|
|
report_path=report_path,
|
|
duration_seconds=metrics.duration_since(started_at),
|
|
)
|
|
print(f"Antwort gespeichert unter {report_path}")
|
|
return 0
|
|
|
|
|
|
if __name__ == "__main__":
|
|
raise SystemExit(main())
|