summaryrefslogtreecommitdiff
path: root/README.md
diff options
context:
space:
mode:
authorSomhairle H. Marisol <[email protected]>2026-09-21 00:58:15 +0800
committerSomhairle H. Marisol <[email protected]>2026-09-21 00:58:15 +0800
commit7b29dbff7e43e87741476f47df17ad1582b16546 (patch)
tree4c9d0832b4e4edd77e59e9cb0a88abf5e729a9f9 /README.md
parent47add3088d50f12c5f48591f26c53cdb59d8283b (diff)
downloadsomhairles-dream-fsharp-7b29dbff7e43e87741476f47df17ad1582b16546.tar.gz
feat(pipeline): add runnable artifact pipeline increment
[Change Nature] - This commit adds the first runnable increment of the F# artifact pipeline: CLI, server, frontend bundle, stage fixture, and tests. It is feature work, not a bug fix. [New Capability] - CLI `run` executes the three-step Blender fixture through the process bridge and writes GLBs, step logs, events, and a manifest; `verify` validates a manifest without Blender. - Server exposes run start, run-scoped SSE, artifact manifest/file routes, and serves the Fable frontend from its build output. - Frontend starts runs, follows run-scoped SSE progress, and links the artifact manifest on completion. [Implementation] - Shared layer holds domain, run state, replay, and artifact contracts; Modeling holds the pipeline, 120s bridge timeout, and result-file protocol; stage/blender/fixture.py owns geometry in Python (bpy owns geometry, F# owns orchestration). - Fable bundle is regenerated into public/ and copied by the server project; solution includes all projects with warnings-as-errors. - README documents build, Fable, server, interpreter/env, fixture limitations, and current verification status. [Impact] - Verified: 40/40 solution tests pass; Release build 0 warnings/errors; real CLI run with bpy 5.0.1 produced 3 GLBs, 3 logs, and a verify-clean manifest; isolated-port server smoke flow succeeded. - Not yet verified: browser end-to-end behavior and production fidelity. Artifacts and caches are gitignored.
Diffstat (limited to 'README.md')
-rw-r--r--README.md117
1 files changed, 117 insertions, 0 deletions
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..7059a51
--- /dev/null
+++ b/README.md
@@ -0,0 +1,117 @@
+# somhairles-dream-fsharp
+
+F# implementation of the heritage boat modeling pipeline: a Blender-driven
+artifact pipeline (CLI), an ASP.NET server that runs and observes artifact
+runs, and a Fable/Three.js frontend that follows run progress live.
+
+Architecture boundary: F# owns the frontend, backend, and orchestration
+(pipeline, artifacts, verification, serving). Python (`bpy`) owns geometry
+generation inside `stage/blender/fixture.py`. There is no F# geometry DSL.
+
+## Layout
+
+- `src/SomhairlesDream.Shared` — domain, run state, replay, artifact contracts
+- `src/SomhairlesDream.Modeling` — pipeline, Blender process bridge, verifier
+- `src/SomhairlesDream.Cli` — `run` and `verify` commands
+- `src/SomhairlesDream.Server` — run API, SSE, static frontend host
+- `src/SomhairlesDream.Frontend` — Fable browser app compiled to `public/`
+- `stage/blender/fixture.py` — deterministic bpy fixture (3 steps, 7 objects)
+- `public/` — static frontend served by the server (index, styles, JS bundle)
+- `tests/` — xUnit test projects per layer
+
+## Build and test
+
+Requires .NET SDK 8 (pinned by `global.json`). Warnings are errors.
+
+```sh
+dotnet build SomhairlesDream.sln
+dotnet test SomhairlesDream.sln
+```
+
+## Frontend (Fable)
+
+`src/SomhairlesDream.Frontend` compiles to `public/`. Regenerate after edits:
+
+```sh
+dotnet fable src/SomhairlesDream.Frontend/SomhairlesDream.Frontend.fsproj \
+ --outDir public --noRestore
+```
+
+The server project copies `public/**` into its build output
+(`CopyToOutputDirectory=PreserveNewest`), so rerun `dotnet build` on the server
+after regenerating the bundle.
+
+## Server
+
+```sh
+dotnet run --project src/SomhairlesDream.Server
+```
+
+Environment variables (all optional):
+
+- `SOMHAIRLES_ARTIFACT_ROOT` — artifact output root (default `.artifacts`)
+- `SOMHAIRLES_STAGE_ROOT` — stage directory containing `blender/fixture.py`
+ (default `stage`)
+- `SOMHAIRLES_BPYTHON` — Python interpreter used to run the fixture
+ (default `python3`)
+
+Routes used by the frontend: `POST /api/runs/start`,
+`GET /api/runs/events?projectId=...&runId=...` (run-scoped SSE),
+`GET /api/artifacts/manifest`, `GET /api/artifacts/file`. The server binds to
+the ASP.NET default (add `--urls http://127.0.0.1:8099` to match the legacy
+port).
+
+## CLI
+
+```sh
+dotnet run --project src/SomhairlesDream.Cli -- run [options]
+dotnet run --project src/SomhairlesDream.Cli -- verify <manifest.json>
+```
+
+`run` options: `--project-id`, `--run-id`, `--base-id`, `--target-id`,
+`--output-root`, `--stage-root`, `--python`, `--render`. `SOMHAIRLES_BPYTHON`
+sets the default interpreter. Exit codes: `0` success, `2` usage, `3` bridge
+failure, `4` pipeline/verify failure. On success it prints the manifest path.
+
+A run produces, under `<output-root>/<projectId>/<runId>/`:
+
+- `events.ndjson`, `manifest.json`
+- `logs/01-foundation.log`, `02-frame.log`, `03-cabin.log`
+- `steps/01-foundation.glb`, `02-frame.glb`, `03-cabin.glb`
+
+`verify` recomputes hashes, checks log presence, path containment, object-ID
+proofs, timestamps, and duplicate steps without needing Blender.
+
+## Python interpreter for bpy
+
+The fixture requires a Python that can `import bpy` (Blender as a module,
+version >= 3.0.0). A system `python3` usually cannot. This project was
+verified with a uv-managed environment at `/tmp/bpyenv/bin/python`
+(`bpy 5.0.1`). Note that `/tmp` is ephemeral; recreate or point
+`SOMHAIRLES_BPYTHON`/`--python` at any interpreter that provides `bpy`.
+
+Example:
+
+```sh
+dotnet run --project src/SomhairlesDream.Cli -- run \
+ --output-root .artifacts --python /tmp/bpyenv/bin/python
+```
+
+## Fixture limitations
+
+- `stage/blender/fixture.py` is a deterministic placeholder geometry fixture
+ (named cubes with `object_id` custom properties), not a production model.
+- Bridge timeout is 120 seconds per step; the bridge requires the fixture to
+ write its result JSON to `--result-output` (stdout/stderr are diagnostics
+ only, retained as step logs).
+- Renders are produced only with `--render` (512x512 PNG per step).
+- Reimport verification counts objects (`2 -> 5 -> 7` across the three steps)
+ and checks the `object_id` custom properties survive the GLB round-trip.
+
+## Verification status
+
+- Full solution test suite and Release build: clean (0 warnings/errors).
+- Real CLI pipeline with `/tmp/bpyenv/bin/python`: 3 GLBs + logs + manifest,
+ `verify` exit 0.
+- Browser end-to-end behavior and production fidelity are NOT yet verified;
+ the pipeline contract tests cover the generated bundle routes only.