# RFC: BDL-013 — Dogfood Beadloom + Agent Instructions + CI

> **Status:** Draft
> **Date:** 2026-02-14
> **PRD:** BDL-013/PRD.md

---

## 1. Overview

This RFC describes the technical implementation of 12 deliverables across
3 packages: A (Dogfood), B (Agent Instructions), C (CI). One small code
change (D12: README.md generation); everything else uses existing v1.3.1
capabilities on the project itself.

---

## 2. Package A: Dogfood

### D9: Pre-commit hook

Run once:

```bash
beadloom install-hooks --mode warn
```

This creates `.git/hooks/pre-commit` that runs `beadloom sync-check` before
each commit. Mode `warn` prints stale pairs but does not block the commit.

Config already has `sync.hook_mode: warn` in `.beadloom/config.yml`.

**Verification:** `git commit` on a repo with stale docs shows warning.

---

### D10: Expanded rules.yml

Current state (2 rules):

```yaml
rules:
  - name: domain-needs-parent     # require: domain → part_of → beadloom
  - name: feature-needs-domain    # require: feature → part_of → domain
```

New rules to add:

```yaml
  # Require: every service must be part_of beadloom
  - name: service-needs-parent
    description: "Every service must be part_of the beadloom service"
    require:
      for: { kind: service }
      has_edge_to: { ref_id: beadloom }
      edge_kind: part_of

  # Deny: domains must not depend on services
  # (services depend on domains, not the other way)
  - name: no-domain-depends-on-service
    description: "Domains must not have depends_on edges to services"
    deny:
      from: { kind: domain }
      to: { kind: service }

  # Require: every feature must have documentation
  # (already enforced by doctor, but explicit rule is better for CI)
```

**Note:** The deny rule `no-domain-depends-on-service` may need an
`unless_edge` exemption if legitimate cross-layer dependencies exist.
We evaluate this during D11.

**Total:** 4 require rules + 1 deny rule (meets G6: ≥4 require + ≥1 deny).

---

### D11: Verify and fix issues

After adding new rules, run:

```bash
beadloom reindex --full
beadloom lint --strict --format json
beadloom doctor
beadloom sync-check
```

**Known issue found during analysis:** The graph has suspicious reverse
edges that may cause lint violations:

```
infrastructure -->|depends_on| beadloom
infrastructure -->|depends_on| context_oracle
infrastructure -->|depends_on| doc_sync
infrastructure -->|depends_on| graph
```

These were likely auto-generated by `import_resolver` because the `reindex`
feature (part of `infrastructure`) imports from all domains. This is
architecturally correct (reindex orchestrates all indexers) but the edges
are on the `infrastructure` domain node rather than the `reindex` feature node.

**Action:** Investigate whether these edges are correct. If not, fix the
graph YAML. If they cause deny rule violations, add `unless_edge` exemptions
with documented rationale.

---

### D12: Generate `.beadloom/README.md`

Two parts: (a) generate for our own project now, (b) add to bootstrap so
all future `beadloom init` projects get one.

**Part a — Create `.beadloom/README.md` for Beadloom itself:**

