keiki-0.1.0.0: README.md
# keiki — 継起
A Haskell library for the **pure core** of event sourcing, workflow
engines, and durable execution, built on one formalism: the
symbolic-register finite-state transducer.
keiki keeps the runtime boundary deliberately small. You describe an
aggregate or workflow once as a typed transducer; the library derives
the event-sourcing facade, replay, acceptors, projections, composition
machinery, diagram renderers, and optional symbolic checks from that
single declaration.
## The name
**継起** (*keiki*) is the Japanese word for **"successive occurrence"** —
events that follow, one after another, each rising out of what came before.
| Kanji | Reading | Meaning |
|---|---|---|
| 継 | *kei* | to continue, to succeed (as an heir does), to follow on |
| 起 | *ki* | to rise, to occur, to begin, to happen |
The choice is literal. An event-sourced aggregate is a sequence of events
in succession, each one rising out of the state the previous events left
behind. *keiki* names that pattern directly: 継 (the prior event is
succeeded by) 起 (the next one rising). The replay fold —
`reconstitute :: [Event] → State` — is exactly the operation the word
describes.
(Disambiguation, since the romanisation is ambiguous: this is 継起, not
景気 *keiki* "economic conditions" nor 計器 *keiki* "gauge / instrument".
Only the 継起 reading carries the "succession of events" sense.)
## What it is
A unified treatment of three problems often solved with separate
runtime concepts:
1. **Event sourcing** — store the immutable log of events, replay to
recover state.
2. **Workflow engines** — coordinate long-running multi-step processes.
3. **Durable execution** — resume cleanly after a crash, mid-process.
keiki models all three as **finite-state transducers** with a typed
register file and predicate-labelled guards: a practical hybrid of
Symbolic Finite Transducers and Streaming String Transducers. From one
`SymTransducer` declaration, the library mechanically derives:
- the Chassaing-shape `Decider` (`decide`/`evolve`/`initialState`/`isTerminal`),
- input- and output-side `Acceptor`s,
- per-vertex projections (the "B-presentation" view),
- composition (`compose`, `alternative`, `feedback1`),
- profunctor / `Category` / `Strong` / `Choice` instances,
- Mermaid and Markdown renderers for documentation,
- single-valuedness checks via SBV + z3 as an opt-in symbolic CI gate.
`delta` / `omega` / `applyEvent` use concrete predicate evaluation — no
solver in the per-event hot path. Solver dispatch is reserved for
build-time analysis.
## Status
Pre-1.0, prepared for the initial `0.1.0.0` Hackage release. The
planned v0.1 surface is implemented and validated against in-tree tests
plus the downstream `jitsurei` worked-example package.
The core package is intentionally codec-free. JSON support lives in
[`keiki-codec-json`](keiki-codec-json/README.md), and downstream codec
testing helpers live in
[`keiki-codec-json-test`](keiki-codec-json-test/README.md).
## Build
Requires GHC 9.12 and (for the symbolic analyses only) `z3` on `PATH`.
```sh
nix develop # provides ghc 9.12, cabal, z3
cabal build all
cabal test all
```
Pure evaluation (`delta`, `omega`, `step`, `reconstitute`) does not
depend on z3. The symbolic checks in `Keiki.Symbolic` will fail loudly
if z3 is missing when invoked.
## A taste
The smallest useful aggregate, in full:
```haskell
emailDelivery
:: SymTransducer (HsPred EmailRegs EmailCmd)
EmailRegs EmailVertex EmailCmd EmailEvent
emailDelivery = B.buildTransducer EmailPending emptyRegFile
(\case EmailSentVertex -> True; _ -> False) do
B.from EmailPending do
B.onCmd inCtorSendEmail $ \d -> B.do
B.slot @"emailRecipient" .= d.recipient
B.slot @"emailSubject" .= d.subject
B.slot @"emailSentAt" .= d.at
B.emit wireEmailSent EmailSentTermFields
{ recipient = d.recipient
, subject = d.subject
, at = d.at
}
B.goto EmailSentVertex
```
`Decider`, `Acceptor`, replay, and the per-vertex view are all derived
from this one declaration. See the sibling `jitsurei/` package for the
full worked aggregates the test suite drives.
## Repository documentation
The repository includes user guides, design notes, and implementation
history:
| Folder | Audience |
|---|---|
| `docs/foundations/` | Onboarding. Reads as a tutorial in ~1 hour; assumes Haskell, no automata-theory background. Start at `00-reading-guide.md`. |
| `docs/guide/` | Action-oriented. `user-guide.md` is the canonical authoring walkthrough; topical guides cover composition, profunctors, symbolic CI, AST drop-down, and B-views. |
| `docs/research/` | Design notes for the library itself. Assume foundations vocabulary. The current baseline is `synthesis-c-foundation-b-presentation-with-worked-examples.md`. |
| `docs/adr/` | Stable architecture decisions distilled from the plan history. |
| `docs/plans/` and `docs/masterplans/` | Execution records for the work that produced v0.1. |
| `docs/historical/` | Superseded design notes, retained for context only. |
For a status snapshot — what's implemented, what's next, and what's intentionally
out of scope — see [`ROADMAP.md`](ROADMAP.md).
Recommended shortest path:
1. `docs/foundations/00-reading-guide.md` — orientation.
2. `docs/guide/user-guide.md` — write your first aggregate.
3. `docs/research/synthesis-c-foundation-b-presentation-with-worked-examples.md` — the design baseline.
## License
BSD-3-Clause. See [`keiki.cabal`](keiki.cabal) for package metadata.