beads-state

$npx mdskill add Tibsfox/gsd-skill-creator/beads-state

Manages agent state as atomic JSON files for crash-recoverable persistence.

  • Stores agent identities, work items, hooks, convoys, and merge requests.
  • Depends on filesystem with atomic write operations, no database.
  • Uses JSON file paths and schemas to organize and retrieve state.
  • Delivers state via file reads and writes for agent orchestration.

SKILL.md

.github/skills/beads-stateView on GitHub ↗
---
name: beads-state
description: Git-friendly, crash-recoverable state persistence for the Gastown orchestration chipset. Manages agent identities, work items, hooks, convoys, and merge requests as JSON files with atomic write operations.
type: skill
category: state
status: stable
origin: tibsfox
modified: false
first_seen: 2026-03-06
first_path: .claude/skills/beads-state/SKILL.md
superseded_by: null
---
# Beads State Persistence

Filesystem-backed state management for multi-agent orchestration. All state is stored as individual JSON files using atomic write operations. No database dependencies.

## State Entities

### Agent Identity

**Path:** `.chipset/state/agents/{id}.json`

Persistent record of an agent in the topology. Contains role, rig assignment, hook pointer, lifecycle status, and optional ephemeral session ID.

```typescript
interface AgentIdentity {
  id: string;           // Unique identifier (e.g., 'polecat-alpha')
  role: AgentRole;      // mayor | witness | refinery | polecat | crew
  rig: string;          // Parent rig name
  hookId: string;       // Pointer to hook bead in state/hooks/
  status: AgentStatus;  // idle | active | stalled | terminated
  sessionId?: string;   // Present only while agent is active
}
```

### Work Item

**Path:** `.chipset/state/work/{bead-id}.json`

A unit of work flowing through the dispatch pipeline. Created by the mayor, assigned via hooks, tracked through lifecycle.

```typescript
interface WorkItem {
  beadId: string;          // Bead-style ID (prefix-xxxxx)
  title: string;
  description: string;
  status: WorkStatus;      // open | hooked | in_progress | done | merged
  assignee?: string;       // Agent ID (undefined if unassigned)
  hookStatus: HookStatus;  // empty | pending | active | completed
  priority: 'P1' | 'P2' | 'P3';
}
```

### Hook

**Path:** `.chipset/state/hooks/{agent-id}.json`

Current work assignment for an agent. Enforces GUPP (Get Up and Push Protocol) -- one agent, one work item at a time.

```typescript
interface HookState {
  agentId: string;
  status: HookStatus;
  workItem?: WorkItem;     // Present when hook is pending/active
  lastActivity: string;    // ISO 8601 timestamp
}
```

**Constraint:** An agent can hold at most one hook at a time. Setting a new hook on an agent that already has an active hook is rejected. The caller must clear the existing hook first.

### Convoy

**Path:** `.chipset/state/convoys/{id}.json`

Groups related work items for batch tracking. The mayor creates convoys to organize beads and monitor aggregate progress.

```typescript
interface Convoy {
  id: string;
  name: string;
  beadIds: string[];
  progress: number;     // 0.0 to 1.0
  createdAt: string;    // ISO 8601
}
```

### Merge Request

**Path:** `.chipset/state/merge-queue/{id}.json`

Queued for the refinery. Processed strictly sequentially -- no parallel merges. Conflicts block the queue and escalate.

```typescript
interface MergeRequest {
  id: string;
  sourceBranch: string;
  targetBranch: string;
  status: 'pending' | 'merging' | 'merged' | 'conflicted';
  beadId: string;
}
```

## Filesystem Layout

```
.chipset/state/
  agents/          Agent identity JSON files
  hooks/           GUPP hook state per agent
  work/            Work item beads
  convoys/         Batch tracking
  merge-queue/     Refinery merge requests
```

Each entity is a single JSON file. The directory structure acts as the "table" -- listing files is the equivalent of a database scan.

## Durability Contract