```markdown
# Beadloom — AI Agent Native Architecture Graph

This project uses **Beadloom** for architecture-as-code — a local knowledge
graph that keeps documentation in sync with code, enforces architectural
boundaries, and provides structured context to AI agents.

## What is Beadloom?

Beadloom is a Context Oracle + Doc Sync Engine designed for AI-assisted
development. It maintains a queryable architecture graph over your codebase,
so agents spend less time searching and more time building.

**Learn more:** [github.com/anthropics/beadloom](https://github.com/anthropics/beadloom)

## Quick Start

### Essential Commands

    # Project overview
    beadloom status

    # Architecture graph (Mermaid)
    beadloom graph

    # Context bundle for a domain/feature
    beadloom ctx <ref-id>

    # Check doc-code freshness
    beadloom sync-check

    # Architecture boundary lint
    beadloom lint

    # Full-text search
    beadloom search "<query>"

    # Rebuild index after changes
    beadloom reindex

### For AI Agents (MCP)

Beadloom exposes tools via Model Context Protocol (MCP):

    beadloom mcp-serve             # start MCP server (stdio)
    beadloom setup-mcp             # configure your editor

MCP tools: `get_context`, `get_graph`, `list_nodes`, `sync_check`,
`search`, `update_node`, `mark_synced`, `generate_docs`.

## Directory Contents

    .beadloom/
    ├── _graph/
    │   ├── services.yml    # Knowledge graph (nodes + edges)
    │   └── rules.yml       # Architecture lint rules
    ├── config.yml          # Project configuration
    ├── beadloom.db         # SQLite index (gitignored)
    └── README.md           # This file

## Why Beadloom?

- **Agent Native** — structured context for LLMs, not another LLM wrapper
- **Doc Sync** — detects when docs go stale after code changes
- **AaC Lint** — enforces architectural boundaries via deny/require rules
- **Local-first** — SQLite + YAML, no cloud services, no API keys
```

**Part b — Add generation to `doc_generator.py`:**

Modify `generate_skeletons()` in `src/beadloom/onboarding/doc_generator.py`
to also write `.beadloom/README.md` during bootstrap. The content is a
template with project name interpolated from scan results.

```python
def _generate_beadloom_readme(project_root: Path, project_name: str) -> Path:
    """Generate .beadloom/README.md with quick-start instructions."""
    readme_path = project_root / ".beadloom" / "README.md"
    content = _BEADLOOM_README_TEMPLATE.format(project_name=project_name)
    readme_path.write_text(content)
    return readme_path
```

Call this from `generate_skeletons()` alongside other doc generation.

**Tests:** Add test in `tests/test_doc_generator.py` verifying README.md
is created during bootstrap with correct project name.

---

### D13: Rename "knowledge graph" → "architecture graph"

Codebase-wide terminology consistency. BACKLOG.md item #1.

**Files to update** (replace "knowledge graph" with "architecture graph",
case-preserving):

| File | Occurrences | Notes |
|------|-------------|-------|
| `README.md` | ~7 | Public-facing, highest priority |
| `docs/**/*.md` | ~12 | Project documentation |
| `src/beadloom/services/cli.py` | 3 | CLI help strings |
| `src/beadloom/services/mcp_server.py` | 1 | MCP server description |
| `src/beadloom/onboarding/doc_generator.py` | 1 | Docstring |
| `SECURITY.md` | 1 | Security policy |
| `tests/*.py` | ~2 | Test descriptions |
| `.beadloom/_graph/services.yml` | 1 | Node summary |

**NOT updated** (historical, already completed epics):
- `.claude/development/docs/features/BDL-00*/` — frozen historical docs
- `CHANGELOG.md` — historical release notes
- `AGENTS.md` — being deleted in D8
- `.beads/issues.jsonl` — closed beads, historical

**Approach:** Single commit, `replace_all` per file. Run `beadloom reindex`
after to update SQLite index. Then `beadloom sync-check` to verify no
staleness introduced.

---

## 3. Package B: Agent Instructions

### Design Principle: Dynamic over Static

All skill files will follow this rule:

- **Methodology** (HOW to work) → static text in the skill file
- **Project structure** (WHAT the project looks like) → `beadloom` commands

```markdown
## Before starting work

# Discover project structure (NEVER hardcode paths):
beadloom status                  # overview: nodes, edges, docs, symbols
beadloom graph                   # architecture: domains → features → services
beadloom ctx <ref-id>            # deep dive: source paths, symbols, docs, constraints
```

---

### D3: Update .claude/CLAUDE.md

Add new section **"2.1 Beadloom CLI — Essentials"** after existing section 2
(Beads CLI). Content migrated from AGENTS.md + new workflow steps:

