Skip to content

Commit e438f43

Browse files
fahchenclaude
andcommitted
chore: add AGENTS.md and mix precommit alias
Add AGENTS.md (agents.md convention) documenting project overview, commands, architecture, and conventions for AI coding agents. CLAUDE.md is a symlink to AGENTS.md for Claude Code compatibility. Replace the `check` mix alias with `precommit`, which mirrors CI (deps.unlock --check-unused, format --check-formatted, compile --warnings-as-errors, credo --strict, dialyzer, test). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 parent b486af5 commit e438f43

3 files changed

Lines changed: 79 additions & 1 deletion

File tree

AGENTS.md

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
# AGENTS.md
2+
3+
Instructions for AI coding agents (Claude Code, Codex, Cursor, Aider, etc.) working in this repository. Follows the [agents.md](https://agents.md) convention.
4+
5+
## Overview
6+
7+
ColouredFlow is a 100% Elixir workflow engine built on [Coloured Petri Nets (CPN)](https://github.com/lmkr/cpnbook). It ships:
8+
9+
- A CPN ML expression language and evaluator.
10+
- A DSL for defining nets in Elixir.
11+
- An event-sourced runtime executing enactments (workflow instances) as GenServers.
12+
- Pluggable storage — in-memory for tests, Ecto/Postgres for production.
13+
14+
## Commands
15+
16+
- `mix precommit`**run before every commit.** Mirrors CI: deps check, format check, compile warnings-as-errors, credo, dialyzer, test.
17+
- `mix test` — full suite. Needs Postgres at `postgres:postgres@localhost`; `test_helper.exs` auto-creates DB `coloured_flow_test`. Set `RESET_DB=1` to drop & recreate.
18+
- `mix test path/to/file_test.exs:LINE` — single test.
19+
- `mix format` · `mix credo --strict` · `mix dialyzer` — individual checks. Dialyzer PLTs cached at `priv/plts/`.
20+
21+
CI: `.github/workflows/elixir.yml` runs the same checks in parallel against Postgres 15.
22+
23+
## Architecture
24+
25+
The code splits into **static CPN structure**, **CPN semantics**, and the **enactment runner**.
26+
27+
### Module map (`lib/coloured_flow/`)
28+
29+
| Path | Role |
30+
| --- | --- |
31+
| `definition/` | Pure data model. `ColouredPetriNet` holds `colour_sets`, `places`, `transitions`, `arcs`, `variables`, `constants`, `functions`, optional `termination_criteria`. |
32+
| `enactment/` | Runtime values: `Marking` (tokens on a place), `BindingElement` (transition bound to input tokens), `Occurrence` (fired binding — the event-source event). |
33+
| `multi_set.ex` | Multiset token bag. Sigil: `~MS[{1, "a"}, {2, "b"}]`. |
34+
| `notation/` | Elixir DSL: `colset/1`, `val/1`, `var/1`, `arc` macro. |
35+
| `builder/` | Converts DSL input into a validated `ColouredPetriNet`. |
36+
| `validators/` | Static definition checks (colour sets, arc typechecks) + enactment-time invariants. |
37+
| `expression/` | CPN ML compiler/evaluator; builds guards and bindings for arc inscriptions. |
38+
| `enabled_binding_elements/` | Given marking + transition, enumerates every firing binding. Core Petri-net semantics. |
39+
| `runner/` | GenServer-based execution engine — see below. |
40+
41+
### Runner (`lib/coloured_flow/runner/`)
42+
43+
Turns a stored CPN + initial markings into a supervised, persistent process tree.
44+
45+
- **Supervision tree.** `Runner.Supervisor``Enactment.Registry` (via-tuple naming) + `Enactment.Supervisor` (`DynamicSupervisor`) → one `Runner.Enactment` GenServer per workflow instance.
46+
- **Enactment state.** `markings`, live `workitems`, monotonically-increasing `version`. Keyed by `enactment_id`, `restart: :transient`. Boot: load latest `Snapshot` (or initial markings) → replay `Occurrence`s via `CatchingUp` → recompute enabled bindings via `WorkitemCalibration` → take new snapshot.
47+
- **Workitem lifecycle.** `enabled → started → completed`, plus `reoffer` (exception recovery) and `withdraw` (system). State machine in `Runner.Enactment.Workitem`. Public API: `WorkitemTransition.{start,complete}_workitem`. Recomputation: `WorkitemCalibration`, `WorkitemCompletion`, `WorkitemConsumption`.
48+
- **Enactment lifecycle.** `running → {terminated | exception}`; `exception` can recover to `running`. Logic in `Runner.Enactment.EnactmentTermination`, driven by `Runner.Termination`. Termination kinds:
49+
50+
| Kind | Trigger |
51+
| --- | --- |
52+
| `:implicit` | no more firable workitems reachable |
53+
| `:explicit` | definition's `termination_criteria` met |
54+
| `:force` | user call |
55+
56+
- **Event sourcing.** Firing a binding element produces an `Occurrence`; snapshots are periodic roll-ups. Recovery = load snapshot + replay occurrences after it.
57+
- **Storage** (`runner/storage/`). `Runner.Storage` behaviour; implementation picked via `Application.get_env(:coloured_flow, ColouredFlow.Runner.Storage)[:storage]`.
58+
59+
| Implementation | Use | Location |
60+
| --- | --- | --- |
61+
| `Storage.Default` | production — Ecto/Postgres | `storage/schemas/`; migrations `storage/migrations/{V0,V1}` |
62+
| `Storage.InMemory` | tests | `storage/in_memory.ex` |
63+
64+
- **Worklist** (`runner/worklist/`). `WorkitemStream.live_query` + `list_live` stream live workitems via cursor (see `TrafficLight` example's `WorkitemPubSub`).
65+
- **Telemetry** (`runner/telemetry/`). Events emitted throughout the enactment lifecycle.
66+
67+
## Conventions
68+
69+
- Prefer `typed_structor` over plain `defstruct` + `@type t` for new data types — used pervasively.
70+
- DSL macros `colset`, `val`, `var`, `return` are registered as `locals_without_parens` — don't add parens when the formatter complains.

CLAUDE.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
AGENTS.md

mix.exs

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,14 @@ defmodule ColouredFlow.MixProject do
5656

5757
defp aliases do
5858
[
59-
check: ["format", "deps.unlock --check-unused", "credo --strict", "dialyzer"]
59+
precommit: [
60+
"deps.unlock --check-unused",
61+
"format --check-formatted",
62+
"compile --warnings-as-errors",
63+
"credo --strict",
64+
"dialyzer",
65+
"test"
66+
]
6067
]
6168
end
6269

0 commit comments

Comments
 (0)