### Atomic Writes

All mutations follow a three-step atomic write protocol:

1. **Write** content to a temporary file in the same directory (`.{name}.tmp`)
2. **Fsync** the temporary file to ensure data reaches disk
3. **Rename** the temporary file to the target path (atomic on POSIX filesystems)

This guarantees that a reader always sees either the complete old state or the complete new state, never a partial write. If the process crashes between steps 1-2, only the temp file is left (cleaned up on next startup). If it crashes between steps 2-3, the temp file contains the full new state and can be recovered.

### JSON Format

All JSON output uses `JSON.stringify` with sorted keys. This produces deterministic output that creates clean, minimal diffs when tracked by git. Sorted keys also make manual inspection easier -- fields appear in a predictable order.

```typescript
// Sorted-key serialization
function serialize(data: unknown): string {
  return JSON.stringify(data, Object.keys(data as object).sort(), 2);
}
```

### No Database Dependencies

State is filesystem-only. No SQLite, no LevelDB, no external services. This means:

- State is readable with `cat` and editable with any text editor
- State is trackable by git (JSON diffs show exactly what changed)
- State survives any process crash (atomic writes prevent corruption)
- State works across all platforms (POSIX rename semantics)
- State requires no setup beyond `mkdir -p`

## StateManager API

The StateManager class provides typed CRUD operations for all state entities.

### Construction

```typescript
const manager = new StateManager({ stateDir: '.chipset/state/' });
```

The `stateDir` parameter is configurable. The manager creates subdirectories on first use.

### Agent Operations

| Method | Signature | Description |
|--------|-----------|-------------|
| `createAgent` | `(role, rig) => AgentIdentity` | Generate unique ID, write agent JSON |
| `getAgent` | `(id) => AgentIdentity \| null` | Read agent by ID, null if not found |
| `updateAgentStatus` | `(id, status) => void` | Atomic status update |
| `listAgents` | `(filter?) => AgentIdentity[]` | List all agents, optional role/rig filter |

### Work Item Operations

| Method | Signature | Description |
|--------|-----------|-------------|
| `createWorkItem` | `(title, description, priority?) => WorkItem` | Generate bead ID, write work JSON |
| `getWorkItem` | `(beadId) => WorkItem \| null` | Read work item by bead ID |
| `updateWorkStatus` | `(beadId, status) => void` | Atomic status update |

### Hook Operations

| Method | Signature | Description |
|--------|-----------|-------------|
| `setHook` | `(agentId, beadId) => void` | Assign work to agent (single assignment enforced) |
| `getHook` | `(agentId) => HookState \| null` | Read hook state for agent |
| `clearHook` | `(agentId) => void` | Remove hook assignment |

### Convoy Operations

| Method | Signature | Description |
|--------|-----------|-------------|
| `createConvoy` | `(name, beadIds) => Convoy` | Create batch with member beads |
| `getConvoy` | `(id) => Convoy \| null` | Read convoy by ID |
| `updateConvoyProgress` | `(id) => void` | Recalculate progress from member bead statuses |

## Error Handling

- **File not found:** Returns `null` for get operations. Never throws on missing state.
- **Concurrent writes:** Last writer wins (rename is atomic). For coordination, use the convoy or hook layer.
- **Corrupt JSON:** Log warning, return `null`. Caller decides recovery strategy.
- **Disk full:** Propagates OS error. Temp file cleanup is best-effort.

## Usage Patterns

### Create and Assign Work

```typescript
const agent = await manager.createAgent('polecat', 'my-rig');
const item = await manager.createWorkItem('Fix auth bug', 'JWT expiry not handled', 'P1');
await manager.setHook(agent.id, item.beadId);
```

### Track Convoy Progress

```typescript
const convoy = await manager.createConvoy('Sprint 1', [item1.beadId, item2.beadId]);
// ... after some work completes ...
await manager.updateConvoyProgress(convoy.id);
const updated = await manager.getConvoy(convoy.id);
console.log(`Progress: ${(updated!.progress * 100).toFixed(0)}%`);
```

