#!/usr/bin/env python3 """Seed Trusted Project State entries for all active projects. Populates the project_state table with curated decisions, requirements, facts, contacts, and milestones so context packs have real content in the highest-trust tier. Usage: python3 scripts/seed_project_state.py --base-url http://dalidou:8100 python3 scripts/seed_project_state.py --base-url http://dalidou:8100 --dry-run """ from __future__ import annotations import argparse import json import urllib.request import sys # Each entry: (project, category, key, value, source) SEED_ENTRIES: list[tuple[str, str, str, str, str]] = [ # ---- p04-gigabit (GigaBIT M1 1.2m Primary Mirror) ---- ("p04-gigabit", "fact", "mirror-spec", "1.2m borosilicate primary mirror for GigaBIT telescope. F/1.5, lightweight isogrid back structure.", "CDR docs + vault"), ("p04-gigabit", "decision", "back-structure", "Option B selected: conical isogrid back structure with variable rib density. Chosen over flat-back for stiffness-to-weight ratio.", "CDR 2026-01"), ("p04-gigabit", "decision", "polishing-vendor", "ABB Space (formerly INO) selected as polishing vendor. Contract includes computer-controlled polishing (CCP) and ion beam figuring (IBF).", "Entente de service 2026-01"), ("p04-gigabit", "requirement", "surface-quality", "Surface figure accuracy: < 25nm RMS after final figuring. Microroughness: < 2nm RMS.", "CDR requirements"), ("p04-gigabit", "contact", "abb-space", "ABB Space (INO), Quebec City. Primary contact for mirror polishing, CCP, and IBF. Project lead: coordinating FDR deliverables.", "vendor records"), ("p04-gigabit", "milestone", "fdr", "Final Design Review (FDR) in preparation. Deliverables include interface drawings, thermal analysis, and updated error budget.", "project timeline"), # ---- p05-interferometer (Fullum Interferometer) ---- ("p05-interferometer", "fact", "system-overview", "Custom Fizeau interferometer for in-situ metrology of large optics. Designed for the Fullum observatory polishing facility.", "vault docs"), ("p05-interferometer", "decision", "cgh-design", "Computer-generated hologram (CGH) selected for null testing of the 1.2m mirror. Vendor: Diffraction International.", "vendor correspondence"), ("p05-interferometer", "requirement", "measurement-accuracy", "Measurement accuracy target: lambda/20 (< 30nm PV) for surface figure verification.", "system requirements"), ("p05-interferometer", "fact", "laser-source", "HeNe laser source at 632.8nm. Beam expansion to cover full 1.2m aperture via diverger + CGH.", "optical design docs"), ("p05-interferometer", "contact", "diffraction-intl", "Diffraction International: CGH vendor. Fabricates the computer-generated hologram for null testing.", "vendor records"), # ---- p06-polisher (Polisher Suite / P11-Polisher-Fullum) ---- ("p06-polisher", "fact", "suite-overview", "Integrated CNC polishing suite for the Fullum observatory. Includes 3-axis polishing machine, metrology integration, and real-time process control.", "vault docs"), ("p06-polisher", "decision", "control-architecture", "Beckhoff TwinCAT 3 selected for real-time motion control. EtherCAT fieldbus for servo drives and I/O.", "architecture docs"), ("p06-polisher", "decision", "firmware-split", "Firmware split into safety layer (PLC-level interlocks) and application layer (trajectory generation, adaptive dwell-time).", "architecture docs"), ("p06-polisher", "requirement", "axis-travel", "Z-axis: 200mm travel for tool engagement. X/Y: covers 1.2m mirror diameter plus overshoot margin.", "mechanical requirements"), ("p06-polisher", "fact", "telemetry", "Real-time telemetry via MQTT. Metrics: spindle RPM, force sensor, temperature probes, position feedback at 1kHz.", "control design docs"), ("p06-polisher", "contact", "fullum-observatory", "Fullum Observatory: site where the polishing suite will be installed. Provides infrastructure (power, vibration isolation, clean environment).", "project records"), # ---- atomizer-v2 ---- ("atomizer-v2", "fact", "product-overview", "Atomizer V2: internal project management and multi-agent orchestration platform. War-room based task coordination.", "repo docs"), ("atomizer-v2", "decision", "projects-first-architecture", "Migration to projects-first architecture: each project is a workspace with its own agents, tasks, and knowledge.", "war-room-migration-plan-v2.md"), # ---- abb-space (P08) ---- ("abb-space", "fact", "contract-overview", "ABB Space mirror polishing contract. Phase 1: spherical mirror polishing (200mm). Schott Zerodur substrate.", "quotes + correspondence"), ("abb-space", "contact", "schott", "Schott AG: substrate supplier for Zerodur mirror blanks. Quote received for 200mm blank.", "vendor records"), # ---- atocore ---- ("atocore", "fact", "architecture", "AtoCore: runtime memory and knowledge layer. FastAPI + SQLite + ChromaDB. Hosted on Dalidou (Docker). Nightly pipeline: backup, extract, triage, synthesis.", "codebase"), ("atocore", "decision", "no-api-keys", "No API keys allowed in AtoCore. LLM-assisted features use OAuth via 'claude -p' CLI or equivalent CLI-authenticated paths.", "DEV-LEDGER 2026-04-12"), ("atocore", "decision", "storage-separation", "Human-readable sources (vault, drive) and machine operational storage (SQLite, ChromaDB) must remain separate. Machine DB is derived state.", "AGENTS.md"), ("atocore", "decision", "extraction-off-hot-path", "Extraction stays off the capture hot path. Batch/manual only. Never block interaction recording with extraction.", "DEV-LEDGER 2026-04-11"), ] def main() -> None: parser = argparse.ArgumentParser(description="Seed Trusted Project State") parser.add_argument("--base-url", default="http://dalidou:8100") parser.add_argument("--dry-run", action="store_true") args = parser.parse_args() base = args.base_url.rstrip("/") created = 0 skipped = 0 errors = 0 for project, category, key, value, source in SEED_ENTRIES: if args.dry_run: print(f" [DRY] {project}/{category}/{key}: {value[:60]}...") created += 1 continue body = json.dumps({ "project": project, "category": category, "key": key, "value": value, "source": source, "confidence": 1.0, }).encode() req = urllib.request.Request( f"{base}/project/state", data=body, headers={"Content-Type": "application/json"}, method="POST", ) try: resp = urllib.request.urlopen(req, timeout=10) result = json.loads(resp.read()) if result.get("created"): created += 1 print(f" + {project}/{category}/{key}") else: skipped += 1 print(f" = {project}/{category}/{key} (already exists)") except Exception as e: errors += 1 print(f" ! {project}/{category}/{key}: {e}", file=sys.stderr) print(f"\nDone: {created} created, {skipped} skipped, {errors} errors") if __name__ == "__main__": main()