```markdown
## 2.1 Beadloom CLI — Essentials

### Project structure (use instead of hardcoded paths)
beadloom status                  # overview: nodes, edges, docs, coverage
beadloom graph                   # Mermaid architecture diagram
beadloom ctx <ref-id>            # full context: code, docs, constraints
beadloom ctx <ref-id> --json     # structured JSON for parsing
beadloom search "<query>"        # FTS5 search across nodes and docs

### Validation (run before committing)
beadloom reindex                 # rebuild index after code/graph changes
beadloom sync-check              # check doc-code freshness (exit 2 = stale)
beadloom lint --strict           # architecture boundary check (exit 1 = violation)
beadloom doctor                  # graph integrity validation

### After changing code
1. beadloom reindex              # re-index changed files
2. beadloom sync-check           # check if docs went stale
3. If stale: update the doc, then beadloom reindex again
4. beadloom lint --strict        # verify architecture boundaries
```

Update section **"0. CRITICAL RULES"** — WHEN COMPLETING bead:

```markdown
### WHEN COMPLETING bead
# 1. Tests pass
uv run pytest

# 2. Beadloom validation
beadloom reindex
beadloom sync-check
beadloom lint --strict

# 3. Final checkpoint
bd comments add <bead-id> "COMPLETED: [results]"

# 4. Close bead
bd close <bead-id>
```

Add to section **"7. Anti-patterns"**:

```markdown
### Beadloom
- Committing without `beadloom sync-check`
- Hardcoding file paths instead of using `beadloom ctx`/`graph`
- Skipping `beadloom reindex` after graph YAML changes
- Ignoring `beadloom lint` violations
```

---

### D4: Update .claude/commands/dev.md

**Remove:** Entire "Beadloom Architecture" section (lines 52-118) with
fictional package structure (`cli/main.py`, `core/graph.py`, `storage/database.py`,
`parsers/symbols.py`, `mcp/server.py`).

**Replace with:**

```markdown
## Beadloom Architecture

### Discover project structure (always use these, never hardcode paths)

beadloom graph                   # Mermaid diagram: domains, features, services, edges
beadloom ctx <domain>            # full context for a domain: source files, symbols, docs
beadloom ctx <feature>           # full context for a feature
beadloom status                  # overview: node counts, doc coverage, health

### Layers (conceptual, verify with `beadloom graph`)

Services (CLI, MCP, TUI) → Domains (context-oracle, graph, doc-sync, onboarding, infrastructure)
Dependencies point inward. Services depend on domains. Reverse is forbidden.

### Validation during development

beadloom reindex                 # after code/graph changes
beadloom sync-check              # before commit: are docs fresh?
beadloom lint --strict           # before commit: architecture boundaries ok?
beadloom doctor                  # graph integrity
```

**Update:** "Completing a bead" section — add Beadloom validation between
pytest and final checkpoint:

```bash
# 1. Make sure tests pass
uv run pytest

# 2. Linter and types
uv run ruff check src/ tests/
uv run mypy src/

# 3. Beadloom validation
beadloom reindex
beadloom sync-check
beadloom lint --strict

# 4. Add final checkpoint
bd comments add <bead-id> "COMPLETED: ..."

# 5. Close the bead
bd close <bead-id>
```

**Update:** "Developer checklist" — add Beadloom items to "When completing":

```markdown
- [ ] `beadloom reindex` — index is fresh
- [ ] `beadloom sync-check` — no stale docs
- [ ] `beadloom lint --strict` — no architecture violations
```

---

### D5: Update .claude/commands/review.md

**Add** new section after "Security Checklist":

```markdown
## Beadloom Checklist

- [ ] `beadloom sync-check` — no stale doc-code pairs
- [ ] `beadloom lint --strict` — no architecture violations
- [ ] `beadloom doctor` — graph integrity ok
- [ ] If graph YAML changed: edges are correct, no orphaned nodes
- [ ] If new domain/feature added: has documentation in docs/
```

