What now works: - M0 scaffold: pyproject (all spec deps), uv/py3.12 env, `python -m festival4d` CLI registering synthetic|ingest|sync|reconstruct|events|serve. Vite hello page. - Synthetic fixture (synthetic.py): 3 shifted-audio videos (offsets 0/+1370/-842 ms), camera-arc poses, stage point cloud -> points.ply, seeded events + anchors, ground_truth.json. `python -m festival4d synthetic` populates data/ + DB. - DB schema exactly per spec §2 (db.py) + CRUD helpers all lanes use. - M3 API (api.py) full against synthetic data: manifest/poses/pointcloud/anchors/ events/detect/annotations; Range-capable video serving (206 verified); CORS for any localhost origin. - Frozen geometry contract: geometry.colmap_to_threejs (M5 math) + unit test (3 known vectors, random round-trip, scipy oracle); mirrored frontend/src/lib/pose.js with identical POSE_TEST_VECTORS. Lane-B stubs: slerp_pose, ray_from_pixel, triangulate_rays, nearest_point_on_ray. - Classifier contract (events_ai.py): MomentClassification model + MomentClassifier protocol + Gemini/Claude/Local provider stubs. - Lane-owned modules stubbed with final signatures (ingest, audio_sync, frames, sfm, events_ai); cli/api catch NotImplementedError and degrade gracefully. - plan/CHANGE_REQUESTS.md created; plan/status/foundation.md updated. Acceptance: pytest 24 passed; serve endpoints verified via curl + browser (video seek, manifest fetch cross-origin, pose.js self-test, 0 console errors). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
44 lines
1.6 KiB
HTML
44 lines
1.6 KiB
HTML
<!doctype html>
|
|
<html lang="en">
|
|
<head>
|
|
<meta charset="UTF-8" />
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
<title>Festival 4D</title>
|
|
<style>
|
|
:root { color-scheme: dark; }
|
|
body {
|
|
margin: 0;
|
|
font: 15px/1.5 -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
|
|
background: #0b0d12;
|
|
color: #e6e8ee;
|
|
padding: 2rem;
|
|
}
|
|
h1 { margin: 0 0 0.25rem; font-size: 1.6rem; }
|
|
.sub { color: #8a92a6; margin-bottom: 1.5rem; }
|
|
.card {
|
|
background: #141824;
|
|
border: 1px solid #232838;
|
|
border-radius: 10px;
|
|
padding: 1rem 1.25rem;
|
|
margin-bottom: 1rem;
|
|
max-width: 720px;
|
|
}
|
|
.ok { color: #59d499; }
|
|
.bad { color: #ff6b6b; }
|
|
table { border-collapse: collapse; width: 100%; }
|
|
th, td { text-align: left; padding: 0.35rem 0.6rem; border-bottom: 1px solid #232838; }
|
|
th { color: #8a92a6; font-weight: 600; }
|
|
code { background: #1c2233; padding: 0.1rem 0.35rem; border-radius: 4px; }
|
|
.pill { display: inline-block; padding: 0.1rem 0.5rem; border-radius: 999px; font-size: 0.8rem; }
|
|
.pill.ok { background: rgba(89,212,153,0.15); }
|
|
.pill.bad { background: rgba(255,107,107,0.15); }
|
|
</style>
|
|
</head>
|
|
<body>
|
|
<h1>Festival 4D</h1>
|
|
<div class="sub">Foundation hello page — proves the API contract, CORS, and the frozen pose helper.</div>
|
|
<div id="app"><div class="card">Loading…</div></div>
|
|
<script type="module" src="/src/main.js"></script>
|
|
</body>
|
|
</html>
|