Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,10 @@
Respond to the user in Japanese by default unless they explicitly request another language.

## Project Structure & Module Organization
Core runtime code lives in `doeff/`: monadic primitives in `program.py`, execution helpers in `core.py` and `interpreter.py`, and effect definitions under `effects/` with corresponding handlers in `handlers/`. Shared utilities sit beside them in `utils.py`, `types.py`, and `cache.py`. Tests that exercise each capability reside in `tests/`, while runnable samples land in `examples/`. Workspace extensions such as OpenAI, Gemini, and pinjected bridges are published from `packages/`; keep connector-specific assets inside their respective subpackages. Use `docs/` for design notes or long-form guides that support future contributors.
Core runtime code lives in `doeff/`: monadic primitives in `program.py`, the `@do` decorator in `do.py`, execution via `run()` in `run.py`, result types in `result.py`, and handler utilities in `handler_utils.py`. CLI commands are in `cli/` with auto-discovery (`discovery.py`) and execution (`run_services.py`). Effect definitions and handlers live in `packages/doeff-core-effects/` (effects in `effects.py`, handlers in `handlers.py`, scheduler in `scheduler.py`). Tests that exercise each capability reside in `tests/`, while runnable samples land in `examples/`. Workspace extensions such as OpenAI, Gemini, agents, and pinjected bridges are published from `packages/`; keep connector-specific assets inside their respective subpackages. Use `docs/` for design notes or long-form guides that support future contributors.

## Build, Test, and Development Commands
Install everything (including dev tools) with `make sync`. Use `uv run pytest` for the full suite, `uv run pytest tests/test_cache.py::test_cache_eviction` to target a single scenario, and `uv run pyright` for static typing. Build distributable artifacts via `uv run python -m build` before publishing packages.
Install everything (including dev tools) with `make sync`. Use `uv run pytest` for the full suite, `uv run pytest tests/test_core_effects.py::test_reader_ask` to target a single scenario, and `uv run pyright` for static typing. Build distributable artifacts via `uv run python -m build` before publishing packages.

**WARNING — Stale Rust VM builds:** `uv sync --group dev` does NOT reliably rebuild the Rust VM extension (`packages/doeff-vm`). If you edit any `.rs` file under `packages/doeff-vm/src/`, you MUST run `make sync` (or `cd packages/doeff-vm && maturin develop --release`) to rebuild. Failing to do so will run tests against a stale binary, producing phantom failures that look like real regressions but disappear after a clean rebuild. Always use `make sync` instead of bare `uv sync`.

Expand Down
33 changes: 17 additions & 16 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ def counter_program():

# Compose handlers explicitly by calling each handler installer.
prog = counter_program()
prog = writer()(prog)
prog = writer(prog)
prog = state()(prog)
prog = reader(env={"greeting": "hello"})(prog)
result = run(scheduled(prog))
Expand Down Expand Up @@ -98,14 +98,14 @@ Scheduler effects (from `doeff_core_effects.scheduler`):

Built-in handlers (from `doeff_core_effects.handlers`):

| Handler | Factory | Effects handled |
| Handler | Installer | Effects handled |
| --- | --- | --- |
| Reader | `reader(env={...})` | `Ask` |
| Lazy Ask | `lazy_ask(env={...})` | `Ask`, `Local` (with caching) |
| State | `state(initial={...})` | `Get`, `Put` |
| Writer | `writer()` | `Tell` / `WriterTellEffect` |
| Writer | `writer` | `Tell` / `WriterTellEffect` |
| Try | `try_handler` | `Try` |
| Slog | `slog_handler()` | `Slog` |
| Slog | `slog_handler` | `Slog` |
| Local | `local_handler` | `Local` |
| Listen | `listen_handler` | `Listen` |
| Await | `await_handler()` | `Await` |
Expand All @@ -131,7 +131,7 @@ def main():
results = yield Gather(t1, t2)
return results

result = run(scheduled(writer()(main())))
result = run(scheduled(writer(main())))
print(result) # ['a', 'b']
```

Expand All @@ -141,22 +141,20 @@ print(result) # ['a', 'b']
# Run a program with auto-discovered interpreter
doeff run --program myapp.module.program

# With explicit interpreter
doeff run --program myapp.program --interpreter myapp.interpreter

# With environment
doeff run --program myapp.program --env myapp.default_env

# Inline code
# Inline Python code
doeff run -c 'return 42'

# Apply transform (T -> Program[U])
doeff run --program myapp.program --apply myapp.transforms.wrap
# Inline Hy code (preferred — compose handlers inline)
doeff run --hy '(import myapp [p]) (import doeff-core-effects [lazy-ask]) ((lazy-ask :env myapp.env_dict) p)'

# JSON output
doeff run --program myapp.program --format json
```

> **Note**: Legacy flags `--interpreter`, `--env`, `--set`, `--apply`, and
> `--transform` still work but emit deprecation warnings. Use `--hy` for
> inline handler composition instead.

The CLI supports automatic interpreter/environment discovery via `doeff-indexer`.
See `docs/14-cli-auto-discovery.md` for marker syntax and hierarchy rules.

Expand Down Expand Up @@ -204,10 +202,13 @@ make bench-smoke
## Development

```bash
uv sync --reinstall # rebuild Rust VM
uv run pytest
make sync # install deps + rebuild Rust VM (maturin develop --release)
uv run pytest # run full test suite
```

> **Warning**: `uv sync` alone does NOT rebuild the Rust VM extension. Always
> use `make sync` after editing `.rs` files under `packages/doeff-vm/`.

## License

MIT License. See `LICENSE`.
Loading
Loading