125 lines
4.3 KiB
Markdown
125 lines
4.3 KiB
Markdown
# Flow Architecture
|
|
|
|
This document describes the current action-runtime architecture.
|
|
|
|
## Runtime Shape
|
|
|
|
Flow is organized around a canonical action plan:
|
|
|
|
```text
|
|
cli -> app -> domain -> actions -> adapters
|
|
```
|
|
|
|
The important boundary is `ActionPlan -> ActionExecutor -> ActionResult`.
|
|
|
|
- `cli`: Typer command declarations and argument parsing in `src/flow/cli.py`.
|
|
- `app`: command use-cases in `src/flow/app/`. These load config/state, compose
|
|
domain planners, and submit action plans.
|
|
- `domain`: pure models, parsers, resolvers, and planners in `src/flow/domain/`.
|
|
- `actions`: canonical action models, expansion, execution, dry-run rendering,
|
|
JSONL audit logging, and rollback in `src/flow/actions/`.
|
|
- `adapters`: filesystem, process, git, package-manager, download, archive,
|
|
container, and tmux implementations in `src/flow/adapters/`.
|
|
|
|
The filesystem is not the core abstraction. It is one adapter used by the
|
|
executor. The core abstraction is the action plan.
|
|
|
|
## Actions
|
|
|
|
`DomainAction` captures user intent:
|
|
|
|
- `kind`: `dotfiles`, `package`, `project`, `repo`, `container`, `remote`,
|
|
`setup`, or `completion`
|
|
- `action`: `link`, `unlink`, `install`, `remove`, `update`, `pull`, `push`,
|
|
`create`, `stop`, and related verbs
|
|
- `payload`: typed-by-domain data or already expanded primitive actions
|
|
- `rollback_policy`: `rollbackable`, `barrier`, or `none`
|
|
|
|
`PrimitiveAction` is the executor-owned operation set:
|
|
|
|
- filesystem: create/remove symlink, write, write JSON, copy, copy tree, remove,
|
|
chmod
|
|
- git: clone, pull, push, fetch, checkout, status
|
|
- process: argv command or explicit user shell hook
|
|
- packages/assets: download and archive extraction
|
|
- containers: run, start, stop, kill, remove, exec
|
|
- tmux: new session, set option, respawn pane
|
|
|
|
Domain actions are expanded before execution. Dry-run output and audit logging
|
|
come from the same primitive list that real execution uses.
|
|
|
|
## Rollback
|
|
|
|
Rollback is explicit and best effort.
|
|
|
|
Supported file/state primitives record reverse actions before mutation. On
|
|
failure, the executor rolls back in reverse order until it reaches a barrier.
|
|
External boundaries such as package-manager commands, user shell hooks, git
|
|
pushes, container lifecycle operations, and interactive command handoffs are not
|
|
guaranteed to roll back.
|
|
|
|
## Command Surface
|
|
|
|
Implemented commands:
|
|
|
|
```text
|
|
flow dotfiles init|link|unlink|status|edit
|
|
flow dotfiles repos list|status|pull|push
|
|
flow packages install|remove|list
|
|
flow setup run|show|list
|
|
flow remote enter|list
|
|
flow enter
|
|
flow dev create|attach|connect|exec|enter|stop|remove|rm|respawn|list
|
|
flow projects check|fetch|summary
|
|
flow sync
|
|
flow completion zsh|install-zsh
|
|
```
|
|
|
|
Global flags:
|
|
|
|
```text
|
|
flow --version
|
|
flow --quiet
|
|
flow --no-color
|
|
```
|
|
|
|
Mutating non-interactive commands expose `--dry-run` where a preview is useful:
|
|
dotfiles link/unlink, dotfiles repo pull/push, package install/remove, setup
|
|
run, remote enter, and dev create.
|
|
|
|
## Dotfiles And Modules
|
|
|
|
The dotfiles repo and `_module.yaml` repos share one abstraction: managed repos.
|
|
`flow dotfiles repos` operates on both. Modules are regular git clones cached
|
|
under the flow data directory; they are not git submodules.
|
|
|
|
Link planning treats conflicts and missing modules as pre-execution failures.
|
|
State is written through actions, and broken tracked symlinks are repaired by
|
|
the same link reconciliation path.
|
|
|
|
## Packages
|
|
|
|
Package manifests are parsed into typed dataclasses. Package-manager commands
|
|
are built as argv lists by the package adapter. Binary and AppImage installs
|
|
expand into download, archive, copy/chmod, cleanup, post-install barrier, and
|
|
state-write primitives.
|
|
|
|
`packages remove` is strict: it refuses unknown packages, removes tracked files,
|
|
and writes updated state through the executor.
|
|
|
|
## Tests And Guards
|
|
|
|
The test suite covers:
|
|
|
|
- action executor dry-run, audit logs, rollback, barriers, domain expansion, and
|
|
primitive dispatch
|
|
- dotfiles discovery, module handling, conflict behavior, rollback, and repo
|
|
operations
|
|
- package manifest parsing, package-manager argv, binary installs, archive
|
|
safety, strict removal, and post-install barriers
|
|
- Typer CLI invocation, help output, completion, and error reporting
|
|
- Docker/Podman e2e for the example dotfiles repo when `FLOW_RUN_E2E=1`
|
|
|
|
Static guard tests reject direct mutating filesystem and command APIs outside
|
|
`actions`, `adapters`, and tests.
|