---

### D6: Update .claude/commands/test.md

**Remove:** Static "Test structure" section (lines 8-29) with fictional
`tests/unit/`, `tests/integration/`, `tests/fixtures/` directories.

**Replace with:**

```markdown
## Test structure

Tests are in `tests/` (flat layout). Discover test files:

ls tests/test_*.py               # all test files
beadloom ctx <domain> --json     # see source files → derive test file names

Naming convention: `src/beadloom/<module>.py` → `tests/test_<module>.py`
CLI tests: `tests/test_cli_<command>.py`
Integration tests: `tests/test_integration*.py`
```

**Update:** Fixture imports in examples to use actual paths (verify with
`beadloom ctx infrastructure`).

---

### D7: Update .claude/commands/coordinator.md

**Add** to "Coordinator checklist before wave commit" section:

```markdown
□ beadloom reindex — index is fresh
□ beadloom sync-check — no stale docs
□ beadloom lint --strict — no architecture violations
□ beadloom doctor — graph integrity ok
```

**Add** to "Requirements for sub-agent upon completion":

```bash
# 1. All tests pass
uv run pytest

# 2. Beadloom validation
beadloom reindex
beadloom sync-check

# 3. Add checkpoint with results
bd comments add <bead-id> "COMPLETED: ..."

# 4. Close the bead
bd close <bead-id>
```

---

### D8: Delete AGENTS.md

**Action:** Delete `/Users/v.zoologov/beadloom/AGENTS.md`

**Content migration checklist** (what moves where):

| AGENTS.md section | Destination | Notes |
|-------------------|-------------|-------|
| Project Overview | `.claude/CLAUDE.md` §0.1 | Already exists, verify up-to-date |
| File Organization | DELETED | Replaced by `beadloom graph`/`ctx` |
| Development Guidelines | `.claude/commands/dev.md` | Already exists, more detailed |
| Code Standards | `.claude/commands/dev.md` | Already exists |
| Quality Gates | `.claude/commands/dev.md` | Already exists |
| Testing Workflow | `.claude/commands/test.md` | Already exists |
| Before Committing | `.claude/CLAUDE.md` §0 | Add `beadloom sync-check` |
| Using Beadloom | `.claude/CLAUDE.md` §2.1 | NEW section (D3) |
| Agent Workflows (MCP) | `.claude/CLAUDE.md` §2.1 | Condensed version |
| Architecture Lint | `.claude/CLAUDE.md` §2.1 | Condensed version |
| After Changing Code | `.claude/CLAUDE.md` §2.1 | Part of workflow |
| Issue Tracking with Beads | `.claude/CLAUDE.md` §2 | Already exists |
| Session Completion Protocol | `.claude/CLAUDE.md` §8 | Already exists |
| Common Development Tasks | `.claude/commands/dev.md` | Condense if unique |
| Important Files | DELETED | Replaced by `beadloom status`/`search` |
| Non-Interactive Shell | `.claude/CLAUDE.md` §7 | Add as anti-pattern |

**Unique content to preserve:**

1. "Adding a New CLI Command" recipe → add to `dev.md` if not already there
2. "Adding a New MCP Tool" recipe → add to `dev.md`
3. "Adding Language Support" recipe → add to `dev.md`
4. Non-interactive shell warning (`cp -f`, `mv -f`, `rm -f`) → add to CLAUDE.md

---

## 4. Package C: CI

### D1: beadloom-aac-lint.yml

New workflow file at `.github/workflows/beadloom-aac-lint.yml`:

```yaml
name: AaC Lint

on:
  push:
    branches: [main]
  pull_request:
    branches: [main]

jobs:
  aac-lint:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: Install uv
        uses: astral-sh/setup-uv@v5

      - name: Set up Python
        run: uv python install 3.12

      - name: Install dependencies
        run: uv sync --extra dev --extra languages

      - name: Reindex
        run: uv run beadloom reindex

      - name: Architecture lint
        run: uv run beadloom lint --strict

      - name: Doc-code sync check
        run: uv run beadloom sync-check

      - name: Doctor
        run: uv run beadloom doctor
```

