Purpose: Multi-agent system for converting natural language event descriptions into valid Hierarchical Event Descriptors (HED) annotations using LangGraph. Part of the Annotation Garden Initiative (AGI). Tech Stack: Python 3.12+, LangGraph, FastAPI, HED JavaScript/Python validators, Cloudflare Pages + Workers, Anthropic Claude via the Claude Platform on AWS (Anthropic-operated Messages API, AWS Marketplace billing; NOT Bedrock). Models: claude-haiku-4-5 (default) and claude-sonnet-5.
src/
├── agents/ # LangGraph agent implementations
├── validation/ # HED validation integration
├── api/ # FastAPI backend (main.py: endpoints, CORS, auth)
├── cli/ # Typer + Rich CLI
└── utils/ # Helper functions
frontend/ # Web interface (Cloudflare Pages; config.js picks backend)
workers/ # Cloudflare Worker proxies (index.js + wrangler.toml)
deploy/ # Deployment assets
tests/ # pytest + coverage
.context/ # Context files (architecture, deployment, HED semantics)
.rules/ # Rule files (git, python, testing, ci_cd, ...)
uv venv
source .venv/bin/activate
uv pip install -e ".[dev]"
uv run pytest # Run tests
uv run pytest -m "not integration" # Skip integration tests
uv run pytest tests/test_hed_lsp.py -v # Single test filehedit.pages.dev (frontend, Cloudflare Pages)
└─> hedit-api.shirazi-10f.workers.dev (Cloudflare Worker proxy: Turnstile,
rate limit, KV cache, CORS; forwards X-API-Key to backend)
└─> api.annotation.garden/hedit (Cloudflare DNS -> Apache reverse
proxy on SCCN VM, hedtools.ucsd.edu)
└─> FastAPI container (port 38427)
Dev mirrors this: develop.hedit.pages.dev -> hedit-dev-api.shirazi-10f.workers.dev
-> api.annotation.garden/hedit-dev -> container port 38428.
frontend/config.js selects the Worker by hostname.
The Workers in workers/index.js are NOT deployed by CI.
After any change to workers/, deploy both environments explicitly:
cd workers
bunx cfman wrangler --account neuromechanist deploy # prod: hedit-api
bunx cfman wrangler --account neuromechanist deploy --env dev # dev: hedit-dev-apiSecrets (BACKEND_API_KEY, TURNSTILE_SECRET_KEY) and KV bindings persist across deploys.
The Worker maintains its own Access-Control-Allow-Headers list in workers/index.js,
separate from the FastAPI CORS middleware in src/api/main.py.
If the frontend starts sending a new request header (or the backend expects one),
BOTH lists must include it, and BOTH Workers must be redeployed.
A stale Worker list makes the browser preflight fail,
which surfaces as "Load failed" (Safari) or
"NetworkError when attempting to fetch resource" (Firefox).
Verify after deploying:
curl -si -X OPTIONS https://hedit-api.shirazi-10f.workers.dev/annotate/stream \
-H 'Origin: https://hedit.pages.dev' \
-H 'Access-Control-Request-Method: POST' \
-H 'Access-Control-Request-Headers: content-type,x-anthropic-model,x-user-id' \
| grep -i access-control- Check context: Review plan.md for current tasks and roadmap
- Branch: Create feature branches from
develop, merge back todevelop - Code: Follow patterns (see
.rules/for standards) - Test:
uv run pytestwith coverage; no mock tests (integration tests use real API calls withANTHROPIC_API_KEYfrom.env) - Commit: Atomic, concise, no emojis, no AI attribution
- PR: Target
developby default, notmain - Review: Address ALL PR review findings; no technical debt carried forward
- main: Production-ready code (stable releases)
- develop: Default target for PRs; active development branch (alpha releases)
- Feature branches: Create from develop, merge back to develop (dev releases)
- Use
scripts/bump_version.py(never edit version manually) - Version suffix rules by target branch:
- PRs to
develop:.devsuffix (e.g.,0.6.8.dev0) - PRs to
main:a(alpha) suffix (e.g.,0.6.8a1) - After merge to main for release:
b(beta) or stable
- PRs to
- Tags: ONLY push after the PR is merged; never push tags from feature branches
- Skip auto-release: Add
[skip-release]to commit messages on main for docs-only, context, or config changes - Prerelease flow:
dev(TestPyPI) ->alpha/beta/stable(PyPI) - Example:
python scripts/bump_version.py patch --prerelease dev
After syncing develop with main (post-release), bump patch and set to .dev0
(e.g., main at 0.6.7a2 -> develop becomes 0.6.8.dev0).
Increment dev number for ongoing work.
Never use alpha versions on develop.
develop: 0.6.8.dev0 -> 0.6.8.dev1 -> 0.6.8.dev2 (TestPyPI)
v (PR merge to main)
main: 0.6.8a1 -> 0.6.8a2 -> 0.6.8 (PyPI)
v (sync back to develop)
develop: 0.6.9.dev0 (next cycle)
- Never use mocks that replace business logic in tests
(HTTP response fixtures like
respxare acceptable for error/retry paths) - Never use
pip,conda, orvirtualenv; useuv - Never use
npmornpx; use Bun (bun,bunx) - Never commit secrets,
.envfiles, or credentials - Never edit version numbers manually; use
scripts/bump_version.py - Never push tags from feature branches
- Never change frontend/backend request headers without redeploying both Workers
.rules/git.md- Branching, commits, PRs, versioning.rules/python.md- UV, ruff, ty.rules/testing.md- No-mock policy, integration tests.rules/ci_cd.md- GitHub Actions standards.rules/code_review.md- PR review toolkit and checklist.rules/documentation.md- Documentation standards.rules/self_improve.md- Capturing learnings into rules
.context/agent-architecture.md- Multi-agent system design.context/api-and-deployment.md- API endpoints, auth modes, hosting details.context/hed-schemas.md- HED schema structure and access.context/hed-validation.md- Validation tools and feedback.context/hed-annotation-rules.md- Core annotation semanticsplan.md- Detailed roadmap and current tasks
- HED Schemas:
/Users/yahya/Documents/git/HED/hed-schemas - HED Validation:
/Users/yahya/Documents/git/HED/hed-javascript - HED Documentation:
/Users/yahya/Documents/git/HED/hed-resources
- Production API: https://api.annotation.garden/hedit
- Development API: https://api.annotation.garden/hedit-dev
- Frontend: https://hedit.pages.dev (dev: https://develop.hedit.pages.dev)
- PyPI Package:
hedit
See plan.md for the detailed roadmap and current tasks.