Tool compatibility analysis

June 6, 2026 · View on GitHub

Status: RESEARCH ONLY. This documents the conflicts between the tools and the target design. Nothing here is implemented yet. It answers "what needs to be done", not "done". Scope: every tool in the stack, not just the ones first discussed.

0. What was read (grounding, not hand-waving)

  • Ralph: ~/.claude/ralph-loop/loop.sh, commands/ralph/build.md, ralph-loop/AGENTS.md.
  • GSD: @opengsd/gsd-core~/.claude/skills/gsd-* (67), ~/.claude/agents/gsd-* (33), ~/.claude/gsd-core/VERSION.
  • Beads: live db (bd ready/stats), .beads/ git-managed hooks, project AGENTS.md rules.
  • claude-mem: plugins/.../claude-mem hooks (SessionStart context injection).
  • harness (this repo): hooks + evaluator + DoD + self-tooling.

1. The core problem, in one picture

Three+ disjoint state stores, none of which references the others:

   PLAN / "what to do"          STATUS / "where am I"        LEARNINGS / "what happened"
 ┌───────────────────────┐   ┌────────────────────────┐   ┌──────────────────────────┐
 │ GSD  .planning/*.md    │   │ GSD  STATE.md + todos   │   │ Ralph PROGRESS.md (append)│
 │ Ralph IMPLEMENTATION_  │   │      + TodoWrite        │   │ GSD pause/resume handoff  │
 │       PLAN.md          │   │ Ralph IMPLEMENTATION_   │   │ claude-mem (semantic)     │
 │ Beads issues (graph)   │   │       PLAN.md checkboxes│   │ bd remember               │
 └───────────────────────┘   │ Beads status (db)       │   └──────────────────────────┘
                              └────────────────────────┘

Neither GSD nor Ralph knows Beads exists (grep -ri beads over both = empty). The project rule "track tasks in bd, never markdown" is a human-imposed bridge that actively fights each tool's native design: GSD wants TodoWrite + STATE.md + its own todo store; Ralph wants IMPLEMENTATION_PLAN.md. Every time you run them "as designed", they re-create a second queue and you get double-entry drift. That friction is the root cause.

2. Per-tool ledger

ToolStrength to KEEPWeakness to COMPENSATENative state (the conflict)
GSDBest structured planning: discuss→research→plan→verify, phase/milestone lifecycle, codebase mapping, wave-parallel subagents at ~15% orchestrator contextOwns a task queue it shouldn't (STATE.md + todos + TodoWrite); token-heavy (~4:1); zero Beads awareness.planning/*.md, STATE.md, own todos, TodoWrite
RalphDead-simple OS-level fresh-session loop (claude -p per iteration — a harder context reset than in-session subagents; ideal for very long unattended grinds); "one thing, search-before-assume, append progress" disciplineRe-implements the queue in markdown; --dangerously-skip-permissions removes the human gate; no quality gates by default; can "vibe-loop" with no done-definitionIMPLEMENTATION_PLAN.md, PROGRESS.md, AGENTS.md (commands), specs/
BeadsDurable dependency-aware queue + status surviving restarts; bd ready = unblocked work; bd rememberNot a planner, not a driver, not a verifier — pure memory; needs something to fill it and something to consume itDB (.beads/) — the one store that should be canonical
claude-memAuto semantic recall across sessions; SessionStart context index ("72% reduction from reuse")Overlaps bd remember; can bloat context if unscopedown store + hooks
skills (impeccable, ui-ux-pro-max, tdd, simplify, code-review, verify, plan, shape)Best-in-class craft finishers; on-demand, cheap (progressive disclosure)Heavy overlap among themselves (simplify vs distill; code-review skill vs code-reviewer agent vs gsd verify) — unclear which to call whenn/a
harness (this)Deterministic quality/security gates + default-FAIL evaluator + no-stub contract — the floor under everythingNew; not yet wired into GSD/Ralph loopshooks + agent

3. Conflict matrix (the overlaps that actually bite)

#ConflictToolsSymptom
AThree task queuesBeads vs GSD(STATE+todos+TodoWrite) vs Ralph(IMPLEMENTATION_PLAN)Double-entry; "bd-only" rule fights native designs
BFour progress/handoff storesRalph PROGRESS vs GSD pause/resume+STATE vs claude-mem vs bd rememberNo single "where am I"; stale handoffs
CThree command specsRalph AGENTS.md vs harness CLAUDE snippet vs GSD detectionLint/test command defined 3×, drifts
DTwo execution driversGSD execute-phase (wave subagents) vs Ralph loop (OS fresh sessions)Both want to own the run
EPermissions/safetyRalph --dangerously-skip-permissions vs user rule "never skip" vs harness guard hookUnattended Ralph removes the human STOP-gate
FMultiple planning entriesGSD discuss/plan vs Ralph PROMPT_plan vs plan/shape skills vs brainstormUnclear front door
GMultiple verifiers, different stancesgsd-verifier (goal-backward) vs harness evaluator (default-FAIL) vs verify/code-review skills vs code-reviewer agentNo single acceptance gate; inconsistent rigor
HMemory contradictionAGENTS.md says "bd remember, NOT MEMORY.md"; global memory system uses MEMORY.md; claude-mem adds a thirdDirectly contradictory instructions

4. Target architecture — Beads as the spine

Keep every strength; route all of them through one queue and one quality floor.

            ┌──────────── PLANNING (GSD) ────────────┐
   idea →   │ discuss → research → plan → decompose   │   .planning/*.md = specs/rationale ONLY
            └───────────────┬────────────────────────┘   (the "what/why", not status)
                            │  EMIT issues (epic=phase, child=task, deps)

                  ╔═════════════════════╗
                  ║   BEADS = the spine ║   single source of truth for STATUS + queue
                  ║   bd ready / close  ║
                  ╚═════════╤═══════════╝
              consume bd ready │ (ONE driver per run)
        ┌───────────────┬─────┴───────────────┐
        ▼ supervised    │                     ▼ unattended grind
   GSD execute-phase    │              Ralph loop (Beads-aware PROMPT)
   (wave subagents)     │              (claude -p, fresh session each)
        └───────────────┴─────┬───────────────┘
                              ▼  per task
            TDD → harness hooks (always on) → reviewers → EVALUATOR (default-FAIL)

                       bd close + commit(bd-id)
        learnings → bd remember (task) + claude-mem (semantic). NO PROGRESS.md/STATE queue.

Rules that fall out of this:

  • One queue: Beads. GSD emits into it; Ralph consumes from it. GSD's TodoWrite/STATE/own-todos are demoted to a thin pointer, never the queue.
  • Two modes, one engine, one dial: GSD (supervised) and Ralph (unattended) are not a choice between tools but two autonomy levels of the same loop over bd ready (see §4a). One mode at a time per task; hand off freely between them because status lives in Beads, not in either tool's markdown.
  • One acceptance gate: harness evaluator (default-FAIL). gsd-verifier becomes a goal-backward feeder of evidence into the DoD; verify/code-review run inside the loop, not as rival gates.
  • One quality floor: harness hooks, on under every driver.
  • One commands source: the project's scripts/check.sh; Ralph AGENTS.md and the harness hook both point at it (no re-spec).
  • Memory split (canonical): bd remember = task-bound facts · claude-mem = semantic recall · MEMORY.md = durable user/project. Fix the AGENTS.md↔global contradiction by scoping, not by banning one.
  • Safety: do not use Ralph's blanket --dangerously-skip-permissions. For unattended runs use a permission allowlist + the harness guard hook + STOP-conditions, preserving a real gate.

4a. Two modes of one engine — the autonomy dial

GSD = control, Ralph = autonomy — correct. But the unification is not "pick one": they are the same execution loop at different autonomy levels, sharing one spine (Beads), one quality floor (harness gates + evaluator), one set of contracts (worker contract, Parallel Decomposition Matrix, closeout). Only two things actually differ:

GSD mode (supervised)Ralph mode (unattended)
Human gate frequencyat phase/wave boundariesonly on STOP-conditions
Context resetin-session wave subagents (~15% orch.)OS-level fresh session per task (claude -p)
Best forambiguous / architectural / first-of-kindatomic, unambiguous, green-spec backlog
Contributes to the mergeplanning depth, control, real parallelismhardest reset, long unattended grind

The dial. A phase/task may run in Ralph mode only when: spec unambiguous + tasks atomic + write-zones disjoint + verification automated (red/green). Otherwise GSD mode. Make it an explicit field — autonomy: supervised | unattended + a reason — same discipline as Maslennikov's enumerated sequential-reasons (no vague "seemed simple").

The handoff that "combines the best." GSD plans the phase and does the risky/ambiguous first tasks under supervision; once the pattern is set and the rest of bd ready is atomic, flip the same queue to Ralph mode and grind it unattended. Both modes leave identical artifacts (commit + bd close + evidence), so either can resume the other's work mid-phase.

Why this is only possible with Beads as the spine. If status lived in GSD's STATE.md or Ralph's IMPLEMENTATION_PLAN.md, the modes could not hand off — you'd be locked into one tool's memory. Routing all status through Beads is exactly what turns "choose a tool" into "turn a dial". That single decision is what makes "best of both" mechanically possible rather than aspirational.

5. The work this implies (future — NOT done here)

  1. GSD→Beads emitter. A post-plan-phase step that turns plan files into bd issues (epic per phase, child per task, bd dep add for deps). Removes the manual bridge.
  2. Beads-aware Ralph PROMPT. Replace IMPLEMENTATION_PLAN.md logic with: bd ready --json → claim one → TDD → harness gates → evaluator → bd close → commit. (IMPLEMENTATION_PLAN.md, if kept, is generated from bd as a read-only view.)
  3. Verifier reconciliation. Make evaluator canonical; map gsd-verifier output into DoD evidence rows.
  4. Single commands source. Generate Ralph AGENTS.md validation section + harness quality-gate.local.sh from one scripts/check.sh.
  5. Memory policy. One short doc resolving H; stop the contradictory instructions.
  6. Demote GSD's native queue. Convention/config so Beads is the sole queue (don't let check-todos/STATE act as a second backlog).
  7. Unattended-safety profile. Allowlist + guard hook instead of skip-permissions.

6. Open decisions (yours — they change the above)

  • Primary driver: GSD execute-phase vs Ralph loop as the default Phase-C engine?
  • claude-mem vs bd remember: keep both with the split above, or drop one?
  • How far to bend GSD: lightweight emitter (GSD stays mostly itself) vs deeper fork (GSD natively writes bd)? The former is cheaper and reversible; recommended first.

7. Sober caveats

  • This is an integration/adapter layer — keep each tool, route through Beads, wrap with gates. It is not a rewrite of GSD or Ralph.
  • Token cost compounds (GSD ~4:1 × multi-agent ~15×). Keep a fast-path for trivial work.
  • GSD, Ralph, Beads are young and move fast; adapters must be thin and re-pointable.
  • After a model upgrade, re-test whether some of this scaffolding became dead weight.

8. Field report: "orchestrator = contract dispatcher" (Maslennikov, Habr)

A practitioner running the same stack (Beads + Superpowers, then a Codex port) independently hit and solved our exact problems. His conclusions sharpen the target design above.

Root cause, confirmed. "The orchestrator confidently reads the contract, nods, then quietly cuts corners." A vague contract gives the agent freedom to reinterpret ("delegate medium/complex" → "delegate only when I'm unsure"), and on average it takes the easier path. One big AGENTS.md/CLAUDE.md is an essay, not a contract — nobody executes an essay. (A commenter's fix: keep the root file for hard invariants only; move modular contracts into folders + slash-commands so a contract loads only when its context is active.) → Validates: our gates must be structural, and the v0.2 orchestrator must be small contextual contracts + machine-readable config, not a growing CLAUDE.md.

Mechanisms worth adopting (for v0.2, not now):

  1. Lifecycle-split skills, not one prompt: setup (repo baseline) · stage (active medium/complex work) · router (asset/skill/agent routing within a step) · closeout (evidence-checks, update Beads/handoff, clean worktrees). He calls closeout the most valuable — "stage can't close without passing evidence-checks; silent debt ended." → This is exactly our evaluator/DoD, but lifted to a stage gate that also cleans state.
  2. Parallel Decomposition Matrix — a mandatory table before delegating: Stream · Goal · Agent · Write zone · Dependencies · Verification · Model · Decision · Reason. Rule: ≥2 independent streams ⇒ run parallel; sequential needs a reason from an enumerated list (dependency chain, write conflict, shared verification bottleneck, shared external resource, uncertain scope, repo limit). "Files are related" is not on the list. → Compensates GSD/Ralph "decorative parallelism" (claims parallel, runs sequential).
  3. Machine-readable contract (orchestrator.toml): inline_subagents_allowed = false, parallel_decomposition_matrix = "required_for_medium_complex", model policy, etc. Plus an explicit per-task spawn authorization phrase, because the runtime obeys the user in the current session, not the repo file.
  4. Worker contract fields each close one silent-failure class: write zone (don't touch a sibling's files), stop rules (return blocked, don't redesign), verification (don't claim without running), asset routing (don't re-discover), parallel group (know you're not alone). → Confirms our task-contract template; adopt verbatim.
  5. Completion ≠ acceptance, 4-way: completion event · artifact · orchestrator review · local verification. accepted: yes is illegal without verification evidence (the exact command + output), re-checked at closeout. → Sharpen our DoD: the artifact must record the verification command and its output, not assert "green".

A caveat that changes our conflict E + the hooks design: he removed his Beads hooks ("worked yesterday, not today" — init order, worktrees, approval mode) and went to explicit bd ready/create/update --claim commands: less hidden behavior, portable, explainable. → Important distinction for us: this applies to stateful/session hooks (auto-priming Beads on SessionStart) — prefer explicit bd calls there. It does not condemn our deterministic gate hooks (PostToolUse lint, PreToolUse guard), which are idempotent and don't depend on session state. Design rule: hooks for deterministic gates; explicit commands for state. Also reinforces dropping Ralph's blanket --dangerously-skip-permissions.

Future direction he names — and we should steal: behavioral / pressure tests for the orchestrator ("TDD for the process"): give a medium/complex task → assert it built the matrix; give two independent subtasks → assert it actually spawned them in parallel; submit a completion with no evidence → assert closeout rejected it. Tests for the contracts, not the model — to find where the agent still slips through. This is the natural QA layer for this harness.

Source: Игорь Масленников, "Собрал оркестратор для Codex на базе Beads и Superpowers", Habr (baseline balanced-v2.12). Same author the original blueprint cited on hook flakiness.


9. Beads is the unified spine — a coordination substrate, not a queue

bd --help (verified live) shows Beads already has the primitives GSD fakes in markdown and Ralph lacks. Issue fields: description, acceptance, design(+file), notes(+append), metadata(JSON), labels, typed deps (parent-child), types incl. decision (ADRs). Commands: comment/comments, note, remember (persists across sessions, injected at bd prime), swarm (parallel epic DAG), merge-slot (serialize write conflicts), gate (human/timer/gh:run/gh:pr/bead async waits), set-state (custom event-sourced state dimensions), lint (enforce required sections per type), --readonly (worker sandbox), mol/formula/cook (reusable work templates), search/find-duplicates (text/AI recall), history, export/federation/dolt (versioned, branchable, federated DB).

Everything-on-Beads mapping

Scattered todayNative Beads home
Ralph PROGRESS.md (per-task log)bd comment <task> (append, --stdin for cmd output) + bd note
GSD .planning plan rationaleissue --design (epic) + specs as linked files
GSD STATE.md / todos / TodoWriteissue status + bd ready
claude-mem / MEMORY.md project factsbd remember [--key] (injected at bd prime)
claude-mem semantic "did we do this?"bd search / bd find-duplicates
DoD criteriaissue --acceptance + bd lint enforces the section
Acceptance evidencebd comment w/ verify cmd+output before bd close; bd history = audit
Worker-contract machine fields (write-zone, model, autonomy)issue --metadata JSON + labels
Two human gates + STOP-conditionsbd gate type=human blocking the step
CI / cross-project waitsbd gate type=gh:run / gh:pr / bead
Parallel Decomposition Matrix (streams+deps)bd swarm (epic DAG)
Parallel write-zone conflictsbd merge-slot (exclusive slot + waiter queue)
autonomy: supervised|unattended dialbd set-state mode=... (event-sourced)
Worker can't write outside its taskbd --readonly sandbox
Reusable phase/task/DoD templatesbd mol molecules / bd formula

The unified engine (everything routes through Beads)

  • Plan (GSD's strength): discuss→plan emits a swarm (epic + child tasks, deps, write-zones in metadata, acceptance per task, rationale in design). bd lint rejects tasks missing required sections — the worker-contract is enforced structurally.
  • Drive (one engine, two modes — §4a): consume bd ready within the swarm. Workers run --readonly except their task; merge-slot serializes conflicting writes; set-state mode is the autonomy dial. GSD mode = wave subagents; Ralph mode = claude -p fresh sessions — both append the SAME bd comment evidence trail.
  • Remember: progress→comment, knowledge→remember, evidence→comment, decisions→ type=decision. No PROGRESS.md, no STATE.md, no handoff.md.
  • Gate: human approvals + STOP-conditions + CI become bd gate beads — durable and visible in the queue, not lost in chat.
  • Verify: the evaluator reads the comment evidence and writes its verdict as a comment; bd lint + acceptance enforce the DoD.

Sober — maturity tiers (verify before relying)

  • Solid core (use now): comment/note, remember, acceptance/design/notes/metadata, deps/ready/epic, lint, --readonly, search.
  • Advanced (spike first): swarm, merge-slot, gate, formula/molecule, federation — powerful but young, and the gt:/rig/polecat vocabulary shows they belong to a larger agent-swarm system; confirm semantics + stability before building the engine on them. Start on the solid core; add advanced primitives one at a time behind a working baseline.

10. Per-tool detail cards (verified surfaces, not assumptions)

GSD@opengsd/gsd-core (open-gsd; ~/.claude/gsd-core/VERSION = 1.3.1, 33 agents, 67 skills; we invoke 6)

  • Shape: thin command (commands/gsd/*.md) → workflow logic (workflows/*.md, 34 files) → bin/gsd-tools.cjs (Node state CLI: init <workflow>, init todos, …) → 11 subagents (agents/gsd-*) → references = the "constitution" (model-profiles, tdd, verification-patterns, checkpoints, questioning, planning-config, continuation-format, git-integration, ui-brand).
  • State (.planning/): STATE.md (position + decisions, read before every op), ROADMAP.md, per-plan SUMMARY.md, plan files, todos. Atomic commit per task.
  • Parallelism: plans → waves; orchestrator ~15% ctx spawns subagents/wave; checkpoints between waves (human-verify / decision); AUTO_CFG auto-mode auto-approves/auto-selects; uses fresh continuation agents, not resume.
  • Model profiles quality|balanced|budget map the 11 agents → opus/sonnet/haiku (balanced default).
  • Update: gsd:update (wipes + reinstalls) + gsd:reapply-patches (LLM 3-way merge of gsd-local-patches/ via backup-meta.json). Beads-aware: NO.

Ralphralph-loop/ (own git clone)

  • Shape: loop.sh (while true; cat PROMPT_$MODE.md | claude -p --dangerously-skip-permissions --output-format=stream-json; git push each iter; optional max-iter) + PROMPT_build / PROMPT_plan + commands/ralph/{build,plan,help} (plan.md ≡ PROMPT_plan — duplicate).
  • State (markdown): PRD.md, specs/, IMPLEMENTATION_PLAN.md (checkbox tasks), PROGRESS.md (append-only), AGENTS.md (commands template, placeholders).
  • Discipline: one task/iter, search-before-assume, tests before commit, append progress, emit IMPLEMENTATION COMPLETE. Gaps: no quality gates, skip-permissions, no beads, can vibe-loop.
  • Update: git pull (it's a clone).

Beadsbd (Go CLI, dolt-backed = versioned/branchable; part of a larger "gt" swarm system: rig / polecat / GT_ROOT)

  • Issue: id, type (task/bug/feature/chore/epic/decision=ADR; custom via config), status, priority, description, acceptance, design(+file), notes(+append), metadata(JSON), labels, typed deps.
  • Memory/log: comment/comments, note, remember(--key, injected at bd prime), history.
  • Coordination: swarm (epic DAG), merge-slot (exclusive write-conflict slot + waiter queue), gate (human/timer/gh:run/gh:pr/bead), set-state (event-sourced state dimensions).
  • Templates: formula (.beads/formulas, Rig→Cook→Run) → cook → proto → mol (pour=persistent / wisp=ephemeral; vars {{}}, bond, distill, squash). lint enforces required sections per type.
  • Recall: query language, search, find-duplicates (text/AI).
  • Distribution: export JSONL, federation (P2P), ship (export:/provides:/external: cross-project caps), github/gitlab/notion, dolt branch/diff/merge.
  • Safety: --readonly (worker sandbox), --actor (audit), --sandbox (no auto-sync).
  • Key realization: Beads already is an orchestration substrate (formula+swarm+gate+merge-slot), not just memory. Building "GSD+Ralph on Beads" risks reinventing what gt/Beads offers — prefer to lean on Beads' native swarm/gate/formula as the engine, GSD for planning depth, Ralph for the OS-level loop.

claude-mem — plugin v10.3.1 (Alex Newman, AGPL-3.0 ⚠ copyleft — matters for redistribution)

  • Shape: hooks (Setup, SessionStart = smart-install + bun worker-service daemon + inject context, UserPromptSubmit, PostToolUse = observation, Stop = summarize + session-complete) + MCP server.
  • Stores auto-extracted "observations" per session; SessionStart injects a token-economical index (titles/types/files/tokens), fetch-on-demand.
  • MCP 3-step: search (query/type/date/project → IDs) → timeline (context around anchor) → get_observations (full by IDs); plus save_memory (manual). Overlaps bd remember/bd search.

Skills/commands — live in 4 places, with real overlap:

  • Local commands (~/.claude/commands/*.md): plan, tdd, verify, code-review, build-fix, refactor-clean, update-docs, skill-create.
  • Installed skills (~/.claude/skills/): impeccable (craft/teach/extract), ui-ux-pro-max (design DB), shape (UX discovery), output-skill (full-output-enforcement) + design family + geo-*.
  • Plugin skills: claude-mem (do/make-plan/mem-search), openclaw (make-plan), gsd:, ralph:.
  • Built-in Claude Code: simplify, code-review, verify, run, init, security-review.
  • Overlaps to resolve: plan (≥3×: command + openclaw + built-in), code-review (command + built-in), verify (command + built-in), simplify (built-in). The router must pick ONE per intent.

11. Distribution & upgrade-safety (install everything; pull updates; never break a step)

Goal: one install pulls GSD + Ralph + Beads + claude-mem + harness, auto-applies our wiring, and an md→bd migration keeps working after upstream updates. Four upstreams = four update channels we don't control: GSD (gsd:update+reapply-patches), Ralph (git pull), Beads (binary), claude-mem (plugin update). Rules that make this safe:

  1. Never edit upstream files — overlay, don't patch. Ship behavior as separate files that compose, not edits to GSD workflows / Ralph PROMPTs:

    • our own driver skill /harness-run that calls GSD's planner/executor and Ralph's loop;
    • our own PROMPT_build.beads.md that loop.sh is pointed at via arg/env (original untouched);
    • GSD→Beads emission as a post-step that reads .planning output and writes bd — outside GSD's files. Overlays survive any update because upstream files are untouched. (Only where an edit is truly unavoidable, fall back to GSD's gsd-local-patches/ reapply pattern — and minimize it.)
  2. Idempotent harness-sync (md→bd). Safe to run any number of times, post-install AND post-update: scan GSD .planning/STATE/todos + Ralph IMPLEMENTATION_PLAN/PROGRESS → upsert into Beads, keyed by a stable metadata.source_ref (create if absent, update if changed, never duplicate). Because it upserts on a key, re-running after an update just reconciles — nothing breaks.

  3. Version pinning + harness-doctor. harness/versions.lock records tested upstream versions. On install/update, doctor compares installed vs tested; if an upstream changed something our overlay depends on (GSD .planning schema, Ralph PROMPT filename, a bd subcommand) it fails loud with a clear message and isolates that overlay (disable it, keep the rest working). "A step breaks" becomes "a step is detected and quarantined" — never silent corruption.

  4. Installer orchestrates. install.sh / plugin Setup hook: ensure Beads (bd init), install/verify GSD+Ralph+claude-mem at pinned versions, drop overlays, run harness-sync, run harness-doctor. One harness-update re-pulls each upstream via its own channel, re-drops overlays, re-runs sync + doctor.

  5. Beads is the durable floor. All state lands in dolt-versioned Beads, so even if one upstream breaks on update, the work survives in bd and you finish in another mode. That safety net is what makes "no step breaks" actually achievable, not aspirational.