**Design decisions:**
- Single Python version (3.12) — AaC lint doesn't need matrix testing
- No path filters — runs on ALL pushes (docs changes can make sync stale)
- Separate from tests.yml — different concern, different failure semantics
- `--extra languages` needed for tree-sitter import resolution

---

### D2: Optimize tests.yml

Add path filters so tests skip on docs-only changes:

```yaml
on:
  push:
    branches: [main]
    paths:
      - 'src/**'
      - 'tests/**'
      - 'pyproject.toml'
      - '.github/workflows/tests.yml'
  pull_request:
    branches: [main]
    paths:
      - 'src/**'
      - 'tests/**'
      - 'pyproject.toml'
      - '.github/workflows/tests.yml'
  workflow_call:
```

**Rationale:** Tests only need to run when source code, test code, or
dependencies change. Doc-only changes (`.md`, `.yml` in `.beadloom/`,
`.claude/`) are validated by `beadloom-aac-lint.yml` instead.

**Note:** `workflow_call` remains without path filters so `pypi-publish.yml`
can still call it unconditionally.

---

## 5. Execution Order

Dependencies between deliverables:

```
D10 (rules.yml) → D11 (fix violations) → D1 (CI aac-lint)
D12 (README.md) — independent (code change + own project file)
D13 (rename)   — independent (terminology consistency)
D3 (CLAUDE.md) ─┐
D4 (dev.md)    ─┤
D5 (review.md) ─┼→ D8 (delete AGENTS.md)
D6 (test.md)   ─┤
D7 (coord.md)  ─┘
D2 (tests.yml) — independent
D9 (pre-commit) — independent
```

**Suggested wave execution:**

| Wave | Beads | Rationale |
|------|-------|-----------|
| 1 | D10, D9, D2, D12, D13 | Independent, foundation work |
| 2 | D11 | Depends on D10 (new rules must exist to verify) |
| 3 | D3, D4, D5, D6, D7 | Can be parallel (independent files) |
| 4 | D8 | Depends on D3-D7 (content must be migrated before deletion) |
| 5 | D1 | Depends on D11 (lint must pass before enabling in CI) |

---

## 6. Testing Strategy

| Deliverable | Verification |
|-------------|-------------|
| D1 | Push to branch, verify GH Actions runs all 4 steps green |
| D2 | Push docs-only change, verify tests.yml is skipped |
| D3 | Run `/compact`, verify agent still knows `beadloom` commands |
| D4 | Invoke `/dev`, verify no hardcoded paths, Beadloom steps present |
| D5 | Invoke `/review`, verify Beadloom checklist present |
| D6 | Invoke `/test`, verify dynamic structure discovery |
| D7 | Invoke `/coordinator`, verify wave checklist has Beadloom |
| D8 | Verify no broken references after AGENTS.md deletion |
| D9 | `git commit` with stale doc → warning appears |
| D10 | `beadloom lint --strict` → 0 violations with 5 rules |
| D11 | `beadloom lint` + `doctor` + `sync-check` all pass |
| D12 | `beadloom init --bootstrap` on temp dir → `.beadloom/README.md` exists; own project has it |
| D13 | `grep -r "knowledge graph" src/ docs/ README.md` returns 0 matches |

---

## 7. Rollback Plan

All changes are file edits committed to git. Rollback = `git revert`.

- D1, D2: Revert workflow files
- D3-D7: Revert skill files
- D8: Restore AGENTS.md from git history
- D12: Revert `doc_generator.py` + delete `.beadloom/README.md`
- D13: Revert terminology changes (git revert the commit)
- D9: `beadloom install-hooks --remove`
- D10: Revert rules.yml
- D11: Revert graph YAML fixes
