Skip to content

Data Design — HELIX Bead Tracker

Data Design — HELIX Bead Tracker

Scope: The .ddx/beads.jsonl issue tracker that anchors HELIX execution. Status: Complete

Data Summary

  • Scope: The bead tracker — HELIX’s only durable execution-state store. Beads are work units (issues, tasks, epics, planning notes) governed by upstream artifacts and consumed by ddx agent execute-bead / ddx agent execute-loop.
  • Storage systems: Append-friendly JSON Lines file (.ddx/beads.jsonl) with per-record locking enforced by the ddx bead CLI. No database, no daemon required for reads.
  • Main concerns: Concurrent writer safety (operator and supervisor may both mutate during a live helix run), stale-claim recovery, deterministic ready/blocked queries, append history preserved in events, and forward- compatible schema evolution without breaking existing tooling.
  • Authority: CONTRACT-001 (ddx bead and .ddx/beads.jsonl belong to DDx; HELIX consumes via the CLI), ADR-002 (tracker write safety model — referenced where available), and API-001 (HELIX-side mutation surface).

Entities and Stores

Entity or StorePurposeKey FieldsVolume / GrowthNotes
beads.jsonl (record per line)Durable issue/work-unit stateid, title, description, status, priority, issue_type, labels[], parent, dependencies[], acceptance, spec-id, events[], claim metadata, created_at, updated_atHundreds to low thousands of records over a project lifetime; one file per repoAppend/rewrite via ddx bead; never edit by hand during a live run
events[] (embedded array per bead)Append-only audit trail of state transitions and execution attemptsevent_type, timestamp, actor, payload10s–100s per bead over its lifetimeBounded by execution count; older events may be summarized but never silently truncated
Claim metadata (embedded fields)Single-writer guard for active executionclaimed-at (ISO-8601 UTC), claimed-pid, claimed-machine, ownerOne slot per in-progress beadCleared by --unclaim, close, or orphan-recovery sweep
Execution-eligibility metadataDistinguishes execution-ready beads from refinement/superseded onesexecution-eligible, superseded-by, replacesSparse — most beads do not need itDrives ddx bead list --execution-ready

Relationships

FromToTypeCardinalityOn Delete
BeadBead (parent)epic-childN:1 (optional)RESTRICT — close epics only after children resolve
BeadBead (dependencies[])depends-onN:M (optional)RESTRICT — closing a dep does not auto-close dependents; readiness recomputes
BeadGoverning artifact (spec-id)governed-byN:1 (optional path string)No delete propagation — spec-id is a path, not a foreign key; drift is surfaced via review
BeadBead (superseded-by / replaces)supersessionN:1 (optional)Supersession redirects readiness queries; original bead remains for audit

Access Patterns and Constraints

Access PatternFrequencyPerformance NeedSupporting Index or Cache
ddx bead list --status open --json (full read)Every supervisor cycleSub-second on thousand-record storesSequential scan of JSONL — acceptable at this scale
ddx bead ready (filter open + deps satisfied + not superseded)Every supervisor cycleSub-secondComputed in-memory after full read
Single-bead update (update, claim, close)Every build cycle (many per helix run)Strict atomicity — no torn writesExclusive file lock around read-modify-rewrite; events[] append captures intent before status changes
Orphan-recovery sweep (claims older than HELIX_ORPHAN_THRESHOLD, default 7200s)Periodic during long runsBounded; touches only stale claimsFilter on claimed-at age + dead-PID check
helix status snapshot (counts by status, focused-epic view)Operator-initiated, ad hocSub-secondReuses the open-list scan

Validation and Security

Field or Data TypeRules / ClassificationProtection or Error Handling
idRequired; opaque (helix-<8hex>); unique within fileGenerator rejects duplicates; corrupt IDs surface as parse failures
statusEnum: open, in_progress, blocked, closed, supersededMutations validated by ddx bead; raw JSONL edits during a live run risk torn state
claimed-atISO-8601 UTC; cleared on --unclaim and closeOrphan recovery uses age threshold + dead-PID check before clearing
claimed-pid, claimed-machineFree-form identifiersDead-PID check is part of orphan recovery; recovery never destroys unrelated worktree state
labels[]Free-form strings; helix, activity:*, kind:*, area:*, story:US-* are conventionalConvention enforced by HELIX skills; tracker accepts any label
description, acceptance, titleFree-form text — may include rendered context digestsNo secret-bearing fields by contract; the tracker is checked into the repo by default. Operators must keep secrets out of bead bodies.
events[] payloadsAppend-only historyNever rewritten by HELIX; corruption is recoverable from git history
File-level accessRepo-relative; readable by anyone with repo read accessTreat as public-ish: do not store secrets, customer data, or credentials

Migration Strategy

  • Tooling: ddx bead is the only sanctioned writer. Schema evolution is managed downstream in DDx; HELIX consumes through the published CLI contract per CONTRACT-001.
  • Approach: Additive fields land first (new optional metadata is ignored by older readers). Status enum extensions require a coordinated reader update before the new value is emitted. Removed fields go through a deprecation cycle — the writer stops emitting first, then a later major version drops read tolerance.
  • Backfill or cleanup: Historical migration from the legacy .helix/issues.jsonl store is captured in docs/helix/02-design/plan-2026-03-27-supervisory-concurrency.md and the surrounding planning beads. The migration was a one-shot rewrite with the legacy file retired; no live rollback path is supported.
  • Rollback: Because the file is plain JSONL under git, any unintended schema drift is recoverable by reverting the offending commit. Live tracker writes during a helix run are audited via events[] so a torn write can be reconstructed without fully reverting the file.