### Filter Agents by Role

```typescript
const polecats = await manager.listAgents({ role: 'polecat' });
const idle = polecats.filter(a => a.status === 'idle');
```

More from Tibsfox/gsd-skill-creator

SkillDescription
3d-interaction-designDesign heuristics for three-dimensional interaction — input modalities (6DoF controllers, gaze, gesture, voice), selection and manipulation techniques (ray-cast, virtual hand, go-go, world-in-miniature), navigation (teleport, continuous, redirected walking), and feedback loops (haptic, audio, visual). Covers Fitts' law in 3D, discoverability vs affordance, safe-zone design, and comfort/simulator sickness mitigation. Use when designing VR/AR interactions, immersive walkthroughs, or any input system where the user's body is the controller.
accessibility-patternsProvides web accessibility best practices for semantic HTML, ARIA, keyboard navigation, color contrast, and screen reader patterns. Use when building UI components, reviewing accessibility, or when user mentions 'a11y', 'accessibility', 'ARIA', 'screen reader', 'keyboard navigation', 'WCAG'.
active-listeningActive listening techniques for effective communication. Covers attending behaviors, paraphrasing, reflective listening, clarifying questions, empathic response, barriers to listening, listening in conflict, and cross-cultural listening. Use when building listening skills, improving understanding in conversation, mediating disputes, or analyzing communication breakdowns.
adversarial-pr-reviewAdversarial spec-compliance PR review — cross-references diffs against approved specs, verifies runtime claims against source, detects competing PRs, audits scope/convention compliance. Use before merging.
agile-methodsAgile and Lean software development methodologies for iterative, adaptive project execution. Covers Scrum (roles, ceremonies, artifacts), Kanban (WIP limits, flow metrics), XP (TDD, pair programming, CI), SAFe overview, Lean Software Development (Poppendieck's 7 principles), user stories (INVEST criteria), estimation via story points and velocity, and the Agile Manifesto's values and principles. Includes Cynefin framework for methodology selection and GSD's relationship to Agile as a structured Lean variant.
algebraic-reasoningSymbolic manipulation, equation solving, and algebraic structures for mathematical reasoning. Covers distributive law, factoring, completing the square, linear through polynomial equation solving, systems of equations (substitution, elimination, Gaussian elimination, matrix methods), algebraic structures (groups, rings, fields), modular arithmetic, polynomial theory, and inequalities. Use when solving equations, simplifying expressions, working with algebraic structures, or performing symbolic manipulation.
algorithmic-awarenessUnderstanding how algorithmic systems shape what users see, know, and do -- from recommendation feeds to search ranking to credit scoring to hiring software. Covers the mechanics of recommendation systems, algorithmic bias and its sources, personalization's effects on information diets, opacity and accountability, AI limitations (hallucination, confident wrongness), and the human-in-the-loop question. Use when a learner needs to think critically about why particular content reached them.
algorithms-data-structuresAlgorithms and data structures from first principles through advanced analysis. Covers sorting (bubble, insertion, selection, merge, quick, heap, radix), searching (linear, binary, BFS, DFS, Dijkstra, A*), fundamental data structures (arrays, linked lists, stacks, queues, hash tables, trees, heaps, graphs, tries), complexity analysis (Big-O, Big-Omega, Big-Theta, amortized), recurrence relations, and algorithm design paradigms (divide-and-conquer, greedy, dynamic programming, backtracking). Use when analyzing, selecting, implementing, or comparing algorithms and data structures.
aminet-browserAminet search and browse: full-text search, category tree navigation, architecture filtering, package detail, and curated collections. Use when searching, browsing, or managing package collections.
aminet-emulatorFS-UAE emulator configuration and launch: hardware profiles, ROM management, WHDLoad integration, config generation, and state snapshots. Use when configuring emulation, managing ROMs, or launching Amiga software.