- Rust — pinned via
rust-toolchain.toml.rustupinstalls the channel automatically on firstcargoinvocation. Required components (rustfmt,clippy,rust-src) are part of the pin. - mold linker —
apt install mold(Debian/Ubuntu),dnf install mold(Fedora),brew install mold(macOS)..cargo/config.tomlroutes the linker through it. - cargo-nextest (optional) —
cargo install --locked cargo-nextest. Process-per-test runner; falls back tocargo testwhen absent. - sccache (required) —
cargo install --locked sccache..cargo/config.tomlsetsrustc-wrapper = "sccache"unconditionally, so the build fails without it on PATH;make doctorsurfaces its absence. (No manualRUSTC_WRAPPERexport needed.) - cargo-hakari (required if you touch any
Cargo.toml) —cargo install --locked cargo-hakari. Regenerateworkspace-hackwithcargo hakari generate && cargo hakari manage-deps --yes. - bacon (optional) —
cargo install --locked bacon. Backgroundcargo check/test/clippyfor the inner loop;bacon.tomlpre-configures jobs. - Node.js 20+ and npm — for the web UI in
ui/and the Playwright e2e tier. - GNU make — used by every shortcut here.
- Python 3.10+ (optional) — only needed for a handful of helper scripts.
Run make doctor after install to verify every tool is on PATH.
make build # cargo build
make test # cargo test --workspace
make check # test + tsc --noEmit on the UI
make clippy # cargo clippy --workspace -- -D warnings
make fmt # cargo fmt --all
make test-ui # Vitest on ui/
make e2e-playwright # Playwright mocked tiermake help lists every target with a one-line description.
crates/
core/ — classifier, atom registry, archetype registry, modality registry,
composer, RO-Crate emitter, claim verifier, task model
conversation/ — LLM-mediated chat service (Anthropic client, sessions, tools, prompt)
cli/ — ecaa-workflow binary (chat, intake, build, dag, serve)
server/ — ecaa-workflow-server binary (Axum HTTP + SSE backend)
harness/ — ecaa-workflow-harness binary (agent loop executor + ProgressClient)
ecaa-conformance/ — ECAA validator + types
ecaa-types/ — shared type schema for ECAA package + audit-proof output
workspace-hack/ — auto-generated by cargo hakari to unify dependency resolution
ui/ — React 18 + Vite + TypeScript frontend
e2e/ — Playwright end-to-end tests (mocked tier)
lib/plotting{,_r}/ — Python + R plot renderers executed in the agent container
config/
modalities/ — per-modality manifests
modality-keywords.yaml
project-class-keywords.yaml
archetypes/ — composer fast-path: declarative scaffolds over atoms
stage-atoms/ — atom library: typed (operation × input × output) triples
downstream-policy/ — JSON policies emitted into packages
compute-profiles/ — AWS + SLURM sizing tables + GPU capability map
gene-panels/ — marker-gene YAMLs consumed by discover_* stages
plot-affordances/ — semantic type → renderer module registry
scripts/ — operational + agent dispatch shell/Python scripts
testdata/scenarios/ — public-data test scenarios
tests/ — conversation fixture corpus, golden workflows, auditability corpus
docs/ecaa-spec/ — ECAA conformance contract: TTL, SHACL, JSON-LD, 8 JSON Schemas
All four binaries link against crates/core; CLI/server also link against crates/conversation. Never fork logic between a binary and core — put it in core and call it from the binary.
cargo fmtandcargo clippy -D warningsare enforced. Run them before pushing.- Deterministic output. Emitted packages must be byte-reproducible for the same intake and config. Use
BTreeMap, notHashMap; avoid timestamps in generated artifacts; avoid random IDs outsideuuid_short(). - Compiler is synchronous.
tokiois allowed inserver,conversation, andcli(forserveonly). Never incoreorharness. Harness usesureq(sync). - 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. It must be the only tool call in its turn. - Adding a modality requires (1) a manifest under
config/modalities/<id>.yaml, (2) the matching archetype underconfig/archetypes/<id>.yaml, (3) a classifier or composer test case incrates/core.
- React 18 function components + hooks only. No router, no global state library, no CSS-in-JS runtime.
App.tsxowns the singleuseConversationanduseSseChatEventsinstances and threads them into both panes. One session + oneEventSourceper page.ui/src/api/chatClient.tsis the source of truth for the chat REST contract.ui/src/types/is generated bymake types— don't hand-edit.
- One logical change per commit.
- Commit messages follow Conventional Commits (
feat(core):,fix(cli):,docs:,refactor:,test:). - Include the matching test update in the same commit as the code change when feasible.
Source comments describe what the code does and why, not when it was written. Do not reference plan documents, phase/sprint identifiers, PR numbers, ticket IDs, or implementation dates in source comments. Put that context in the commit message — it rots gracefully and stays discoverable via git log / git blame.