A deterministic, offline compiler that turns a natural-language description of a bioinformatics analysis into a self-contained, agent-executable RO-Crate package — with a full-lifecycle conversational shell wrapped around the executing package.
The compiler classifies the intake, selects an archetype, builds a task DAG, emits a package, and an execution harness drives an agent (Claude Code, a shell script, anything callable with a package path) against the emitted DAG. The emitted package is an ECAA (Evidence-Carrying Analysis Artifact) v0.2 package — a typed RO-Crate that carries, alongside the analysis itself, the claims it supports, the evidence backing each claim, and the decision record that produced them. An embedded ECAA validator checks the package against a machine-checkable contract over those subgraphs. Emit-time validation defaults to pure-Rust JSON Schema (schema_only) and is advisory (warn-only) on a plain emit unless ECAA_VALIDATION_BLOCK_ON_FAIL=1; the local conformance gate (make conformance, ECAA_CONFORMANCE_MODE=1) runs it block-on-fail. The contract establishes machine-checkable consistency between an analysis's claims, evidence, decisions, and execution provenance — it does not establish biological validity; treat verdicts as a hygiene floor, not a quality ceiling.
The only host dependency is a container runtime — Docker, or (preferred) rootless Podman. From a clone of this repo:
make up # build the server image and run it → http://127.0.0.1:3000
make down # stop it (make logs to tail)Or run a prebuilt release image instead of building it — point ECAA_IMAGE at a published tag (or digest) and run it through the same compose:
export ECAA_IMAGE=ghcr.io/<org>/ecaa-workflow-server:v0.1.0 # tag or ...@sha256:<digest>
./deploy/ecaa pull && ./deploy/ecaa up # → http://127.0.0.1:3000The server binds the host loopback (auth-free, like a local process) and launches per-task agent containers as siblings over the mounted runtime socket. Configuration comes from a .env beside compose.yaml — auto-created from deploy/env.compose.example on first run; set ECAA_ANTHROPIC_API_KEY there for live chat (omit it for offline mock chat). To run analyses, log in to Claude Code once so ~/.claude holds subscription credentials (mounted read-only). ./deploy/ecaa doctor runs a preflight; shared-server / cloud / HPC deployment is in deploy/; building and publishing release images is below.
| Component | Crate / dir | Role |
|---|---|---|
| Compiler | crates/{core, cli} |
Classifier → DAG → emitter. Synchronous, no LLM dependency. |
| Conversation shim | crates/conversation |
Closed tool vocabulary wraps the compiler. LLM is a UX shim only. |
| Chat server | crates/server |
Axum HTTP + SSE backend at /api/chat/* and /api/git/*. |
| Execution harness | crates/harness |
Loops an agent subprocess against ready tasks. Local / Mock / AWS / SLURM executors. |
| ECAA validator | crates/{ecaa-conformance, ecaa-types} + docs/ecaa-spec/ |
Emits + validates the ECAA conformance contract. ecaa-conformance re-exports core's public API and is the conformance harness a second implementer runs against their own packages — not an independent reimplementation of core. |
| Web UI | ui/ |
React 18 + Vite + TypeScript chat surface. |
Current ECAA profile IRI: https://w3id.org/ecaa/v0.2. The active spec files are in docs/ecaa-spec/: v0.2.md, ecaa-v0.2.ttl, ecaa-v0.2.shacl.ttl, and ecaa-v0.2.jsonld.
Release images are multi-arch (linux/amd64,linux/arm64) and pushed to a container registry (e.g. GHCR). There is no CI — an operator builds and pushes them locally. Authenticate, then build with your own registry namespace and a versioned tag:
echo "$GHCR_PAT" | docker login ghcr.io -u <user> --password-stdin # PAT needs write:packages
# build + push BOTH the server and the bio-min task image; prints the pushed manifest digest:
make release-image \
SERVER_IMAGE=ghcr.io/<org>/ecaa-workflow-server:v0.1.0 \
BIO_MIN_IMAGE=ghcr.io/<org>/bio-min:v0.1.0Pin consumers to the printed sha256: digest (tags are mutable; digests are not). The registry repo must already exist (gh repo / registry UI) — the tooling can push but cannot create remotes. For a full signed release (SBOM + cosign signature + SHA256SUMS + GitHub release):
TAG=v0.1.0 make release \
SERVER_IMAGE=ghcr.io/<org>/ecaa-workflow-server:v0.1.0 \
BIO_MIN_IMAGE=ghcr.io/<org>/bio-min:v0.1.0 \
COSIGN_KEY=cosign.keymake release refuses a dirty tree; release-sbom / release-sign require syft/grype / cosign on PATH. Honest ceiling without CI: SLSA build L1 self-attested provenance + a cosign-signed SBOM (L2/L3 need a hosted builder). make help lists the individual release-* targets.
Linux x86-64 is the primary supported target. macOS works for dev. Windows requires WSL2.
# 1. System tools
sudo apt-get install -y build-essential pkg-config libssl-dev mold git curl # Debian/Ubuntu
# or: sudo dnf install -y @development-tools openssl-devel mold git curl # Fedora/RHEL
# or: brew install mold openssl@3 pkg-config # macOS
# 2. Rust toolchain (auto-installs the pinned channel from rust-toolchain.toml)
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y
source "$HOME/.cargo/env"
# 3. Cargo dev tools
cargo install --locked cargo-nextest cargo-hakari
# 4. Node.js 20+ (for the UI + Playwright); verify: node --version # ≥ 20
# 5. Build + install binaries + UI deps
make build && make install
(cd ui && npm install)make doctor prints toolchain readiness; make help lists targets.
Run the stack from source in two terminals:
make dev-server # chat server on :3000 (cargo run)
make dev-ui # Vite dev UI on :5173 (proxies /api/* to :3000)Execution requires the installed harness binary.
make dev-server/make dev-uirun from source, so they work withoutmake install. But the Start execution button spawns theecaa-workflow-harnessbinary by name fromPATH(override withECAA_HARNESS_BIN_PATH). If you skippedmake install, execution fails withfailed to spawn harness: No such file or directory; runmake installto fix it. (The Docker path above bundles the harness, so this only affects from-source runs.)
The chat surface boots in offline mode without an API key (the UI renders but assistant turns are mocked). For LLM-mediated chat, export ECAA_ANTHROPIC_API_KEY=<your key> before make dev-server. For local production configuration, start from .env.example — its active defaults are loopback/local and durable under $HOME/.ecaa-workflow; live API, eval, debug, AWS, SLURM, and external-validator knobs are commented until deliberately enabled.
Smoke-test the compiler against a bundled scenario:
ecaa-workflow intake \
--input testdata/scenarios/01-bulk-rnaseq-ibd/request.md \
--output /tmp/ibd-package
ecaa-workflow dag --package /tmp/ibd-packagemake test # cargo test --workspace
make test-ui # Vitest + axe a11y
make check # test + tsc --noEmit
make e2e-playwright # mocked Playwright tier- Compiler is synchronous.
tokiois allowed inserver,conversation, andcli(forserveonly). Never incoreorharness. Harness usesureq(sync). - Deterministic output. Emitted packages are byte-reproducible. Use
BTreeMap, notHashMap. Avoid timestamps and random IDs outsideuuid_short(). - LLM as UX shim. Closed tool vocabulary (
Tool::COUNTasserted at compile time). High-impact actions are gated by deterministic server state, not LLM inference. - Confirmation discipline.
emit_packagereturnsPreconditionFailureunlesssession.user_confirmed == true. The button click is a server-side action the LLM observes only viaget_session_state. - ECAA conformance. Every normal emitted package carries the eight required ECAA v0.2 sidecars:
runtime/intake-conversation.jsonl,runtime/decisions.jsonl,runtime/validation-reports.jsonl,runtime/proofs.jsonl,runtime/claim-verification.json,runtime/verifier-decisions.jsonl,runtime/assumptions.jsonl, andruntime/audit-proof-report.json. There is no reduced ECAA mode switch;ECAA_ABLATE_*flags are the only code-backed way to emit non-conformant control artifacts.
config/ is the source of truth for modalities, archetypes, atoms, compute profiles, gene panels, plot affordances, and downstream-policy contracts. config/archetypes/ and config/stage-atoms/ carry their own READMEs. Runtime environment variables are catalogued in .env.example.
User guide: USERS.md. Methods summary: METHODS.md. Contributor guide: CONTRIBUTING.md. ECAA spec: docs/ecaa-spec/.
Apache-2.0 — see LICENSE.