Each layer owns one thing. The boundaries are deliberate. The alignment delta is what holds them honest.
Swink AgentShore reads project state from three sources. Mixing them together is what most multi-agent systems get wrong: state ends up duplicated, drifts apart, and the LLM Agents end up reasoning about a stale snapshot of reality.
Epics → stories → tasks. Dependencies between them. bd ready is what the policy asks when it needs to know what's actually doable right now. BEADS is owned by the bd tool; Swink AgentShore reads it through the standard interface.
Issues, PRs, comments, labels. Mirrored to and from BEADS via external_ref="gh-N". This is the layer humans inspect, comment on, and steer. Swink AgentShore writes here freely (creating, editing, labeling, decomposing, closing), with every mutation receiving an idempotency key and audit record.
Plays, parameters, rewards, agent histories, PPO experience rows, policy checkpoints. Lives in .agentshore/agentshore.db in the project root. Local, inspectable, namespaced schema (agentshore_dev_v1). This is what the RL Agent is: not in a model file, but in the trajectory of decisions it has already made.
Could BEADS be a table inside Swink AgentShore's SQLite? Yes. Could GitHub be the project graph? In theory. The design pulls them apart on purpose:
| Concern | Owner |
|---|---|
| Epic/story/task graph | BEADS |
| Dependency edges | BEADS |
bd ready queue | BEADS |
| Issue text, labels, assignment | GitHub |
| PR state, review threads, merges | GitHub |
| Human comments and steering | GitHub |
| PPO experience rows | Swink AgentShore SQLite |
| Policy checkpoints | Swink AgentShore SQLite |
| Mutation audit, idempotency keys | Swink AgentShore SQLite |
| Per-tick alignment delta | Swink AgentShore SQLite (computed from BEADS) |
The reward signal that ties the three layers together is the alignment_delta: the per-tick change in state.graph.global_closure_ratio. In plain language: is the work shaped like the goal, and getting closer to done?
It's a float | None. None means the project graph hasn't been seeded yet. The first play of any session is Seed Project, which invokes bd to build the epic/story/task graph from open GitHub issues. Once seeded, alignment becomes a live signal the policy can optimize against.
There's no goals.yaml. The goal is whatever the open issues say it is. The policy's first move on a fresh repo is to read GitHub, build BEADS, and let alignment start flowing. Everything downstream (play selection, agent routing, reward) is bootstrapped from that one read.